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">
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 %}
<label for="case">Select Case to add:</label>
<select name="case" id="case">
@@ -11,4 +11,4 @@
<button type="submit">Add</button>
<button _="on click remove #add-case-form">Cancel</button>
</form>
</span
</span>
+4 -57
View File
@@ -5,39 +5,7 @@
{% partialdef casedetails-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">
<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>
{% include 'atlas/partials/casedetails_management_links.html' %}
</div>
{% endpartialdef %}
@@ -122,32 +90,11 @@
<div class="col-12">
<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 %}
<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 }}>
<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>
{% include 'atlas/partials/case_list_item.html' %}
{% endfor %}
</div>
</ol>
</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.
Expects variables available from parent loop: casedetail, collection, forloop
Keep markup minimal and safe — icons use Bootstrap Icons classes if available. #}
<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 }})
<span class="btn-group btn-group-sm me-2" role="group" aria-label="management-actions">
<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>
{% else %}
<span class="text-muted small">No series</span>
{% endif %}
{% if can_edit %}
<a class="text-decoration-none" href="{% url 'atlas:case_series_update' pk=casedetail.case.pk %}" title="Edit case series">
<i class="bi bi-pencil-square"></i> Edit series
<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>
{% 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)
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":
@@ -4215,6 +4233,11 @@ def remove_case_from_collection(request, case_pk, collection_pk):
# Remove the case from the collection
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}")