Refactor case management links and add case list item partial for improved organization and rendering in collection detail view

This commit is contained in:
Ross
2025-11-16 22:51:22 +00:00
parent c02a46fab1
commit 875744a08a
5 changed files with 87 additions and 83 deletions
@@ -1,6 +1,6 @@
<span id="add-case-form"> <span id="add-case-form">
This form allows you to add an existing case to the collection. You may find it easier to do this from the individual case pages or the <a href="{% url 'atlas:case_view' %}">case overview view</a> which allows you to add multiple cases at once. This form allows you to add an existing case to the collection. You may find it easier to do this from the individual case pages or the <a href="{% url 'atlas:case_view' %}">case overview view</a> which allows you to add multiple cases at once.
<form hx-post="{% url 'atlas:add_case_to_collection' collection.id %}" hx-swap="outerHTML"> <form hx-post="{% url 'atlas:add_case_to_collection' collection.id %}" hx-target="#full-question-list" hx-swap="beforeend">
{% csrf_token %} {% csrf_token %}
<label for="case">Select Case to add:</label> <label for="case">Select Case to add:</label>
<select name="case" id="case"> <select name="case" id="case">
@@ -11,4 +11,4 @@
<button type="submit">Add</button> <button type="submit">Add</button>
<button _="on click remove #add-case-form">Cancel</button> <button _="on click remove #add-case-form">Cancel</button>
</form> </form>
</span </span>
+4 -57
View File
@@ -5,39 +5,7 @@
{% partialdef casedetails-management-links %} {% partialdef casedetails-management-links %}
<div class="btn-toolbar" role="toolbar" aria-label="Case management links"> <div class="btn-toolbar" role="toolbar" aria-label="Case management links">
<div class="btn-group btn-group-sm me-2" role="group" aria-label="management-actions"> {% include 'atlas/partials/casedetails_management_links.html' %}
<a class="btn btn-outline-secondary" href="{% url 'atlas:collection_case_displaysetup' casedetail.collection.pk casedetail.case.pk %}" title="Setup default display">
<i class="bi bi-display"></i>
</a>
<a class="btn btn-outline-secondary" href="{% url 'atlas:collection_case_details' casedetail.collection.pk casedetail.case.pk %}" title="Case details">
<i class="bi bi-info-square"></i>
</a>
{% if collection.collection_type == "QUE" %}
<a class="btn btn-outline-secondary" href='{% url "atlas:collection_case_questions" casedetail.collection.pk casedetail.case.pk %}' title="Manage questions">
{% if casedetail.question_schema %}
<i class="bi bi-question-square text-success"></i>
{% else %}
<i class="bi bi-question-square text-danger"></i>
{% endif %}
</a>
{% endif %}
{% if casedetail.case.previous_case %}
<a class="btn btn-outline-secondary" href='{% url "atlas:collection_case_priors" casedetail.collection.pk casedetail.case.pk %}' title="Manage priors">
<i class="bi bi-link-45deg"></i>
</a>
{% endif %}
</div>
<div class="btn-group btn-group-sm" role="group" aria-label="status-indicator">
{% if casedetail.default_viewerstate %}
<button type="button" class="btn btn-sm btn-outline-success" aria-disabled="true" title="This case has a default viewerstate defined">
<i class="bi bi-check"></i>
</button>
{% endif %}
</div>
</div> </div>
{% endpartialdef %} {% endpartialdef %}
@@ -122,32 +90,11 @@
<div class="col-12"> <div class="col-12">
<h3 class="mb-3">Cases</h3> <h3 class="mb-3">Cases</h3>
<div class="list-group sortable" id="full-question-list"> <ol id="full-question-list" class="sortable list-group list-group-numbered">
{% for casedetail in casesdetails %} {% for casedetail in casesdetails %}
<div class="list-group-item list-group-item-action mb-2 p-3 d-flex justify-content-between align-items-start" data-question_pk={{ casedetail.case.pk }}> {% include 'atlas/partials/case_list_item.html' %}
<div>
<div class="fw-bold">
<a href="{% url 'atlas:collection_case_view' pk=collection.pk case_number=forloop.counter0 %}">Case {{ forloop.counter }}</a>
<span class="ms-2">{{ casedetail.case.title }}</span>
</div>
<div class="small text-muted mt-1">
{% if casedetail.case.series.count == 0 %}
<span class="text-warning">No series attached</span>
{% else %}
{{ casedetail.case.series.count }} series
{% endif %}
{% if casedetail.question_schema %}
&nbsp;&nbsp;<span class="text-success">Questions defined</span>
{% endif %}
</div>
</div>
<div class="ms-3 d-flex align-items-center">
{% partial casedetails-management-links %}
</div>
</div>
{% endfor %} {% endfor %}
</div> </ol>
</div> </div>
</div> </div>
@@ -0,0 +1,27 @@
<li class="list-group-item d-flex gap-3 align-items-start" data-question_pk="{{ casedetail.case.pk }}">
<div class="flex-fill">
<div class="d-flex justify-content-between align-items-start">
<div>
<a class="h6 mb-0 text-decoration-none" href="{% url 'atlas:collection_case_view' pk=collection.pk case_number=forloop.counter0 %}">{{ casedetail.case.title }}</a>
<div class="small text-muted">Case {{ forloop.counter }} &mdash; <span class="text-truncate">{{ casedetail.case.description|default_if_none:""|truncatechars:80 }}</span></div>
</div>
</div>
<div class="mt-2 small text-muted">
{% if casedetail.case.series.count == 0 %}
<span class="text-warning">No series attached</span>
{% else %}
{{ casedetail.case.series.count }} series
{% endif %}
{% if casedetail.question_schema %}
&nbsp;&nbsp;<span class="text-success">Questions defined</span>
{% endif %}
</div>
</div>
<div class="d-flex align-items-center ms-3">
{% include 'atlas/partials/casedetails_management_links.html' %}
</div>
</li>
@@ -1,26 +1,33 @@
{# Partial: per-case management links shown on collection detail case list. <span class="btn-group btn-group-sm me-2" role="group" aria-label="management-actions">
Expects variables available from parent loop: casedetail, collection, forloop <a class="btn btn-outline-secondary" href="{% url 'atlas:collection_case_displaysetup' casedetail.collection.pk casedetail.case.pk %}" title="Setup default display">
Keep markup minimal and safe — icons use Bootstrap Icons classes if available. #} <i class="bi bi-display"></i>
<span class="d-inline-flex gap-2 align-items-center">
<a class="text-decoration-none" href="{% url 'atlas:collection_case_view' pk=collection.pk case_number=forloop.counter0 %}" title="Open case view">
<i class="bi bi-eye"></i> View
</a>
<a class="text-decoration-none" href="{% url 'atlas:case_detail' casedetail.case.pk %}" title="Case details">
<i class="bi bi-info-circle"></i> Details
</a>
{% if casedetail.case.series.count > 0 %}
<a class="text-decoration-none" href="{% url 'atlas:case_displaysets' casedetail.case.pk %}" title="Series ({{ casedetail.case.series.count }})">
<i class="bi bi-images"></i> Series ({{ casedetail.case.series.count }})
</a> </a>
{% else %}
<span class="text-muted small">No series</span>
{% endif %}
{% if can_edit %} <a class="btn btn-outline-secondary" href="{% url 'atlas:collection_case_details' casedetail.collection.pk casedetail.case.pk %}" title="Case details">
<a class="text-decoration-none" href="{% url 'atlas:case_series_update' pk=casedetail.case.pk %}" title="Edit case series"> <i class="bi bi-info-square"></i>
<i class="bi bi-pencil-square"></i> Edit series
</a> </a>
{% endif %}
</span> {% if collection.collection_type == "QUE" %}
<a class="btn btn-outline-secondary" href='{% url "atlas:collection_case_questions" casedetail.collection.pk casedetail.case.pk %}' title="Manage questions">
{% if casedetail.question_schema %}
<i class="bi bi-question-square text-success"></i>
{% else %}
<i class="bi bi-question-square text-danger"></i>
{% endif %}
</a>
{% endif %}
{% if casedetail.case.previous_case %}
<a class="btn btn-outline-secondary" href='{% url "atlas:collection_case_priors" casedetail.collection.pk casedetail.case.pk %}' title="Manage priors">
<i class="bi bi-link-45deg"></i>
</a>
{% endif %}
</div>
<div class="btn-group btn-group-sm" role="group" aria-label="status-indicator">
{% if casedetail.default_viewerstate %}
<button type="button" class="btn btn-sm btn-outline-success" aria-disabled="true" title="This case has a default viewerstate defined">
<i class="bi bi-check"></i>
</button>
{% endif %}
</span>
+24 -1
View File
@@ -1151,7 +1151,25 @@ def add_case_to_collection(request, collection_id):
print(case) print(case)
collection.add_case(case) collection.add_case(case)
return HttpResponse(f"Case added to collection {collection.name} (refresh to see)") # Render the new case list item and return it so HTMX can append it
try:
casedetail = collection.casedetail_set.get(case=case)
except Exception:
return HttpResponse("Case added, but could not render item.")
total = collection.casedetail_set.count()
can_edit = request.user.is_superuser or collection.author.filter(pk=request.user.pk).exists()
rendered = render_to_string(
"atlas/partials/case_list_item.html",
{
"casedetail": casedetail,
"collection": collection,
"forloop": {"counter": total, "counter0": max(0, total - 1)},
"can_edit": can_edit,
},
request=request,
)
return HttpResponse(rendered)
# if request.method == "POST": # if request.method == "POST":
@@ -4215,6 +4233,11 @@ def remove_case_from_collection(request, case_pk, collection_pk):
# Remove the case from the collection # Remove the case from the collection
collection.cases.remove(case) collection.cases.remove(case)
# If this was an HTMX request, return an empty response so the caller
# can swap out (remove) the surrounding element (e.g., the <li>).
if request.htmx:
return HttpResponse("")
return HttpResponse(f"Case removed from collection: {collection.name}") return HttpResponse(f"Case removed from collection: {collection.name}")