diff --git a/atlas/static/atlas/js/markup_inserter.js b/atlas/static/atlas/js/markup_inserter.js index 97edf4d5..ab974670 100644 --- a/atlas/static/atlas/js/markup_inserter.js +++ b/atlas/static/atlas/js/markup_inserter.js @@ -39,12 +39,15 @@ toolbar.querySelectorAll('.markup-insert-button').forEach(function(btn){ btn.addEventListener('click', function(){ const t = btn.dataset.type; + // determine a sensible default case id from the DOM context + const detected = detectCurrentCase(textarea); + const detectedCase = detected && detected.id ? detected.id : null; if(t === 'case'){ openCasePicker(textarea); } else if(t === 'finding'){ - openFindingPicker(textarea); + openFindingPicker(textarea, detectedCase); } else if(t === 'displayset'){ - openDisplaysetPicker(textarea); + openDisplaysetPicker(textarea, detectedCase); } }); }); @@ -195,6 +198,11 @@ Object.assign(overlay.style, {position:'fixed',left:0,top:0,right:0,bottom:0,background:'rgba(0,0,0,0.4)',zIndex:1050,display:'flex',alignItems:'center',justifyContent:'center'}); const dialog = document.createElement('div'); dialog.className='markup-case-picker-dialog card'; Object.assign(dialog.style, {width:'min(900px,95%)',maxHeight:'80vh',overflow:'auto'}); const header = document.createElement('div'); header.className='card-header d-flex justify-content-between align-items-center'; header.innerHTML = 'Select finding'; + var detectedF = detectCurrentCase(textarea); + if(detectedF && detectedF.id){ + var badgeF = document.createElement('span'); badgeF.className = 'badge bg-secondary ms-2'; badgeF.style.marginLeft='8px'; badgeF.textContent = 'Filtering: ' + (detectedF.title || ('#'+detectedF.id)); + header.appendChild(badgeF); + } const closeBtn = document.createElement('button'); closeBtn.type='button'; closeBtn.className='btn-close'; closeBtn.setAttribute('aria-label','Close'); closeBtn.addEventListener('click', function(){ document.body.removeChild(overlay); }); header.appendChild(closeBtn); const body = document.createElement('div'); body.className='card-body'; const input = document.createElement('input'); input.type='search'; input.className='form-control mb-2'; input.placeholder='Type to search findings...'; @@ -205,7 +213,9 @@ input.addEventListener('input', function(){ if(timer) clearTimeout(timer); timer = setTimeout(function(){ var q = encodeURIComponent(input.value || ''); var url = window.location.origin + '/atlas/search/findings/?q=' + q + (caseId ? '&case=' + caseId : ''); fetch(url, {credentials:'same-origin'}).then(function(r){ return r.text(); }).then(function(html){ results.innerHTML = html; }).catch(function(e){ console.error('finding picker fetch error', e); results.innerHTML = '
Search failed
'; }); }, 300); }); results.addEventListener('click', function(e){ var item = e.target.closest('.list-group-item'); if(!item) return; var pk = item.getAttribute('data-finding-pk'); if(!pk) return; insertAtCursor(textarea, '[['+'finding:'+pk+']]' ); if(overlay && overlay.parentNode) overlay.parentNode.removeChild(overlay); }); - overlay.tabIndex = -1; overlay.focus(); fetch(window.location.origin + '/atlas/search/findings/').then(function(r){ return r.text(); }).then(function(html){ results.innerHTML = html; }).catch(function(){}); + overlay.tabIndex = -1; overlay.focus(); + var initFindingsUrl = window.location.origin + '/atlas/search/findings/' + (caseId ? '?case=' + caseId : ''); + fetch(initFindingsUrl).then(function(r){ return r.text(); }).then(function(html){ results.innerHTML = html; }).catch(function(){}); }catch(err){ console.error('openFindingPicker error', err); } } @@ -216,7 +226,14 @@ overlay.className = 'markup-case-picker-overlay'; Object.assign(overlay.style, {position:'fixed',left:0,top:0,right:0,bottom:0,background:'rgba(0,0,0,0.4)',zIndex:1050,display:'flex',alignItems:'center',justifyContent:'center'}); const dialog = document.createElement('div'); dialog.className='markup-case-picker-dialog card'; Object.assign(dialog.style, {width:'min(900px,95%)',maxHeight:'80vh',overflow:'auto'}); - const header = document.createElement('div'); header.className='card-header d-flex justify-content-between align-items-center'; header.innerHTML = 'Select display set'; + const header = document.createElement('div'); header.className='card-header d-flex justify-content-between align-items-center'; + header.innerHTML = 'Select display set'; + // show current case filter if present + var detected = detectCurrentCase(textarea); + if(detected && detected.id){ + var badge = document.createElement('span'); badge.className = 'badge bg-secondary ms-2'; badge.style.marginLeft='8px'; badge.textContent = 'Filtering: ' + (detected.title || ('#'+detected.id)); + header.appendChild(badge); + } const closeBtn = document.createElement('button'); closeBtn.type='button'; closeBtn.className='btn-close'; closeBtn.setAttribute('aria-label','Close'); closeBtn.addEventListener('click', function(){ document.body.removeChild(overlay); }); header.appendChild(closeBtn); const body = document.createElement('div'); body.className='card-body'; const input = document.createElement('input'); input.type='search'; input.className='form-control mb-2'; input.placeholder='Type to search display sets...'; @@ -227,8 +244,64 @@ input.addEventListener('input', function(){ if(timer) clearTimeout(timer); timer = setTimeout(function(){ var q = encodeURIComponent(input.value || ''); var url = window.location.origin + '/atlas/search/displaysets/?q=' + q + (caseId ? '&case=' + caseId : ''); fetch(url, {credentials:'same-origin'}).then(function(r){ return r.text(); }).then(function(html){ results.innerHTML = html; }).catch(function(e){ console.error('displayset picker fetch error', e); results.innerHTML = '
Search failed
'; }); }, 300); }); results.addEventListener('click', function(e){ var item = e.target.closest('.list-group-item'); if(!item) return; var pk = item.getAttribute('data-ds-pk'); if(!pk) return; insertAtCursor(textarea, '[['+'displayset:'+pk+']]' ); if(overlay && overlay.parentNode) overlay.parentNode.removeChild(overlay); }); - overlay.tabIndex = -1; overlay.focus(); fetch(window.location.origin + '/atlas/search/displaysets/').then(function(r){ return r.text(); }).then(function(html){ results.innerHTML = html; }).catch(function(){}); + overlay.tabIndex = -1; overlay.focus(); + var initDisplaysetsUrl = window.location.origin + '/atlas/search/displaysets/' + (caseId ? '?case=' + caseId : ''); + fetch(initDisplaysetsUrl).then(function(r){ return r.text(); }).then(function(html){ results.innerHTML = html; }).catch(function(){}); }catch(err){ console.error('openDisplaysetPicker error', err); } } + function detectCurrentCase(contextEl){ + try{ + var result = { id: null, title: null }; + var root = contextEl && contextEl.closest ? contextEl.closest('form,body') : document; + var inp = root.querySelector('input[name="case"]') || root.querySelector('input[name="case_id"]') || document.querySelector('input[name="case"]') || document.querySelector('input[name="case_id"]'); + if(inp && inp.value) result.id = inp.value; + + // Look for explicit metadata element + var meta = document.querySelector('#current-case-meta') || document.querySelector('[data-current-case]'); + if(meta){ + if(!result.id) result.id = meta.getAttribute('data-current-case') || meta.getAttribute('data-case-pk') || meta.value || null; + result.title = meta.getAttribute('data-current-case-title') || meta.getAttribute('data-case-title') || null; + } + + // Fallback: look for ancestor attributes + if(!result.id){ + var anc = contextEl; + while(anc){ + if(anc.getAttribute && (anc.getAttribute('data-case-pk') || anc.getAttribute('data-case-id'))){ + result.id = anc.getAttribute('data-case-pk') || anc.getAttribute('data-case-id'); + break; + } + anc = anc.parentElement; + } + } + + // Fallback: check URL query string for ?case= or ?case_id= + if(!result.id){ + try{ + var params = new URLSearchParams(window.location.search); + if(params.has('case')) result.id = params.get('case'); + else if(params.has('case_id')) result.id = params.get('case_id'); + }catch(e){} + } + + // Fallback: try to parse a /case// segment from the pathname + if(!result.id){ + try{ + var m = window.location.pathname.match(/\/case\/(\d+)(?:\/|$)/i) || window.location.pathname.match(/\/atlas\/case\/(\d+)(?:\/|$)/i); + if(m) result.id = m[1]; + }catch(e){} + } + + // If there's an H2 like 'Display Sets: TITLE' try to use it as title + if(!result.title){ + var h2 = document.querySelector('h2'); + if(h2 && /Display Sets:/i.test(h2.textContent || '')){ + result.title = (h2.textContent || '').replace(/Display Sets:\s*/i, '').trim(); + } + } + return result; + }catch(e){ return { id: null, title: null }; } + } + })(window); diff --git a/atlas/templates/atlas/partials/_displayset_search_results.html b/atlas/templates/atlas/partials/_displayset_search_results.html index 43eb2768..32e58ba3 100644 --- a/atlas/templates/atlas/partials/_displayset_search_results.html +++ b/atlas/templates/atlas/partials/_displayset_search_results.html @@ -4,7 +4,12 @@
- {{ ds.name }} +
+ {{ ds.name }} + {% if ds.case %} +
Case: {{ ds.case.title }} (#{% if ds.case.pk %}{{ ds.case.pk }}{% endif %})
+ {% endif %} +
{{ ds.pk }}

{{ ds.description }}

diff --git a/atlas/templates/atlas/partials/displayset_search_widget.html b/atlas/templates/atlas/partials/displayset_search_widget.html index c5211de0..bc92889d 100644 --- a/atlas/templates/atlas/partials/displayset_search_widget.html +++ b/atlas/templates/atlas/partials/displayset_search_widget.html @@ -1,4 +1,7 @@
+ {% if case %} + + {% endif %} {% with input_id=input_id|default:'displayset-search-input' target_id=target_id|default:'displayset-search-results' %}