.
This commit is contained in:
@@ -481,4 +481,8 @@ td.user-answer-score-2::after {
|
|||||||
|
|
||||||
.proposed-answer {
|
.proposed-answer {
|
||||||
color: darkblue
|
color: darkblue
|
||||||
|
}
|
||||||
|
|
||||||
|
.notes .complete {
|
||||||
|
color: darkslategray;
|
||||||
}
|
}
|
||||||
+4
-1
@@ -126,4 +126,7 @@ class QuestionNote(models.Model):
|
|||||||
return "{} [{}] {} / {}".format(self.author, self.created_on, self.note_type, self.note)
|
return "{} [{}] {} / {}".format(self.author, self.created_on, self.note_type, self.note)
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return "/"
|
return "/"
|
||||||
|
|
||||||
|
def get_object_url(self):
|
||||||
|
return self.question.get_absolute_url()
|
||||||
@@ -57,6 +57,7 @@ urlpatterns = [
|
|||||||
path("exam/submit", views.exam_submit, name="global_exam_answers_submit"),
|
path("exam/submit", views.exam_submit, name="global_exam_answers_submit"),
|
||||||
#path('', include('generic.urls')),
|
#path('', include('generic.urls')),
|
||||||
path("feedback/<str:question_type>/<int:pk>", views.AddQuestionNote.as_view(), name="feedback_create"),
|
path("feedback/<str:question_type>/<int:pk>", views.AddQuestionNote.as_view(), name="feedback_create"),
|
||||||
|
path("feedback/note/<int:pk>/complete", views.feedback_mark_complete, name="feedback_mark_complete"),
|
||||||
#path("feedback/", views.AddQuestionNote.as_view(), name="feedback"),
|
#path("feedback/", views.AddQuestionNote.as_view(), name="feedback"),
|
||||||
path("feedback/answer", views.answer_suggestion_submit, name="answer_suggestion_submit"),
|
path("feedback/answer", views.answer_suggestion_submit, name="answer_suggestion_submit"),
|
||||||
path("feedback/answer/confirm", views.answer_suggestion_confirm, name="answer_suggestion_confirm"),
|
path("feedback/answer/confirm", views.answer_suggestion_confirm, name="answer_suggestion_confirm"),
|
||||||
|
|||||||
+37
-14
@@ -1,3 +1,4 @@
|
|||||||
|
from django.core.exceptions import PermissionDenied
|
||||||
from django.shortcuts import render, get_object_or_404, redirect
|
from django.shortcuts import render, get_object_or_404, redirect
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from django import forms
|
from django import forms
|
||||||
@@ -23,7 +24,7 @@ from django.http import Http404, JsonResponse
|
|||||||
|
|
||||||
from django.http import HttpResponseRedirect, HttpResponse
|
from django.http import HttpResponseRedirect, HttpResponse
|
||||||
|
|
||||||
from physics.models import CidUserAnswer as PhysicsCidUserAnswer
|
from physics.models import CidUserAnswer as PhysicsCidUserAnswer, Question
|
||||||
from physics.models import Exam as PhysicsExam
|
from physics.models import Exam as PhysicsExam
|
||||||
|
|
||||||
from anatomy.models import CidUserAnswer as AnatomyCidUserAnswer
|
from anatomy.models import CidUserAnswer as AnatomyCidUserAnswer
|
||||||
@@ -48,6 +49,9 @@ from generic.models import QuestionNote
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
def feedback_checker(user):
|
||||||
|
return user.groups.filter(name="feedback_checker").exists()
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def profile(request):
|
def profile(request):
|
||||||
@@ -162,6 +166,22 @@ def feedback_create(request, question_type, pk):
|
|||||||
|
|
||||||
return JsonResponse({"success": False, "error": "Invalid exam type"})
|
return JsonResponse({"success": False, "error": "Invalid exam type"})
|
||||||
|
|
||||||
|
def get_question_and_content_type(pk, question_type):
|
||||||
|
if question_type == "rapid":
|
||||||
|
question = Rapid
|
||||||
|
content_type = ContentType.objects.get(model="rapid")
|
||||||
|
elif question_type == "anatomy":
|
||||||
|
question = AnatomyQuestion
|
||||||
|
content_type = ContentType.objects.get(model="anatomyquestion")
|
||||||
|
elif question_type == "long":
|
||||||
|
question = Long
|
||||||
|
content_type = ContentType.objects.get(model="long")
|
||||||
|
else:
|
||||||
|
raise PermissionError()
|
||||||
|
|
||||||
|
return question, content_type
|
||||||
|
|
||||||
|
|
||||||
class AddQuestionNote(CreateView):
|
class AddQuestionNote(CreateView):
|
||||||
model = QuestionNote
|
model = QuestionNote
|
||||||
form_class = QuestionNoteForm
|
form_class = QuestionNoteForm
|
||||||
@@ -178,22 +198,24 @@ class AddQuestionNote(CreateView):
|
|||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
pk = self.kwargs["pk"]
|
pk = self.kwargs["pk"]
|
||||||
question_type = self.kwargs["question_type"]
|
question_type = self.kwargs["question_type"]
|
||||||
if question_type == "rapid":
|
|
||||||
question = Rapid
|
question, content_type = get_question_and_content_type(pk, question_type)
|
||||||
content_type = ContentType.objects.get(model="rapid")
|
|
||||||
elif question_type == "anatomy":
|
|
||||||
question = AnatomyQuestion
|
|
||||||
content_type = ContentType.objects.get(model="anatomyquestion")
|
|
||||||
elif question_type == "long":
|
|
||||||
question = Long
|
|
||||||
content_type = ContentType.objects.get(model="long")
|
|
||||||
else:
|
|
||||||
raise PermissionError()
|
|
||||||
|
|
||||||
get_object_or_404(question, pk=pk)
|
get_object_or_404(question, pk=pk)
|
||||||
return { "content_type" : content_type,
|
return { "content_type" : content_type,
|
||||||
"object_id" : pk }
|
"object_id" : pk }
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def feedback_mark_complete(request, pk):
|
||||||
|
q = get_object_or_404(QuestionNote, pk=pk)
|
||||||
|
|
||||||
|
if request.user not in q.question.author.all() and not request.user.groups.filter(name="feedback_checker").exists():
|
||||||
|
raise PermissionDenied()
|
||||||
|
|
||||||
|
q.complete = True
|
||||||
|
q.save()
|
||||||
|
return redirect(q.get_object_url())
|
||||||
|
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
def answer_suggestion_submit(request):
|
def answer_suggestion_submit(request):
|
||||||
if request.is_ajax and request.method == "POST":
|
if request.is_ajax and request.method == "POST":
|
||||||
@@ -249,10 +271,11 @@ def answer_suggestion_confirm(request):
|
|||||||
return JsonResponse({"success": True, "error": "Answer changed"})
|
return JsonResponse({"success": True, "error": "Answer changed"})
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def view_feedback(request, pk):
|
@user_passes_test(feedback_checker)
|
||||||
|
def view_feedback(request):
|
||||||
# exam = get_object_or_404(Exam, pk=pk)
|
# exam = get_object_or_404(Exam, pk=pk)
|
||||||
|
|
||||||
feedback_notes = QuestionNote.objects.all()
|
feedback_notes = QuestionNote.objects.filter(complete=False)
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
|
|||||||
@@ -37,6 +37,8 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
|
{% if view_feedback %}
|
||||||
Notes:
|
Notes:
|
||||||
<ul>
|
<ul>
|
||||||
{% for note in question.rapid_notes.all %}
|
{% for note in question.rapid_notes.all %}
|
||||||
@@ -46,13 +48,17 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
Anon Notes:
|
Anon Notes:
|
||||||
<ul>
|
<ul class="notes">
|
||||||
{% for note in question.anon_notes.all %}
|
{% for note in question.anon_notes.all %}
|
||||||
<li>
|
<li {% if note.complete %}class='complete' {% endif %}>
|
||||||
{{ note.created_on }} by {{ note.author }}: {{ note.note }}
|
{{ note.created_on }} by {{ note.author }}: {{note.note_type}} / {{ note.note }}
|
||||||
|
{% if not note.complete %}
|
||||||
|
(<a href="{% url 'feedback_mark_complete' pk=note.pk %}">Mark complete</a>)
|
||||||
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div id="single-dicom-viewer" class="dicom-viewer" data-images="{{ question.GetImageUrls }}" data-annotations=''></div>
|
<div id="single-dicom-viewer" class="dicom-viewer" data-images="{{ question.GetImageUrls }}" data-annotations=''></div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+5
-1
@@ -101,9 +101,13 @@ def question_detail(request, pk):
|
|||||||
# if request.user not in rapid.author.all():
|
# if request.user not in rapid.author.all():
|
||||||
# raise PermissionDenied
|
# raise PermissionDenied
|
||||||
|
|
||||||
|
view_feedback = False
|
||||||
|
if request.user.groups.filter(name="rapid_checker").exists() or request.user.groups.filter(name="feedback_checker").exists() or request.user in rapid.author.all():
|
||||||
|
view_feedback = True
|
||||||
|
|
||||||
# logging.debug(rapid.rapid_notes.first())
|
# logging.debug(rapid.rapid_notes.first())
|
||||||
# logging.debug(rapid.subspecialty.first().name.all())
|
# logging.debug(rapid.subspecialty.first().name.all())
|
||||||
return render(request, "rapids/question_detail.html", {"question": rapid})
|
return render(request, "rapids/question_detail.html", {"question": rapid, "view_feedback" : view_feedback})
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
|||||||
@@ -3,9 +3,10 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="anatomy">
|
<div class="anatomy">
|
||||||
<h1>Feedback</h1>
|
<h1>Feedback</h1>
|
||||||
|
Displays a list of feedback reports yet to be acted upon
|
||||||
<ul>
|
<ul>
|
||||||
{% for note in notes %}
|
{% for note in notes %}
|
||||||
<li>{{note.content_type }}: {{note.note_type}} / {{note.note}} [{{note.complete}}]</li>
|
<li><a href="{{ note.get_object_url }}">{{note.content_type }}</a>: {{note.note_type}} / {{note.note}} </li>
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
Reference in New Issue
Block a user