Refactor case collection form to use crispy forms for improved layout and styling
This commit is contained in:
+152
-85
@@ -12,7 +12,7 @@ from django.forms import (
|
|||||||
CharField,
|
CharField,
|
||||||
ValidationError,
|
ValidationError,
|
||||||
modelformset_factory,
|
modelformset_factory,
|
||||||
CheckboxSelectMultiple
|
CheckboxSelectMultiple,
|
||||||
)
|
)
|
||||||
from django.forms import inlineformset_factory
|
from django.forms import inlineformset_factory
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
@@ -45,7 +45,7 @@ from atlas.models import (
|
|||||||
|
|
||||||
from anatomy.models import Modality
|
from anatomy.models import Modality
|
||||||
|
|
||||||
from generic.models import Examination#, Sign
|
from generic.models import Examination # , Sign
|
||||||
|
|
||||||
# from generic.models import Examination, Site, Condition, Sign
|
# from generic.models import Examination, Site, Condition, Sign
|
||||||
|
|
||||||
@@ -58,7 +58,13 @@ from tinymce.widgets import TinyMCE
|
|||||||
|
|
||||||
from dal import autocomplete
|
from dal import autocomplete
|
||||||
|
|
||||||
from autocomplete import widgets as htmx_widgets, Autocomplete, AutocompleteWidget, ModelAutocomplete, register as autocomplete_register
|
from autocomplete import (
|
||||||
|
widgets as htmx_widgets,
|
||||||
|
Autocomplete,
|
||||||
|
AutocompleteWidget,
|
||||||
|
ModelAutocomplete,
|
||||||
|
register as autocomplete_register,
|
||||||
|
)
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@@ -73,28 +79,30 @@ from typing import Any
|
|||||||
from helpers.cimar import CimarAPI, NotFoundError
|
from helpers.cimar import CimarAPI, NotFoundError
|
||||||
from rad.settings import CIMAR_USERNAME, CIMAR_PASSWORD
|
from rad.settings import CIMAR_USERNAME, CIMAR_PASSWORD
|
||||||
|
|
||||||
|
|
||||||
class ClearableInput(TextInput):
|
class ClearableInput(TextInput):
|
||||||
template_name = "crispy_forms/widgets/clearable_input_single_line.html"
|
template_name = "crispy_forms/widgets/clearable_input_single_line.html"
|
||||||
|
|
||||||
|
|
||||||
class ClearableTextarea(Textarea):
|
class ClearableTextarea(Textarea):
|
||||||
template_name = "crispy_forms/widgets/clearable_input.html"
|
template_name = "crispy_forms/widgets/clearable_input.html"
|
||||||
|
|
||||||
|
|
||||||
class CaseSelect(Select):
|
class CaseSelect(Select):
|
||||||
template_name = "atlas/case_select_widget.html"
|
template_name = "atlas/case_select_widget.html"
|
||||||
|
|
||||||
|
|
||||||
def create_option(self, *args, **kwargs):
|
def create_option(self, *args, **kwargs):
|
||||||
option = super().create_option(*args, **kwargs)
|
option = super().create_option(*args, **kwargs)
|
||||||
|
|
||||||
return option
|
return option
|
||||||
|
|
||||||
def get_context(self, name: str, value, attrs) -> dict[str, Any]:
|
def get_context(self, name: str, value, attrs) -> dict[str, Any]:
|
||||||
context = super().get_context(name, value, attrs)
|
context = super().get_context(name, value, attrs)
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ConditionForm(ModelForm):
|
class ConditionForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Condition
|
model = Condition
|
||||||
@@ -119,26 +127,56 @@ class CaseCollectionForm(ModelForm):
|
|||||||
exclude = ["cases", "valid_cid_users", "valid_user_users", "author"]
|
exclude = ["cases", "valid_cid_users", "valid_user_users", "author"]
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.user = kwargs.pop(
|
self.user = kwargs.pop("user")
|
||||||
"user"
|
|
||||||
) # To get request.user. Do not use kwargs.pop('user', None) due to potential security hole
|
|
||||||
if kwargs.get("instance"):
|
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", {})
|
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)
|
ModelForm.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
super(CaseCollectionForm, self).__init__(*args, **kwargs)
|
super(CaseCollectionForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
# Identify show_ fields
|
||||||
|
show_fields = [f for f in self.fields if f.startswith("show_")]
|
||||||
|
show_pre_fields = [f for f in show_fields if f.endswith("_pre")]
|
||||||
|
show_post_fields = [f for f in show_fields if f.endswith("_post")]
|
||||||
|
|
||||||
|
self.helper = FormHelper()
|
||||||
|
self.helper.form_id = "id-casecollection-form"
|
||||||
|
self.helper.form_class = "casecollection-form"
|
||||||
|
self.helper.form_method = "post"
|
||||||
|
self.helper.form_action = ""
|
||||||
|
self.helper.form_tag = True
|
||||||
|
# Group cid_user_groups and user_user_groups together if they exist in the form
|
||||||
|
user_fields = []
|
||||||
|
for f in ["cid_user_groups", "user_user_groups"]:
|
||||||
|
if f in self.fields:
|
||||||
|
user_fields.append(f)
|
||||||
|
|
||||||
|
other_fields = [f for f in self.fields if f not in show_fields and f not in user_fields]
|
||||||
|
|
||||||
|
self.helper.layout = Layout(
|
||||||
|
Fieldset("Collection Details", *other_fields),
|
||||||
|
# Add grouped user fields if present
|
||||||
|
Fieldset("Valid User Groups", *user_fields) if user_fields else None,
|
||||||
|
Div(
|
||||||
|
Div(
|
||||||
|
Fieldset("Show fields (pre-exam)", *show_pre_fields),
|
||||||
|
css_class="col-md-6",
|
||||||
|
style="float:left;",
|
||||||
|
),
|
||||||
|
Div(
|
||||||
|
Fieldset("Show fields (post-exam)", *show_post_fields),
|
||||||
|
css_class="col-md-6",
|
||||||
|
style="float:left;",
|
||||||
|
),
|
||||||
|
css_class="row",
|
||||||
|
style="display: flex; flex-wrap: wrap;",
|
||||||
|
),
|
||||||
|
Submit("submit", "Save Collection", css_class="btn btn-primary"),
|
||||||
|
)
|
||||||
|
|
||||||
def save(self, commit=True):
|
def save(self, commit=True):
|
||||||
# Get the unsaved Case instance
|
# Get the unsaved Case instance
|
||||||
instance = ModelForm.save(self, False)
|
instance = ModelForm.save(self, False)
|
||||||
|
|
||||||
|
|
||||||
# Do we need to save all changes now?
|
# Do we need to save all changes now?
|
||||||
# if commit:
|
# if commit:
|
||||||
instance.save()
|
instance.save()
|
||||||
@@ -174,7 +212,14 @@ class StructureForm(ModelForm):
|
|||||||
class SeriesFindingForm(ModelForm):
|
class SeriesFindingForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SeriesFinding
|
model = SeriesFinding
|
||||||
exclude = ["series", "annotation_json", "viewport_json", "current_image_id_index", "annotation_json_3d", "viewer_state_3d"]
|
exclude = [
|
||||||
|
"series",
|
||||||
|
"annotation_json",
|
||||||
|
"viewport_json",
|
||||||
|
"current_image_id_index",
|
||||||
|
"annotation_json_3d",
|
||||||
|
"viewer_state_3d",
|
||||||
|
]
|
||||||
|
|
||||||
widgets = {
|
widgets = {
|
||||||
"findings": autocomplete.ModelSelect2Multiple(
|
"findings": autocomplete.ModelSelect2Multiple(
|
||||||
@@ -186,7 +231,6 @@ class SeriesFindingForm(ModelForm):
|
|||||||
"conditions": autocomplete.ModelSelect2Multiple(
|
"conditions": autocomplete.ModelSelect2Multiple(
|
||||||
url="atlas:condition-autocomplete"
|
url="atlas:condition-autocomplete"
|
||||||
),
|
),
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
@@ -297,12 +341,10 @@ class SeriesForm(ModelForm):
|
|||||||
"description": Textarea(attrs={"maxlength": 1000, "rows": 5, "cols": 80}),
|
"description": Textarea(attrs={"maxlength": 1000, "rows": 5, "cols": 80}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# def save(self, commit=True):
|
||||||
#def save(self, commit=True):
|
|
||||||
# # Get the unsaved Case instance
|
# # Get the unsaved Case instance
|
||||||
# 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
|
||||||
|
|
||||||
@@ -320,20 +362,19 @@ class SeriesForm(ModelForm):
|
|||||||
# instance.save()
|
# instance.save()
|
||||||
# self.save_m2m()
|
# self.save_m2m()
|
||||||
|
|
||||||
|
|
||||||
# return instance
|
# return instance
|
||||||
|
|
||||||
class CaseForm(ModelForm):
|
|
||||||
|
|
||||||
|
class CaseForm(ModelForm):
|
||||||
class Media:
|
class Media:
|
||||||
# Django also includes a few javascript files necessary
|
# Django also includes a few javascript files necessary
|
||||||
# for the operation of this form element. You need to
|
# for the operation of this form element. You need to
|
||||||
# include <script src="/admin/jsi18n"></script>
|
# include <script src="/admin/jsi18n"></script>
|
||||||
# in the template.
|
# in the template.
|
||||||
#history = forms.CharField(
|
# history = forms.CharField(
|
||||||
# widget=ClearableTextarea(attrs={"maxlength": 1000, "rows": 5, "cols": 80}),
|
# widget=ClearableTextarea(attrs={"maxlength": 1000, "rows": 5, "cols": 80}),
|
||||||
# required=False,
|
# required=False,
|
||||||
#)
|
# )
|
||||||
|
|
||||||
css = {
|
css = {
|
||||||
"all": ["css/widgets.css"],
|
"all": ["css/widgets.css"],
|
||||||
@@ -348,7 +389,7 @@ class CaseForm(ModelForm):
|
|||||||
|
|
||||||
# This is populated if we create the case from an exam/collection
|
# This is populated if we create the case from an exam/collection
|
||||||
self.collection = None
|
self.collection = None
|
||||||
if kwargs["initial"] is not None and "exams" in kwargs["initial"]:
|
if kwargs["initial"] is not None and "exams" in kwargs["initial"]:
|
||||||
collections = kwargs["initial"].pop("exams")
|
collections = kwargs["initial"].pop("exams")
|
||||||
logging.debug(collections)
|
logging.debug(collections)
|
||||||
|
|
||||||
@@ -362,20 +403,16 @@ class CaseForm(ModelForm):
|
|||||||
# a list of primary key for the selected data.
|
# a list of primary key for the selected data.
|
||||||
# initial["exams"] = [t.pk for t in kwargs["instance"].exams.all()]
|
# initial["exams"] = [t.pk for t in kwargs["instance"].exams.all()]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ModelForm.__init__(self, *args, **kwargs)
|
ModelForm.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
super(CaseForm, self).__init__(*args, **kwargs)
|
super(CaseForm, self).__init__(*args, **kwargs)
|
||||||
# self.fields["series"].queryset =
|
# self.fields["series"].queryset =
|
||||||
|
|
||||||
if self.user.groups.filter(name="atlas_editor").exists():
|
if self.user.groups.filter(name="atlas_editor").exists():
|
||||||
case_queryset = Case.objects.all().order_by("pk").prefetch_related(
|
case_queryset = Case.objects.all().order_by("pk").prefetch_related()
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
case_queryset = get_cases_available_to_user(self.user)
|
case_queryset = get_cases_available_to_user(self.user)
|
||||||
self.fields["previous_case"].queryset=case_queryset
|
self.fields["previous_case"].queryset = case_queryset
|
||||||
|
|
||||||
|
|
||||||
self.helper = FormHelper()
|
self.helper = FormHelper()
|
||||||
self.helper.form_id = "id-case-form"
|
self.helper.form_id = "id-case-form"
|
||||||
@@ -401,10 +438,8 @@ class CaseForm(ModelForm):
|
|||||||
"diagnostic_certainty",
|
"diagnostic_certainty",
|
||||||
"cimar_uuid",
|
"cimar_uuid",
|
||||||
),
|
),
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
return (
|
return (
|
||||||
super()
|
super()
|
||||||
@@ -433,7 +468,7 @@ class CaseForm(ModelForm):
|
|||||||
"open_access",
|
"open_access",
|
||||||
"previous_case",
|
"previous_case",
|
||||||
"diagnostic_certainty",
|
"diagnostic_certainty",
|
||||||
"cimar_uuid"
|
"cimar_uuid",
|
||||||
]
|
]
|
||||||
# fields = ['question', 'findings', 'subspecialty', 'references']
|
# fields = ['question', 'findings', 'subspecialty', 'references']
|
||||||
widgets = {
|
widgets = {
|
||||||
@@ -474,7 +509,6 @@ class CaseForm(ModelForm):
|
|||||||
# Get the unsaved Case instance
|
# Get the unsaved Case instance
|
||||||
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
|
||||||
|
|
||||||
@@ -501,8 +535,10 @@ class CaseForm(ModelForm):
|
|||||||
logging.debug(f"{instance=}")
|
logging.debug(f"{instance=}")
|
||||||
|
|
||||||
# Create through model
|
# Create through model
|
||||||
#cd = CaseDetail(case=instance, collection=exam, sort_order=case_no)
|
# cd = CaseDetail(case=instance, collection=exam, sort_order=case_no)
|
||||||
self.collection.cases.add(instance, through_defaults={"sort_order": case_no})
|
self.collection.cases.add(
|
||||||
|
instance, through_defaults={"sort_order": case_no}
|
||||||
|
)
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
@@ -520,6 +556,7 @@ CaseDifferentialFormSet = inlineformset_factory(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class ResourceForm(ModelForm):
|
class ResourceForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Resource
|
model = Resource
|
||||||
@@ -532,7 +569,6 @@ class ResourceForm(ModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class CaseResourceForm(ModelForm):
|
class CaseResourceForm(ModelForm):
|
||||||
|
|
||||||
def __init__(self, *args, user, **kwargs):
|
def __init__(self, *args, user, **kwargs):
|
||||||
super(CaseResourceForm, self).__init__(*args, **kwargs)
|
super(CaseResourceForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
@@ -550,7 +586,7 @@ class CaseResourceForm(ModelForm):
|
|||||||
self.fields["pre_review"] = BooleanField(required=False)
|
self.fields["pre_review"] = BooleanField(required=False)
|
||||||
|
|
||||||
|
|
||||||
#class CaseSeriesForm(ModelForm):
|
# class CaseSeriesForm(ModelForm):
|
||||||
#
|
#
|
||||||
# def __init__(self, *args, user, **kwargs):
|
# def __init__(self, *args, user, **kwargs):
|
||||||
# super(CaseSeriesForm, self).__init__(*args, **kwargs)
|
# super(CaseSeriesForm, self).__init__(*args, **kwargs)
|
||||||
@@ -574,7 +610,6 @@ class CaseResourceForm(ModelForm):
|
|||||||
# )
|
# )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CaseCollectionCaseForm(ModelForm):
|
class CaseCollectionCaseForm(ModelForm):
|
||||||
def __init__(self, *args, user, collection=None, **kwargs):
|
def __init__(self, *args, user, collection=None, **kwargs):
|
||||||
super(CaseCollectionCaseForm, self).__init__(*args, **kwargs)
|
super(CaseCollectionCaseForm, self).__init__(*args, **kwargs)
|
||||||
@@ -588,7 +623,7 @@ class CaseCollectionCaseForm(ModelForm):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
#SeriesFormSet = inlineformset_factory(
|
# SeriesFormSet = inlineformset_factory(
|
||||||
# Case,
|
# Case,
|
||||||
# Series.case.through,
|
# Series.case.through,
|
||||||
# form=CaseSeriesForm,
|
# form=CaseSeriesForm,
|
||||||
@@ -596,7 +631,7 @@ class CaseCollectionCaseForm(ModelForm):
|
|||||||
# can_delete=True,
|
# can_delete=True,
|
||||||
# extra=0,
|
# extra=0,
|
||||||
# max_num=10,
|
# max_num=10,
|
||||||
#)
|
# )
|
||||||
|
|
||||||
CaseCollectionCaseFormSet = inlineformset_factory(
|
CaseCollectionCaseFormSet = inlineformset_factory(
|
||||||
CaseCollection,
|
CaseCollection,
|
||||||
@@ -621,7 +656,13 @@ CaseResourceFormSet = inlineformset_factory(
|
|||||||
SeriesImageFormSet = inlineformset_factory(
|
SeriesImageFormSet = inlineformset_factory(
|
||||||
Series,
|
Series,
|
||||||
SeriesImage,
|
SeriesImage,
|
||||||
exclude=["dicom_tags_ohif", "replaced", "image_md5_hash", "image_blake3_hash", "is_dicom"],
|
exclude=[
|
||||||
|
"dicom_tags_ohif",
|
||||||
|
"replaced",
|
||||||
|
"image_md5_hash",
|
||||||
|
"image_blake3_hash",
|
||||||
|
"is_dicom",
|
||||||
|
],
|
||||||
can_delete=True,
|
can_delete=True,
|
||||||
extra=0,
|
extra=0,
|
||||||
max_num=2000,
|
max_num=2000,
|
||||||
@@ -630,19 +671,23 @@ SeriesImageFormSet = inlineformset_factory(
|
|||||||
|
|
||||||
class JsonAnswerForm(Form):
|
class JsonAnswerForm(Form):
|
||||||
json_answer = JSONSchemaField(
|
json_answer = JSONSchemaField(
|
||||||
schema = {},
|
schema={},
|
||||||
#options = 'schema/options.json'
|
# options = 'schema/options.json'
|
||||||
options = 'schema/options.json'
|
options="schema/options.json",
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
fields = ["json_answer"]
|
fields = ["json_answer"]
|
||||||
|
|
||||||
def __init__(self, *args, question_schema=None, **kwargs):
|
def __init__(self, *args, question_schema=None, **kwargs):
|
||||||
super(JsonAnswerForm, self).__init__(*args, **kwargs)
|
super(JsonAnswerForm, self).__init__(*args, **kwargs)
|
||||||
if question_schema is not None:
|
if question_schema is not None:
|
||||||
self.fields["json_answer"] = JSONSchemaField(schema=question_schema, options='schema/options.json')
|
self.fields["json_answer"] = JSONSchemaField(
|
||||||
|
schema=question_schema, options="schema/options.json"
|
||||||
|
)
|
||||||
self.fields["json_answer"].label = False
|
self.fields["json_answer"].label = False
|
||||||
|
|
||||||
|
|
||||||
class BaseReportAnswerForm(ModelForm):
|
class BaseReportAnswerForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
fields = ["answer"]
|
fields = ["answer"]
|
||||||
@@ -653,22 +698,23 @@ class BaseReportAnswerForm(ModelForm):
|
|||||||
# (False, 'No')])
|
# (False, 'No')])
|
||||||
# "findings": TinyMCE(attrs={"cols": 80, "rows": 20}),
|
# "findings": TinyMCE(attrs={"cols": 80, "rows": 20}),
|
||||||
# "mark_scheme": TinyMCE(attrs={"cols": 80, "rows": 30}),
|
# "mark_scheme": TinyMCE(attrs={"cols": 80, "rows": 30}),
|
||||||
"answer": Textarea(attrs={"cols": 100, "rows": 5, "placeholder":"Report text"}),
|
"answer": Textarea(
|
||||||
|
attrs={"cols": 100, "rows": 5, "placeholder": "Report text"}
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
# help_texts = {
|
# help_texts = {
|
||||||
# "answer": "Write your answer in here."
|
# "answer": "Write your answer in here."
|
||||||
# }
|
# }
|
||||||
|
|
||||||
def __init__(self, *args, case_detail, **kwargs):
|
def __init__(self, *args, case_detail, **kwargs):
|
||||||
super(BaseReportAnswerForm, self).__init__(*args, **kwargs)
|
super(BaseReportAnswerForm, self).__init__(*args, **kwargs)
|
||||||
self.fields["answer"].required = False
|
self.fields["answer"].required = False
|
||||||
|
|
||||||
|
|
||||||
class BaseQuestionAnswerForm(ModelForm):
|
class BaseQuestionAnswerForm(ModelForm):
|
||||||
json_answer = JSONSchemaField(
|
json_answer = JSONSchemaField(schema={}, options="schema/options.json")
|
||||||
schema = {},
|
|
||||||
options = 'schema/options.json'
|
|
||||||
)
|
|
||||||
class Meta:
|
class Meta:
|
||||||
fields = ["json_answer"]
|
fields = ["json_answer"]
|
||||||
labels = {"json_answer": ""}
|
labels = {"json_answer": ""}
|
||||||
@@ -677,11 +723,13 @@ class BaseQuestionAnswerForm(ModelForm):
|
|||||||
# "answer": "Write your answer in here."
|
# "answer": "Write your answer in here."
|
||||||
# }
|
# }
|
||||||
|
|
||||||
def __init__(self, *args, case_detail, **kwargs):
|
def __init__(self, *args, case_detail, **kwargs):
|
||||||
super(BaseQuestionAnswerForm, self).__init__(*args, **kwargs)
|
super(BaseQuestionAnswerForm, self).__init__(*args, **kwargs)
|
||||||
#self.fields["json_answer"].schema = case_detail.question_schema
|
# self.fields["json_answer"].schema = case_detail.question_schema
|
||||||
if case_detail.question_schema is not None:
|
if case_detail.question_schema is not None:
|
||||||
self.fields["json_answer"] = JSONSchemaField(schema=case_detail.question_schema, options="schema/options.json")
|
self.fields["json_answer"] = JSONSchemaField(
|
||||||
|
schema=case_detail.question_schema, options="schema/options.json"
|
||||||
|
)
|
||||||
self.fields["json_answer"].label = ""
|
self.fields["json_answer"].label = ""
|
||||||
|
|
||||||
|
|
||||||
@@ -689,18 +737,22 @@ class CidReportAnswerForm(BaseReportAnswerForm):
|
|||||||
class Meta(BaseReportAnswerForm.Meta):
|
class Meta(BaseReportAnswerForm.Meta):
|
||||||
model = CidReportAnswer
|
model = CidReportAnswer
|
||||||
|
|
||||||
|
|
||||||
class UserReportAnswerForm(BaseReportAnswerForm):
|
class UserReportAnswerForm(BaseReportAnswerForm):
|
||||||
class Meta(BaseReportAnswerForm.Meta):
|
class Meta(BaseReportAnswerForm.Meta):
|
||||||
model = UserReportAnswer
|
model = UserReportAnswer
|
||||||
|
|
||||||
|
|
||||||
class CidQuestionAnswerForm(BaseQuestionAnswerForm):
|
class CidQuestionAnswerForm(BaseQuestionAnswerForm):
|
||||||
class Meta(BaseQuestionAnswerForm.Meta):
|
class Meta(BaseQuestionAnswerForm.Meta):
|
||||||
model = CidReportAnswer
|
model = CidReportAnswer
|
||||||
|
|
||||||
|
|
||||||
class UserQuestionAnswerForm(BaseQuestionAnswerForm):
|
class UserQuestionAnswerForm(BaseQuestionAnswerForm):
|
||||||
class Meta(BaseQuestionAnswerForm.Meta):
|
class Meta(BaseQuestionAnswerForm.Meta):
|
||||||
model = UserReportAnswer
|
model = UserReportAnswer
|
||||||
|
|
||||||
|
|
||||||
class CidReportAnswerMarkForm(ModelForm):
|
class CidReportAnswerMarkForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CidReportAnswer
|
model = CidReportAnswer
|
||||||
@@ -720,7 +772,7 @@ class CidReportAnswerMarkForm(ModelForm):
|
|||||||
self.fields["score"].required = False
|
self.fields["score"].required = False
|
||||||
|
|
||||||
|
|
||||||
#class AddCollectionToCaseForm(Form):
|
# class AddCollectionToCaseForm(Form):
|
||||||
#
|
#
|
||||||
# def __init__(self, *args, user, **kwargs):
|
# def __init__(self, *args, user, **kwargs):
|
||||||
# super(AddCollectionToCaseForm, self).__init__(*args, **kwargs)
|
# super(AddCollectionToCaseForm, self).__init__(*args, **kwargs)
|
||||||
@@ -761,8 +813,8 @@ class CidReportAnswerMarkForm(ModelForm):
|
|||||||
#
|
#
|
||||||
# return collection_set
|
# return collection_set
|
||||||
|
|
||||||
class AddCollectionToCaseForm(Form):
|
|
||||||
|
|
||||||
|
class AddCollectionToCaseForm(Form):
|
||||||
def __init__(self, *args, user, **kwargs):
|
def __init__(self, *args, user, **kwargs):
|
||||||
super(AddCollectionToCaseForm, self).__init__(*args, **kwargs)
|
super(AddCollectionToCaseForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
@@ -783,7 +835,7 @@ class AddCollectionToCaseForm(Form):
|
|||||||
instance = super(AddCollectionToCaseForm, self).save(*args, **kwargs)
|
instance = super(AddCollectionToCaseForm, self).save(*args, **kwargs)
|
||||||
|
|
||||||
# Here we save the modified project selection back into the database
|
# Here we save the modified project selection back into the database
|
||||||
instance.casecollection_set.set(self.cleaned_data['casecollection'])
|
instance.casecollection_set.set(self.cleaned_data["casecollection"])
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
@@ -798,7 +850,6 @@ class AddCollectionToCaseForm(Form):
|
|||||||
|
|
||||||
|
|
||||||
class SelfReviewForm(ModelForm):
|
class SelfReviewForm(ModelForm):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SelfReview
|
model = SelfReview
|
||||||
fields = ["user_exam", "case", "comments", "findings", "interpretation"]
|
fields = ["user_exam", "case", "comments", "findings", "interpretation"]
|
||||||
@@ -817,12 +868,12 @@ class SelfReviewForm(ModelForm):
|
|||||||
class UncategorisedDicomForm(ModelForm):
|
class UncategorisedDicomForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = UncategorisedDicom
|
model = UncategorisedDicom
|
||||||
fields = ["image"]#, "user"]
|
fields = ["image"] # , "user"]
|
||||||
|
|
||||||
|
|
||||||
#UncategorisedDicomFormset = formset_factory(UncategorisedDicomForm)
|
# UncategorisedDicomFormset = formset_factory(UncategorisedDicomForm)
|
||||||
|
|
||||||
#class ConditionAutocompleteFormModel(forms.ModelForm):
|
# class ConditionAutocompleteFormModel(forms.ModelForm):
|
||||||
# class Meta:
|
# class Meta:
|
||||||
# model = Condition
|
# model = Condition
|
||||||
# fields = ["name"]
|
# fields = ["name"]
|
||||||
@@ -833,49 +884,56 @@ class UncategorisedDicomForm(ModelForm):
|
|||||||
# )
|
# )
|
||||||
# }
|
# }
|
||||||
|
|
||||||
|
|
||||||
class ConditionAutocomplete(ModelAutocomplete):
|
class ConditionAutocomplete(ModelAutocomplete):
|
||||||
model = Condition
|
model = Condition
|
||||||
search_attrs = ["name"]
|
search_attrs = ["name"]
|
||||||
|
|
||||||
class ConditionAutocompleteForm(Form):
|
|
||||||
condition = ModelChoiceField(queryset=Condition.objects.all(), widget=AutocompleteWidget(
|
|
||||||
ac_class=ConditionAutocomplete#, options=dict(model=Condition)
|
|
||||||
|
|
||||||
))
|
class ConditionAutocompleteForm(Form):
|
||||||
|
condition = ModelChoiceField(
|
||||||
|
queryset=Condition.objects.all(),
|
||||||
|
widget=AutocompleteWidget(
|
||||||
|
ac_class=ConditionAutocomplete # , options=dict(model=Condition)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
autocomplete_register(ConditionAutocomplete)
|
autocomplete_register(ConditionAutocomplete)
|
||||||
|
|
||||||
|
|
||||||
class CaseCollectionAuthorForm(ExamAuthorFormMixin):
|
class CaseCollectionAuthorForm(ExamAuthorFormMixin):
|
||||||
class Meta(ExamAuthorFormMixin.Meta):
|
class Meta(ExamAuthorFormMixin.Meta):
|
||||||
model = CaseCollection
|
model = CaseCollection
|
||||||
|
|
||||||
|
|
||||||
class CaseAuthorForm(ExamAuthorFormMixin):
|
class CaseAuthorForm(ExamAuthorFormMixin):
|
||||||
class Meta(ExamAuthorFormMixin.Meta):
|
class Meta(ExamAuthorFormMixin.Meta):
|
||||||
model = Case
|
model = Case
|
||||||
|
|
||||||
|
|
||||||
class SeriesAuthorForm(ExamAuthorFormMixin):
|
class SeriesAuthorForm(ExamAuthorFormMixin):
|
||||||
class Meta(ExamAuthorFormMixin.Meta):
|
class Meta(ExamAuthorFormMixin.Meta):
|
||||||
model = Series
|
model = Series
|
||||||
|
|
||||||
|
|
||||||
class ExamGroupsForm(ExamGroupsFormMixin):
|
class ExamGroupsForm(ExamGroupsFormMixin):
|
||||||
class Meta(ExamGroupsFormMixin.Meta):
|
class Meta(ExamGroupsFormMixin.Meta):
|
||||||
model = CaseCollection
|
model = CaseCollection
|
||||||
|
|
||||||
class AnswerJSONForm(Form):
|
|
||||||
|
|
||||||
json = JSONSchemaField(
|
class AnswerJSONForm(Form):
|
||||||
schema = 'schema/schema.json',
|
json = JSONSchemaField(schema="schema/schema.json", options="schema/options.json")
|
||||||
options = 'schema/options.json'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class SvelteJSONEditorWidgetOverride(SvelteJSONEditorWidget):
|
class SvelteJSONEditorWidgetOverride(SvelteJSONEditorWidget):
|
||||||
template_name = "atlas/svelte_jsoneditor_widget_override.html"
|
template_name = "atlas/svelte_jsoneditor_widget_override.html"
|
||||||
|
|
||||||
class CaseDetailForm(ModelForm):
|
|
||||||
|
|
||||||
|
class CaseDetailForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CaseDetail
|
model = CaseDetail
|
||||||
fields = ["question_schema", "question_answers"]#, "user"]
|
fields = ["question_schema", "question_answers"] # , "user"]
|
||||||
|
|
||||||
widgets = {
|
widgets = {
|
||||||
"question_schema": SvelteJSONEditorWidgetOverride(),
|
"question_schema": SvelteJSONEditorWidgetOverride(),
|
||||||
@@ -892,20 +950,19 @@ class QuestionSchemaForm(ModelForm):
|
|||||||
"schema": SvelteJSONEditorWidgetOverride(),
|
"schema": SvelteJSONEditorWidgetOverride(),
|
||||||
}
|
}
|
||||||
|
|
||||||
#class ModelPriorCaseForm(ModelForm):
|
|
||||||
|
# class ModelPriorCaseForm(ModelForm):
|
||||||
# class Meta:
|
# class Meta:
|
||||||
# model = CasePrior
|
# model = CasePrior
|
||||||
# fields = ["case_detail", "prior_case", "relation_text", "prior_visibility"]
|
# fields = ["case_detail", "prior_case", "relation_text", "prior_visibility"]
|
||||||
|
|
||||||
class PriorCaseForm(Form):
|
|
||||||
|
|
||||||
|
class PriorCaseForm(Form):
|
||||||
relation = CharField(max_length=255, required=True)
|
relation = CharField(max_length=255, required=True)
|
||||||
|
|
||||||
prior_visibility = CharField(max_length=2, required=True)
|
prior_visibility = CharField(max_length=2, required=True)
|
||||||
|
|
||||||
|
# def __init__(self, *args, **kwargs):
|
||||||
|
|
||||||
#def __init__(self, *args, **kwargs):
|
|
||||||
# self.case_detail = kwargs.pop(
|
# self.case_detail = kwargs.pop(
|
||||||
# "case_detail"
|
# "case_detail"
|
||||||
# ) # To get request.user. Do not use kwargs.pop('user', None) due to potential security hole
|
# ) # To get request.user. Do not use kwargs.pop('user', None) due to potential security hole
|
||||||
@@ -922,6 +979,7 @@ class PriorCaseForm(Form):
|
|||||||
# # widget=Select(verbose_name="Series", is_stacked=False),
|
# # widget=Select(verbose_name="Series", is_stacked=False),
|
||||||
# )
|
# )
|
||||||
|
|
||||||
|
|
||||||
class CaseSeriesForm(forms.ModelForm):
|
class CaseSeriesForm(forms.ModelForm):
|
||||||
def __init__(self, *args, queryset, user=None, is_atlas_editor=False, **kwargs):
|
def __init__(self, *args, queryset, user=None, is_atlas_editor=False, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
@@ -931,6 +989,7 @@ class CaseSeriesForm(forms.ModelForm):
|
|||||||
model = SeriesDetail # through model for Case.series
|
model = SeriesDetail # through model for Case.series
|
||||||
fields = ["series", "sort_order", "feedback"]
|
fields = ["series", "sort_order", "feedback"]
|
||||||
|
|
||||||
|
|
||||||
class CaseUpdateSeriesForm(forms.ModelForm):
|
class CaseUpdateSeriesForm(forms.ModelForm):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.user = kwargs.pop("user")
|
self.user = kwargs.pop("user")
|
||||||
@@ -942,10 +1001,12 @@ class CaseUpdateSeriesForm(forms.ModelForm):
|
|||||||
self.helper.form_action = "submit"
|
self.helper.form_action = "submit"
|
||||||
self.helper.form_tag = False
|
self.helper.form_tag = False
|
||||||
self.helper.layout = Layout()
|
self.helper.layout = Layout()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Case
|
model = Case
|
||||||
fields = [] # No fields, just for compatibility with UpdateView
|
fields = [] # No fields, just for compatibility with UpdateView
|
||||||
|
|
||||||
|
|
||||||
class BaseSeriesFormSet(BaseInlineFormSet):
|
class BaseSeriesFormSet(BaseInlineFormSet):
|
||||||
def __init__(self, *args, queryset=None, **kwargs):
|
def __init__(self, *args, queryset=None, **kwargs):
|
||||||
self.series_queryset = queryset
|
self.series_queryset = queryset
|
||||||
@@ -953,7 +1014,7 @@ class BaseSeriesFormSet(BaseInlineFormSet):
|
|||||||
|
|
||||||
def get_form_kwargs(self, index):
|
def get_form_kwargs(self, index):
|
||||||
kwargs = super().get_form_kwargs(index)
|
kwargs = super().get_form_kwargs(index)
|
||||||
kwargs['queryset'] = self.series_queryset
|
kwargs["queryset"] = self.series_queryset
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
@@ -966,6 +1027,7 @@ SeriesFormSet = inlineformset_factory(
|
|||||||
can_delete=True,
|
can_delete=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class CaseDisplaySetForm(forms.ModelForm):
|
class CaseDisplaySetForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CaseDisplaySet
|
model = CaseDisplaySet
|
||||||
@@ -977,8 +1039,12 @@ class CaseDisplaySetForm(forms.ModelForm):
|
|||||||
"conditions",
|
"conditions",
|
||||||
]
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
"name": forms.TextInput(attrs={"class": "form-control", "placeholder": "Display Set Name"}),
|
"name": forms.TextInput(
|
||||||
"description": forms.Textarea(attrs={"class": "form-control", "rows": 3, "placeholder": "Description"}),
|
attrs={"class": "form-control", "placeholder": "Display Set Name"}
|
||||||
|
),
|
||||||
|
"description": forms.Textarea(
|
||||||
|
attrs={"class": "form-control", "rows": 3, "placeholder": "Description"}
|
||||||
|
),
|
||||||
"findings": autocomplete.ModelSelect2Multiple(
|
"findings": autocomplete.ModelSelect2Multiple(
|
||||||
url="atlas:finding-autocomplete"
|
url="atlas:finding-autocomplete"
|
||||||
),
|
),
|
||||||
@@ -1007,6 +1073,7 @@ class CaseCollectionUpdateCaseForm(forms.ModelForm):
|
|||||||
self.helper.form_action = "submit"
|
self.helper.form_action = "submit"
|
||||||
self.helper.form_tag = False
|
self.helper.form_tag = False
|
||||||
self.helper.layout = Layout()
|
self.helper.layout = Layout()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CaseCollection
|
model = CaseCollection
|
||||||
fields = [] # No fields, just for compatibility with UpdateView
|
fields = [] # No fields, just for compatibility with UpdateView
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
{% extends "atlas/exams.html" %}
|
{% extends "atlas/exams.html" %}
|
||||||
<!-- {% load static from static %} -->
|
<!-- {% load static from static %} -->
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -36,7 +37,7 @@
|
|||||||
<form class="highlight" action="" method="post" enctype="multipart/form-data" id="atlas-form">
|
<form class="highlight" action="" method="post" enctype="multipart/form-data" id="atlas-form">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|
||||||
{{ form }}
|
{% crispy form form.helper %}
|
||||||
{% comment %} <h3>Cases:</h3>
|
{% comment %} <h3>Cases:</h3>
|
||||||
Add cases here. These can only be added once created (they can also be added to cases on creation). Click and drag to change order.
|
Add cases here. These can only be added once created (they can also be added to cases on creation). Click and drag to change order.
|
||||||
<input type="button" value="Add More Cases" id="add_more_case">
|
<input type="button" value="Add More Cases" id="add_more_case">
|
||||||
@@ -60,7 +61,7 @@
|
|||||||
{{ case_formset.empty_form }}
|
{{ case_formset.empty_form }}
|
||||||
</li>
|
</li>
|
||||||
</div> {% endcomment %}
|
</div> {% endcomment %}
|
||||||
<input type="submit" class="submit-button" value="Submit" name="submit">
|
{% comment %} <input type="submit" class="submit-button" value="Submit" name="submit"> {% endcomment %}
|
||||||
</form>
|
</form>
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(() => {
|
$(document).ready(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user