improve json editing
This commit is contained in:
+23
-1
@@ -17,6 +17,7 @@ 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 django_jsonforms.forms import JSONSchemaField
|
||||||
|
from django_svelte_jsoneditor.widgets import SvelteJSONEditorWidget
|
||||||
|
|
||||||
|
|
||||||
from atlas.models import (
|
from atlas.models import (
|
||||||
@@ -517,6 +518,21 @@ SeriesImageFormSet = inlineformset_factory(
|
|||||||
max_num=2000,
|
max_num=2000,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class JsonAnswerForm(Form):
|
||||||
|
json_answer = JSONSchemaField(
|
||||||
|
schema = "schema/report.json",
|
||||||
|
#options = 'schema/options.json'
|
||||||
|
options = {}
|
||||||
|
)
|
||||||
|
class Meta:
|
||||||
|
fields = ["json_answer"]
|
||||||
|
|
||||||
|
def __init__(self, *args, case_detail, **kwargs):
|
||||||
|
super(JsonAnswerForm, self).__init__(*args, **kwargs)
|
||||||
|
if case_detail.question_schema is not None:
|
||||||
|
self.fields["json_answer"] = JSONSchemaField(schema=case_detail.question_schema, options={})
|
||||||
|
|
||||||
class BaseReportAnswerForm(ModelForm):
|
class BaseReportAnswerForm(ModelForm):
|
||||||
json_answer = JSONSchemaField(
|
json_answer = JSONSchemaField(
|
||||||
schema = "schema/report.json",
|
schema = "schema/report.json",
|
||||||
@@ -721,6 +737,12 @@ class AnswerJSONForm(Form):
|
|||||||
)
|
)
|
||||||
|
|
||||||
class CaseDetailForm(ModelForm):
|
class CaseDetailForm(ModelForm):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CaseDetail
|
model = CaseDetail
|
||||||
fields = ["sort_order", "question_schema"]#, "user"]
|
fields = ["sort_order", "question_schema", "question_answers"]#, "user"]
|
||||||
|
|
||||||
|
widgets = {
|
||||||
|
"question_schema": SvelteJSONEditorWidget(),
|
||||||
|
"question_answers": SvelteJSONEditorWidget(),
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.0.2 on 2024-05-20 09:38
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('atlas', '0052_alter_casecollection_end_date_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='casedetail',
|
||||||
|
name='question_answers',
|
||||||
|
field=models.JSONField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -961,6 +961,7 @@ class CaseDetail(models.Model):
|
|||||||
collection = models.ForeignKey(CaseCollection, on_delete=models.CASCADE)
|
collection = models.ForeignKey(CaseCollection, on_delete=models.CASCADE)
|
||||||
|
|
||||||
question_schema = models.JSONField(null=True, blank=True)
|
question_schema = models.JSONField(null=True, blank=True)
|
||||||
|
question_answers = models.JSONField(null=True, blank=True)
|
||||||
|
|
||||||
sort_order = models.IntegerField(default=1000)
|
sort_order = models.IntegerField(default=1000)
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,36 @@
|
|||||||
{% extends 'atlas/exams.html' %}
|
{% extends 'atlas/exams.html' %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>{{case_detail.collection.name}} / {{case_detail.case.pk}}</h2>
|
<h2>{{case_detail.collection.name}} / {{case_detail.case.pk}}</h2>
|
||||||
|
|
||||||
|
<p>See https://django-jsonform.readthedocs.io/en/latest/guide/inputs.html for formatting</p>
|
||||||
|
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form.as_p }}
|
{{ form.as_p }}
|
||||||
<button type="submit">Submit</button>
|
<button type="submit" value="save" name="submit">Submit</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<h2>Blank form</h2>
|
||||||
|
<form>
|
||||||
|
{{ blank_form}}
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<h2>Correct answers</h2>
|
||||||
|
<form method="POST" class="post-form">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{example_form}}
|
||||||
|
<button type="submit" value="answer" name="submit">Save Correct Answers</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block js %}
|
||||||
|
|
||||||
|
{% comment %} {{ example_form.media }} {% endcomment %}
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/@json-editor/json-editor@latest/dist/jsoneditor.min.js"></script>
|
||||||
|
<script src="/static/django_jsonforms/jsoneditor_init.js"></script>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
{% extends 'atlas/base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h2>Case: {{ case.title }}</h2>
|
||||||
|
{{ case_detail.question_schema }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ case.question_answers }}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -3,8 +3,8 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>Atlas</h2>
|
<h2>Atlas</h2>
|
||||||
|
|
||||||
<a href="{% url 'atlas:user_collections' %}">Available collections</a><br/>
|
<a href="{% url 'atlas:user_collections' %}">Colletion to view / take</a><br/>
|
||||||
View my <a href='{% url "atlas:case_view" %}?author={{request.user.id}}'>cases</a>.<br/>
|
View my <a href='{% url "atlas:case_view" %}?author={{request.user.id}}'>cases</a>.<br/>
|
||||||
<a href="{% url 'atlas:user_uploads' %}">My uploads</a>
|
<a href="{% url 'atlas:user_uploads' %}">Uploads awaiting import</a>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -176,6 +176,11 @@ urlpatterns = [
|
|||||||
views.collection_case_view_take_user,
|
views.collection_case_view_take_user,
|
||||||
name="collection_case_view_take_user",
|
name="collection_case_view_take_user",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"collection/<int:pk>/<int:case_number>/take/answers",
|
||||||
|
views.collection_case_view_take_user_answers,
|
||||||
|
name="collection_case_view_take_user_answers",
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"collection/<int:pk>/json_edit",
|
"collection/<int:pk>/json_edit",
|
||||||
views.GenericExamViews.exam_json_edit,
|
views.GenericExamViews.exam_json_edit,
|
||||||
|
|||||||
+66
-3
@@ -47,6 +47,7 @@ from .forms import (
|
|||||||
ConditionAutocompleteForm,
|
ConditionAutocompleteForm,
|
||||||
ConditionForm,
|
ConditionForm,
|
||||||
FindingForm,
|
FindingForm,
|
||||||
|
JsonAnswerForm,
|
||||||
ResourceForm,
|
ResourceForm,
|
||||||
SelfReviewForm,
|
SelfReviewForm,
|
||||||
SeriesAuthorForm,
|
SeriesAuthorForm,
|
||||||
@@ -1566,18 +1567,51 @@ def collection_take_start(request, pk):
|
|||||||
def collection_case_details(request, exam_id, case_id):
|
def collection_case_details(request, exam_id, case_id):
|
||||||
case_detail = CaseDetail.objects.get(case=case_id, collection=exam_id)
|
case_detail = CaseDetail.objects.get(case=case_id, collection=exam_id)
|
||||||
|
|
||||||
if request.method == 'POST':
|
|
||||||
|
if request.method == 'POST' and request.POST.get('submit') == 'answer':
|
||||||
|
#answers = request.POST
|
||||||
|
case_detail.question_answers = json.loads(request.POST.get("json_answer"))
|
||||||
|
case_detail.save()
|
||||||
|
example_form = JsonAnswerForm(request.POST, case_detail=case_detail)
|
||||||
|
|
||||||
|
else:
|
||||||
|
post_data = None
|
||||||
|
|
||||||
|
if case_detail.question_schema is not None and case_detail.question_answers is not None:
|
||||||
|
question_keys = set(case_detail.question_schema["properties"].keys())
|
||||||
|
answer_keys = set(case_detail.question_answers.keys())
|
||||||
|
|
||||||
|
answers = {}
|
||||||
|
for key, value in case_detail.question_answers.items():
|
||||||
|
if key in question_keys:
|
||||||
|
answers[key] = value
|
||||||
|
|
||||||
|
diff = question_keys - answer_keys
|
||||||
|
|
||||||
|
for key in diff:
|
||||||
|
answers[key] = ""
|
||||||
|
|
||||||
|
|
||||||
|
post_data = request.POST.copy()
|
||||||
|
post_data["json_answer"]= json.dumps(answers)
|
||||||
|
example_form = JsonAnswerForm(post_data, case_detail=case_detail)
|
||||||
|
|
||||||
|
if request.method == 'POST' and request.POST.get('submit') == 'save':
|
||||||
form = CaseDetailForm(request.POST, instance=case_detail)
|
form = CaseDetailForm(request.POST, instance=case_detail)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
form.save()
|
form.save()
|
||||||
# Add any additional logic or redirection here
|
# Add any additional logic or redirection here
|
||||||
else:
|
else:
|
||||||
|
|
||||||
form = CaseDetailForm(instance=case_detail)
|
form = CaseDetailForm(instance=case_detail)
|
||||||
|
|
||||||
|
blank_form = JsonAnswerForm(case_detail=case_detail)
|
||||||
|
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
request, "atlas/collection_case_detail.html", {"case_detail": case_detail,
|
request, "atlas/collection_case_detail.html", {"case_detail": case_detail,
|
||||||
"form": form}
|
"form": form, "example_form": example_form,
|
||||||
|
"blank_form": blank_form}
|
||||||
)
|
)
|
||||||
|
|
||||||
@user_is_collection_author_or_atlas_editor
|
@user_is_collection_author_or_atlas_editor
|
||||||
@@ -1790,6 +1824,35 @@ def collection_take_overview(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def collection_case_view_take_user_answers(request, pk: int, case_number: int):
|
||||||
|
return collection_case_view_take_answers(request, pk, case_number)
|
||||||
|
|
||||||
|
def collection_case_view_take_answers(
|
||||||
|
request, pk: int, case_number: int, cid=None, passcode=None
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
collection = get_object_or_404(CaseCollection, pk=pk)
|
||||||
|
|
||||||
|
collection.check_user_can_take(cid, passcode, request.user)
|
||||||
|
|
||||||
|
case, case_count = collection.get_case_by_index(case_number, case_count=True)
|
||||||
|
|
||||||
|
cid_user_exam = collection.get_or_create_cid_user_exam(
|
||||||
|
cid=cid, user_user=request.user
|
||||||
|
)
|
||||||
|
|
||||||
|
case_detail = CaseDetail.objects.get(case=case, collection=collection)
|
||||||
|
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"atlas/collection_case_view_take_answers.html",
|
||||||
|
{
|
||||||
|
"collection": collection,
|
||||||
|
"case": case,
|
||||||
|
"case_detail": case_detail,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
def collection_case_view_take_user(request, pk: int, case_number: int):
|
def collection_case_view_take_user(request, pk: int, case_number: int):
|
||||||
return collection_case_view_take(request, pk, case_number)
|
return collection_case_view_take(request, pk, case_number)
|
||||||
|
|||||||
+1
-1
@@ -80,7 +80,7 @@ INSTALLED_APPS = [
|
|||||||
"autocomplete",
|
"autocomplete",
|
||||||
'markdownify.apps.MarkdownifyConfig',
|
'markdownify.apps.MarkdownifyConfig',
|
||||||
'django_jsonforms',
|
'django_jsonforms',
|
||||||
|
'django_svelte_jsoneditor'
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
|||||||
+2
-1
@@ -47,4 +47,5 @@ django-sortedm2m # remove once migrations squashed
|
|||||||
loguru
|
loguru
|
||||||
pylibjpeg
|
pylibjpeg
|
||||||
pylibjpeg-libjpeg
|
pylibjpeg-libjpeg
|
||||||
django-jsonforms
|
django-jsonforms
|
||||||
|
django_svelte_jsoneditor
|
||||||
Reference in New Issue
Block a user