Enhance self-review functionality with new detail views, improved UI, and dynamic case management
This commit is contained in:
@@ -1,78 +1,139 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
{% if cid is not None %}
|
||||
CID: {{cid}}
|
||||
{% endif %}
|
||||
|
||||
<h2>Collection: {{collection.name}}
|
||||
|
||||
{% if collection.in_review_mode or cid_user_exam.completed %}
|
||||
<span class="stamp-white">REVIEW</span>
|
||||
{% endif %}
|
||||
</h2>
|
||||
|
||||
|
||||
{% if not collection.review_only %}
|
||||
{{answer_count}} out of {{collection_length}} cases answered. Click to go to case.
|
||||
{% endif %}
|
||||
<div class="sba-finish-list">
|
||||
<ul>
|
||||
{% for question, answer, self_review in question_answer_tuples %}
|
||||
<li> <span class="{% if not collection.review_only and not answer %}unanswered{% endif %}">
|
||||
<a href="
|
||||
{% if cid is not None %}
|
||||
{% url 'atlas:collection_case_view_take' pk=collection.id case_number=forloop.counter0 cid=cid passcode=passcode %}
|
||||
{% else %}
|
||||
{% url 'atlas:collection_case_view_take_user' pk=collection.id case_number=forloop.counter0 %}
|
||||
{% endif %}
|
||||
">
|
||||
Case: {{forloop.counter}}
|
||||
|
||||
{% if answer.completed or cid_user_exam.completed %}
|
||||
<span title="You have completed this case"><i class="bi bi-check-square-fill"></i>
|
||||
</span>
|
||||
{% endif %}
|
||||
{% if self_review %} <span class="self-review-complete" title="You have reviewed this case."> <i class="bi-card-checklist"></i></span>{% endif %}
|
||||
|
||||
</a>
|
||||
<br/>
|
||||
{% if not collection.review_only %}
|
||||
{% if not answer %}
|
||||
No answer
|
||||
{% else %}
|
||||
<details><summary>Answered</summary>
|
||||
|
||||
{% if aswer.answer %}
|
||||
{{answer.answer}}
|
||||
{% else %}
|
||||
{{answer.json_answer}}
|
||||
{% endif %}
|
||||
|
||||
</details>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</span>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<div class="d-flex flex-wrap justify-content-between align-items-start gap-3 mb-3">
|
||||
<div>
|
||||
<h2 class="h4 mb-1">
|
||||
{{ collection.name }}
|
||||
{% if collection.in_review_mode or cid_user_exam.completed %}
|
||||
<span class="badge bg-light text-dark ms-2">Review</span>
|
||||
{% endif %}
|
||||
</h2>
|
||||
<div class="text-muted small">
|
||||
{% if cid is not None %}
|
||||
CID: <strong>{{ cid }}</strong>
|
||||
{% else %}
|
||||
Your collection overview
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card border-secondary" style="min-width: 280px;">
|
||||
<div class="card-body py-2 px-3">
|
||||
<div class="small text-muted">Progress</div>
|
||||
{% if not collection.review_only %}
|
||||
<div class="fw-semibold">{{ answer_count }} / {{ collection_length }} answered</div>
|
||||
<div class="progress mt-2" style="height: 8px;">
|
||||
<div class="progress-bar" role="progressbar" style="width: {% widthratio answer_count collection_length 100 %}%"></div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="fw-semibold">Review-only collection</div>
|
||||
{% endif %}
|
||||
<div class="mt-2 small">Started: {{ cid_user_exam.start_time }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="list-group mb-3">
|
||||
{% for question, answer, self_review in question_answer_tuples %}
|
||||
<div class="list-group-item {% if not answer %}bg-danger-subtle border-danger-subtle{% endif %}">
|
||||
<div class="d-flex flex-wrap justify-content-between align-items-start gap-2">
|
||||
<div>
|
||||
<div class="fw-semibold">
|
||||
Case {{ forloop.counter }}{% if collection.show_title_post %}: {{ question.case.title|default:question.case.pk|truncatechars:70 }}{% endif %}
|
||||
{% if answer and answer.completed or cid_user_exam.completed %}
|
||||
<span class="badge bg-success-subtle text-success-emphasis ms-2">Completed</span>
|
||||
{% elif answer %}
|
||||
<span class="badge bg-warning-subtle text-warning-emphasis ms-2">Saved</span>
|
||||
{% else %}
|
||||
<span class="badge bg-danger-subtle text-danger-emphasis ms-2">Not answered</span>
|
||||
{% endif %}
|
||||
{% if self_review %}
|
||||
<span class="badge bg-info-subtle text-info-emphasis ms-1">Self review added</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if collection.show_title_post %}
|
||||
<div class="small text-muted">
|
||||
{{ question.case }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
<a class="btn btn-sm btn-primary"
|
||||
href="{% if cid is not None %}{% url 'atlas:collection_case_view_take' pk=collection.id case_number=forloop.counter0 cid=cid passcode=passcode %}{% else %}{% url 'atlas:collection_case_view_take_user' pk=collection.id case_number=forloop.counter0 %}{% endif %}">
|
||||
Open Case
|
||||
</a>
|
||||
{% if cid is None %}
|
||||
<a class="btn btn-sm btn-outline-secondary"
|
||||
href="{% url 'atlas:collection_case_view_take_user_answers' pk=collection.id case_number=forloop.counter0 %}">
|
||||
View Answer / Report
|
||||
</a>
|
||||
{% else %}
|
||||
<a class="btn btn-sm btn-outline-secondary"
|
||||
href="{% url 'atlas:collection_case_view_take' pk=collection.id case_number=forloop.counter0 cid=cid passcode=passcode %}">
|
||||
View Answer / Report
|
||||
</a>
|
||||
{% endif %}
|
||||
<a class="btn btn-sm btn-outline-info"
|
||||
href="{% url 'atlas:add_self_review' cid_user_exam.id question.case.id %}">
|
||||
{% if self_review %}Add New Self Review{% else %}Add Self Review{% endif %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Start time: {{cid_user_exam.start_time}}
|
||||
{% if self_review %}
|
||||
<div class="mt-2 pt-2 border-top">
|
||||
<div class="small fw-semibold mb-1">Your self reviews</div>
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
{% for review in self_review %}
|
||||
<a class="btn btn-sm btn-outline-info"
|
||||
href="{% url 'atlas:self_review_detail' cid_user_exam.id question.case.id review.id %}">
|
||||
View review {{ forloop.counter }}
|
||||
</a>
|
||||
<a class="btn btn-sm btn-outline-warning"
|
||||
href="{% url 'atlas:self_review_update' cid_user_exam.id question.case.id review.id %}">
|
||||
Edit review {{ forloop.counter }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if not collection.review_only %}
|
||||
{% if answer %}
|
||||
<details class="mt-2">
|
||||
<summary class="small text-muted">Preview saved answer/report</summary>
|
||||
<div class="small mt-2 p-2 bg-body-tertiary rounded">
|
||||
{% if answer.answer %}
|
||||
{{ answer.answer|linebreaksbr }}
|
||||
{% else %}
|
||||
{{ answer.json_answer }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</details>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% if not collection.review_only and not cid_user_exam.completed %}
|
||||
<p>Completed: <span id="completed-state">{{cid_user_exam.completed}}</span></p>
|
||||
<form hx-post=""
|
||||
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
|
||||
hx-delete
|
||||
hx-confirm="Finish session?"
|
||||
hx-target="#completed-state"
|
||||
_="on htmx:afterOnLoad remove me"
|
||||
>
|
||||
<button type="submit" name="finish" value="finish">Finish</button>
|
||||
</form>
|
||||
<div class="card border-warning-subtle">
|
||||
<div class="card-body d-flex flex-wrap justify-content-between align-items-center gap-2">
|
||||
<div>
|
||||
<div class="fw-semibold">Ready to submit this session?</div>
|
||||
<div class="small text-muted">Completed: <span id="completed-state">{{ cid_user_exam.completed }}</span></div>
|
||||
</div>
|
||||
<form hx-post=""
|
||||
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
|
||||
hx-delete
|
||||
hx-confirm="Finish session?"
|
||||
hx-target="#completed-state"
|
||||
_="on htmx:afterOnLoad remove me"
|
||||
class="m-0">
|
||||
<button type="submit" name="finish" value="finish" class="btn btn-warning">Finish Session</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +1,31 @@
|
||||
{% for cd in casedetails %}
|
||||
{% with idx=forloop.counter0 %}
|
||||
{% if cid %}
|
||||
<a class="dropdown-item {% if idx == current %}active{% endif %}" href="{% url 'atlas:collection_case_view_take' pk=collection.pk case_number=idx cid=cid passcode=passcode %}">
|
||||
{% else %}
|
||||
<a class="dropdown-item {% if idx == current %}active{% endif %}" href="{% url 'atlas:collection_case_view_take_user' pk=collection.pk case_number=idx %}">
|
||||
{% endif %}
|
||||
Case {{ forloop.counter }}: {{ cd.case.title|default:cd.case.pk|truncatechars:60 }}
|
||||
</a>
|
||||
{% endwith %}
|
||||
{% for item in jump_items %}
|
||||
<div class="dropdown-item-text {% if not item.has_answer %}bg-danger-subtle border border-danger-subtle rounded{% elif item.idx == current %}bg-primary-subtle rounded{% endif %} py-2 px-2 mb-1">
|
||||
<div class="d-flex justify-content-between align-items-start gap-2">
|
||||
<a class="text-decoration-none small fw-semibold"
|
||||
href="{{ item.case_url }}">
|
||||
Case {{ item.idx|add:1 }}: {{ item.cd.case.title|default:item.cd.case.pk|truncatechars:45 }}
|
||||
</a>
|
||||
<div class="d-flex gap-1">
|
||||
{% if item.has_answer %}
|
||||
<span class="badge bg-success-subtle text-success-emphasis">Answered</span>
|
||||
{% else %}
|
||||
<span class="badge bg-danger-subtle text-danger-emphasis">Not answered</span>
|
||||
{% endif %}
|
||||
{% if item.has_self_review %}
|
||||
<span class="badge bg-info-subtle text-info-emphasis">Self review</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex flex-wrap gap-1 mt-2">
|
||||
<a class="btn btn-outline-secondary btn-sm py-0 px-2" href="{{ item.answer_url }}">Answer</a>
|
||||
{% if item.self_review_view_url %}
|
||||
<a class="btn btn-outline-info btn-sm py-0 px-2" href="{{ item.self_review_view_url }}">View review</a>
|
||||
<a class="btn btn-outline-warning btn-sm py-0 px-2" href="{{ item.self_review_edit_url }}">Edit</a>
|
||||
{% else %}
|
||||
<a class="btn btn-outline-info btn-sm py-0 px-2" href="{{ item.self_review_add_url }}">Add review</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% empty %}
|
||||
<div class="dropdown-item-text text-muted small px-2 py-2">No cases available.</div>
|
||||
{% endfor %}
|
||||
|
||||
@@ -24,20 +24,30 @@
|
||||
<div class="small text-muted">
|
||||
Updated: {{ review.review_update_date|date:"Y-m-d H:i" }}
|
||||
</div>
|
||||
<div class="btn-group btn-group-sm" role="group" aria-label="Edit self review">
|
||||
<a class="btn btn-outline-primary"
|
||||
<div class="d-flex flex-wrap gap-1" role="group" aria-label="Self review actions">
|
||||
<a class="btn btn-outline-primary btn-sm"
|
||||
href="{% url 'atlas:self_review_detail' cid_user_exam.id case.id review.id %}">
|
||||
View
|
||||
</a>
|
||||
<button type="button" class="btn btn-outline-info btn-sm"
|
||||
onclick="openSelfReviewPopup('{% url 'atlas:self_review_detail' cid_user_exam.id case.id review.id %}')">
|
||||
View popup
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm"
|
||||
onclick="openSelfReviewSidebar('{% url 'atlas:self_review_detail' cid_user_exam.id case.id review.id %}')">
|
||||
View sidebar
|
||||
</button>
|
||||
<a class="btn btn-outline-warning btn-sm"
|
||||
href="{% url 'atlas:self_review_update' cid_user_exam.id case.id review.id %}">
|
||||
Edit
|
||||
</a>
|
||||
<button type="button"
|
||||
class="btn btn-outline-info"
|
||||
<button type="button" class="btn btn-outline-warning btn-sm"
|
||||
onclick="openSelfReviewPopup('{% url 'atlas:self_review_update' cid_user_exam.id case.id review.id %}')">
|
||||
Popup
|
||||
Edit popup
|
||||
</button>
|
||||
<button type="button"
|
||||
class="btn btn-outline-secondary"
|
||||
<button type="button" class="btn btn-outline-warning btn-sm"
|
||||
onclick="openSelfReviewSidebar('{% url 'atlas:self_review_update' cid_user_exam.id case.id review.id %}')">
|
||||
Sidebar
|
||||
Edit sidebar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<div class="p-3">
|
||||
<div class="card border-secondary shadow-sm mb-2">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h2 class="h6 mb-0">Self Review</h2>
|
||||
<span class="badge bg-primary-subtle text-primary-emphasis">{{ user_exam.exam }}</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="small text-muted mb-2">Case: <strong>{{ case }}</strong></div>
|
||||
|
||||
<div class="row g-2 mb-3">
|
||||
<div class="col-6">
|
||||
<div class="p-2 border rounded">
|
||||
<div class="small text-muted">Findings</div>
|
||||
<div class="fw-semibold">{{ review.findings|default:"-" }}/5</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="p-2 border rounded">
|
||||
<div class="small text-muted">Interpretation</div>
|
||||
<div class="fw-semibold">{{ review.interpretation|default:"-" }}/5</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="small text-muted mb-1">Comments</div>
|
||||
<div class="p-2 border rounded bg-body-tertiary">
|
||||
{% if review.comments %}
|
||||
{{ review.comments|linebreaksbr }}
|
||||
{% else %}
|
||||
<span class="text-muted">No comments added.</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="small text-muted mb-3">
|
||||
Updated: {{ review.review_update_date }}
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2 flex-wrap">
|
||||
<a class="btn btn-outline-warning btn-sm"
|
||||
href="{% url 'atlas:self_review_update' user_exam.id case.id review.id %}?embed=1">
|
||||
Edit in sidebar
|
||||
</a>
|
||||
<a class="btn btn-outline-secondary btn-sm"
|
||||
href="{% url 'atlas:self_review_detail' user_exam.id case.id review.id %}">
|
||||
Open full page
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,52 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container px-0" style="max-width: 920px;">
|
||||
<div class="card border-secondary shadow-sm mb-3">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h2 class="h5 mb-0">Self Review</h2>
|
||||
<span class="badge bg-primary-subtle text-primary-emphasis">{{ user_exam.exam }}</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="small text-muted mb-3">Case: <strong>{{ case }}</strong></div>
|
||||
<div class="row g-2 mb-3">
|
||||
<div class="col-sm-6">
|
||||
<div class="p-2 border rounded">
|
||||
<div class="small text-muted">Findings</div>
|
||||
<div class="fw-semibold">{{ review.findings|default:"-" }}/5</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="p-2 border rounded">
|
||||
<div class="small text-muted">Interpretation</div>
|
||||
<div class="fw-semibold">{{ review.interpretation|default:"-" }}/5</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<div class="small text-muted mb-1">Comments</div>
|
||||
<div class="p-2 border rounded bg-body-tertiary">
|
||||
{% if review.comments %}
|
||||
{{ review.comments|linebreaksbr }}
|
||||
{% else %}
|
||||
<span class="text-muted">No comments added.</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="small text-muted mb-3">
|
||||
Created: {{ review.review_date }}<br>
|
||||
Updated: {{ review.review_update_date }}
|
||||
</div>
|
||||
<div class="d-flex gap-2 flex-wrap">
|
||||
<a class="btn btn-outline-warning"
|
||||
href="{% url 'atlas:self_review_update' user_exam.id case.id review.id %}">
|
||||
Edit Self Review
|
||||
</a>
|
||||
<a class="btn btn-outline-secondary" href="{{ review.get_absolute_url }}">
|
||||
Back to case
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -25,6 +25,11 @@ urlpatterns = [
|
||||
views.SelfReviewUpdate.as_view(),
|
||||
name="self_review_update",
|
||||
),
|
||||
path(
|
||||
"self_review/<int:user_exam_id>/<int:case_id>/view/<int:pk>",
|
||||
views.SelfReviewDetail.as_view(),
|
||||
name="self_review_detail",
|
||||
),
|
||||
path(
|
||||
"self_review/<int:user_exam_id>/<int:case_id>/delete/<int:pk>",
|
||||
views.SelfReviewDelete.as_view(),
|
||||
|
||||
+114
@@ -1884,11 +1884,94 @@ def collection_case_jump_partial(request, pk: int):
|
||||
cid = request.GET.get('cid')
|
||||
passcode = request.GET.get('passcode')
|
||||
|
||||
try:
|
||||
cid_value = int(cid) if cid is not None else None
|
||||
except Exception:
|
||||
cid_value = None
|
||||
|
||||
cid_user_exam = collection.get_or_create_cid_user_exam(
|
||||
cid=cid_value,
|
||||
user_user=request.user,
|
||||
)
|
||||
|
||||
if cid_value is not None:
|
||||
answers = CidReportAnswer.objects.filter(cid=cid_value, question__in=casedetails)
|
||||
else:
|
||||
answers = UserReportAnswer.objects.filter(user=request.user, question__in=casedetails)
|
||||
|
||||
answer_case_ids = {
|
||||
ans.question.case_id
|
||||
for ans in answers
|
||||
if (ans.answer or ans.json_answer)
|
||||
}
|
||||
|
||||
latest_reviews = (
|
||||
cid_user_exam.selfreview_set.filter(case__in=[cd.case for cd in casedetails])
|
||||
.select_related("case")
|
||||
.order_by("case_id", "-review_update_date")
|
||||
)
|
||||
|
||||
latest_review_by_case = {}
|
||||
for review in latest_reviews:
|
||||
if review.case_id not in latest_review_by_case:
|
||||
latest_review_by_case[review.case_id] = review
|
||||
|
||||
jump_items = []
|
||||
for idx, cd in enumerate(casedetails):
|
||||
if cid is not None:
|
||||
case_url = reverse(
|
||||
"atlas:collection_case_view_take",
|
||||
kwargs={"pk": collection.pk, "case_number": idx, "cid": cid, "passcode": passcode},
|
||||
)
|
||||
answer_url = case_url
|
||||
else:
|
||||
case_url = reverse(
|
||||
"atlas:collection_case_view_take_user",
|
||||
kwargs={"pk": collection.pk, "case_number": idx},
|
||||
)
|
||||
answer_url = reverse(
|
||||
"atlas:collection_case_view_take_user_answers",
|
||||
kwargs={"pk": collection.pk, "case_number": idx},
|
||||
)
|
||||
|
||||
add_url = reverse(
|
||||
"atlas:add_self_review",
|
||||
kwargs={"user_exam_id": cid_user_exam.id, "case_id": cd.case_id},
|
||||
)
|
||||
|
||||
review = latest_review_by_case.get(cd.case_id)
|
||||
review_view_url = None
|
||||
review_edit_url = None
|
||||
if review is not None:
|
||||
review_view_url = reverse(
|
||||
"atlas:self_review_detail",
|
||||
kwargs={"user_exam_id": cid_user_exam.id, "case_id": cd.case_id, "pk": review.id},
|
||||
)
|
||||
review_edit_url = reverse(
|
||||
"atlas:self_review_update",
|
||||
kwargs={"user_exam_id": cid_user_exam.id, "case_id": cd.case_id, "pk": review.id},
|
||||
)
|
||||
|
||||
jump_items.append(
|
||||
{
|
||||
"idx": idx,
|
||||
"cd": cd,
|
||||
"case_url": case_url,
|
||||
"answer_url": answer_url,
|
||||
"self_review_add_url": add_url,
|
||||
"self_review_view_url": review_view_url,
|
||||
"self_review_edit_url": review_edit_url,
|
||||
"has_answer": cd.case_id in answer_case_ids,
|
||||
"has_self_review": review is not None,
|
||||
}
|
||||
)
|
||||
|
||||
html = render_to_string(
|
||||
'atlas/partials/_collection_case_jump.html',
|
||||
{
|
||||
'collection': collection,
|
||||
'casedetails': casedetails,
|
||||
'jump_items': jump_items,
|
||||
'current': current,
|
||||
'cid': cid,
|
||||
'passcode': passcode,
|
||||
@@ -5644,6 +5727,37 @@ class SelfReviewDelete(DeleteView):
|
||||
return self.user_exam.exam.get_case_take_url(self.case)
|
||||
|
||||
|
||||
class SelfReviewDetail(DetailView):
|
||||
"""Read-only self-review view for a specific user exam and case.
|
||||
|
||||
This is the default viewing mode for self reviews. Add ``?embed=1`` to
|
||||
render the compact sidebar-friendly template.
|
||||
"""
|
||||
|
||||
model = SelfReview
|
||||
|
||||
def get_template_names(self):
|
||||
if self.request.GET.get("embed") == "1":
|
||||
return ["atlas/partials/_selfreview_detail_embed.html"]
|
||||
return ["atlas/selfreview_detail.html"]
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
return get_object_or_404(
|
||||
SelfReview,
|
||||
pk=self.kwargs["pk"],
|
||||
user_exam_id=self.kwargs["user_exam_id"],
|
||||
case_id=self.kwargs["case_id"],
|
||||
)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(SelfReviewDetail, self).get_context_data(**kwargs)
|
||||
context["review"] = self.object
|
||||
context["user_exam"] = self.object.user_exam
|
||||
context["case"] = self.object.case
|
||||
context["embed"] = self.request.GET.get("embed") == "1"
|
||||
return context
|
||||
|
||||
|
||||
class SelfReviewUpdate(UpdateView):
|
||||
"""Edit an existing self-review entry for a case attempt.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user