Skip to content

Nested Documents UI — Phase 3: History Token Wiring for Virtual Catalogues #3663

@luis100

Description

@luis100

Overview

Wire virtual catalogue selection into the browser history so that selecting "Emails" in the dropdown updates the URL and navigating directly to that URL restores the correct catalogue view. Reuses the existing $prefilter URL scheme — no new URL token types, no changes to Search.RESOLVER.

Part of: #3382
Depends on: #3662 (Phase 2 — virtual catalogue list IDs must exist before history can reference them)


URL Format

The existing prefilter URL scheme is:

#search/$prefilter/title/{TITLE}/@{CLASS}/{field}/{value}

Virtual catalogues use the listId in place of the class name. Examples:

Action URL
Select "Emails" catalogue (no filter) #search/$prefilter/title/Emails/@Search_emails
Select "Emails" and search by subject #search/$prefilter/title/Emails/@Search_emails/subject_txt/quarterly
Select standard AIP search #search/$prefilter/title/AIPs/@IndexedAIP

The @Search_emails token is parsed by the existing handlePreFilterSearch() in CatalogueSearch, which puts it into classFilters keyed by "Search_emails". The constructor then recognises it as a virtual catalogue listId (not a class simple name) and pre-selects it.


Bug Fix in CatalogueSearch.handlePreFilterSearch()

File: roda-ui/roda-wui/src/main/java/org/roda/wui/client/common/search/CatalogueSearch.java

Currently, when @Search_emails appears with no following field/value tokens (user just selected the catalogue), filterTokens is empty. SearchFilters.createFilterFromHistoryTokens([]) returns AllFilterParameter. The existing code then rejects this with a logger error:

// CURRENT — incorrectly rejects empty filter tokens
if (!filter.equals(new Filter(new AllFilterParameter()))) {
  classFilters.put(aClass, filter);
} else {
  logger.error("Could not parse filter...");  // ← fires for @Search_emails with no fields
}

Fix: distinguish "empty filter tokens = valid catalogue selection" from "parse failure":

// FIXED
if (!filterTokens.isEmpty()) {
  // User provided field/value tokens — use the parsed filter
  classFilters.put(aClass, filter);
} else if (!classes.isEmpty()) {
  // @X with no filter tokens — valid: show the catalogue unfiltered
  classFilters.put(aClass, new Filter(new AllFilterParameter()));
} else {
  logger.error("Could not parse filter for classes: " + StringUtils.join(classes, ", "));
}

Note

This fix also benefits standard class selectors (@IndexedAIP with no filter), which previously had the same silent-rejection behaviour.


CatalogueSearch Constructor — Recognise Virtual ListIds in classFilters

After the existing loop over searchableClasses, add a block that checks for virtual catalogue listIds:

// After the searchableClasses loop:
for (String listId : virtualCatalogueIds) {
  if (classFilters.containsKey(listId)) {
    Filter userFilter = classFilters.get(listId);
    // Merge with base ChildOfFilterParameter (Phase 2 logic)
    preselectedDropdownValue = listId;
    // ... build and register the virtual list builder as in Phase 2
  }
}

// After all list builders are registered:
if (preselectedDropdownValue != null) {
  searchWrapper.changeDropdownSelectedValue(preselectedDropdownValue);
}

Dropdown Change → History Push

In CatalogueSearch, register a value-change handler on the SearchWrapper dropdown. When the user switches to a virtual catalogue, push a new history token:

searchWrapper.addDropdownValueChangeHandler(event -> {
  String selectedValue = event.getValue();
  if (virtualCatalogueIds.contains(selectedValue)) {
    String label = ConfigurationManager.resolveTranslation(
      RodaConstants.UI_LISTS_PROPERTY, selectedValue,
      RodaConstants.UI_LISTS_CATALOGUE_LABEL_I18N_PROPERTY);
    History.newItem(
      Search.RESOLVER.getHistoryToken()
        + "/" + RodaConstants.SEARCH_WITH_PREFILTER_HANDLER
        + "/title/" + URL.encodeQueryString(label)
        + "/@" + selectedValue,
      false  // do not fire history change event — already handling it
    );
  }
});

Warning

Pass false as the second argument to History.newItem() to avoid a re-entrant history change event that would reload the page. The current view is already correct; we only want the URL to update for bookmarking/sharing.


No Changes Required

The following files do not need changes for this phase:

  • Search.javaRESOLVER already handles $prefilter tokens
  • SearchWithPreFilters.java — already strips title/{TITLE} and passes the rest to CatalogueSearch
  • Any backend/API code

Files to Change

File Action
roda-ui/.../client/common/search/CatalogueSearch.java Edit — fix handlePreFilterSearch, handle virtual listIds in constructor, add dropdown change handler

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions