Skip to content

[Listing] Search-mode extension seam (SearchModeRegistry) for pluggable smart search - #4076

Open
xIrusux wants to merge 28 commits into
2026.xfrom
semantic-search-mode-seam
Open

[Listing] Search-mode extension seam (SearchModeRegistry) for pluggable smart search#4076
xIrusux wants to merge 28 commits into
2026.xfrom
semantic-search-mode-seam

Conversation

@xIrusux

@xIrusux xIrusux commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Part of pimcore/product-management#1369 (Studio semantic-search UI). PR 1 of 3 — backend-power-tools-bundle registers its Smart search: Text / Image modes against this seam (follow-up PR); pimcore/backend-power-tools-bundle#753 adds the user permission.

What

  • SearchModeAbstract + SearchModeRegistry (based on DynamicTypeRegistryAbstract), bound as Element/Listing/SearchModeRegistry, SDK-exported from sdk/modules/element — bundles register modes from their plugin modules, same attach pattern as the existing component/dynamic-type registries.
  • SearchModeSelect: dropdown as a left Compact segment of SearchTermFilter — mode menu with icons, per-mode availability, disabled entries with grey type/class hints, warning line under the input, purple collapsed label when a smart mode is active ("Full text"/"Default" for the built-in mode).
  • Filter pipeline: hidden searchMode value (Clear-all resets to full text); the searchTerm descriptor emits the active mode's column filter instead of system.fulltext; registered mode filter types are stripped from restored base filters (a duplicate simple column filter of the same type is a BE 422).
  • Blocking: a selected-but-blocked mode disables Apply (sidebar) / Enter (modal top bars); a restored blocked state degrades to full text at query build as last line of defense.
  • Opt-in per listing via GeneralFiltersDecoratorConfig.elementType — enabled on the asset grid, data-object grid, and the search modal's Assets/Data Objects tabs. Listings without it, and installs with no registered modes, render today's plain search bar (zero visual change).
  • New full-text-search / smart-search icons via generate-icons (the script's known ride-along rewrites of 5 unrelated icons were reverted). Icons are hand-drawn to match the library's stroke style — swap for the Figma exports if the design team has finals.
  • 4 new i18n keys, synced to de/fr/it/es/sv/no (validator errors in sv/no are pre-existing True/False quoting issues, untouched).

Verified

  • tsc --noEmit and eslint clean on all changed files. No unit tests per team practice; end-to-end verification happens with the BPT consumer PR in the demo env.

🤖 Generated with Claude Code

Generic seam for pluggable search modes on the listing search bar, so bundles
(first consumer: backend-power-tools semantic search) can register modes that
swap what the search input emits:

- SearchModeAbstract + SearchModeRegistry (DynamicTypeRegistryAbstract-based),
  bound as Element/Listing/SearchModeRegistry and SDK-exported
- SearchModeSelect dropdown as a left Compact segment of SearchTermFilter,
  with per-mode availability, disabled entries with hints, warning line, and
  a purple collapsed label for active smart modes
- searchMode filter value (hidden descriptor, Clear-all resets to full text);
  the searchTerm descriptor emits the active mode's column filter instead of
  system.fulltext; registered mode filter types are stripped from restored
  base filters (duplicates would 422)
- blocked modes gate Apply (sidebar) and Enter (search-modal top bars)
- opt-in per listing via GeneralFiltersDecoratorConfig.elementType (asset and
  data-object grids + search-modal Assets/Data Objects tabs); listings without
  it keep the plain search bar, as does any install with no registered modes
- new full-text-search / smart-search icons (generate-icons ride-along
  rewrites reverted)

Part of pimcore/product-management#1369.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings September 3, 2026 07:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Saved-search restoration, filter cleanup, and blocked-search clearing have unresolved moderate issues.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds an SDK-extensible search-mode registry and integrates smart-search modes into asset and data-object listings.

Changes:

  • Adds search-mode contracts, registry, selector UI, icons, and translations.
  • Routes search terms through selected modes with availability handling.
  • Enables modes for asset/object grids and search-modal tabs.

Unresolved comments:

  • Moderate (1 vote)search-mode-filter.ts:20: Saved smart searches do not restore their mode/query correctly. Add registry-aware restoration and tests.
  • Moderate (2 votes)element-filter-setup.ts:44: Cleanup excludes hidden or permission-gated modes. Derive cleanup types from all registry entries.
  • Moderate (1 vote)search-mode-abstract.ts:67: The public contract lacks generic deserialization for saved searches. Add a restoration hook, integration, and test.
  • Nit (2 votes)search-mode-select.tsx:74: Use the repository’s IconButton abstraction.
  • Moderate (1 vote)search-term-filter.tsx:58: Blocked modes prevent clearing the applied search. Allow empty searches through the guard.
File summaries
File Reviewed change
translations/studio.sv.yaml Adds Swedish labels.
translations/studio.no.yaml Adds Norwegian labels.
translations/studio.it.yaml Adds Italian labels.
translations/studio.fr.yaml Adds French labels.
translations/studio.es.yaml Adds Spanish labels.
translations/studio.en.yaml Adds English labels.
translations/studio.de.yaml Adds German labels.
assets/js/src/sdk/modules/element/index.ts Exports the search-mode API.
assets/js/src/core/modules/search/modal/tabs/object/listing/object-search-listing.tsx Enables object search modes.
assets/js/src/core/modules/search/modal/tabs/asset/listing/asset-search-listing.tsx Enables asset search modes.
assets/js/src/core/modules/icon-library/index.ts Registers new icons.
assets/js/src/core/modules/element/listing/decorators/general-filters/view-layer/components/sidebar/tabs/filters/filter-container-inner.tsx Applies and gates mode state.
assets/js/src/core/modules/element/listing/decorators/general-filters/view-layer/components/search/search-term-filter.tsx Integrates mode selection with search.
assets/js/src/core/modules/element/listing/decorators/general-filters/view-layer/components/search/search-mode-select.tsx Implements the mode selector.
assets/js/src/core/modules/element/listing/decorators/general-filters/view-layer/components/search/search-mode-select.styles.ts Styles the selector.
assets/js/src/core/modules/element/listing/decorators/general-filters/search-modes/use-search-mode.ts Resolves mode state and availability.
assets/js/src/core/modules/element/listing/decorators/general-filters/search-modes/search-mode-registry.ts Adds the registry.
assets/js/src/core/modules/element/listing/decorators/general-filters/search-modes/search-mode-abstract.ts Defines the extension contract.
assets/js/src/core/modules/element/listing/decorators/general-filters/search-modes/constants.ts Defines the built-in mode ID.
assets/js/src/core/modules/element/listing/decorators/general-filters/general-filters-decorator.ts Adds listing opt-in configuration.
assets/js/src/core/modules/element/listing/decorators/general-filters/element-filters/use-element-filter-values.ts Adds mode filter state.
assets/js/src/core/modules/element/listing/decorators/general-filters/element-filters/element-filter-types.ts Extends filter context types.
assets/js/src/core/modules/element/listing/decorators/general-filters/element-filters/element-filter-setup.ts Builds mode-aware query context.
assets/js/src/core/modules/element/listing/decorators/general-filters/element-filters/definitions/search-term-filter.tsx Emits mode-specific filters.
assets/js/src/core/modules/element/listing/decorators/general-filters/element-filters/definitions/search-mode-filter.ts Defines hidden mode state.
assets/js/src/core/modules/element/listing/decorators/general-filters/element-filters/definitions/index.ts Registers the mode descriptor.
assets/js/src/core/modules/element/listing/decorators/general-filters/element-filters/build-element-filter-query.ts Removes conflicting base filters.
assets/js/src/core/modules/data-object/listing/index.ts Enables object listing modes.
assets/js/src/core/modules/asset/listing/index.ts Enables asset listing modes.
assets/js/src/core/assets/icons/smart-search.inline.svg Adds the smart-search icon.
assets/js/src/core/assets/icons/full-text-search.inline.svg Adds the full-text icon.
assets/js/src/core/app/config/services/service-ids.ts Adds the registry service ID.
assets/js/src/core/app/config/services/index.ts Binds the registry service.
Review details
  • Files reviewed: 31/34 changed files
  • Comments generated: 5
  • Review effort level: Balanced

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@xIrusux xIrusux added this to the 2026.3.0 milestone Sep 3, 2026
@xIrusux xIrusux self-assigned this Sep 3, 2026
xIrusux and others added 23 commits September 3, 2026 10:11
…rch degradation

- Derive registeredFilterTypes from every registry entry, not only visible
  modes, so a hidden mode's filter is still cleaned from restored base filters
- Let an empty term through the blocked-mode guard so clearing recovers from a
  blocked smart search instead of keeping the stale applied query
- Saved-search restore: exclude registered mode filter types from the field
  filters and reset the search mode to full text; a saved smart search degrades
  cleanly until a mode-level restore contract lands with the first concrete mode

Co-Authored-By: Claude <noreply@anthropic.com>
Replace the hardwired SearchModeSelect mount with the component-registry
slot 'element.listing.search.slots.prefix' (SlotRenderer, same pattern as
asset.tree.node.meta). SearchModeSelect becomes a self-contained default
entry registered by the element module: it reads the listing context via
hooks, owns the mode-change side effects, and renders nothing when no
modes are registered. Any bundle can now put other controls beside the
listing search input without touching the search-mode contract.

Co-Authored-By: Claude <noreply@anthropic.com>
…mode warning

Verified via Playwright in the demo: the blocked-mode warning rendered into the
DOM but was invisible in both modal tabs until size='auto'.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e-seam

Conflict resolution: 2026.x moved the service bindings from services/index.ts
into the side-effect-free install-core-services.ts — took the refactored
index.ts and re-added the SearchModeRegistry binding in the installer.
build-dist: kept the branch build; the workflow regenerates it on push.

Co-Authored-By: Claude <noreply@anthropic.com>
… Array#push)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
The search icon/Enter in the filter sidebar applied only the term: a drafted
smart mode never reached the applied store, so the search silently ran as
full text and the draft re-seeded from applied, visibly reverting the mode
selection. The shortcut now behaves like Apply for the control values
(searchMode, fieldFilters, directChildren, unreferenced) and respects the
blocked gate on every surface; pql still applies only through the Apply
button. Found and verified via Playwright gestures in the demo.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…it fail state

The warning Text rendered inline after the Compact row and drifted into the
top bar's horizontal-scroll overflow — present in the DOM, invisible on
screen (measured at x=1304 in a 1336px-wide modal). It now renders as a
block line under the input. A blocked mode additionally shows a warning
status on the input, and an attempted search escalates to an error status
with the warning in danger color until the block is resolved.

Verified via Playwright geometry and state assertions in the demo.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- warning renders in the darker warn shade (colorWarningTextActive) with the
  warning-circle icon, matching the design frame
- the search-modal top bars pass their selects into SearchTermFilter as
  prefixControls, so the warning line spans the row and left-aligns with the
  type select instead of the input column
- the input carries no warning border at rest; an attempted search while
  blocked shows the error border and turns the warning red until resolved

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- trigger uses the shared IconTextButton with the resting border pinned to
  colorBorder, matching the search button on the other end of the input
- the chevron toggles down/up with the dropdown open state and renders at
  12px (sizing goes through icon.options — IconTextButton's separate
  iconOptions prop is dead and worth its own cleanup), vertically centered

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- smart-search-text / smart-search-visual replace the shared smart-search
  icon (generate-icons ride-alongs reverted)
- a mode reporting available: false can never work on the surface (per the
  backend-computed targets, e.g. image search on data objects) and is now
  hidden instead of rendered disabled; blocked-but-fixable modes keep their
  entry, hint and warning

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Feature-specific icons ship with the bundle that registers the modes, via
the runtime IconLibrary registration. Core keeps full-text-search for its
built-in menu entry.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replaces the hand-drawn placeholders with the official SVG exports
(full-text-search, smart-search-text, smart-search-visual; fills converted
to currentColor), owned by the core library like every other bundle-consumed
icon — the earlier bundle-side IconLibrary registration is reverted in
backend-power-tools.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
xIrusux and others added 3 commits September 3, 2026 20:02
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ack)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Sep 3, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants