Add modal for viewing display set details and update URLs and views

This commit is contained in:
Ross
2026-02-08 22:42:14 +00:00
parent 1eeb0d89d9
commit bdb7b653b6
4 changed files with 120 additions and 0 deletions
@@ -373,6 +373,7 @@
{% endif %}
<span>
<a href="{% url 'atlas:case_displaysets_detail' ds.pk %}">View Display Set</a>
<button type="button" class="btn btn-secondary btn-sm view-displayset-modal ms-2" data-ds-id="{{ ds.pk }}" data-url="{% url 'atlas:case_displaysets_modal' ds.pk %}">View in Modal</button>
</span>
<div>
<strong>Findings:</strong>
@@ -493,6 +494,22 @@
{% include 'question_notes.html' %}
</div>
<div class="modal fade" id="displaysetModal" tabindex="-1" aria-labelledby="displaysetModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="displaysetModalLabel">Display Set Details</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body" id="displaysetModalBody">
<p>Loading...</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<p><b>Checked by:</b> {% for verified in case.verified.all %} <a
href="{% url 'atlas:verified_detail' pk=verified.pk %}">{{verified}}</a>, {% endfor %}</p>
@@ -773,6 +790,30 @@
});
});
// Display Set modal handler
const dsModal = new bootstrap.Modal(document.getElementById("displaysetModal"));
const dsModalBody = document.getElementById("displaysetModalBody");
document.querySelectorAll(".view-displayset-modal").forEach(button => {
button.addEventListener("click", function () {
const url = this.getAttribute("data-url");
dsModalBody.innerHTML = "<p>Loading...</p>";
fetch(url)
.then(response => response.text())
.then(html => {
dsModalBody.innerHTML = html;
setTimeout(function () {
try { window.mountDicomViewers(); } catch (e) { console.warn('mountDicomViewers not available', e); }
}, 200);
})
.catch(error => {
console.error("Error loading display set details:", error);
dsModalBody.innerHTML = "<p>Failed to load display set.</p>";
});
dsModal.show();
});
});
});
@@ -0,0 +1,71 @@
<div class="case-displayset-modal">
<div class="mb-3">
<h5>{{ ds.name }}</h5>
{% if ds.description %}
<div class="text-muted">{{ ds.description }}</div>
{% endif %}
</div>
{% if ds.viewerstate and ds.annotations %}
<div class="mb-3">
<button
type="button"
class="btn btn-primary"
onclick='importAnnotations_main_viewer({{ ds.annotations|safe }}); importViewerState_main_viewer({{ ds.viewerstate|safe }});'
>Load into viewer</button>
</div>
{% endif %}
<div class="mt-2">
<strong>Findings:</strong>
{% if ds.findings.all %}
<ul>
{% for finding in ds.findings.all %}
<li>{{ finding }}</li>
{% endfor %}
</ul>
{% else %}
<span class="text-muted">None</span>
{% endif %}
</div>
<div>
<strong>Structures:</strong>
{% if ds.structures.all %}
<ul>
{% for structure in ds.structures.all %}
<li>{{ structure }}</li>
{% endfor %}
</ul>
{% else %}
<span class="text-muted">None</span>
{% endif %}
</div>
<div>
<strong>Conditions:</strong>
{% if ds.conditions.all %}
<ul>
{% for condition in ds.conditions.all %}
<li>{{ condition }}</li>
{% endfor %}
</ul>
{% else %}
<span class="text-muted">None</span>
{% endif %}
</div>
<div class="mt-3">
<details>
<summary class="small text-muted" style="cursor:pointer;">Show advanced (viewer state & annotations)</summary>
<div>
<strong>Viewer State:</strong>
<pre class="small">{{ ds.viewerstate|default:"{}" }}</pre>
</div>
<div>
<strong>Annotations:</strong>
<pre class="small">{{ ds.annotations|default:"{}" }}</pre>
</div>
</details>
</div>
</div>
+1
View File
@@ -380,6 +380,7 @@ urlpatterns = [
path("case/<int:pk>/display_sets/add", views.case_displaysets_add, name="case_displaysets_add"),
path("<int:pk>/display_sets/edit", views.case_displaysets_edit, name="case_displaysets_edit"),
path("<int:pk>/display_sets/detail", views.case_displaysets_detail, name="case_displaysets_detail"),
path("<int:pk>/display_sets/modal", views.case_displaysets_modal, name="case_displaysets_modal"),
path("<int:pk>/display_sets/delete", views.case_displaysets_delete, name="case_displaysets_delete"),
path(
"case/<int:pk>/dicom_json",
+7
View File
@@ -540,6 +540,13 @@ def case_displaysets_detail(request, pk):
# Redirect to the case_displaysets page with ?displayset=<pk>
return redirect(f"{reverse('atlas:case_displaysets', args=[case.pk])}?displayset={pk}")
@login_required
def case_displaysets_modal(request, pk):
"""Return HTML fragment for a CaseDisplaySet to be shown inside a modal."""
displayset = get_object_or_404(CaseDisplaySet, pk=pk)
return render(request, 'atlas/case_displayset_modal.html', {'ds': displayset})
def case_displaysets_delete(request, pk):
try:
displayset = CaseDisplaySet.objects.get(pk=pk)