From 8bb9705aad1cf6f32b78d331fcd2901b29181bc1 Mon Sep 17 00:00:00 2001 From: PouyaMohseni Date: Wed, 14 Jan 2026 14:26:44 -0500 Subject: [PATCH 1/9] feat: add sort support to instrument list queries - sort based on umil label (main label) - add a function-based sort for `sort=desc` to have null first --- .../apps/instruments/views/instrument_list.py | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/web-app/django/VIM/apps/instruments/views/instrument_list.py b/web-app/django/VIM/apps/instruments/views/instrument_list.py index b3012a90..c5746c8a 100644 --- a/web-app/django/VIM/apps/instruments/views/instrument_list.py +++ b/web-app/django/VIM/apps/instruments/views/instrument_list.py @@ -211,6 +211,28 @@ def _get_solr_connection(self): """Get a Solr connection.""" return pysolr.Solr(settings.SOLR_URL, timeout=settings.SOLR_TIMEOUT) + def _build_sort_param(self, lang_code: str) -> str | None: + """ + Builds a Solr sort expression that: + - puts missing labels FIRST + - sorts alphabetically by language-specific UMIL label + """ + sort_order = self.request.GET.get("sort", "").lower() + if sort_order not in ("asc", "desc"): + return None + + umil_label_field = f"instrument_umil_label_{lang_code}_s" + + if sort_order == "desc": + return ( + f"if(exists({umil_label_field}),1,0) asc, " + f"{umil_label_field} {sort_order}" + ) + elif sort_order == "asc": + return f"{umil_label_field} {sort_order}" + else: + pass + def _build_solr_query(self, language: Language, include_facets: bool = False): """Build Solr query parameters supporting combined search + HBS filtering.""" lang_code = language.wikidata_code @@ -233,6 +255,9 @@ def _build_solr_query(self, language: Language, include_facets: bool = False): if hbs_facet: filter_queries.append(f"hbs_prim_cat_s:{hbs_facet}") + # Build sorting filter + sort_param = self._build_sort_param(lang_code) + umil_label_field = f"instrument_umil_label_{lang_code}_s" params = { @@ -251,6 +276,10 @@ def _build_solr_query(self, language: Language, include_facets: bool = False): if filter_queries: params["fq"] = filter_queries + # Add sort if any + if sort_param: + params["sort"] = sort_param + return params def _get_solr_page_results( From 82fca785663a501b5ac0e3a6a6a8403876123a94 Mon Sep 17 00:00:00 2001 From: PouyaMohseni Date: Wed, 14 Jan 2026 15:28:50 -0500 Subject: [PATCH 2/9] feat: preserve sort parameter in pagination links --- .../templates/instruments/includes/paginationOptions.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web-app/django/VIM/templates/instruments/includes/paginationOptions.html b/web-app/django/VIM/templates/instruments/includes/paginationOptions.html index 23f43d59..d4f65305 100644 --- a/web-app/django/VIM/templates/instruments/includes/paginationOptions.html +++ b/web-app/django/VIM/templates/instruments/includes/paginationOptions.html @@ -24,7 +24,7 @@ {% if page_obj.has_previous %}
  • @@ -32,7 +32,7 @@
  • @@ -50,7 +50,7 @@ {% if page_obj.has_next %}
  • @@ -58,7 +58,7 @@
  • From 072de62bb448c535a5eb7dea072f20bb853d5b5c Mon Sep 17 00:00:00 2001 From: PouyaMohseni Date: Wed, 14 Jan 2026 15:57:42 -0500 Subject: [PATCH 3/9] feat: preserve sort parameter in facets and clear links --- .../apps/instruments/views/instrument_list.py | 81 ++++++++++++++++--- 1 file changed, 72 insertions(+), 9 deletions(-) diff --git a/web-app/django/VIM/apps/instruments/views/instrument_list.py b/web-app/django/VIM/apps/instruments/views/instrument_list.py index c5746c8a..ee3364c6 100644 --- a/web-app/django/VIM/apps/instruments/views/instrument_list.py +++ b/web-app/django/VIM/apps/instruments/views/instrument_list.py @@ -178,6 +178,13 @@ def get_context_data(self, **kwargs): ), } + # Add sort data to context + sort_order = self.request.GET.get("sort", "").lower() + if sort_order not in ("asc", "desc"): + sort_order = None + + context["sort"] = sort_order + # Add URL building helpers for preserving search query in HBS facet links context["current_search_query"] = search_query @@ -185,24 +192,80 @@ def get_context_data(self, **kwargs): enhanced_hbs_facets = [] for facet in hbs_facet_list: facet_copy = facet.copy() - # Build URL that preserves search query (with proper encoding) + + # Build base params list + params = [] + clear_params = [] + if search_query: - encoded_query = requests.utils.quote(search_query) - facet_copy["url"] = f"?query={encoded_query}&hbs_facet={facet['value']}" - facet_copy["clear_url"] = f"?query={encoded_query}" - else: - facet_copy["url"] = f"?hbs_facet={facet['value']}" - facet_copy["clear_url"] = "?" + params.append(f"query={requests.utils.quote(search_query)}") + clear_params.append(f"query={requests.utils.quote(search_query)}") + + if sort_order: + params.append(f"sort={sort_order}") + + # Current facet is added to main URL + params.append(f"hbs_facet={facet['value']}") + + facet_copy["url"] = "?" + "&".join(params) + facet_copy["clear_url"] = ( + "?" + "&".join(clear_params) if clear_params else "?" + ) + # Add active state for current HBS filter facet_copy["is_active"] = facet["value"] == hbs_facet enhanced_hbs_facets.append(facet_copy) context["hbs_facets"] = enhanced_hbs_facets # Add clear filter URLs for UI - context["clear_search_url"] = f"?hbs_facet={hbs_facet}" if hbs_facet else "?" + params = {} + if search_query: + params["query"] = search_query + if hbs_facet: + params["hbs_facet"] = hbs_facet + if sort_order: + params["sort"] = sort_order + + # clear_search_url: remove 'query' + clear_search_params = {k: v for k, v in params.items() if k != "query"} + context["clear_search_url"] = ( + "?" + + "&".join( + [ + f"{k}={requests.utils.quote(str(v))}" + for k, v in clear_search_params.items() + ] + ) + if clear_search_params + else "?" + ) + # clear_hbs_url: remove 'hbs_facet' + clear_hbs_params = {k: v for k, v in params.items() if k != "hbs_facet"} context["clear_hbs_url"] = ( - f"?query={requests.utils.quote(search_query)}" if search_query else "?" + "?" + + "&".join( + [ + f"{k}={requests.utils.quote(str(v))}" + for k, v in clear_hbs_params.items() + ] + ) + if clear_hbs_params + else "?" + ) + # clear_sort_url: remove 'sort' + clear_sort_params = {k: v for k, v in params.items() if k != "sort"} + context["clear_sort_url"] = ( + "?" + + "&".join( + [ + f"{k}={requests.utils.quote(str(v))}" + for k, v in clear_sort_params.items() + ] + ) + if clear_sort_params + else "?" ) + # clear_all_filters_url: remove everything context["clear_all_filters_url"] = "?" return context From 23116e11747dc6194686881c54079d8e9b0fedf2 Mon Sep 17 00:00:00 2001 From: PouyaMohseni Date: Thu, 15 Jan 2026 09:59:54 -0500 Subject: [PATCH 4/9] feat: show sort order in Active Filters --- .../VIM/apps/instruments/views/instrument_list.py | 15 ++++++++------- .../django/VIM/templates/instruments/index.html | 8 ++++++++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/web-app/django/VIM/apps/instruments/views/instrument_list.py b/web-app/django/VIM/apps/instruments/views/instrument_list.py index ee3364c6..11be7e07 100644 --- a/web-app/django/VIM/apps/instruments/views/instrument_list.py +++ b/web-app/django/VIM/apps/instruments/views/instrument_list.py @@ -167,6 +167,13 @@ def get_context_data(self, **kwargs): (x["name"] for x in hbs_facet_list if x["value"] == hbs_facet), "" ) + # Add sort data to context + sort_order = self.request.GET.get("sort", "").lower() + if sort_order not in ("asc", "desc"): + sort_order = None + + context["sort"] = sort_order + # Add combined filter state for UI context["has_filters"] = bool(search_query or hbs_facet) context["active_filters"] = { @@ -176,15 +183,9 @@ def get_context_data(self, **kwargs): if hbs_facet else None ), + "sort": sort_order if sort_order else None, } - # Add sort data to context - sort_order = self.request.GET.get("sort", "").lower() - if sort_order not in ("asc", "desc"): - sort_order = None - - context["sort"] = sort_order - # Add URL building helpers for preserving search query in HBS facet links context["current_search_query"] = search_query diff --git a/web-app/django/VIM/templates/instruments/index.html b/web-app/django/VIM/templates/instruments/index.html index 75c34a93..5e7c0f87 100644 --- a/web-app/django/VIM/templates/instruments/index.html +++ b/web-app/django/VIM/templates/instruments/index.html @@ -46,6 +46,14 @@
    Active Filters
    title="Remove HBS filter">×
    {% endif %} + {% if active_filters.sort %} + + Sort: {{ active_filters.sort }} + × + + {% endif %} Clear All From 20464d68cd93902584277beaac436ab226aed797 Mon Sep 17 00:00:00 2001 From: PouyaMohseni Date: Thu, 15 Jan 2026 10:10:00 -0500 Subject: [PATCH 5/9] feat: improve visualization by showing complete sort query --- .../apps/instruments/views/instrument_list.py | 8 +++++++- .../django/VIM/templates/instruments/index.html | 16 ++++++++-------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/web-app/django/VIM/apps/instruments/views/instrument_list.py b/web-app/django/VIM/apps/instruments/views/instrument_list.py index 11be7e07..a746ebf8 100644 --- a/web-app/django/VIM/apps/instruments/views/instrument_list.py +++ b/web-app/django/VIM/apps/instruments/views/instrument_list.py @@ -183,7 +183,13 @@ def get_context_data(self, **kwargs): if hbs_facet else None ), - "sort": sort_order if sort_order else None, + "sort": ( + "Ascending" + if sort_order == "asc" + else "Descending" + if sort_order == "desc" + else None + ), } # Add URL building helpers for preserving search query in HBS facet links diff --git a/web-app/django/VIM/templates/instruments/index.html b/web-app/django/VIM/templates/instruments/index.html index 5e7c0f87..c5b199ff 100644 --- a/web-app/django/VIM/templates/instruments/index.html +++ b/web-app/django/VIM/templates/instruments/index.html @@ -38,14 +38,6 @@
    Active Filters
    title="Remove search filter">× {% endif %} - {% if active_filters.hbs_classification %} - - HBS: {{ active_filters.hbs_classification.name }} - × - - {% endif %} {% if active_filters.sort %} Sort: {{ active_filters.sort }} @@ -54,6 +46,14 @@
    Active Filters
    title="Remove Sort filter">×
    {% endif %} + {% if active_filters.hbs_classification %} + + HBS: {{ active_filters.hbs_classification.name }} + × + + {% endif %} Clear All From 440b662749d2cdb8c545ff3761274ee8333117c7 Mon Sep 17 00:00:00 2001 From: PouyaMohseni Date: Thu, 15 Jan 2026 10:42:41 -0500 Subject: [PATCH 6/9] fix: add `sort_order` to `has_filters` in the context --- web-app/django/VIM/apps/instruments/views/instrument_list.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web-app/django/VIM/apps/instruments/views/instrument_list.py b/web-app/django/VIM/apps/instruments/views/instrument_list.py index a746ebf8..522883e3 100644 --- a/web-app/django/VIM/apps/instruments/views/instrument_list.py +++ b/web-app/django/VIM/apps/instruments/views/instrument_list.py @@ -175,7 +175,7 @@ def get_context_data(self, **kwargs): context["sort"] = sort_order # Add combined filter state for UI - context["has_filters"] = bool(search_query or hbs_facet) + context["has_filters"] = bool(search_query or hbs_facet or sort_order) context["active_filters"] = { "search": search_query if search_query else None, "hbs_classification": ( From 43275c92b2ed99be5279a225aa64abd024215ae2 Mon Sep 17 00:00:00 2001 From: PouyaMohseni Date: Thu, 15 Jan 2026 12:25:41 -0500 Subject: [PATCH 7/9] feat: add enhanced sort oprions URI to preserve search query and facets --- .../apps/instruments/views/instrument_list.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/web-app/django/VIM/apps/instruments/views/instrument_list.py b/web-app/django/VIM/apps/instruments/views/instrument_list.py index 522883e3..d78d635d 100644 --- a/web-app/django/VIM/apps/instruments/views/instrument_list.py +++ b/web-app/django/VIM/apps/instruments/views/instrument_list.py @@ -173,6 +173,9 @@ def get_context_data(self, **kwargs): sort_order = None context["sort"] = sort_order + context["sort_list"] = [ + {"value": value, "url": None} for value in ("asc", "desc", "default") + ] # Add combined filter state for UI context["has_filters"] = bool(search_query or hbs_facet or sort_order) @@ -272,6 +275,28 @@ def get_context_data(self, **kwargs): if clear_sort_params else "?" ) + + # Enhanced sort options for UI with proper URLs that preserve search query + sort_values = tuple(value["value"] for value in context["sort_list"]) + sort_list = [] + for value in sort_values: + temp_params = {k: v for k, v in params.items() if k != "sort"} + if value != "default": + temp_params["sort"] = value + url = ( + "?" + + "&".join( + [ + f"{k}={requests.utils.quote(str(v))}" + for k, v in temp_params.items() + ] + ) + if temp_params + else "?" + ) + sort_list.append({"value": value, "url": url}) + context["sort_list"] = sort_list + # clear_all_filters_url: remove everything context["clear_all_filters_url"] = "?" From cd8bc52d3558167e36899c9ea5a261b618558368 Mon Sep 17 00:00:00 2001 From: PouyaMohseni Date: Thu, 15 Jan 2026 12:26:03 -0500 Subject: [PATCH 8/9] feat: add sort options as form list to UI - This also supports RTL --- .../VIM/templates/instruments/index.html | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/web-app/django/VIM/templates/instruments/index.html b/web-app/django/VIM/templates/instruments/index.html index c5b199ff..4556161c 100644 --- a/web-app/django/VIM/templates/instruments/index.html +++ b/web-app/django/VIM/templates/instruments/index.html @@ -60,6 +60,45 @@
    Active Filters
    {% endif %} + +
    + + +

    Hornbostel-Sachs Classification


    From 9a73476e5d5c55deed627b92bf328c8432e92040 Mon Sep 17 00:00:00 2001 From: PouyaMohseni Date: Thu, 15 Jan 2026 12:43:17 -0500 Subject: [PATCH 9/9] fix: decrease sort btn size --- web-app/django/VIM/apps/instruments/views/instrument_list.py | 4 +--- web-app/django/VIM/templates/instruments/index.html | 2 +- web-app/django/manage.py | 1 + 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/web-app/django/VIM/apps/instruments/views/instrument_list.py b/web-app/django/VIM/apps/instruments/views/instrument_list.py index d78d635d..0bdd7656 100644 --- a/web-app/django/VIM/apps/instruments/views/instrument_list.py +++ b/web-app/django/VIM/apps/instruments/views/instrument_list.py @@ -189,9 +189,7 @@ def get_context_data(self, **kwargs): "sort": ( "Ascending" if sort_order == "asc" - else "Descending" - if sort_order == "desc" - else None + else "Descending" if sort_order == "desc" else None ), } diff --git a/web-app/django/VIM/templates/instruments/index.html b/web-app/django/VIM/templates/instruments/index.html index 4556161c..d9ad3291 100644 --- a/web-app/django/VIM/templates/instruments/index.html +++ b/web-app/django/VIM/templates/instruments/index.html @@ -66,7 +66,7 @@
    Active Filters
    Sort