feat: Enhance case selection functionality with dedicated select button and improved event handling

This commit is contained in:
Ross
2026-04-27 23:07:06 +01:00
parent 585a19013a
commit 7031942198
3 changed files with 69 additions and 23 deletions
+59 -20
View File
@@ -1,4 +1,3 @@
{% load case_widgets %} {% load case_widgets %}
{% partialdef case-series %} {% partialdef case-series %}
@@ -475,6 +474,7 @@
<details class="series-move-panel border rounded p-2"> <details class="series-move-panel border rounded p-2">
<summary class="small fw-semibold">Move selected series to another case</summary> <summary class="small fw-semibold">Move selected series to another case</summary>
aaoecuthsaoehntu
{% if move_series_form %} {% if move_series_form %}
<form id="move-selected-series-form" class="d-flex flex-column gap-2 mt-2"> <form id="move-selected-series-form" class="d-flex flex-column gap-2 mt-2">
{{ move_series_form.destination_case }} {{ move_series_form.destination_case }}
@@ -498,6 +498,30 @@
if (window.__moveSeriesCaseSelectionBound) return; if (window.__moveSeriesCaseSelectionBound) return;
window.__moveSeriesCaseSelectionBound = true; window.__moveSeriesCaseSelectionBound = true;
function applyMoveCaseSelection(casePk, caseTitle) {
if (!casePk) return;
const form = document.getElementById('move-selected-series-form');
const hiddenInput = form ? form.querySelector("[name='destination_case']") : null;
const label = document.getElementById('selected-move-case');
const results = document.getElementById('move-series-case-search-results');
if (!hiddenInput) return;
hiddenInput.value = casePk;
if (label) {
label.innerHTML = 'Selected destination: <strong>' + caseTitle + ' (' + casePk + ')</strong>';
label.classList.remove('text-muted');
}
if (results) {
results.querySelectorAll('.list-group-item[data-case-pk]').forEach(function (item) {
item.classList.toggle('active', String(item.getAttribute('data-case-pk')) === String(casePk));
});
}
syncMoveSeriesSubmitState();
}
function syncMoveSeriesSubmitState() { function syncMoveSeriesSubmitState() {
const form = document.getElementById('move-selected-series-form'); const form = document.getElementById('move-selected-series-form');
const hiddenInput = form ? form.querySelector("[name='destination_case']") : null; const hiddenInput = form ? form.querySelector("[name='destination_case']") : null;
@@ -506,29 +530,44 @@
submitBtn.disabled = !hiddenInput.value; submitBtn.disabled = !hiddenInput.value;
} }
document.body.addEventListener('case:selected', async function (e) { function selectFromRow(row) {
if (!row) return;
const casePk = row.getAttribute('data-case-pk');
const caseTitleEl = row.querySelector('h6');
const caseTitle = caseTitleEl ? caseTitleEl.textContent.trim() : ('Case #' + casePk);
applyMoveCaseSelection(casePk, caseTitle);
}
// Hard fallback: capture-phase click listener scoped to this widget results.
document.addEventListener('click', function (e) {
try {
const row = e.target.closest('#move-series-case-search-results .list-group-item[data-case-pk]');
if (!row) return;
if (e.target.closest('a,button,form,input')) return;
selectFromRow(row);
} catch (err) {
console.error('Move series capture click handler error', err);
}
}, true);
// Mirror uploads-style delegated click handling directly on rows.
document.body.addEventListener('click', function (e) {
try {
const item = e.target.closest('#move-series-case-search-results .list-group-item[data-case-pk]');
if (!item) return;
if (e.target.closest('a,button,form,input')) return;
selectFromRow(item);
} catch (err) {
console.error('Move series row click handler error', err);
}
});
document.body.addEventListener('case:selected', function (e) {
try { try {
console.log('Received case:selected event', e);
const detail = e.detail || {}; const detail = e.detail || {};
const casePk = detail.casePk; const casePk = detail.casePk;
const caseTitle = detail.caseTitle || ('Case #' + casePk); const caseTitle = detail.caseTitle || ('Case #' + casePk);
if (!casePk) return; applyMoveCaseSelection(casePk, caseTitle);
// Only react to selections from this move panel's widget.
if (!e.target || !e.target.closest('#move-selected-series-form')) return;
const form = document.getElementById('move-selected-series-form');
const hiddenInput = form ? form.querySelector("[name='destination_case']") : null;
const label = document.getElementById('selected-move-case');
if (!hiddenInput) return;
hiddenInput.value = casePk;
if (label) {
label.innerHTML = 'Selected destination: <strong>' + caseTitle + ' (' + casePk + ')</strong>';
label.classList.remove('text-muted');
}
syncMoveSeriesSubmitState();
} catch (err) { } catch (err) {
console.error('Move series case:selected handler error', err); console.error('Move series case:selected handler error', err);
} }
@@ -28,7 +28,8 @@
</form> </form>
<a class="btn btn-sm btn-outline-secondary ms-2" href="{% url 'atlas:case_detail' case.pk %}" target="_blank" rel="noopener">View</a> <a class="btn btn-sm btn-outline-secondary ms-2" href="{% url 'atlas:case_detail' case.pk %}" target="_blank" rel="noopener">View</a>
{% else %} {% else %}
<a class="btn btn-sm btn-outline-secondary" href="{% url 'atlas:case_detail' case.pk %}">View</a> <button type="button" class="btn btn-sm btn-outline-primary case-select-btn" data-case-select="{{ case.pk }}">Select</button>
<a class="btn btn-sm btn-outline-secondary ms-2" href="{% url 'atlas:case_detail' case.pk %}">View</a>
{% endif %} {% endif %}
</div> </div>
</div> </div>
@@ -60,8 +60,14 @@
targetEl.addEventListener('click', function(e){ targetEl.addEventListener('click', function(e){
var item = e.target.closest('.list-group-item'); var item = e.target.closest('.list-group-item');
if (!item || !targetEl.contains(item)) return; if (!item || !targetEl.contains(item)) return;
// Ignore clicks on interactive elements inside the item (links, buttons, forms, inputs)
if (e.target.closest('a,button,form,input')) return; // Explicit select action button should always select the row.
if (e.target.closest('.case-select-btn')) {
e.preventDefault();
} else {
// Ignore other interactive elements inside the item (links, buttons, forms, inputs)
if (e.target.closest('a,button,form,input')) return;
}
var casePk = item.getAttribute('data-case-pk'); var casePk = item.getAttribute('data-case-pk');
if (!casePk) { if (!casePk) {