.
This commit is contained in:
@@ -109,6 +109,7 @@ Author(s): {% for author in exam.author.all %}
|
||||
|
||||
<details>
|
||||
<summary>Extra</summary>
|
||||
Occasionally the order of questions can get out of sync. If you are exeriancing issues with the order of questions you can reset the order here.
|
||||
<button title="This will clear all user answers and attempts"
|
||||
hx-post="{% url exam.get_app_name|add:':order_questions' exam.pk %}"
|
||||
hx-swap="outerHTML"
|
||||
|
||||
+6
-3
@@ -500,6 +500,9 @@ class ExamViews(View, LoginRequiredMixin):
|
||||
if exam.authors_only:
|
||||
return False
|
||||
|
||||
if exam.open_access:
|
||||
return True
|
||||
|
||||
if user.groups.filter(name="cid_user_manager").exists():
|
||||
return True
|
||||
|
||||
@@ -697,8 +700,8 @@ class ExamViews(View, LoginRequiredMixin):
|
||||
return self.exam_list(request, all=True)
|
||||
|
||||
def order_questions(self, request, exam_id):
|
||||
if not self.check_user_edit_access(request.user):
|
||||
raise PermissionDenied
|
||||
if not self.check_user_edit_access(request.user, exam_id=exam_id):
|
||||
return HttpResponse("Permission denied")
|
||||
|
||||
exam = get_object_or_404(self.Exam, pk=exam_id)
|
||||
|
||||
@@ -1518,7 +1521,7 @@ class ExamViews(View, LoginRequiredMixin):
|
||||
exams = self.Exam.objects.all()
|
||||
filter = self.ExtraExamFilter(request.GET, queryset=exams)
|
||||
else:
|
||||
exams = self.Exam.objects.filter(author__id=request.user.id)
|
||||
exams = self.Exam.objects.filter(author__id=request.user.id) | self.Exam.objects.filter(open_access=True)
|
||||
filter = self.BasicExamFilter(request.GET, queryset=exams)
|
||||
|
||||
return render(
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
{% load thumbnail %}
|
||||
<div class="rapids">
|
||||
|
||||
<a href="{% url 'rapids:mark_review' exam_pk=exam.pk sk=0 %}"><button>Review exam</button></a></p>
|
||||
{% if exam.exam_mode %}
|
||||
<a href="{% url 'rapids:mark_review' exam_pk=exam.pk sk=0 %}"><button>Review exam</button></a></p>
|
||||
{% endif %}
|
||||
|
||||
<ol id="full-question-list" class="sortable">
|
||||
{% for question in questions.all %}
|
||||
|
||||
@@ -32,6 +32,10 @@
|
||||
Exam(s): {% for exam in question.exams.all %}
|
||||
<a href="{% url 'rapids:exam_overview' pk=exam.pk %}">{{ exam }}</a>,
|
||||
{% endfor %}
|
||||
<button class="btn btn-sm" hx-get="{% url 'rapids:question_add_exam' question_id=question.pk %}"
|
||||
hx-target="#exam-list"
|
||||
hx-swap="innerHTML">Edit exam(s)</button>
|
||||
<span id="exam-list"></span>
|
||||
|
||||
{% comment %} <button id="add-to-exam" data-exam_json_edit_url="{% url 'generic:generic_exam_json_edit' %}"
|
||||
data-exam_list_url="{% url 'api-1:rapid_user_exams' %}" data-type="rapids" data-csrf="{{ csrf_token}}"
|
||||
|
||||
@@ -45,6 +45,13 @@ urlpatterns = [
|
||||
views.question_anonymise_dicom,
|
||||
name="question_anonymise_dicom",
|
||||
),
|
||||
path(
|
||||
"question/<int:question_id>/add_exam",
|
||||
views.question_add_exam,
|
||||
name="question_add_exam",
|
||||
),
|
||||
path("answer/<int:answer_id>/confirm", views.confirm_answer, name="confirm_answer"),
|
||||
path("answer/<int:answer_id>/delete", views.delete_answer, name="delete_answer"),
|
||||
path("exam/<int:exam_pk>/<int:sk>/mark", views.mark, name="mark"),
|
||||
path("exam/<int:exam_pk>/<int:sk>/mark/all", views.mark_all, name="mark_all"),
|
||||
path(
|
||||
|
||||
@@ -18,6 +18,7 @@ from django.urls import reverse_lazy, reverse
|
||||
|
||||
from django.http import Http404, JsonResponse
|
||||
from django.http import HttpResponseRedirect, HttpResponse
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from .forms import (
|
||||
ExamAuthorForm,
|
||||
@@ -988,3 +989,81 @@ class AnswerAutocomplete(autocomplete.Select2QuerySetView):
|
||||
qs = qs.filter(answer__istartswith=self.q)
|
||||
|
||||
return qs
|
||||
|
||||
|
||||
def confirm_answer(request, answer_id: int):
|
||||
if request.htmx:
|
||||
answer = get_object_or_404(Answer, pk=answer_id)
|
||||
|
||||
# Check if the user has permission to confirm the answer
|
||||
if not answer.can_edit(request.user):
|
||||
return HttpResponse("Invalid permissions", status=403)
|
||||
|
||||
answer.clean()
|
||||
answer.proposed = False
|
||||
answer.save()
|
||||
return HttpResponse("Answer accepted")
|
||||
|
||||
raise PermissionDenied()
|
||||
|
||||
def delete_answer(request, answer_id: int):
|
||||
if request.htmx:
|
||||
answer = get_object_or_404(Answer, pk=answer_id)
|
||||
|
||||
# Check if the user has permission to confirm the answer
|
||||
if not answer.can_edit(request.user):
|
||||
return HttpResponse("Invalid permissions", status=403)
|
||||
|
||||
answer.delete()
|
||||
return HttpResponse("Answer deleted")
|
||||
raise PermissionDenied()
|
||||
|
||||
def question_add_exam(request, question_id: int):
|
||||
if request.htmx:
|
||||
question = get_object_or_404(Rapid, pk=question_id)
|
||||
|
||||
if not question.can_edit(request.user):
|
||||
return HttpResponse("Invalid permissions", status=403)
|
||||
|
||||
|
||||
if request.POST:
|
||||
exam_id = request.POST.get("exam_id", None)
|
||||
|
||||
if exam_id is None:
|
||||
return HttpResponse("No exam id provided", status=400)
|
||||
|
||||
exam = get_object_or_404(Exam, pk=exam_id)
|
||||
|
||||
if request.POST.get("remove", False) == "true":
|
||||
question.exams.remove(exam)
|
||||
return HttpResponse("Question removed from exam.")
|
||||
else:
|
||||
question.exams.add(exam)
|
||||
|
||||
return HttpResponse("Question added to exam.")
|
||||
else:
|
||||
# Return a list of exams that we can add to the question
|
||||
|
||||
exams = Exam.objects.filter(author=request.user) | Exam.objects.filter(open_access=True)
|
||||
exams = exams.difference(question.exams.all())
|
||||
|
||||
if not exams:
|
||||
return HttpResponse("No exams available to add")
|
||||
|
||||
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()
|
||||
Reference in New Issue
Block a user