numerous uploading fixes
This commit is contained in:
+28
-3
@@ -16,6 +16,8 @@ from django.forms import (
|
|||||||
)
|
)
|
||||||
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
|
||||||
|
from django_jsonforms.forms import JSONSchemaField
|
||||||
|
|
||||||
|
|
||||||
from atlas.models import (
|
from atlas.models import (
|
||||||
Case,
|
Case,
|
||||||
@@ -516,8 +518,13 @@ SeriesImageFormSet = inlineformset_factory(
|
|||||||
)
|
)
|
||||||
|
|
||||||
class BaseReportAnswerForm(ModelForm):
|
class BaseReportAnswerForm(ModelForm):
|
||||||
|
json_answer = JSONSchemaField(
|
||||||
|
schema = "schema/report.json",
|
||||||
|
#options = 'schema/options.json'
|
||||||
|
options = {}
|
||||||
|
)
|
||||||
class Meta:
|
class Meta:
|
||||||
fields = ["answer"]
|
fields = ["answer", "json_answer"]
|
||||||
|
|
||||||
widgets = {
|
widgets = {
|
||||||
# "normal": RadioSelect(
|
# "normal": RadioSelect(
|
||||||
@@ -532,9 +539,13 @@ class BaseReportAnswerForm(ModelForm):
|
|||||||
# "answer": "Write your answer in here."
|
# "answer": "Write your answer in here."
|
||||||
# }
|
# }
|
||||||
|
|
||||||
def __init__(self, *args, **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
|
||||||
|
#self.fields["json_answer"].schema = case_detail.question_schema
|
||||||
|
if case_detail.question_schema is not None:
|
||||||
|
self.fields["json_answer"] = JSONSchemaField(schema=case_detail.question_schema, options={})
|
||||||
|
|
||||||
|
|
||||||
class CidReportAnswerForm(BaseReportAnswerForm):
|
class CidReportAnswerForm(BaseReportAnswerForm):
|
||||||
class Meta(BaseReportAnswerForm.Meta):
|
class Meta(BaseReportAnswerForm.Meta):
|
||||||
@@ -698,4 +709,18 @@ class CaseAuthorForm(ExamAuthorFormMixin):
|
|||||||
model = Case
|
model = Case
|
||||||
class SeriesAuthorForm(ExamAuthorFormMixin):
|
class SeriesAuthorForm(ExamAuthorFormMixin):
|
||||||
class Meta(ExamAuthorFormMixin.Meta):
|
class Meta(ExamAuthorFormMixin.Meta):
|
||||||
model = Series
|
model = Series
|
||||||
|
|
||||||
|
|
||||||
|
class AnswerJSONForm(Form):
|
||||||
|
|
||||||
|
json = JSONSchemaField(
|
||||||
|
schema = 'schema/schema.json',
|
||||||
|
#options = 'schema/options.json'
|
||||||
|
options = {}
|
||||||
|
)
|
||||||
|
|
||||||
|
class CaseDetailForm(ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = CaseDetail
|
||||||
|
fields = ["sort_order", "question_schema"]#, "user"]
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# Generated by Django 5.0.2 on 2024-04-29 10:32
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('atlas', '0048_cidreportanswer_completed_userreportanswer_completed_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casedetail',
|
||||||
|
name='questions',
|
||||||
|
field=models.JSONField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='cidreportanswer',
|
||||||
|
name='json_answer',
|
||||||
|
field=models.JSONField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='userreportanswer',
|
||||||
|
name='json_answer',
|
||||||
|
field=models.JSONField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.0.2 on 2024-04-29 11:06
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('atlas', '0049_casedetail_questions_cidreportanswer_json_answer_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='casedetail',
|
||||||
|
old_name='questions',
|
||||||
|
new_name='question_schema',
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -957,6 +957,8 @@ class CaseDetail(models.Model):
|
|||||||
case = models.ForeignKey(Case, on_delete=models.CASCADE)
|
case = models.ForeignKey(Case, on_delete=models.CASCADE)
|
||||||
collection = models.ForeignKey(CaseCollection, on_delete=models.CASCADE)
|
collection = models.ForeignKey(CaseCollection, on_delete=models.CASCADE)
|
||||||
|
|
||||||
|
question_schema = models.JSONField(null=True, blank=True)
|
||||||
|
|
||||||
sort_order = models.IntegerField(default=1000)
|
sort_order = models.IntegerField(default=1000)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@@ -968,6 +970,8 @@ class BaseReportAnswer(models.Model):
|
|||||||
|
|
||||||
answer = models.TextField(blank=True)
|
answer = models.TextField(blank=True)
|
||||||
|
|
||||||
|
json_answer = models.JSONField(null=True, blank=True)
|
||||||
|
|
||||||
feedback = models.TextField(blank=True)
|
feedback = models.TextField(blank=True)
|
||||||
|
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"title": "Report",
|
||||||
|
"description": "Report text",
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"report"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"report": {
|
||||||
|
"type": "string",
|
||||||
|
"title": "Report"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{% extends 'atlas/exams.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h2>{{case_detail.collection.name}} / {{case_detail.case.pk}}</h2>
|
||||||
|
|
||||||
|
<form method="POST">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form.as_p }}
|
||||||
|
<button type="submit">Submit</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
|
|
||||||
{% if collection.show_ohif_viewer_link %}
|
{% if collection.show_ohif_viewer_link %}
|
||||||
<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>
|
<a target="_blank" href="/ohif/viewer/dicomjson?url=https://www.penracourses.org.uk{% url 'atlas:case_dicom_json' case.pk %}">View case in OHIF</a>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
@@ -128,6 +128,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<form method="POST" class="post-form">{% csrf_token %}
|
<form method="POST" class="post-form">{% csrf_token %}
|
||||||
{% if collection.collection_type == "REP" %}
|
{% if collection.collection_type == "REP" %}
|
||||||
|
{{form.json.errors}}
|
||||||
<div class="form-contents">
|
<div class="form-contents">
|
||||||
<fieldset {% if completed %}disabled="disabled"{% endif %}>
|
<fieldset {% if completed %}disabled="disabled"{% endif %}>
|
||||||
{{form}}
|
{{form}}
|
||||||
@@ -200,6 +201,7 @@
|
|||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block js %}
|
{% block js %}
|
||||||
|
{{ form.media }}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
window.images = {
|
window.images = {
|
||||||
{% for series in series_list %}
|
{% for series in series_list %}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
<ol id="full-question-list" class="sortable">
|
<ol id="full-question-list" class="sortable">
|
||||||
{% for casedetail in casesdetails %}
|
{% for casedetail in casesdetails %}
|
||||||
<li data-question_pk={{casedetail.case.pk}}><a title="sort_order: {{casedetail.sort_order}}" href="{% url 'atlas:collection_case_view' pk=collection.pk case_number=forloop.counter0 %}">Case {{forloop.counter}}</a>
|
<li data-question_pk={{casedetail.case.pk}}><a title="sort_order: {{casedetail.sort_order}}" href="{% url 'atlas:collection_case_view' pk=collection.pk case_number=forloop.counter0 %}">Case {{forloop.counter}}</a>
|
||||||
: {{casedetail.case.title}}
|
: {{casedetail.case.title}} (<a href='{% url "atlas:collection_case_details" casedetail.collection.pk casedetail.case.pk %}'>edit</a>)
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ urlpatterns = [
|
|||||||
views.GenericExamViews.exam_user_status_user,
|
views.GenericExamViews.exam_user_status_user,
|
||||||
name="exam_user_status_user",
|
name="exam_user_status_user",
|
||||||
),
|
),
|
||||||
|
#path("collection/<int:pk>/<int:sk>/test", views.test_form, name="test_form"),
|
||||||
path(
|
path(
|
||||||
"exam/<int:exam_id>/cids/edit",
|
"exam/<int:exam_id>/cids/edit",
|
||||||
views.GenericExamViews.exam_cids_edit,
|
views.GenericExamViews.exam_cids_edit,
|
||||||
@@ -110,6 +111,11 @@ urlpatterns = [
|
|||||||
views.GenericExamViews.exam_users_edit,
|
views.GenericExamViews.exam_users_edit,
|
||||||
name="exam_users_edit",
|
name="exam_users_edit",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"collection/<int:exam_id>/case/<int:case_id>/details",
|
||||||
|
views.collection_case_details,
|
||||||
|
name="collection_case_details",
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"collection/<int:exam_id>/cids/<int:cid>/delete_answers",
|
"collection/<int:exam_id>/cids/<int:cid>/delete_answers",
|
||||||
views.delete_collection_cid_answers,
|
views.delete_collection_cid_answers,
|
||||||
|
|||||||
+21
-3
@@ -39,6 +39,7 @@ from .forms import (
|
|||||||
CaseCollectionAuthorForm,
|
CaseCollectionAuthorForm,
|
||||||
CaseCollectionCaseFormSet,
|
CaseCollectionCaseFormSet,
|
||||||
CaseCollectionForm,
|
CaseCollectionForm,
|
||||||
|
CaseDetailForm,
|
||||||
CaseForm,
|
CaseForm,
|
||||||
CaseResourceFormSet,
|
CaseResourceFormSet,
|
||||||
CidReportAnswerForm,
|
CidReportAnswerForm,
|
||||||
@@ -1561,6 +1562,23 @@ def collection_take_start(request, pk):
|
|||||||
request, "atlas/collection_review_start.html", template_variables
|
request, "atlas/collection_review_start.html", template_variables
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@user_is_collection_author_or_atlas_editor
|
||||||
|
def collection_case_details(request, exam_id, case_id):
|
||||||
|
case_detail = CaseDetail.objects.get(case=case_id, collection=exam_id)
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = CaseDetailForm(request.POST, instance=case_detail)
|
||||||
|
if form.is_valid():
|
||||||
|
form.save()
|
||||||
|
# Add any additional logic or redirection here
|
||||||
|
else:
|
||||||
|
form = CaseDetailForm(instance=case_detail)
|
||||||
|
|
||||||
|
|
||||||
|
return render(
|
||||||
|
request, "atlas/collection_case_detail.html", {"case_detail": case_detail,
|
||||||
|
"form": form}
|
||||||
|
)
|
||||||
|
|
||||||
@user_is_collection_author_or_atlas_editor
|
@user_is_collection_author_or_atlas_editor
|
||||||
def collection_mark_overview(request, pk):
|
def collection_mark_overview(request, pk):
|
||||||
@@ -1830,9 +1848,9 @@ def collection_case_view_take(
|
|||||||
if collection.collection_type == "REP":
|
if collection.collection_type == "REP":
|
||||||
if not collection.publish_results:
|
if not collection.publish_results:
|
||||||
if answer:
|
if answer:
|
||||||
form = ReportAnswerForm(request.POST, instance=answer)
|
form = ReportAnswerForm(request.POST, instance=answer, case_detail=case_detail)
|
||||||
else:
|
else:
|
||||||
form = ReportAnswerForm(request.POST)
|
form = ReportAnswerForm(request.POST, case_detail=case_detail)
|
||||||
|
|
||||||
if not cid_user_exam.completed and not (
|
if not cid_user_exam.completed and not (
|
||||||
answer is not None and answer.completed
|
answer is not None and answer.completed
|
||||||
@@ -1876,7 +1894,7 @@ def collection_case_view_take(
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if collection.collection_type == "REP":
|
if collection.collection_type == "REP":
|
||||||
form = ReportAnswerForm(instance=answer)
|
form = ReportAnswerForm(instance=answer, case_detail=case_detail)
|
||||||
|
|
||||||
series_list = case.series.all().prefetch_related("images", "examination", "plane")
|
series_list = case.series.all().prefetch_related("images", "examination", "plane")
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ INSTALLED_APPS = [
|
|||||||
"crispy_bootstrap4",
|
"crispy_bootstrap4",
|
||||||
"autocomplete",
|
"autocomplete",
|
||||||
'markdownify.apps.MarkdownifyConfig',
|
'markdownify.apps.MarkdownifyConfig',
|
||||||
|
'django_jsonforms',
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -86,4 +86,9 @@ form input:required {
|
|||||||
|
|
||||||
.select2-selection__rendered {
|
.select2-selection__rendered {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.json-editor-btn-edit, .json-editor-btn-collapse {
|
||||||
|
padding: 1px;
|
||||||
|
font-size: small;
|
||||||
}
|
}
|
||||||
+2
-1
@@ -46,4 +46,5 @@ django-clone
|
|||||||
django-sortedm2m # remove once migrations squashed
|
django-sortedm2m # remove once migrations squashed
|
||||||
loguru
|
loguru
|
||||||
pylibjpeg
|
pylibjpeg
|
||||||
pylibjpeg-libjpeg
|
pylibjpeg-libjpeg
|
||||||
|
django-jsonforms
|
||||||
Reference in New Issue
Block a user