• 
      

    Search: Add faceted search view routing and templates

    Review Request #15054 — Created May 13, 2026 and updated

    Information

    Review Board
    release-8.x

    Reviewers

    Updates RBSearchView and adds the templates, CSS, and datagrid
    infrastructure for the new faceted search results page.

    RBSearchView.dispatch now checks whether the active backend exposes
    get_es_client. If it does, a FacetedSearchEngine is constructed and
    _use_faceted is set to True. Any exception during construction falls
    back silently to the existing Haystack path. Numeric queries still
    redirect directly to the matching review request when accessible.

    get_template_names returns search/results.html for the faceted path
    and search/results_legacy.html for the Haystack path.

    get_context_data on the faceted path calls
    FacetedSearchEngine.search, builds the group sidebar items with total
    counts, resolves human-readable labels for searchable filter buckets
    (reviewer, group, repository), and assembles the filter panel context
    including current values, bucket lists, and option counts.

    Search results are displayed using Review Board's existing datagrid
    infrastructure. Three new datagrid classes are added:
    SearchReviewRequestDataGrid, SearchUsersDataGrid, and
    SearchGroupDataGrid. Each takes an ES-ordered PK list and an ES total
    count, builds a Case/When-ordered ORM queryset from those PKs, and
    overrides pagination to use the ES total rather than a COUNT(*). Letter
    navigation for users and groups is handled server-side by injecting a
    prefix or regexp filter clause directly into the ES query, avoiding
    any full result fetch regardless of dataset size.

    results.html is the new template for the faceted path, providing the
    filter sidebar and results list. results_legacy.html is the existing
    template renamed, unchanged in behaviour. search_listview.html and
    search_paginator.html are new search-specific datagrid templates.

    search.less adds styles for the filter sidebar, bucket counts, active
    filter indicators, and the Contents filter checkbox group.

    _comment.html and _group.html are new partial templates for
    rendering comment and group search results inline.

    Ran full test suite.
    Verified that dispatch correctly routes to the faceted path when
    Elasticsearch is available and falls back silently to the Haystack
    path when it is not or when engine construction fails.

    Verified template selection, user attachment on search hits, numeric
    query redirection, and Whoosh wildcard rewriting.

    Confirmed the existing Haystack path is unaffected.

    Verified that review request, user, and group results all display
    correctly in their respective datagrids with correct column data and
    ES-ordered rows.

    Verified that letter navigation on the users and groups tabs filters
    correctly server-side via ES prefix/regexp queries and that the active
    letter is correctly highlighted after navigation.

    Verified that pagination reflects ES total counts rather than ORM
    counts across all three result tabs.

    Confirmed correct behaviour when switching between result tabs,
    applying sidebar filters, and navigating pages.

    Summary ID
    Search: Add faceted search view routing and templates
    105a36cb381445bd09b39770cf57516ee7401bd0
    Integrated datagrids to search results
    552082fd10a7c27c8a7d40f6b783f44ee00720e8
    Description From Last Updated

    'django.contrib.auth.models.User' imported but unused Column: 1 Error code: F401

    reviewbot reviewbot

    'django.urls.reverse' imported but unused Column: 1 Error code: F401

    reviewbot reviewbot

    line too long (138 > 79 characters) Column: 80 Error code: E501

    reviewbot reviewbot

    continuation line under-indented for visual indent Column: 27 Error code: E128

    reviewbot reviewbot

    line too long (82 > 79 characters) Column: 80 Error code: E501

    reviewbot reviewbot

    line too long (138 > 79 characters) Column: 80 Error code: E501

    reviewbot reviewbot

    continuation line under-indented for visual indent Column: 27 Error code: E128

    reviewbot reviewbot

    redefinition of unused 'User' from line 21 Column: 9 Error code: F811

    reviewbot reviewbot

    line too long (81 > 79 characters) Column: 80 Error code: E501

    reviewbot reviewbot

    local variable 'parts' is assigned to but never used Column: 9 Error code: F841

    reviewbot reviewbot

    line too long (81 > 79 characters) Column: 80 Error code: E501

    reviewbot reviewbot

    line break before binary operator Column: 21 Error code: W503

    reviewbot reviewbot

    'haystack.query.EmptySearchQuerySet' imported but unused Column: 1 Error code: F401

    reviewbot reviewbot

    multiple spaces before keyword Column: 34 Error code: E272

    reviewbot reviewbot

    continuation line unaligned for hanging indent Column: 21 Error code: E131

    reviewbot reviewbot

    continuation line unaligned for hanging indent Column: 21 Error code: E131

    reviewbot reviewbot

    line break before binary operator Column: 21 Error code: W503

    reviewbot reviewbot

    line too long (80 > 79 characters) Column: 80 Error code: E501

    reviewbot reviewbot

    undefined name 'SafeString' Column: 10 Error code: F821

    reviewbot reviewbot

    'django.contrib.auth.models.User' imported but unused Column: 1 Error code: F401

    reviewbot reviewbot

    'django.urls.reverse' imported but unused Column: 1 Error code: F401

    reviewbot reviewbot

    line too long (138 > 79 characters) Column: 80 Error code: E501

    reviewbot reviewbot

    continuation line under-indented for visual indent Column: 27 Error code: E128

    reviewbot reviewbot

    line too long (82 > 79 characters) Column: 80 Error code: E501

    reviewbot reviewbot

    line too long (138 > 79 characters) Column: 80 Error code: E501

    reviewbot reviewbot

    continuation line under-indented for visual indent Column: 27 Error code: E128

    reviewbot reviewbot

    redefinition of unused 'User' from line 21 Column: 9 Error code: F811

    reviewbot reviewbot

    line too long (81 > 79 characters) Column: 80 Error code: E501

    reviewbot reviewbot

    local variable 'parts' is assigned to but never used Column: 9 Error code: F841

    reviewbot reviewbot

    line too long (81 > 79 characters) Column: 80 Error code: E501

    reviewbot reviewbot

    line break before binary operator Column: 21 Error code: W503

    reviewbot reviewbot

    line too long (81 > 79 characters) Column: 80 Error code: E501

    reviewbot reviewbot

    line too long (82 > 79 characters) Column: 80 Error code: E501

    reviewbot reviewbot

    dictionary key 'D' repeated with different values Column: 5 Error code: F601

    reviewbot reviewbot

    dictionary key 'D' repeated with different values Column: 5 Error code: F601

    reviewbot reviewbot

    multiple spaces before keyword Column: 31 Error code: E272

    reviewbot reviewbot

    too many blank lines (2) Column: 5 Error code: E303

    reviewbot reviewbot

    expected 1 blank line, found 0 Column: 5 Error code: E301

    reviewbot reviewbot
    Checks run (1 failed, 1 succeeded)
    flake8 failed.
    JSHint passed.

    flake8

    dan.casares
    Review request changed
    Commits:
    Summary ID Author
    Search: Add faceted search view routing and templates
    407e9e37a703f4ae0878fc5ce4ab865cd41f92f3 DanielCasaresIglesias
    Search: Add faceted search view routing and templates
    9b9ccd0c68798fc5b86004152ef7f80455032c62 DanielCasaresIglesias

    Checks run (1 failed, 1 succeeded)

    flake8 failed.
    JSHint passed.

    flake8

    dan.casares
    Review request changed
    Commits:
    Summary ID Author
    Search: Add faceted search view routing and templates
    9b9ccd0c68798fc5b86004152ef7f80455032c62 DanielCasaresIglesias
    Search: Add faceted search view routing and templates
    0de4195f9a7315e369db6bcf7a527a92ecb2c77c DanielCasaresIglesias

    Checks run (1 failed, 1 succeeded)

    flake8 failed.
    JSHint passed.

    flake8

    dan.casares
    dan.casares
    Review request changed
    Change Summary:

    Added Any/All filter toggle interface.
    Integrated datagrids into search results.
    Updated testing.

    Description:
    ~  

    Updates RBSearchView and adds the templates and CSS for the new faceted

    ~   search results page.

      ~

    Updates RBSearchView and adds the templates, CSS, and datagrid

      ~ infrastructure for the new faceted search results page.

       
       

    RBSearchView.dispatch now checks whether the active backend exposes

        get_es_client. If it does, a FacetedSearchEngine is constructed and
    ~   _use_faceted is set to True. Any exception during construction falls back
    ~   silently to the existing Haystack path. Numeric queries still redirect directly
    ~   to the matching review request when accessible.

      ~ _use_faceted is set to True. Any exception during construction falls
      ~ back silently to the existing Haystack path. Numeric queries still
      ~ redirect directly to the matching review request when accessible.

       
    ~  

    get_template_names returns search/results.html for the faceted path and

    ~   search/results_legacy.html for the Haystack path.

      ~

    get_template_names returns search/results.html for the faceted path

      ~ and search/results_legacy.html for the Haystack path.

       
    ~  

    get_context_data on the faceted path calls FacetedSearchEngine.search,

    ~   builds the group sidebar items with total counts, resolves human-readable
    ~   labels for searchable filter buckets (reviewer, group, repository), and
    ~   assembles the filter panel context including current values, bucket lists, and
    ~   option counts.

      ~

    get_context_data on the faceted path calls

      ~ FacetedSearchEngine.search, builds the group sidebar items with total
      ~ counts, resolves human-readable labels for searchable filter buckets
      ~ (reviewer, group, repository), and assembles the filter panel context
      ~ including current values, bucket lists, and option counts.

       
    ~  

    results.html is the new template for the faceted path, providing the filter

    ~   sidebar and results list. results_legacy.html is the existing template
    ~   renamed, unchanged in behaviour.

      ~

    Search results are displayed using Review Board's existing datagrid

      ~ infrastructure. Three new datagrid classes are added:
      ~ SearchReviewRequestDataGrid, SearchUsersDataGrid, and
      + SearchGroupDataGrid. Each takes an ES-ordered PK list and an ES total
      + count, builds a Case/When-ordered ORM queryset from those PKs, and
      + overrides pagination to use the ES total rather than a COUNT(*). Letter
      + navigation for users and groups is handled server-side by injecting a
      + prefix or regexp filter clause directly into the ES query, avoiding
      + any full result fetch regardless of dataset size.

       
    ~  

    search.less adds styles for the filter sidebar, bucket counts, active filter

    ~   indicators, and the Contents filter checkbox group.

      ~

    results.html is the new template for the faceted path, providing the

      ~ filter sidebar and results list. results_legacy.html is the existing
      + template renamed, unchanged in behaviour. search_listview.html and
      + search_paginator.html are new search-specific datagrid templates.

       
    ~  

    _comment.html and _group.html are new partial templates for rendering

    ~   comment and group search results inline.

      ~

    search.less adds styles for the filter sidebar, bucket counts, active

      ~ filter indicators, and the Contents filter checkbox group.

      +
      +

    _comment.html and _group.html are new partial templates for

      + rendering comment and group search results inline.

    Testing Done:
    ~  

    Verified that dispatch correctly routes to the faceted path when

    ~   Elasticsearch is available and falls back silently to the Haystack path when it
    ~   is not or when engine construction fails. Verified template selection, user
    ~   attachment on search hits, numeric query redirection, and Whoosh wildcard
    ~   rewriting. Confirmed the existing Haystack path is unaffected.

      ~

    Ran full test suite.

      ~ Verified that dispatch correctly routes to the faceted path when
      ~ Elasticsearch is available and falls back silently to the Haystack
      ~ path when it is not or when engine construction fails.

      ~
      +

    Verified template selection, user attachment on search hits, numeric

      + query redirection, and Whoosh wildcard rewriting.

      +
      +

    Confirmed the existing Haystack path is unaffected.

      +
      +

    Verified that review request, user, and group results all display

      + correctly in their respective datagrids with correct column data and
      + ES-ordered rows.

      +
      +

    Verified that letter navigation on the users and groups tabs filters

      + correctly server-side via ES prefix/regexp queries and that the active
      + letter is correctly highlighted after navigation.

      +
      +

    Verified that pagination reflects ES total counts rather than ORM

      + counts across all three result tabs.

      +
      +

    Confirmed correct behaviour when switching between result tabs,

      + applying sidebar filters, and navigating pages.

    Commits:
    Summary ID Author
    Search: Add faceted search view routing and templates
    bdeb43497a0aca208a555832cbf3bd415624d722 DanielCasaresIglesias
    Search: Add faceted search view routing and templates
    105a36cb381445bd09b39770cf57516ee7401bd0 Daniel Casares-Iglesias
    Integrated datagrids to search results
    552082fd10a7c27c8a7d40f6b783f44ee00720e8 Daniel Casares-Iglesias

    Checks run (1 failed, 1 succeeded)

    flake8 failed.
    JSHint passed.

    flake8