Refactor case prior display: extract prior card markup into a separate partial for improved maintainability and readability
This commit is contained in:
@@ -38,73 +38,7 @@
|
|||||||
|
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
{% for case, added, relation, visibility in available_priors %}
|
{% for case, added, relation, visibility in available_priors %}
|
||||||
<div class="col-12 col-md-6 col-lg-4" data-case="{{case.id}}">
|
{% include 'atlas/partials/_prior_card.html' with case=case added=added relation=relation visibility=visibility case_detail=case_detail collection=collection %}
|
||||||
<div class="card h-100 shadow-sm {% if added %}border-success{% else %}border-secondary{% endif %}">
|
|
||||||
<div class="card-body d-flex flex-column">
|
|
||||||
<div class="d-flex justify-content-between align-items-start mb-2">
|
|
||||||
<h5 class="card-title mb-0">{{case.title}}</h5>
|
|
||||||
<div>
|
|
||||||
{% if added %}
|
|
||||||
<span class="badge bg-success">Added</span>
|
|
||||||
{% else %}
|
|
||||||
<span class="badge bg-secondary">Available</span>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p class="card-text small text-muted mb-2">Relation: <span class="fw-medium">{{ relation }}</span></p>
|
|
||||||
|
|
||||||
<div class="mb-3 small">{{case.get_series_blocks|safe}}</div>
|
|
||||||
|
|
||||||
<div class="mt-auto">
|
|
||||||
<div class="d-flex gap-2 mb-2">
|
|
||||||
<a href="{% url 'atlas:case_detail' case.id %}" class="btn btn-sm btn-outline-primary">View case</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% if not added %}
|
|
||||||
<form class="row g-2" hx-post="{% url 'atlas:collection_case_priors' collection.id case_detail.case.pk %}"
|
|
||||||
hx-target="#htmx-response-{{case.id}}">
|
|
||||||
{% csrf_token %}
|
|
||||||
<input type="hidden" name="prior_case_id" value="{{case.id}}" />
|
|
||||||
<div class="col-12">
|
|
||||||
<input class="form-control form-control-sm" type="text" name="relation" value="{{relation}}" placeholder="Relation to case" />
|
|
||||||
</div>
|
|
||||||
<div class="col-8">
|
|
||||||
<select class="form-select form-select-sm" name="prior_visibility" id="prior_visibility_{{case.id}}">
|
|
||||||
<option value="AL" {% if visibility == 'AL' %}selected{% endif %}>Always</option>
|
|
||||||
<option value="RE" {% if visibility == 'RE' %}selected{% endif %}>Review</option>
|
|
||||||
<option value="NO" {% if visibility == 'NO' %}selected{% endif %}>None</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-4 d-grid">
|
|
||||||
<button class="btn btn-sm btn-primary" type="submit">Add</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{% else %}
|
|
||||||
<form hx-post="{% url 'atlas:collection_case_priors' collection.id case_detail.case.pk %}"
|
|
||||||
hx-target="#htmx-response-{{case.id}}">
|
|
||||||
{% csrf_token %}
|
|
||||||
<input type="hidden" name="remove" value="{{case.id}}" />
|
|
||||||
<div class="mb-2 small text-muted">Current relation: <strong>{{relation}}</strong></div>
|
|
||||||
<div class="d-flex gap-2">
|
|
||||||
<select class="form-select form-select-sm w-50" name="prior_visibility" id="prior_visibility_{{case.id}}" disabled>
|
|
||||||
<option value="AL" {% if visibility == 'AL' %}selected{% endif %}>Always</option>
|
|
||||||
<option value="RE" {% if visibility == 'RE' %}selected{% endif %}>Review</option>
|
|
||||||
<option value="NO" {% if visibility == 'NO' %}selected{% endif %}>None</option>
|
|
||||||
</select>
|
|
||||||
<button class="btn btn-sm btn-danger" type="submit">Remove</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card-footer bg-transparent">
|
|
||||||
<span id="htmx-response-{{case.id}}" class="small"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
<div id="prior-card-{{case.id}}" class="col-12 col-md-6 col-lg-4" data-case="{{case.id}}">
|
||||||
|
<div class="card h-100 shadow-sm {% if added %}border-success{% else %}border-secondary{% endif %}">
|
||||||
|
<div class="card-body d-flex flex-column">
|
||||||
|
<div class="d-flex justify-content-between align-items-start mb-2">
|
||||||
|
<h5 class="card-title mb-0">{{case.title}}</h5>
|
||||||
|
<div>
|
||||||
|
{% if added %}
|
||||||
|
<span class="badge bg-success">Added</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="badge bg-secondary">Available</span>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="card-text small text-muted mb-2">Relation: <span class="fw-medium">{{ relation }}</span></p>
|
||||||
|
|
||||||
|
<div class="mb-3 small">{{case.get_series_blocks|safe}}</div>
|
||||||
|
|
||||||
|
<div class="mt-auto">
|
||||||
|
<div class="d-flex gap-2 mb-2">
|
||||||
|
<a href="{% url 'atlas:case_detail' case.id %}" class="btn btn-sm btn-outline-primary">View case</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if not added %}
|
||||||
|
<form class="row g-2" hx-post="{% url 'atlas:collection_case_priors' collection.id case_detail.case.pk %}"
|
||||||
|
hx-target="#prior-card-{{case.id}}" hx-swap="outerHTML">
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="hidden" name="prior_case_id" value="{{case.id}}" />
|
||||||
|
<div class="col-12">
|
||||||
|
<input class="form-control form-control-sm" type="text" name="relation" value="{{relation}}" placeholder="Relation to case" />
|
||||||
|
</div>
|
||||||
|
<div class="col-8">
|
||||||
|
<select class="form-select form-select-sm" name="prior_visibility" id="prior_visibility_{{case.id}}">
|
||||||
|
<option value="AL" {% if visibility == 'AL' %}selected{% endif %}>Always</option>
|
||||||
|
<option value="RE" {% if visibility == 'RE' %}selected{% endif %}>Review</option>
|
||||||
|
<option value="NO" {% if visibility == 'NO' %}selected{% endif %}>None</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-4 d-grid">
|
||||||
|
<button class="btn btn-sm btn-primary" type="submit">Add</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% else %}
|
||||||
|
<form hx-post="{% url 'atlas:collection_case_priors' collection.id case_detail.case.pk %}"
|
||||||
|
hx-target="#prior-card-{{case.id}}" hx-swap="outerHTML">
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="hidden" name="remove" value="{{case.id}}" />
|
||||||
|
<div class="mb-2 small text-muted">Current relation: <strong>{{relation}}</strong></div>
|
||||||
|
<div class="d-flex gap-2">
|
||||||
|
<select class="form-select form-select-sm w-50" name="prior_visibility" id="prior_visibility_{{case.id}}" disabled>
|
||||||
|
<option value="AL" {% if visibility == 'AL' %}selected{% endif %}>Always</option>
|
||||||
|
<option value="RE" {% if visibility == 'RE' %}selected{% endif %}>Review</option>
|
||||||
|
<option value="NO" {% if visibility == 'NO' %}selected{% endif %}>None</option>
|
||||||
|
</select>
|
||||||
|
<button class="btn btn-sm btn-danger" type="submit">Remove</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-footer bg-transparent">
|
||||||
|
<small class="text-muted">Case ID: {{ case.id }}</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
+51
-13
@@ -2758,33 +2758,71 @@ def collection_take_start(request, pk, cid=None, passcode=None):
|
|||||||
@user_is_collection_author_or_atlas_editor
|
@user_is_collection_author_or_atlas_editor
|
||||||
def collection_case_priors(request, exam_id, case_id):
|
def collection_case_priors(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)
|
||||||
|
collection = case_detail.collection
|
||||||
|
|
||||||
if request.htmx:
|
if request.htmx:
|
||||||
|
# Ensure we can render the updated single-card partial and return it so HTMX
|
||||||
|
# can swap the card on the client side.
|
||||||
if "remove" in request.POST:
|
if "remove" in request.POST:
|
||||||
p = CasePrior.objects.get(
|
prior_pk = request.POST["remove"]
|
||||||
case_detail=case_detail, prior_case=request.POST["remove"]
|
try:
|
||||||
|
p = CasePrior.objects.get(case_detail=case_detail, prior_case=prior_pk)
|
||||||
|
p.delete()
|
||||||
|
except CasePrior.DoesNotExist:
|
||||||
|
# Already removed; continue and render the not-added card
|
||||||
|
pass
|
||||||
|
|
||||||
|
prior_case = Case.objects.get(pk=prior_pk)
|
||||||
|
added = False
|
||||||
|
relation = ""
|
||||||
|
visibility = "AL"
|
||||||
|
|
||||||
|
html = render_to_string(
|
||||||
|
"atlas/partials/_prior_card.html",
|
||||||
|
{
|
||||||
|
"case": prior_case,
|
||||||
|
"added": added,
|
||||||
|
"relation": relation,
|
||||||
|
"visibility": visibility,
|
||||||
|
"case_detail": case_detail,
|
||||||
|
"collection": collection,
|
||||||
|
},
|
||||||
|
request=request,
|
||||||
)
|
)
|
||||||
p.delete()
|
return HttpResponse(html)
|
||||||
return HttpResponse(f"Case removed")
|
|
||||||
elif "prior_case_id" in request.POST:
|
elif "prior_case_id" in request.POST:
|
||||||
if not request.POST["relation"]:
|
if not request.POST.get("relation"):
|
||||||
return HttpResponse(
|
return HttpResponse(
|
||||||
"You need to enter text to describe the relationship between the cases"
|
"You need to enter text to describe the relationship between the cases",
|
||||||
|
status=400,
|
||||||
)
|
)
|
||||||
prior_case = Case.objects.get(pk=request.POST["prior_case_id"])
|
prior_case = Case.objects.get(pk=request.POST["prior_case_id"])
|
||||||
p, created = CasePrior.objects.get_or_create(
|
p, created = CasePrior.objects.get_or_create(
|
||||||
case_detail=case_detail, prior_case=prior_case
|
case_detail=case_detail, prior_case=prior_case
|
||||||
)
|
)
|
||||||
p.relation_text = request.POST["relation"]
|
p.relation_text = request.POST.get("relation", "")
|
||||||
|
p.prior_visibility = request.POST.get("prior_visibility", "AL")
|
||||||
p.prior_visibility = request.POST["prior_visibility"]
|
|
||||||
|
|
||||||
p.save()
|
p.save()
|
||||||
|
|
||||||
return HttpResponse(f"Case added")
|
added = True
|
||||||
|
relation = p.relation_text
|
||||||
|
visibility = p.prior_visibility
|
||||||
|
|
||||||
|
html = render_to_string(
|
||||||
|
"atlas/partials/_prior_card.html",
|
||||||
|
{
|
||||||
|
"case": prior_case,
|
||||||
|
"added": added,
|
||||||
|
"relation": relation,
|
||||||
|
"visibility": visibility,
|
||||||
|
"case_detail": case_detail,
|
||||||
|
"collection": collection,
|
||||||
|
},
|
||||||
|
request=request,
|
||||||
|
)
|
||||||
|
return HttpResponse(html)
|
||||||
else:
|
else:
|
||||||
return HttpResponse("False")
|
return HttpResponse("False", status=400)
|
||||||
raise Http404()
|
|
||||||
|
|
||||||
collection = case_detail.collection
|
collection = case_detail.collection
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user