From 7075bba7a2ed9f8f0579a7809825003ed7f33ba1 Mon Sep 17 00:00:00 2001 From: Ross Date: Wed, 17 Jul 2024 22:00:57 +0100 Subject: [PATCH] enable priors in atlas --- atlas/forms.py | 23 +++- atlas/migrations/0056_caseprior.py | 26 +++++ .../0057_alter_caseprior_prior_case.py | 19 ++++ atlas/models.py | 26 +++++ .../atlas/collection_case_priors.html | 101 ++++++++++++++++++ .../atlas/collection_case_view_take.html | 27 ++++- atlas/urls.py | 5 + atlas/views.py | 91 +++++++++++++++- 8 files changed, 312 insertions(+), 6 deletions(-) create mode 100644 atlas/migrations/0056_caseprior.py create mode 100644 atlas/migrations/0057_alter_caseprior_prior_case.py create mode 100644 atlas/templates/atlas/collection_case_priors.html diff --git a/atlas/forms.py b/atlas/forms.py index 471aaacf..f69bea76 100755 --- a/atlas/forms.py +++ b/atlas/forms.py @@ -780,4 +780,25 @@ class QuestionSchemaForm(ModelForm): widgets = { "schema": SvelteJSONEditorWidgetOverride(), - } \ No newline at end of file + } + +class PriorCaseForm(Form): + + relation = CharField(max_length=255, required=True) + + #def __init__(self, *args, **kwargs): + # self.case_detail = kwargs.pop( + # "case_detail" + # ) # To get request.user. Do not use kwargs.pop('user', None) due to potential security hole + + # super(PriorCaseForm, self).__init__(*args, **kwargs) + + # prior_cases = self.case_detail.case.get_all_prior_cases() + + # if not prior_cases: + # prior_cases = Case.objects.none() + + # self.fields["case"] = ChoiceField( + # required=False, + # # widget=Select(verbose_name="Series", is_stacked=False), + # ) \ No newline at end of file diff --git a/atlas/migrations/0056_caseprior.py b/atlas/migrations/0056_caseprior.py new file mode 100644 index 00000000..3ae3f454 --- /dev/null +++ b/atlas/migrations/0056_caseprior.py @@ -0,0 +1,26 @@ +# Generated by Django 5.0.2 on 2024-07-15 11:28 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('atlas', '0055_questionschema'), + ] + + operations = [ + migrations.CreateModel( + name='CasePrior', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('relation_text', models.CharField(blank=True, help_text='Text to describe the relationship between the cases', max_length=255)), + ('case_detail', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='atlas.casedetail')), + ('prior_case', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='prior_case', to='atlas.case')), + ], + options={ + 'unique_together': {('case_detail', 'prior_case')}, + }, + ), + ] diff --git a/atlas/migrations/0057_alter_caseprior_prior_case.py b/atlas/migrations/0057_alter_caseprior_prior_case.py new file mode 100644 index 00000000..fce771d5 --- /dev/null +++ b/atlas/migrations/0057_alter_caseprior_prior_case.py @@ -0,0 +1,19 @@ +# Generated by Django 5.0.2 on 2024-07-15 12:22 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('atlas', '0056_caseprior'), + ] + + operations = [ + migrations.AlterField( + model_name='caseprior', + name='prior_case', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='prior_case', to='atlas.case'), + ), + ] diff --git a/atlas/models.py b/atlas/models.py index b9c76a07..ee26a74c 100644 --- a/atlas/models.py +++ b/atlas/models.py @@ -461,6 +461,18 @@ class Case(models.Model, AuthorMixin, QuestionMixin): def get_viva_details_json(self): return json.dumps(self.get_viva_details()) + def get_all_prior_cases(self): + prior_cases = [] + + while self.previous_case is not None: + prior_cases.append(self.previous_case) + self = self.previous_case + + return prior_cases + + def get_series(self): + return self.series.all().prefetch_related("images", "examination", "plane") + def extract_image_dicom_json_from_ds(ds, url, image_index): to_keep = [ @@ -1007,6 +1019,9 @@ class CaseDetail(models.Model): class Meta: ordering = ("sort_order",) + def __str__(self) -> str: + return f"{self.case} -> {self.collection}" + def get_question_schema(self): return json.dumps(self.question_schema) @@ -1014,6 +1029,17 @@ class CaseDetail(models.Model): """Returns the correct question answers as a json string""" return json.dumps(self.question_answers) +class CasePrior(models.Model): + case_detail = models.ForeignKey(CaseDetail, on_delete=models.CASCADE) + prior_case = models.ForeignKey(Case, on_delete=models.CASCADE, related_name="prior_case") + + relation_text = models.CharField(max_length=255, blank=True, help_text="Text to describe the relationship between the cases") + + class Meta: + unique_together = ("case_detail", "prior_case") + + def __str__(self) -> str: + return f"{self.case_detail.case} -> {self.prior_case}" class BaseReportAnswer(models.Model): question = models.ForeignKey(CaseDetail, on_delete=models.CASCADE) diff --git a/atlas/templates/atlas/collection_case_priors.html b/atlas/templates/atlas/collection_case_priors.html new file mode 100644 index 00000000..067f2103 --- /dev/null +++ b/atlas/templates/atlas/collection_case_priors.html @@ -0,0 +1,101 @@ +{% extends 'atlas/exams.html' %} + + + +{% block content %} + +
+ + {% if previous %} + Previous question + {% endif %} + Viewing question as part of collection: {{collection.name}} [{{case_number|add:1}}/{{collection_length}}] + {% if next %} + Next question + {% endif %} +
+ + +

Case: {{case_detail.case.title}}

+ +

This page allows you to add series from prior cases to a case in a collection. In order to be available here the cases must be linked on the system.

+

It is necessary to give a description of how the cases are related that will be displayed to the user when viewing the case.

+ +

Available priors

+ + + + + +{% comment %}
+ {% csrf_token %} + {{ form }} + +
{% endcomment %} + +{% comment %}

Blank form

+
+ {{ blank_form}} +
{% endcomment %} + + + +{% endblock %} + +{% block css %} + +{% endblock %} + +{% block js %} + + +{% endblock %} \ No newline at end of file diff --git a/atlas/templates/atlas/collection_case_view_take.html b/atlas/templates/atlas/collection_case_view_take.html index 2414487d..5d2fe7c2 100644 --- a/atlas/templates/atlas/collection_case_view_take.html +++ b/atlas/templates/atlas/collection_case_view_take.html @@ -63,13 +63,21 @@ Images - {% for series in series_list %} - + {% for series, prior, relation in series_to_load %} + Series {{ forloop.counter }}: {{series.get_block}} + {% if prior %} +
Prior: {{relation}} + {% endif %} +
{% endfor %} @@ -263,6 +271,10 @@ background-color: darkblue; } + .series-block.prior { + border: darkgray solid 1px; + } + fieldset:disabled textarea { background-color: black; } @@ -291,6 +303,11 @@ .answer-block>div { padding-top: 10px; } + + .relation { + opacity: 0.5; + font-size: 0.8em; + } {% endblock %} @@ -299,9 +316,13 @@ {% comment %} {% endcomment %}