diff --git a/atlas/forms.py b/atlas/forms.py index bdc6572e..bf431330 100755 --- a/atlas/forms.py +++ b/atlas/forms.py @@ -23,6 +23,7 @@ from atlas.models import ( CidReportAnswer, Differential, Finding, + Resource, SelfReview, Series, SeriesImage, @@ -74,7 +75,7 @@ class ConditionForm(ModelForm): class CaseCollectionForm(ModelForm): class Meta: model = CaseCollection - exclude = ["cases", "valid_cid_users"] + exclude = ["cases", "valid_cid_users", "author"] def __init__(self, *args, **kwargs): self.user = kwargs.pop( @@ -92,6 +93,18 @@ class CaseCollectionForm(ModelForm): 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 Meta: @@ -343,8 +356,6 @@ class CaseForm(ModelForm): instance = ModelForm.save(self, False) - - # Prepare a 'save_m2m' method for the form, 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): @@ -446,6 +472,15 @@ CaseCollectionCaseFormSet = inlineformset_factory( 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( Series, diff --git a/atlas/migrations/0046_resource_caseresource_case_resource.py b/atlas/migrations/0046_resource_caseresource_case_resource.py new file mode 100644 index 00000000..92008054 --- /dev/null +++ b/atlas/migrations/0046_resource_caseresource_case_resource.py @@ -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'), + ), + ] diff --git a/atlas/migrations/0047_caseresource_pre_review_resource_author.py b/atlas/migrations/0047_caseresource_pre_review_resource_author.py new file mode 100644 index 00000000..068cf7ec --- /dev/null +++ b/atlas/migrations/0047_caseresource_pre_review_resource_author.py @@ -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), + ), + ] diff --git a/atlas/models.py b/atlas/models.py index b9aa01ac..61e601b8 100644 --- a/atlas/models.py +++ b/atlas/models.py @@ -364,6 +364,8 @@ class Case(models.Model, AuthorMixin, QuestionMixin): blank=True, ) + resource = models.ManyToManyField("Resource", through="CaseResource") + def get_app_name(self): return "atlas" @@ -1142,3 +1144,33 @@ class UncategorisedDicom(models.Model): class DuplicateDicom(Exception): 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("{}", 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}" \ No newline at end of file diff --git a/atlas/tables.py b/atlas/tables.py index 886fed87..8c4b36cb 100755 --- a/atlas/tables.py +++ b/atlas/tables.py @@ -5,6 +5,7 @@ from generic.tables import SeriesImageColumn from .models import ( Case, + CaseCollection, Condition, PathologicalProcess, Presentation, @@ -318,7 +319,7 @@ class CaseCollectionTable(tables.Table): selection = tables.CheckBoxColumn(accessor="pk", orderable=False) class Meta: - model = Case + model = CaseCollection template_name = "django_tables2/bootstrap4.html" fields = ( "name", diff --git a/atlas/templates/atlas/case_display_block.html b/atlas/templates/atlas/case_display_block.html index 08718652..a1928d54 100755 --- a/atlas/templates/atlas/case_display_block.html +++ b/atlas/templates/atlas/case_display_block.html @@ -1,5 +1,6 @@