Enhance finding search functionality to support series findings and improve result display with badges
This commit is contained in:
@@ -209,7 +209,20 @@
|
||||
var timer = null;
|
||||
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 + (currentCaseF ? '&case=' + currentCaseF : ''); 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 = '<div class="alert alert-danger">Search failed</div>'; }); }, 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); });
|
||||
results.addEventListener('click', function(e){
|
||||
var item = e.target.closest('.list-group-item');
|
||||
if(!item) return;
|
||||
var sfpk = item.getAttribute('data-seriesfinding-pk');
|
||||
var fpk = item.getAttribute('data-finding-pk');
|
||||
if(sfpk){
|
||||
insertAtCursor(textarea, '[['+'seriesfinding:'+sfpk+']]' );
|
||||
} else if(fpk){
|
||||
insertAtCursor(textarea, '[['+'finding:'+fpk+']]' );
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
if(overlay && overlay.parentNode) overlay.parentNode.removeChild(overlay);
|
||||
});
|
||||
overlay.tabIndex = -1; overlay.focus();
|
||||
function fetchInitialFindings(){ var initFindingsUrl = window.location.origin + '/atlas/search/findings/' + (currentCaseF ? '?case=' + currentCaseF : ''); fetch(initFindingsUrl).then(function(r){ return r.text(); }).then(function(html){ results.innerHTML = html; }).catch(function(){}); }
|
||||
fetchInitialFindings();
|
||||
|
||||
@@ -1,16 +1,25 @@
|
||||
<div class="list-group">
|
||||
{% if findings %}
|
||||
{% for f in findings %}
|
||||
<div class="list-group-item d-flex justify-content-between align-items-center" data-finding-pk="{{ f.pk }}">
|
||||
<div class="list-group-item d-flex justify-content-between align-items-center" data-finding-pk="{{ f.pk }}" data-seriesfinding-pk="{{ f.pk }}">
|
||||
<div class="flex-fill">
|
||||
<div class="d-flex w-100 justify-content-between">
|
||||
<strong class="mb-1">{{ f.name }}</strong>
|
||||
<strong class="mb-1">{% if f.series %}{{ f.series.id }}{% else %}Series{% endif %}{% if f.description %}: {{ f.description|truncatechars:80 }}{% endif %}</strong>
|
||||
<small class="text-muted">{{ f.pk }}</small>
|
||||
</div>
|
||||
<p class="mb-1 text-truncate">{{ f.description }}</p>
|
||||
<p class="mb-1 text-truncate">
|
||||
{% if f.findings.all %}
|
||||
{% for sub in f.findings.all %}
|
||||
<span class="badge bg-light text-dark me-1">{{ sub.name }}</span>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{{ f.description }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="ms-2">
|
||||
<a class="btn btn-sm btn-outline-secondary" href="{% url 'atlas:finding_detail' f.pk %}">View</a>
|
||||
{% if f.series %}
|
||||
<a class="btn btn-sm btn-outline-secondary" href="{% url 'atlas:series_detail' pk=f.series.pk %}">View series</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
+8
-4
@@ -365,16 +365,20 @@ def finding_search(request):
|
||||
# Allow both HTMX and standard fetch/ajax requests (don't require the HTMX header)
|
||||
q = request.GET.get('q', '').strip()
|
||||
case_id = request.GET.get('case')
|
||||
qs = Finding.objects.all()
|
||||
# Use SeriesFinding objects for the widget (series-scoped findings)
|
||||
qs = SeriesFinding.objects.select_related('series').prefetch_related('findings')
|
||||
if case_id:
|
||||
try:
|
||||
cid = int(case_id)
|
||||
qs = qs.filter(case__pk=cid)
|
||||
# Series are linked to cases through SeriesDetail; filter SeriesFinding by linked series' case
|
||||
qs = qs.filter(series__seriesdetail__case__pk=cid)
|
||||
except Exception:
|
||||
pass
|
||||
if q:
|
||||
qs = qs.filter(name__icontains=q)
|
||||
qs = qs.order_by('name')[:50]
|
||||
qs = qs.filter(
|
||||
Q(description__icontains=q) | Q(findings__name__icontains=q)
|
||||
)
|
||||
qs = qs.order_by('-pk').distinct()[:50]
|
||||
html = render_to_string('atlas/partials/_finding_search_results.html', {'findings': qs}, request=request)
|
||||
return HttpResponse(html)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user