fix a number of issues and start adding resources
This commit is contained in:
+38
-3
@@ -23,6 +23,7 @@ from atlas.models import (
|
|||||||
CidReportAnswer,
|
CidReportAnswer,
|
||||||
Differential,
|
Differential,
|
||||||
Finding,
|
Finding,
|
||||||
|
Resource,
|
||||||
SelfReview,
|
SelfReview,
|
||||||
Series,
|
Series,
|
||||||
SeriesImage,
|
SeriesImage,
|
||||||
@@ -74,7 +75,7 @@ class ConditionForm(ModelForm):
|
|||||||
class CaseCollectionForm(ModelForm):
|
class CaseCollectionForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CaseCollection
|
model = CaseCollection
|
||||||
exclude = ["cases", "valid_cid_users"]
|
exclude = ["cases", "valid_cid_users", "author"]
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.user = kwargs.pop(
|
self.user = kwargs.pop(
|
||||||
@@ -92,6 +93,18 @@ class CaseCollectionForm(ModelForm):
|
|||||||
|
|
||||||
super(CaseCollectionForm, self).__init__(*args, **kwargs)
|
super(CaseCollectionForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def save(self, commit=True):
|
||||||
|
# Get the unsaved Case instance
|
||||||
|
instance = ModelForm.save(self, False)
|
||||||
|
|
||||||
|
|
||||||
|
# Do we need to save all changes now?
|
||||||
|
# if commit:
|
||||||
|
instance.save()
|
||||||
|
self.save_m2m()
|
||||||
|
|
||||||
|
return instance
|
||||||
|
|
||||||
|
|
||||||
class FindingForm(ModelForm):
|
class FindingForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
@@ -343,8 +356,6 @@ class CaseForm(ModelForm):
|
|||||||
instance = ModelForm.save(self, False)
|
instance = ModelForm.save(self, False)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Prepare a 'save_m2m' method for the form,
|
# Prepare a 'save_m2m' method for the form,
|
||||||
old_save_m2m = self.save_m2m
|
old_save_m2m = self.save_m2m
|
||||||
|
|
||||||
@@ -390,6 +401,21 @@ CaseDifferentialFormSet = inlineformset_factory(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class CaseResourceForm(ModelForm):
|
||||||
|
|
||||||
|
def __init__(self, *args, user, **kwargs):
|
||||||
|
super(CaseResourceForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
if not user.groups.filter(name="atlas_editor").exists():
|
||||||
|
queryset = Resource.objects.filter(author__id=user.id)
|
||||||
|
else:
|
||||||
|
queryset = Resource.objects.all()
|
||||||
|
|
||||||
|
self.fields["resource"] = ModelChoiceField(
|
||||||
|
required=False,
|
||||||
|
queryset=queryset,
|
||||||
|
# widget=Select(verbose_name="Series", is_stacked=False),
|
||||||
|
)
|
||||||
|
|
||||||
class CaseSeriesForm(ModelForm):
|
class CaseSeriesForm(ModelForm):
|
||||||
|
|
||||||
@@ -446,6 +472,15 @@ CaseCollectionCaseFormSet = inlineformset_factory(
|
|||||||
max_num=50,
|
max_num=50,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
CaseResourceFormSet = inlineformset_factory(
|
||||||
|
Case,
|
||||||
|
Resource.case_set.through,
|
||||||
|
form=CaseResourceForm,
|
||||||
|
exclude=[],
|
||||||
|
can_delete=True,
|
||||||
|
extra=0,
|
||||||
|
max_num=10,
|
||||||
|
)
|
||||||
|
|
||||||
SeriesImageFormSet = inlineformset_factory(
|
SeriesImageFormSet = inlineformset_factory(
|
||||||
Series,
|
Series,
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
# Generated by Django 5.0.2 on 2024-04-04 19:24
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('atlas', '0045_casecollection_authors_only'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Resource',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255)),
|
||||||
|
('description', models.TextField(blank=True, null=True)),
|
||||||
|
('url', models.URLField(blank=True, null=True)),
|
||||||
|
('file', models.FileField(blank=True, null=True, upload_to='atlas/resources/')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='CaseResource',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('case', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='atlas.case')),
|
||||||
|
('resource', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='atlas.resource')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='case',
|
||||||
|
name='resource',
|
||||||
|
field=models.ManyToManyField(through='atlas.CaseResource', to='atlas.resource'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# Generated by Django 5.0.2 on 2024-04-04 22:07
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('atlas', '0046_resource_caseresource_case_resource'),
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='caseresource',
|
||||||
|
name='pre_review',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='resource',
|
||||||
|
name='author',
|
||||||
|
field=models.ManyToManyField(blank=True, help_text='Author of the resource', related_name='resources', to=settings.AUTH_USER_MODEL),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -364,6 +364,8 @@ class Case(models.Model, AuthorMixin, QuestionMixin):
|
|||||||
blank=True,
|
blank=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
resource = models.ManyToManyField("Resource", through="CaseResource")
|
||||||
|
|
||||||
def get_app_name(self):
|
def get_app_name(self):
|
||||||
return "atlas"
|
return "atlas"
|
||||||
|
|
||||||
@@ -1142,3 +1144,33 @@ class UncategorisedDicom(models.Model):
|
|||||||
|
|
||||||
class DuplicateDicom(Exception):
|
class DuplicateDicom(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class Resource(models.Model, AuthorMixin):
|
||||||
|
name = models.CharField(max_length=255)
|
||||||
|
description = models.TextField(blank=True, null=True)
|
||||||
|
url = models.URLField(blank=True, null=True)
|
||||||
|
file = models.FileField(upload_to="atlas/resources/", blank=True, null=True)
|
||||||
|
author = models.ManyToManyField(
|
||||||
|
settings.AUTH_USER_MODEL,
|
||||||
|
blank=True,
|
||||||
|
help_text="Author of the resource",
|
||||||
|
related_name="resources",
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("atlas:resource_detail", kwargs={"pk": self.pk})
|
||||||
|
|
||||||
|
def get_link(self):
|
||||||
|
return format_html("<a href='{}'>{}</a>", self.get_absolute_url(), self.name)
|
||||||
|
|
||||||
|
class CaseResource(models.Model):
|
||||||
|
resource = models.ForeignKey(Resource, on_delete=models.CASCADE)
|
||||||
|
case = models.ForeignKey(Case, on_delete=models.CASCADE)
|
||||||
|
|
||||||
|
pre_review = models.BooleanField(default=False)
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return f"{self.resource} - {self.case}"
|
||||||
+2
-1
@@ -5,6 +5,7 @@ from generic.tables import SeriesImageColumn
|
|||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
Case,
|
Case,
|
||||||
|
CaseCollection,
|
||||||
Condition,
|
Condition,
|
||||||
PathologicalProcess,
|
PathologicalProcess,
|
||||||
Presentation,
|
Presentation,
|
||||||
@@ -318,7 +319,7 @@ class CaseCollectionTable(tables.Table):
|
|||||||
selection = tables.CheckBoxColumn(accessor="pk", orderable=False)
|
selection = tables.CheckBoxColumn(accessor="pk", orderable=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Case
|
model = CaseCollection
|
||||||
template_name = "django_tables2/bootstrap4.html"
|
template_name = "django_tables2/bootstrap4.html"
|
||||||
fields = (
|
fields = (
|
||||||
"name",
|
"name",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<div class="atlas {% if case.scrapped %}atlas-scrapped{% endif %}">
|
<div class="atlas {% if case.scrapped %}atlas-scrapped{% endif %}">
|
||||||
<div><a href="https://viewer.penracourses.org.uk/viewer/dicomjson?url=https://www.penracourses.org.uk{% url 'atlas:case_dicom_json' case.pk %}">View case in OHIF</a> <a target="_blank" href="https://viewer.penracourses.org.uk/viewer/dicomjson?url=https://www.penracourses.org.uk{% url 'atlas:case_dicom_json' case.pk %}">(new tab)</a></div>
|
<div><a href="https://viewer.penracourses.org.uk/viewer/dicomjson?url=https://www.penracourses.org.uk{% url 'atlas:case_dicom_json' case.pk %}">View case in OHIF</a> <a target="_blank" href="https://viewer.penracourses.org.uk/viewer/dicomjson?url=https://www.penracourses.org.uk{% url 'atlas:case_dicom_json' case.pk %}">(new tab)</a></div>
|
||||||
|
<div><a href="/ohif/viewer/dicomjson?url=https://www.penracourses.org.uk{% url 'atlas:case_dicom_json' case.pk %}">View case in OHIF</a>
|
||||||
|
|
||||||
<div class="date">
|
<div class="date">
|
||||||
{{ case.created_date|date:"d/m/Y" }}
|
{{ case.created_date|date:"d/m/Y" }}
|
||||||
|
|||||||
@@ -38,10 +38,16 @@
|
|||||||
$('#casedifferential_formset').append($('#empty_casedifferential_form').html().replace(/__prefix__/g, form_idx));
|
$('#casedifferential_formset').append($('#empty_casedifferential_form').html().replace(/__prefix__/g, form_idx));
|
||||||
$('#id_differentialcase-TOTAL_FORMS').val(parseInt(form_idx) + 1);
|
$('#id_differentialcase-TOTAL_FORMS').val(parseInt(form_idx) + 1);
|
||||||
}
|
}
|
||||||
|
function add_resource_input_form() {
|
||||||
|
var form_idx = $('#id_resourcecase-TOTAL_FORMS').val();
|
||||||
|
$('#caseresource_formset').append($('#empty_caseresource_form').html().replace(/__prefix__/g, form_idx));
|
||||||
|
$('#id_resourcecase-TOTAL_FORMS').val(parseInt(form_idx) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$('#add_more_series').click(() => { add_series_input_form() });
|
$('#add_more_series').click(() => { add_series_input_form() });
|
||||||
$('#add_more_differential').click(() => { add_differential_input_form() });
|
$('#add_more_differential').click(() => { add_differential_input_form() });
|
||||||
|
$('#add_more_resource').click(() => { add_resource_input_form() });
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
@@ -91,6 +97,20 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{{ casedifferential_formset.management_form }}
|
{{ casedifferential_formset.management_form }}
|
||||||
|
<h3>Resource:</h3>
|
||||||
|
Add resource here.
|
||||||
|
<input type="button" value="Add Another Resource" id="add_more_resource">
|
||||||
|
<div id="caseresource_formset">
|
||||||
|
{% for form in caseresource_formset %}
|
||||||
|
<ul class="no-error caseresource_formset">
|
||||||
|
{{form.non_field_errors}}
|
||||||
|
{{form.errors}}
|
||||||
|
{{ form.as_ul }}
|
||||||
|
</ul>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{{ caseresource_formset.management_form }}
|
||||||
|
<br/>
|
||||||
<input type="submit" class="submit-button" value="Submit" name="submit">
|
<input type="submit" class="submit-button" value="Submit" name="submit">
|
||||||
</form>
|
</form>
|
||||||
<div id="empty_series_form" style="display:none">
|
<div id="empty_series_form" style="display:none">
|
||||||
@@ -103,4 +123,9 @@
|
|||||||
{{ casedifferential_formset.empty_form.as_ul }}
|
{{ casedifferential_formset.empty_form.as_ul }}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="empty_caseresource_form" style="display:none">
|
||||||
|
<ul class='no_error caseresource_formset'>
|
||||||
|
{{ caseresource_formset.empty_form.as_ul }}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
+14
-2
@@ -39,6 +39,7 @@ from .forms import (
|
|||||||
CaseCollectionCaseFormSet,
|
CaseCollectionCaseFormSet,
|
||||||
CaseCollectionForm,
|
CaseCollectionForm,
|
||||||
CaseForm,
|
CaseForm,
|
||||||
|
CaseResourceFormSet,
|
||||||
CidReportAnswerForm,
|
CidReportAnswerForm,
|
||||||
CidReportAnswerMarkForm,
|
CidReportAnswerMarkForm,
|
||||||
ConditionAutocompleteForm,
|
ConditionAutocompleteForm,
|
||||||
@@ -550,9 +551,9 @@ class CaseCollectionCreate(RevisionMixin, LoginRequiredMixin, CreateView):
|
|||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
self.object = form.save(commit=False)
|
self.object = form.save(commit=False)
|
||||||
self.object.save()
|
self.object.save()
|
||||||
|
|
||||||
form.instance.author.add(self.request.user.id)
|
form.instance.author.add(self.request.user.id)
|
||||||
|
|
||||||
|
|
||||||
context = self.get_context_data(form=form)
|
context = self.get_context_data(form=form)
|
||||||
case_formset = context["case_formset"]
|
case_formset = context["case_formset"]
|
||||||
if case_formset.is_valid():
|
if case_formset.is_valid():
|
||||||
@@ -773,14 +774,22 @@ class AtlasCreateBase(RevisionMixin, LoginRequiredMixin):
|
|||||||
context["casedifferential_formset"] = CaseDifferentialFormSet(
|
context["casedifferential_formset"] = CaseDifferentialFormSet(
|
||||||
self.request.POST, self.request.FILES
|
self.request.POST, self.request.FILES
|
||||||
)
|
)
|
||||||
|
context["caseresource_formset"] = CaseResourceFormSet(
|
||||||
|
self.request.POST, self.request.FILES,
|
||||||
|
form_kwargs={"user": self.request.user},
|
||||||
|
)
|
||||||
context["series_formset"].full_clean()
|
context["series_formset"].full_clean()
|
||||||
context["casedifferential_formset"].full_clean()
|
context["casedifferential_formset"].full_clean()
|
||||||
|
context["caseresource_formset"].full_clean()
|
||||||
else:
|
else:
|
||||||
# context["series_formset"] = SeriesFormSet(instance=Case.objects.filter(author__id=self.request.user.id), queryset=Series.objects.filter(author__id=self.request.user.id))
|
# context["series_formset"] = SeriesFormSet(instance=Case.objects.filter(author__id=self.request.user.id), queryset=Series.objects.filter(author__id=self.request.user.id))
|
||||||
context["series_formset"] = SeriesFormSet(
|
context["series_formset"] = SeriesFormSet(
|
||||||
form_kwargs={"user": self.request.user}
|
form_kwargs={"user": self.request.user}
|
||||||
)
|
)
|
||||||
context["casedifferential_formset"] = CaseDifferentialFormSet()
|
context["casedifferential_formset"] = CaseDifferentialFormSet()
|
||||||
|
context["caseresource_formset"] = CaseResourceFormSet(
|
||||||
|
form_kwargs={"user": self.request.user}
|
||||||
|
)
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
@@ -795,12 +804,15 @@ class AtlasCreateBase(RevisionMixin, LoginRequiredMixin):
|
|||||||
context = self.get_context_data(form=form)
|
context = self.get_context_data(form=form)
|
||||||
series_formset = context["series_formset"]
|
series_formset = context["series_formset"]
|
||||||
casedifferential_formset = context["casedifferential_formset"]
|
casedifferential_formset = context["casedifferential_formset"]
|
||||||
if series_formset.is_valid() and casedifferential_formset.is_valid():
|
caseresource_formset = context["caseresource_formset"]
|
||||||
|
if series_formset.is_valid() and casedifferential_formset.is_valid() and caseresource_formset.is_valid():
|
||||||
response = super().form_valid(form)
|
response = super().form_valid(form)
|
||||||
series_formset.instance = self.object
|
series_formset.instance = self.object
|
||||||
series_formset.save()
|
series_formset.save()
|
||||||
casedifferential_formset.instance = self.object
|
casedifferential_formset.instance = self.object
|
||||||
casedifferential_formset.save()
|
casedifferential_formset.save()
|
||||||
|
caseresource_formset.instance = self.object
|
||||||
|
caseresource_formset.save()
|
||||||
# If the normal submit button is pressed we save as normal
|
# If the normal submit button is pressed we save as normal
|
||||||
if "submit" in self.request.POST:
|
if "submit" in self.request.POST:
|
||||||
return response
|
return response
|
||||||
|
|||||||
Reference in New Issue
Block a user