Add case selection modal for importing series into existing cases

This commit is contained in:
Ross
2026-03-02 11:42:25 +00:00
parent ed3bd3433b
commit 4e6f72e045
+98
View File
@@ -130,6 +130,7 @@
type="button"
class="btn btn-primary"
>Import {% if case %}into case{% endif %}</button>
<button id="import-into-case-button" type="button" class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#caseSelectModal">Import into case…</button>
</div>
<div id="import-status"></div>
@@ -167,7 +168,104 @@
</div>
</div>
<!-- Case select modal for importing into an existing case -->
<div class="modal fade" id="caseSelectModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Import into case</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-2">
<label for="case-search-input-modal" class="form-label">Search cases</label>
<input id="case-search-input-modal" name="q" class="form-control" type="search"
placeholder="Type to search cases..."
hx-get="{% url 'atlas:case_search' %}"
hx-include="#case-search-input-modal"
hx-target="#case-search-results-modal"
hx-trigger="keyup changed delay:400ms"
autocomplete="off">
</div>
<div id="case-search-results-modal" class="mt-2">
<!-- initial empty state; results will be loaded by HTMX -->
<div class="text-muted small">Type to search cases to import into.</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<script>
// Handle selecting a case from the modal results to import selected series into it
document.body.addEventListener('click', async function (e) {
// Only handle clicks inside the case select modal results
const anchor = e.target.closest('#case-search-results-modal .list-group-item, #case-search-results-modal .list-group-item-action');
if (!anchor) return;
e.preventDefault();
// Determine case pk: prefer data-case-pk, else parse from href
let casePk = anchor.getAttribute('data-case-pk');
if (!casePk) {
const href = anchor.getAttribute('href') || '';
const m = href.match(/case\/(\d+)\/?$/);
if (m) casePk = m[1];
}
if (!casePk) {
console.error('Could not determine case id for import');
return;
}
// Gather selected series (same logic as import button)
const selected = Array.from(document.querySelectorAll('input[name="selection"]:checked'))
.filter(cb => !cb.disabled)
.map(cb => cb.value);
const allCheckboxes = Array.from(document.querySelectorAll('input[name="selection"]'));
const selectable = allCheckboxes.filter(cb => !cb.disabled).map(cb => cb.value);
const selection = selected.length ? selected : selectable;
if (!selection.length) {
alert('Please select at least one series to import into the case.');
return;
}
// Build import URL template and replace trailing 0 with casePk
const importTemplate = "{% url 'api-1:import_dicoms_case' 0 %}";
const importUrl = importTemplate.replace(/0\/?$/, casePk + '/');
const form = new URLSearchParams();
for (const s of selection) form.append('selection', s);
const orderSeriesInput = document.querySelector('input[name="order-series"]:checked');
if (orderSeriesInput) form.append('order-series', orderSeriesInput.value);
const csrfToken = '{{ csrf_token }}';
try {
const resp = await fetch(importUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-CSRFToken': csrfToken,
},
body: form.toString(),
credentials: 'same-origin'
});
const text = await resp.text();
// Close modal and show result in import-status
const modalEl = document.getElementById('caseSelectModal');
if (modalEl && window.bootstrap && bootstrap.Modal) {
bootstrap.Modal.getInstance(modalEl)?.hide();
}
const statusDiv = document.getElementById('import-status');
if (statusDiv) statusDiv.innerHTML = `<div>Imported into case ${casePk}: ${text}</div>`;
// Optionally reload to reflect imported state
setTimeout(function(){ location.reload(); }, 1200);
} catch (err) {
console.error('Import into case failed', err);
alert('Import failed — check console for details.');
}
});
// Update the selected count shown beside action buttons
function updateSelectionCount() {
const all = Array.from(document.querySelectorAll('input[name="selection"]'));