Add AddExamForm and update exam_edit_fragment for exam management
This commit is contained in:
@@ -0,0 +1,23 @@
|
|||||||
|
{% load static %}
|
||||||
|
<div id="exam-list">
|
||||||
|
<form hx-post="{% url 'anatomy:question_add_exam' question_id=question.pk %}" hx-target="#exam-list" hx-swap="innerHTML">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="input-group mb-2">
|
||||||
|
{{ form.exam }}
|
||||||
|
<button class="btn btn-sm btn-primary" type="submit">Add</button>
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="document.getElementById('exam-list').innerHTML='';">Close</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<div class="mb-2 small">Current exams:
|
||||||
|
{% for exam in question.exams.all %}
|
||||||
|
<form class="d-inline me-1" hx-post="{% url 'anatomy:question_add_exam' question_id=question.pk %}" hx-target="#exam-list" hx-swap="innerHTML">
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="hidden" name="exam_id" value="{{ exam.id }}">
|
||||||
|
<input type="hidden" name="remove" value="true">
|
||||||
|
<button class="btn btn-sm btn-outline-danger mb-1" type="submit" hx-confirm="Are you sure you want to remove this exam?">{{ exam }}</button>
|
||||||
|
</form>
|
||||||
|
{% empty %}
|
||||||
|
<span class="text-muted">No exams</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
+37
-27
@@ -59,6 +59,21 @@ from .models import (
|
|||||||
# HalfMarkAnswers,
|
# HalfMarkAnswers,
|
||||||
# IncorrectAnswers,
|
# IncorrectAnswers,
|
||||||
)
|
)
|
||||||
|
from generic.widgets import ExamSearchWidget
|
||||||
|
|
||||||
|
|
||||||
|
class AddExamForm(forms.Form):
|
||||||
|
exam = forms.ModelChoiceField(queryset=Exam.objects.none(), required=True, widget=ExamSearchWidget(exam_model=Exam), label="Exam to add")
|
||||||
|
|
||||||
|
def __init__(self, *args, user=None, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
if user is None:
|
||||||
|
qs = Exam.objects.none()
|
||||||
|
elif user.groups.filter(name="anatomy_checker").exists():
|
||||||
|
qs = Exam.objects.all()
|
||||||
|
else:
|
||||||
|
qs = Exam.objects.filter(author__id=user.id) | Exam.objects.filter(open_access=True)
|
||||||
|
self.fields["exam"].queryset = qs.distinct()
|
||||||
from generic.models import CidUser, Examination
|
from generic.models import CidUser, Examination
|
||||||
from generic.views import AuthorRequiredMixin, ExamCloneMixin, ExamCreateBase, ExamDeleteBase, ExamGroupsUpdateBase, ExamUpdateBase, ExamViews, GenericViewBase, UpdateQuestionMixin
|
from generic.views import AuthorRequiredMixin, ExamCloneMixin, ExamCreateBase, ExamDeleteBase, ExamGroupsUpdateBase, ExamUpdateBase, ExamViews, GenericViewBase, UpdateQuestionMixin
|
||||||
from reversion.views import RevisionMixin
|
from reversion.views import RevisionMixin
|
||||||
@@ -1627,44 +1642,39 @@ def question_add_exam(request, question_id: int):
|
|||||||
return HttpResponse("Invalid permissions", status=403)
|
return HttpResponse("Invalid permissions", status=403)
|
||||||
|
|
||||||
|
|
||||||
if request.POST:
|
# POST: handle add/remove; if exam_id provided use existing behaviour
|
||||||
|
if request.method == "POST":
|
||||||
exam_id = request.POST.get("exam_id", None)
|
exam_id = request.POST.get("exam_id", None)
|
||||||
|
|
||||||
if exam_id is None:
|
if exam_id:
|
||||||
return HttpResponse("No exam id provided", status=400)
|
|
||||||
|
|
||||||
exam = get_object_or_404(Exam, pk=exam_id)
|
exam = get_object_or_404(Exam, pk=exam_id)
|
||||||
|
|
||||||
if request.POST.get("remove", False) == "true":
|
if request.POST.get("remove", False) == "true":
|
||||||
question.exams.remove(exam)
|
question.exams.remove(exam)
|
||||||
return HttpResponse("Question removed from exam.")
|
|
||||||
else:
|
else:
|
||||||
question.exams.add(exam)
|
question.exams.add(exam)
|
||||||
|
|
||||||
return HttpResponse("Question added to exam.")
|
# return updated fragment
|
||||||
|
form = AddExamForm(user=request.user)
|
||||||
|
return render(request, "anatomy/partials/exam_edit_fragment.html", {"form": form, "question": question})
|
||||||
|
|
||||||
|
# else try to process from the search form
|
||||||
|
form = AddExamForm(request.POST, user=request.user)
|
||||||
|
if form.is_valid():
|
||||||
|
exam = form.cleaned_data.get("exam")
|
||||||
|
if request.POST.get("remove", False) == "true":
|
||||||
|
question.exams.remove(exam)
|
||||||
else:
|
else:
|
||||||
# Return a list of exams that we can add to the question
|
question.exams.add(exam)
|
||||||
|
|
||||||
exams = Exam.objects.filter(author=request.user)
|
form = AddExamForm(user=request.user)
|
||||||
exams = exams.difference(question.exams.all())
|
return render(request, "anatomy/partials/exam_edit_fragment.html", {"form": form, "question": question})
|
||||||
|
else:
|
||||||
|
# render form with errors
|
||||||
|
return render(request, "anatomy/partials/exam_edit_fragment.html", {"form": form, "question": question})
|
||||||
|
|
||||||
if not exams:
|
# GET: render the fragment with the add form and current exams
|
||||||
return HttpResponse("No exams available to add")
|
form = AddExamForm(user=request.user)
|
||||||
|
return render(request, "anatomy/partials/exam_edit_fragment.html", {"form": form, "question": question})
|
||||||
html = "Exams to add to question: <br>"
|
|
||||||
for exam in exams:
|
|
||||||
html = html + (f"<span id='htmx-exam-list'><form><input name='exam_id' value='{exam.id}' type='hidden'><button hx-post=\"{request.path}\""
|
|
||||||
f">{exam.name}: {exam.id}</button></form>"
|
|
||||||
)
|
|
||||||
html = html + "<br>Exams to remove from question: <br>"
|
|
||||||
for exam in question.exams.all():
|
|
||||||
html = html + (f"<span id='htmx-exam-list'><form><input name='exam_id' value='{exam.id}' type='hidden'><input name='remove' value='true' type='hidden'><button hx-post=\"{request.path}\""
|
|
||||||
f"hx-confirm='Are you sure you want to remove this exam from the question?'"
|
|
||||||
f">{exam.name}: {exam.id}</button></form>"
|
|
||||||
)
|
|
||||||
html = html + "<button _='on click remove #htmx-exam-list'>Cancel</button>"
|
|
||||||
|
|
||||||
return HttpResponse(mark_safe(html))
|
|
||||||
|
|
||||||
|
|
||||||
raise PermissionDenied()
|
raise PermissionDenied()
|
||||||
|
|||||||
Reference in New Issue
Block a user