diff --git a/atlas/forms.py b/atlas/forms.py
index 0f127ac1..19c83027 100755
--- a/atlas/forms.py
+++ b/atlas/forms.py
@@ -13,6 +13,7 @@ from django.forms import inlineformset_factory
from atlas.models import (
Case,
+ CaseCollection,
Differential,
Finding,
Series,
@@ -50,6 +51,26 @@ class ConditionForm(ModelForm):
),
}
+class CaseCollectionForm(ModelForm):
+ class Meta:
+ model = CaseCollection
+ exclude = ["cases", "author"]
+
+ def __init__(self, *args, **kwargs):
+ self.user = kwargs.pop(
+ "user"
+ ) # To get request.user. Do not use kwargs.pop('user', None) due to potential security hole
+ if kwargs.get("instance"):
+ # We get the 'initial' keyword argument or initialize it
+ # as a dict if it didn't exist.
+ initial = kwargs.setdefault("initial", {})
+ # The widget for a ModelMultipleChoiceField expects
+ # a list of primary key for the selected data.
+ # initial["exams"] = [t.pk for t in kwargs["instance"].exams.all()]
+
+ ModelForm.__init__(self, *args, **kwargs)
+
+ super(CaseCollectionForm, self).__init__(*args, **kwargs)
class FindingForm(ModelForm):
class Meta:
@@ -153,7 +174,7 @@ class SeriesForm(ModelForm):
else:
case_queryset = Case.objects.filter(
author__id=self.user.id
- ) #| Case.objects.filter(open_access=True)
+ ) # | Case.objects.filter(open_access=True)
self.fields["case"] = ModelMultipleChoiceField(
required=False,
@@ -226,7 +247,6 @@ class CaseForm(ModelForm):
ModelForm.__init__(self, *args, **kwargs)
super(CaseForm, self).__init__(*args, **kwargs)
- print(1)
# self.fields["series"].queryset =
@@ -313,25 +333,60 @@ CaseDifferentialFormSet = inlineformset_factory(
},
)
+
class BaseSeriesFormSet(BaseInlineFormSet):
- def __init__(self, *args, **kwargs):
- super(BaseSeriesFormSet, self).__init__(*args, **kwargs)
+ def __init__(self, *args, **kwargs):
- self.queryset = Series.case.through.objects.filter(series__author__id=99)
+ super(BaseSeriesFormSet, self).__init__(*args, **kwargs)
- #for form in self.forms:
- # form.fields['series'].queryset = series_queryset
+ self.queryset = Series.case.through.objects.filter(series__author__id=99)
+
+ # for form in self.forms:
+ # form.fields['series'].queryset = series_queryset
+
+
+class CaseSeriesForm(ModelForm):
+ def __init__(self, *args, user, **kwargs):
+ super(CaseSeriesForm, self).__init__(*args, **kwargs)
+
+ self.fields["series"] = ModelChoiceField(
+ required=False,
+ queryset=Series.objects.filter(author__id=user.id),
+ # widget=Select(verbose_name="Series", is_stacked=False),
+ )
+
+class CaseCollectionCaseForm(ModelForm):
+ def __init__(self, *args, user, **kwargs):
+ super(CaseCollectionCaseForm, self).__init__(*args, **kwargs)
+
+ self.fields["case"] = ModelChoiceField(
+ required=False,
+ queryset=Case.objects.filter(author__id=user.id),
+ # widget=Select(verbose_name="Series", is_stacked=False),
+ )
SeriesFormSet = inlineformset_factory(
Case,
Series.case.through,
- formset=BaseSeriesFormSet,
+ form=CaseSeriesForm,
+ # formset=BaseSeriesFormSet,
exclude=[],
can_delete=True,
- extra=1,
+ extra=0,
max_num=10,
)
+CaseCollectionCaseFormSet = inlineformset_factory(
+ CaseCollection,
+ Case.casecollection_set.through,
+ form=CaseCollectionCaseForm,
+ # formset=BaseSeriesFormSet,
+ exclude=[],
+ can_delete=True,
+ extra=0,
+ max_num=50,
+)
+
SeriesImageFormSet = inlineformset_factory(
Series,
diff --git a/atlas/migrations/0028_casecollection_author.py b/atlas/migrations/0028_casecollection_author.py
new file mode 100644
index 00000000..1405097e
--- /dev/null
+++ b/atlas/migrations/0028_casecollection_author.py
@@ -0,0 +1,20 @@
+# Generated by Django 3.2.10 on 2022-03-29 20:53
+
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ('atlas', '0027_auto_20220325_2138'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='casecollection',
+ name='author',
+ field=models.ManyToManyField(blank=True, help_text='Author of the collection', to=settings.AUTH_USER_MODEL),
+ ),
+ ]
diff --git a/atlas/migrations/0029_casecollection_show_report.py b/atlas/migrations/0029_casecollection_show_report.py
new file mode 100644
index 00000000..3c716f14
--- /dev/null
+++ b/atlas/migrations/0029_casecollection_show_report.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.10 on 2022-03-29 20:59
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('atlas', '0028_casecollection_author'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='casecollection',
+ name='show_report',
+ field=models.BooleanField(default=False, help_text='Show the case report'),
+ ),
+ ]
diff --git a/atlas/models.py b/atlas/models.py
index f4e12a21..9caf3de4 100644
--- a/atlas/models.py
+++ b/atlas/models.py
@@ -572,6 +572,14 @@ class CaseCollection(models.Model):
show_title = models.BooleanField(default=False, help_text="Show the title of the cases")
show_description = models.BooleanField(default=False, help_text="Show the description of the cases")
show_discussion = models.BooleanField(default=False, help_text="Show the case discussion")
+ show_report = models.BooleanField(default=False, help_text="Show the case report")
+
+ author = models.ManyToManyField(
+ settings.AUTH_USER_MODEL,
+ blank=True,
+ help_text="Author of the collection",
+ #related_name="atlas_authored_cases",
+ )
def get_absolute_url(self):
return reverse("atlas:collection_detail_view", kwargs={"pk": self.pk})
diff --git a/atlas/templates/atlas/base.html b/atlas/templates/atlas/base.html
index 9167abee..a2f7d33e 100755
--- a/atlas/templates/atlas/base.html
+++ b/atlas/templates/atlas/base.html
@@ -19,8 +19,9 @@ Atlas:
{% if request.user.is_authenticated %}
Cases /
Series /
+Collections /
Categories /
-Create Case /
+Create Case /
Create Series
{% endif %}
{% comment %}
diff --git a/atlas/templates/atlas/casecollection_form.html b/atlas/templates/atlas/casecollection_form.html
new file mode 100755
index 00000000..08432abd
--- /dev/null
+++ b/atlas/templates/atlas/casecollection_form.html
@@ -0,0 +1,54 @@
+{% extends "atlas/base.html" %}
+
+
+{% block css %}
+{% endblock %}
+{% block js %}
+
+{{form.media}}
+
+
+
+{% endblock %}
+{% block content %}
+
Create Collection
+Use this form to create a collection of cases
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/atlas/templates/atlas/collection_case_view.html b/atlas/templates/atlas/collection_case_view.html
index f623e033..50c2da29 100644
--- a/atlas/templates/atlas/collection_case_view.html
+++ b/atlas/templates/atlas/collection_case_view.html
@@ -43,6 +43,16 @@
{% endif %}
+{% if collection.show_report and case.report%}
+
+
+ Report:
+
+
+ {{case.report}}
+
+
+{% endif %}
{% if previous %}
diff --git a/atlas/templates/atlas/collection_detail_view.html b/atlas/templates/atlas/collection_detail_view.html
index 0b9f37a9..37d8f668 100644
--- a/atlas/templates/atlas/collection_detail_view.html
+++ b/atlas/templates/atlas/collection_detail_view.html
@@ -1,6 +1,11 @@
{% extends 'atlas/base.html' %}
{% block content %}
+{% if request.user.is_authenticated %}
+
+{% endif %}
{{collection.name}}
{% for case in collection.cases.all %}
diff --git a/atlas/templates/atlas/series_viewer.html b/atlas/templates/atlas/series_viewer.html
index 0a50cb3f..3510e47d 100755
--- a/atlas/templates/atlas/series_viewer.html
+++ b/atlas/templates/atlas/series_viewer.html
@@ -1,4 +1,5 @@
{{ series.modality}}, {{ series.examination }}, {{ series.plane }}, {{ series.contrast }}
+Description: {{series.description}}
{% if series.case %}
Associated case:
diff --git a/atlas/urls.py b/atlas/urls.py
index b7c6ba4f..15ce88bb 100755
--- a/atlas/urls.py
+++ b/atlas/urls.py
@@ -1,4 +1,6 @@
from django.urls import path, include
+from django.views.generic import RedirectView
+
from atlas.models import Condition, Finding, Presentation, Structure
from . import views
@@ -7,12 +9,15 @@ app_name = "atlas"
urlpatterns = [
path("", views.CaseView.as_view(), name="index"),
+ path("create/", RedirectView.as_view(pattern_name='atlas:case_create', permanent=False), name="create"),
path("author//", views.author_detail, name="author_detail"),
path("author/", views.author_list, name="author_list"),
path("case/", views.CaseView.as_view(), name="case_view"),
path("collection/", views.collection_index_view, name="collection_index_view"),
- path("collections/", views.collection_detail_view, name="collection_detail_view"),
- path("collections//", views.collection_case_view, name="collection_case_view"),
+ path("collection/create", views.CaseCollectionCreate.as_view(), name="collection_create"),
+ path("collection//update", views.CaseCollectionUpdate.as_view(), name="collection_update"),
+ path("collection/", views.collection_detail_view, name="collection_detail_view"),
+ path("collection//", views.collection_case_view, name="collection_case_view"),
path("condition/", views.ConditionView.as_view(), name="condition_view"),
path("categories/", views.categories_list, name="categories_list"),
path("condition/", views.condition_detail, name="condition_detail"),
@@ -97,7 +102,7 @@ urlpatterns = [
# path("all_questions/", views.all_questions, name="all_questions"),
path("case//scrap", views.atlas_scrap, name="case_scrap"),
path("case//delete", views.CaseDelete.as_view(), name="case_delete"),
- path("case/create/", views.AtlasCreate.as_view(), name="create"),
+ path("case/create/", views.AtlasCreate.as_view(), name="case_create"),
path("series/create", views.SeriesCreate.as_view(), name="series_create"),
path(
"series//create",
diff --git a/atlas/views.py b/atlas/views.py
index d4a196e6..d2f3829a 100755
--- a/atlas/views.py
+++ b/atlas/views.py
@@ -27,6 +27,8 @@ from django.http import Http404, JsonResponse
from django.http import HttpResponseRedirect, HttpResponse
from .forms import (
+ CaseCollectionCaseFormSet,
+ CaseCollectionForm,
CaseForm,
ConditionForm,
FindingForm,
@@ -349,6 +351,60 @@ def case_clone(request, pk):
return render(request, "atlas/case_form.html", context)
+class CaseCollectionCreate(RevisionMixin, LoginRequiredMixin, CreateView):
+ model = CaseCollection
+ form_class = CaseCollectionForm
+
+ def get_initial(self):
+ # print(self.request)
+ if "pk" in self.kwargs:
+ initial = super(CaseCollectionCreate, self).get_initial()
+ # case = get_object_or_404(Case, pk=self.kwargs["pk"])
+
+ # initial["case"] = case.id
+
+ return initial
+
+ def get_form_kwargs(self):
+ kwargs = super(CaseCollectionCreate, self).get_form_kwargs()
+ kwargs.update({"user": self.request.user})
+ return kwargs
+
+ def get_context_data(self, **kwargs):
+ context = super(CaseCollectionCreate, self).get_context_data(**kwargs)
+
+ if self.request.POST:
+ context["case_formset"] = CaseCollectionCaseFormSet(
+ self.request.POST,
+ self.request.FILES,
+ form_kwargs={"user": self.request.user},
+ )
+ context["case_formset"].full_clean()
+ else:
+ context["case_formset"] = CaseCollectionCaseFormSet(
+ form_kwargs={"user": self.request.user}
+ )
+ return context
+
+ def form_valid(self, form):
+
+ self.object = form.save(commit=False)
+ self.object.save()
+
+ form.instance.author.add(self.request.user.id)
+
+ context = self.get_context_data(form=form)
+ case_formset = context["case_formset"]
+ if case_formset.is_valid():
+ response = super().form_valid(form)
+ case_formset.instance = self.object
+ case_formset.save()
+ return response
+
+ else:
+ return super().form_invalid(form)
+
+
class SeriesCreate(RevisionMixin, LoginRequiredMixin, CreateView):
model = Series
form_class = SeriesForm
@@ -399,6 +455,67 @@ class SeriesCreate(RevisionMixin, LoginRequiredMixin, CreateView):
return super().form_invalid(form)
+class CaseCollectionUpdate(RevisionMixin, LoginRequiredMixin, UpdateView):
+ model = CaseCollection
+ form_class = CaseCollectionForm
+
+ # fields = '__all__'
+ # #fields = [ 'condition' ]
+ # #initial = {'date_of_death': '05/01/2018'}
+ # exclude = [ 'created_date', 'published_date' ]
+
+ def get_form_kwargs(self):
+ kwargs = super(CaseCollectionUpdate, self).get_form_kwargs()
+ kwargs.update({"user": self.request.user})
+ return kwargs
+
+ def get_context_data(self, **kwargs):
+ context = super(CaseCollectionUpdate, self).get_context_data(**kwargs)
+ if self.request.POST:
+ context["case_formset"] = CaseCollectionCaseFormSet(
+ self.request.POST,
+ self.request.FILES,
+ instance=self.object,
+ form_kwargs={"user": self.request.user},
+ )
+ context["case_formset"].full_clean()
+ else:
+ context["case_formset"] = CaseCollectionCaseFormSet(
+ instance=self.object, form_kwargs={"user": self.request.user}
+ )
+ return context
+
+ def form_valid(self, form):
+ # save exam orders (there must be a better way to do this)
+ # exam_orders = {}
+ # for exam in self.object.exams.all():
+ # exam_orders[exam] = list(exam.exam_questions.all())
+
+ self.object = form.save(commit=False)
+ self.object.save()
+
+ form.instance.author.add(self.request.user.id)
+
+ context = self.get_context_data(form=form)
+ case_formset = context["case_formset"]
+ # logger.debug(formset.is_valid())
+ if case_formset.is_valid():
+ response = super().form_valid(form)
+ case_formset.instance = self.object
+ case_formset.save()
+
+ # restore exam orders
+ # for exam in self.object.exams.all():
+ # if exam in exam_orders and self.object in exam_orders[exam]:
+ # print(exam_orders[exam])
+ # exam.exam_questions.set(exam_orders[exam])
+ # exam.save()
+
+ return response
+ else:
+ return super().form_invalid(form)
+
+
class SeriesUpdate(
RevisionMixin, LoginRequiredMixin, AuthorOrCheckerRequiredMixin, UpdateView
):
@@ -494,7 +611,9 @@ class AtlasCreateBase(RevisionMixin, LoginRequiredMixin):
context = super(AtlasCreateBase, self).get_context_data(**kwargs)
if self.request.POST:
context["series_formset"] = SeriesFormSet(
- self.request.POST, self.request.FILES, queryset=Series.objects.filter(author__id=self.request.user.id)
+ self.request.POST,
+ self.request.FILES,
+ form_kwargs={"user": self.request.user},
)
context["casedifferential_formset"] = CaseDifferentialFormSet(
self.request.POST, self.request.FILES
@@ -502,8 +621,10 @@ class AtlasCreateBase(RevisionMixin, LoginRequiredMixin):
context["series_formset"].full_clean()
context["casedifferential_formset"].full_clean()
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()
+ # 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(
+ form_kwargs={"user": self.request.user}
+ )
context["casedifferential_formset"] = CaseDifferentialFormSet()
return context
@@ -569,7 +690,10 @@ class AtlasUpdate(
context = super(AtlasUpdate, self).get_context_data(**kwargs)
if self.request.POST:
context["series_formset"] = SeriesFormSet(
- self.request.POST, self.request.FILES, instance=self.object, queryset=Series.objects.filter(author__id=self.request.user.id)
+ self.request.POST,
+ self.request.FILES,
+ instance=self.object,
+ form_kwargs={"user": self.request.user},
)
context["casedifferential_formset"] = CaseDifferentialFormSet(
self.request.POST, self.request.FILES, instance=self.object
@@ -577,7 +701,9 @@ class AtlasUpdate(
context["series_formset"].full_clean()
context["casedifferential_formset"].full_clean()
else:
- context["series_formset"] = SeriesFormSet(instance=self.object, queryset=Series.objects.filter(author__id=self.request.user.id))
+ context["series_formset"] = SeriesFormSet(
+ instance=self.object, form_kwargs={"user": self.request.user}
+ )
context["casedifferential_formset"] = CaseDifferentialFormSet(
instance=self.object
)
@@ -908,12 +1034,18 @@ def categories_list(request):
def collection_index_view(request):
collections = CaseCollection.objects.all()
- return render(request, "atlas/collection_index_view.html", {"collections": collections})
+ return render(
+ request, "atlas/collection_index_view.html", {"collections": collections}
+ )
+
def collection_detail_view(request, pk):
collection = get_object_or_404(CaseCollection, pk=pk)
- return render(request, "atlas/collection_detail_view.html", {"collection": collection})
+ return render(
+ request, "atlas/collection_detail_view.html", {"collection": collection}
+ )
+
def collection_case_view(request, pk, case_number):
collection = get_object_or_404(CaseCollection, pk=pk)
@@ -926,5 +1058,15 @@ def collection_case_view(request, pk, case_number):
previous = case_number > 0
next = case_number < (len(cases) - 1)
-
- return render(request, "atlas/collection_case_view.html", {"collection": collection, "case": case, "series_list": series_list, "case_number": case_number, "previous": previous, "next": next})
\ No newline at end of file
+ return render(
+ request,
+ "atlas/collection_case_view.html",
+ {
+ "collection": collection,
+ "case": case,
+ "series_list": series_list,
+ "case_number": case_number,
+ "previous": previous,
+ "next": next,
+ },
+ )