Add category search functionality with results display
This commit is contained in:
@@ -0,0 +1,34 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Search results for "{{ query }}"</h5>
|
||||||
|
|
||||||
|
{% for group_name, items in results.items %}
|
||||||
|
{% if items.exists %}
|
||||||
|
<h6 class="mt-3">{{ group_name|capfirst }}</h6>
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
{% for item in items %}
|
||||||
|
<li>
|
||||||
|
{% if group_name == 'conditions' %}
|
||||||
|
<a href="{% url 'atlas:condition_detail' item.pk %}">{{ item.name }}</a>
|
||||||
|
{% elif group_name == 'findings' %}
|
||||||
|
<a href="{% url 'atlas:finding_detail' item.pk %}">{{ item.name }}</a>
|
||||||
|
{% elif group_name == 'structures' %}
|
||||||
|
<a href="{% url 'atlas:structure_detail' item.pk %}">{{ item.name }}</a>
|
||||||
|
{% elif group_name == 'subspecialties' %}
|
||||||
|
<a href="{% url 'atlas:subspecialty_detail' item.pk %}">{{ item.name }}</a>
|
||||||
|
{% elif group_name == 'presentations' %}
|
||||||
|
<a href="{% url 'atlas:presentation_detail' item.pk %}">{{ item.name }}</a>
|
||||||
|
{% else %}
|
||||||
|
{{ item.name }}
|
||||||
|
{% endif %}
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% if not results.conditions.exists and not results.findings.exists and not results.structures.exists and not results.subspecialties.exists and not results.presentations.exists %}
|
||||||
|
<p class="text-muted">No matches found.</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -12,6 +12,24 @@
|
|||||||
<li><a href="{% url 'atlas:pathological_process_view' %}">Pathological Process</li></a>
|
<li><a href="{% url 'atlas:pathological_process_view' %}">Pathological Process</li></a>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<div class="mt-4 mb-3">
|
||||||
|
<form method="get" class="d-flex" action="" id="category-search-form">
|
||||||
|
<input id="category-search-input" type="search" name="q" placeholder="Search all categories (conditions, findings, structures...)" value="{{ query|default:'' }}" class="form-control me-2"
|
||||||
|
hx-get="{% url 'atlas:categories_search_partial' %}"
|
||||||
|
hx-trigger="keyup changed delay:500ms"
|
||||||
|
hx-target="#category-search-results"
|
||||||
|
hx-swap="innerHTML"
|
||||||
|
hx-include="#category-search-input" />
|
||||||
|
<button class="btn btn-primary" type="submit">Search</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="category-search-results">
|
||||||
|
{% if results is not None %}
|
||||||
|
{% include 'atlas/_categories_search_results.html' %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
{% if request.user.is_staff %}
|
{% if request.user.is_staff %}
|
||||||
<p>Manage <a href="{% url 'generic:examination_view' %}">Examinations</a>
|
<p>Manage <a href="{% url 'generic:examination_view' %}">Examinations</a>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -347,6 +347,7 @@ urlpatterns = [
|
|||||||
path("question_schema/schemas", views.question_schema_schemas, name="question_schema_schemas"),
|
path("question_schema/schemas", views.question_schema_schemas, name="question_schema_schemas"),
|
||||||
path("condition/", views.ConditionView.as_view(), name="condition_view"),
|
path("condition/", views.ConditionView.as_view(), name="condition_view"),
|
||||||
path("categories/", views.categories_list, name="categories_list"),
|
path("categories/", views.categories_list, name="categories_list"),
|
||||||
|
path("categories/search_partial/", views.categories_search_partial, name="categories_search_partial"),
|
||||||
path("condition/<int:pk>", views.condition_detail, name="condition_detail"),
|
path("condition/<int:pk>", views.condition_detail, name="condition_detail"),
|
||||||
path(
|
path(
|
||||||
"condition/<int:pk>/delete",
|
"condition/<int:pk>/delete",
|
||||||
|
|||||||
+44
-9
@@ -1999,16 +1999,51 @@ class SubspecialtyAutocomplete(autocomplete.Select2QuerySetView):
|
|||||||
@login_required
|
@login_required
|
||||||
# @user_is_atlas_editor
|
# @user_is_atlas_editor
|
||||||
def categories_list(request):
|
def categories_list(request):
|
||||||
# condition = get_object_or_404(Condition, pk=pk)
|
# Allow an optional global search across category models via GET `q`.
|
||||||
|
query = request.GET.get("q", "").strip()
|
||||||
|
|
||||||
# logging.debug(atlas.subspecialty.first().name.all())
|
results = None
|
||||||
return render(
|
if query:
|
||||||
request,
|
from .models import Condition, Finding, Structure, Subspecialty, Presentation
|
||||||
"atlas/categories_list.html",
|
|
||||||
# {
|
# Simple case-insensitive contains search on `name` field for each model
|
||||||
# "condition": condition,
|
conditions = Condition.objects.filter(name__icontains=query).order_by("name")
|
||||||
# },
|
findings = Finding.objects.filter(name__icontains=query).order_by("name")
|
||||||
)
|
structures = Structure.objects.filter(name__icontains=query).order_by("name")
|
||||||
|
subspecialties = Subspecialty.objects.filter(name__icontains=query).order_by("name")
|
||||||
|
presentations = Presentation.objects.filter(name__icontains=query).order_by("name")
|
||||||
|
|
||||||
|
results = {
|
||||||
|
"conditions": conditions,
|
||||||
|
"findings": findings,
|
||||||
|
"structures": structures,
|
||||||
|
"subspecialties": subspecialties,
|
||||||
|
"presentations": presentations,
|
||||||
|
}
|
||||||
|
|
||||||
|
return render(request, "atlas/categories_list.html", {"query": query, "results": results})
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def categories_search_partial(request):
|
||||||
|
"""Return only the search results partial for HTMX requests.
|
||||||
|
|
||||||
|
Expects GET param `q`.
|
||||||
|
"""
|
||||||
|
query = request.GET.get("q", "").strip()
|
||||||
|
results = {"conditions": (), "findings": (), "structures": (), "subspecialties": (), "presentations": ()}
|
||||||
|
if query:
|
||||||
|
from .models import Condition, Finding, Structure, Subspecialty, Presentation
|
||||||
|
|
||||||
|
results = {
|
||||||
|
"conditions": Condition.objects.filter(name__icontains=query).order_by("name"),
|
||||||
|
"findings": Finding.objects.filter(name__icontains=query).order_by("name"),
|
||||||
|
"structures": Structure.objects.filter(name__icontains=query).order_by("name"),
|
||||||
|
"subspecialties": Subspecialty.objects.filter(name__icontains=query).order_by("name"),
|
||||||
|
"presentations": Presentation.objects.filter(name__icontains=query).order_by("name"),
|
||||||
|
}
|
||||||
|
|
||||||
|
return render(request, "atlas/_categories_search_results.html", {"query": query, "results": results})
|
||||||
|
|
||||||
|
|
||||||
# def collection_view(request):
|
# def collection_view(request):
|
||||||
|
|||||||
@@ -237,7 +237,10 @@
|
|||||||
console.error('Error hiding review modal', err);
|
console.error('Error hiding review modal', err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
Reference in New Issue
Block a user