Enhance case display sets management with HTMX integration and improved UI elements
This commit is contained in:
@@ -1,21 +1,49 @@
|
||||
{# Partial: Case Display Sets (displaysets) #}
|
||||
{# Buttons adapt at runtime: if an in-page viewer is present (importAnnotations_main_viewer), #}
|
||||
{# "View" loads the display set into it; otherwise falls back to the modal viewer. #}
|
||||
{# An Edit button is shown separately when can_edit is truthy. #}
|
||||
<div>
|
||||
<h5 class="mt-3">Case Display Sets</h5>
|
||||
<ul class="list-group">
|
||||
{% for ds in case.display_sets.all %}
|
||||
<li class="list-group-item">
|
||||
<b>Name: {{ ds.name }}</b>
|
||||
{% if ds.description %}
|
||||
<span class="text-muted">({{ ds.description }})</span>
|
||||
{% 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>
|
||||
<li class="list-group-item" id="displayset-row-{{ ds.pk }}">
|
||||
<div class="d-flex align-items-center justify-content-between flex-wrap gap-2">
|
||||
<div>
|
||||
<b>{{ ds.name }}</b>
|
||||
{% if ds.description %}
|
||||
<span class="text-muted ms-1">({{ ds.description }})</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="d-flex gap-2 flex-shrink-0">
|
||||
{% if ds.viewerstate or ds.annotations %}
|
||||
<button type="button"
|
||||
class="btn btn-primary btn-sm ds-view-btn"
|
||||
data-ds-id="{{ ds.pk }}"
|
||||
data-modal-url="{% url 'atlas:case_displaysets_modal' ds.pk %}"
|
||||
data-annotations='{{ ds.annotations|safe }}'
|
||||
data-viewerstate='{{ ds.viewerstate|safe }}'>
|
||||
<i class="bi bi-display"></i> View Display Set
|
||||
</button>
|
||||
{% endif %}
|
||||
<button type="button"
|
||||
class="btn btn-secondary btn-sm view-displayset-modal"
|
||||
data-ds-id="{{ ds.pk }}"
|
||||
data-url="{% url 'atlas:case_displaysets_modal' ds.pk %}">
|
||||
<i class="bi bi-eye"></i> View in Modal
|
||||
</button>
|
||||
{% if can_edit %}
|
||||
<a href="{% url 'atlas:case_displaysets_detail' ds.pk %}?edit=1"
|
||||
class="btn btn-outline-secondary btn-sm">
|
||||
<i class="bi bi-pencil"></i> Edit
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-2">
|
||||
<strong>Findings:</strong>
|
||||
{% if ds.findings.all %}
|
||||
<ul>
|
||||
<ul class="mb-1">
|
||||
{% for finding in ds.findings.all %}
|
||||
<li>{{ finding.get_link }}</li>
|
||||
{% endfor %}
|
||||
@@ -27,7 +55,7 @@
|
||||
<div>
|
||||
<strong>Structures:</strong>
|
||||
{% if ds.structures.all %}
|
||||
<ul>
|
||||
<ul class="mb-1">
|
||||
{% for structure in ds.structures.all %}
|
||||
<li>{{ structure.get_link }}</li>
|
||||
{% endfor %}
|
||||
@@ -39,7 +67,7 @@
|
||||
<div>
|
||||
<strong>Conditions:</strong>
|
||||
{% if ds.conditions.all %}
|
||||
<ul>
|
||||
<ul class="mb-1">
|
||||
{% for condition in ds.conditions.all %}
|
||||
<li>{{ condition.get_link }}</li>
|
||||
{% endfor %}
|
||||
@@ -48,25 +76,64 @@
|
||||
<span class="text-muted">None</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
<details>
|
||||
<summary class="small text-muted" style="cursor:pointer;">Show advanced (viewer state & annotations)</summary>
|
||||
<div>
|
||||
{% include 'atlas/partials/json_pretty.html' with json_value=ds.viewerstate title='Viewer State' %}
|
||||
</div>
|
||||
<div>
|
||||
{% include 'atlas/partials/json_pretty.html' with json_value=ds.annotations title='Annotations' %}
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
{% empty %}
|
||||
<div class="displayset-empty-state">
|
||||
<span class="text-muted">No display sets for this case.</span>
|
||||
<li class="list-group-item text-muted">
|
||||
No display sets for this case.
|
||||
{% if can_edit %}
|
||||
<a class="displayset-empty-link" href="{% url 'atlas:case_displaysets' case.pk %}">Add one now</a>
|
||||
<a href="{% url 'atlas:case_displaysets' case.pk %}">Add one now</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
/**
|
||||
* For each "View Display Set" button:
|
||||
* - If the page has an in-page viewer (importAnnotations_main_viewer available),
|
||||
* load the display set's state into it and scroll the viewer into view.
|
||||
* - Otherwise, fall back to the existing modal loader (loadDisplaysetModal).
|
||||
*/
|
||||
document.querySelectorAll('.ds-view-btn').forEach(function (btn) {
|
||||
btn.addEventListener('click', function () {
|
||||
var dsId = btn.dataset.dsId;
|
||||
var modalUrl = btn.dataset.modalUrl;
|
||||
var annotations = btn.dataset.annotations;
|
||||
var viewerstate = btn.dataset.viewerstate;
|
||||
|
||||
var hasInPageViewer = (
|
||||
typeof window.importAnnotations_main_viewer === 'function' &&
|
||||
typeof window.importViewerState_main_viewer === 'function'
|
||||
);
|
||||
|
||||
if (hasInPageViewer) {
|
||||
// Ensure viewer UI is visible before applying display set state.
|
||||
var viewerDetails = document.getElementById('dicom-viewer-details');
|
||||
if (viewerDetails && viewerDetails.tagName === 'DETAILS') {
|
||||
viewerDetails.open = true;
|
||||
}
|
||||
|
||||
try { window.importAnnotations_main_viewer(JSON.parse(annotations || '{}')); } catch (e) { console.warn('displayset annotations import error', e); }
|
||||
try { window.importViewerState_main_viewer(JSON.parse(viewerstate || '{}')); } catch (e) { console.warn('displayset viewerstate import error', e); }
|
||||
|
||||
try { window.dispatchEvent(new Event('resize')); } catch (e) {}
|
||||
if (typeof window.resizeDicomViewers === 'function') {
|
||||
try { window.resizeDicomViewers(); } catch (e) { console.warn('displayset viewer resize error', e); }
|
||||
}
|
||||
|
||||
// Scroll the viewer into view
|
||||
var viewer = document.getElementById('main_viewer') || document.querySelector('.dicom-viewer-root');
|
||||
if (viewer) { viewer.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); }
|
||||
} else if (typeof window.loadDisplaysetModal === 'function') {
|
||||
window.loadDisplaysetModal(modalUrl, dsId);
|
||||
} else {
|
||||
// Ultimate fallback: navigate to the detail page
|
||||
window.location.href = modalUrl;
|
||||
}
|
||||
});
|
||||
});
|
||||
}());
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user