Skip to content

[Studio UI] Filter sidebars: apply on Enter in the remaining modules - #4090

Open
ValeriaMaltseva wants to merge 4 commits into
2026.2from
fix/filter-sidebars-apply-on-enter
Open

[Studio UI] Filter sidebars: apply on Enter in the remaining modules#4090
ValeriaMaltseva wants to merge 4 commits into
2026.2from
fix/filter-sidebars-apply-on-enter

Conversation

@ValeriaMaltseva

Copy link
Copy Markdown
Contributor

Summary

#4012 (fixes pimcore/platform-version#354) made the Translations "Search & Filter" sidebar apply immediately, by adding an optional onCommit to the shared filter components (DynamicFilterProviderFieldFilters, consumed by DynamicTypeFieldFilterTextComponent via onPressEnter) and wiring exactly one host. The plumbing was deliberately host-agnostic, but the other five sidebars still required a click on "Apply", and the top search field still ignored Enter and the magnifier in two modules.

This wires up the remaining five and closes the search-field gap.

The decision that had to be settled first

On commit, the applied store receives the whole current draft, not only the committed key.

A single-key write looks equivalent — FiltersStore.setValues merges, so previously applied values survive — but the element listing wraps its sidebar in useDraftSync, which mirrors the applied store back into the draft. A single-key write there would push the previously applied values back over the other filters the user had typed but not applied, silently discarding them. Publishing the whole draft also keeps Enter and "Apply" doing exactly the same thing, which is the easier rule to explain.

That rule now lives in one place — commitFilterValues in components/filters — rather than being re-implemented per host, and it is the only part of this PR with a unit test.

The shape, now identical in all six hosts

// 1. one place per host that says what "apply" means
const applyFilters = (committed?: FilterValues): void => {  }

// 2. the Apply button
const handleApplyFilters = (): void => { applyFilters() }

// 3. field filters — a prop, since the host renders <FieldFilters> itself
const {, onFilterCommit } = useXFieldFilterEditor({
  onCommit: (fieldFilters) => { applyFilters({ fieldFilters }) }
})

// 4. renderer-built controls — a context, since FiltersRenderer builds them
<FilterCommitProvider onCommit={ applyFilters }>
  <FiltersRenderer section='search'  />
</FilterCommitProvider>

Two transports rather than one, because they are forced: the host renders FieldFilters directly, so a prop works; FiltersRenderer constructs controls from descriptors, so only a context reaches them. Notifications and Reports have no renderer-built controls and use steps 1–3 only.

Changes

components/filters

  • store/commit-filter-values.ts — new commitFilterValues(appliedStore, draftValues, committed?), with the reasoning above recorded in its doc comment. Covered by commit-filter-values.test.ts.
  • store/filter-commit-context.tsx — new FilterCommitProvider / useFilterCommitOptional, so a control built by FiltersRenderer can reach the host's apply.
  • adapter.tsuseFilterQuery's returned builder takes an optional second overrides argument, for the one host (Reports) that has no applied store to write into. Additive; existing callers are unaffected.

Element listing (Data Objects / Assets / Documents)

  • search-term-filter.tsxonSearch was if (!handleSearchTermInSidebar) { … }, i.e. a no-op in exactly the case where the field is rendered in the sidebar. It now goes through the panel's commit, which also resets paging. Outside the sidebar (element selectors, search modals — all of which set handleSearchTermInSidebar: false) it keeps writing straight to the applied store, unchanged.
  • filter-container-inner.tsx — the Apply handler is extracted into applyFilters(committed?), shared by the button, the search field and the field filters, so the three cannot drift. It still shapes which keys are published (pql only in advanced mode, unreferenced/searchTerm only when configured) and still calls setPage(1) + setDataLoadingState('filters-applied').
  • use-field-filter-editor.tsx — takes onCommit, returns onFilterCommit.

Notes & Events, Recycle Bin

  • filters.tsxSearchTermControl wired only onChange, so Enter and the magnifier did nothing (the original [Versions] Show date/time with seconds #354 bug, still present in these two). Added onSearch.
  • hook + tab — onFilterCommit on the field filters.

Notifications, Reports

  • hook + tab — onFilterCommit on the field filters. Neither has a search-term control.

Translations

  • Moved onto the shared helper and the common shape. No behaviour change.

Verification

  • npm run check-types — clean.
  • npx eslint js/src/core — clean.
  • npx jest ./js/src — 60 suites / 441 tests pass, including the 3 new ones.
  • Not verified in a browser; the manual checklist below is what a reviewer should run.

Manual test checklist

For each of Data Objects/Assets/Documents, Notes & Events, Notifications, Recycle Bin, Reports, Translations:

  1. Add a text field filter, type a value, press Enter → the list filters immediately, without clicking "Apply".
  2. Type into two text field filters, press Enter in the second → both are applied (whole-draft semantics).
  3. Element listing, Notes & Events, Recycle Bin: type in the top search field, press Enter, and separately click the magnifier → both apply.
  4. Element listing specifically — type a value into one field filter but do not press Enter, then press Enter in a different field filter. The first value must still be there. This is the useDraftSync case the whole-draft decision exists for.
  5. Element selector dialogs and the search modal still search on Enter as before (these render the same search component outside the sidebar).
  6. "Apply" and "Clear all filters" behave as before everywhere. Notes & Events, Notifications, Recycle Bin and Translations had their apply path rewritten, so worth a click even though the resulting write is identical.
  7. Non-text field filters (date, number, select) still wait for "Apply" — only the text type implements commit.

Known gaps

Both were called out as out of scope in the issue and are unchanged here: FieldFilters still has no Storybook story despite now carrying a public interaction path, and there is no test coverage of the filters framework or the field-filter dynamic types beyond the pure helper added in this PR — there is no existing seam to extend for the UI behaviour itself.

Fixes pimcore/platform-version#454

#4012 made the Translations sidebar apply on Enter
by adding an optional onCommit to the shared filter components and wiring
one host. The plumbing was host-agnostic but the other five sidebars still
required a click on "Apply", and the top search field ignored Enter and the
magnifier in Notes & Events and Recycle Bin.

Committing publishes the whole draft, not only the committed key. A
single-key write looks equivalent because FiltersStore.setValues merges,
but the element listing mirrors the applied store back into the draft via
useDraftSync, which would then overwrite the user's other unapplied edits.
Publishing the whole draft also keeps Enter and "Apply" doing the same
thing. That rule now lives in one place, commitFilterValues.

Every host follows the same shape: one applyFilters() that the Apply button
calls, injected into its field-filter editor hook as onCommit, and published
through FilterCommitProvider for the controls that FiltersRenderer builds
and so cannot receive a prop.

- components/filters: add commitFilterValues and the FilterCommit context;
  useFilterQuery's builder takes optional value overrides, for the one host
  (Reports) that has no applied store.
- Element listing: SearchTermFilter.onSearch was a no-op whenever the field
  was rendered in the sidebar; it now goes through the panel's commit, which
  also resets paging. Outside the sidebar (element selectors, search modals)
  it keeps writing straight to the applied store.
- Notes & Events, Recycle Bin: add onSearch to their search controls.
- Notes & Events, Notifications, Recycle Bin, Translations, Reports: pass
  onCommit to FieldFilters.

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings September 9, 2026 13:40
@ValeriaMaltseva ValeriaMaltseva added this to the 2026.2.10 milestone Sep 9, 2026

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.

🔵 Needs a closer look

Cross-module filter behavior requires final human review and browser verification.

Pull request overview

Extends Enter-to-apply filtering across all remaining filter sidebars while preserving whole-draft semantics.

Changes:

  • Adds shared filter commit context and whole-draft commit utility.
  • Enables Enter and search-icon application across six filter hosts.
  • Adds query override support and commit-helper tests.
File summaries
File Change
assets/js/src/core/modules/translations/translations-sidebar/components/filter-tab/filter-tab.tsx Adopts shared commit behavior.
assets/js/src/core/modules/translations/filters/hooks/use-translations-field-filter-editor.ts Delegates field commits to the host.
assets/js/src/core/modules/translations/filters/filters.tsx Uses the shared commit context.
assets/js/src/core/modules/reports/reports-view/components/report-sidebar/components/columns-filters/use-field-filter-editor.ts Exposes report filter commits.
assets/js/src/core/modules/reports/reports-view/components/report-sidebar/components/columns-filters/columns-filters.tsx Applies committed report filters.
assets/js/src/core/modules/recycle-bin/recycle-bin-sidebar/components/filter-tab/filter-tab.tsx Wires search and field commits.
assets/js/src/core/modules/recycle-bin/filters/hooks/use-recycle-bin-field-filter-editor.ts Adds field-filter commit handling.
assets/js/src/core/modules/recycle-bin/filters/filters.tsx Handles search submission.
assets/js/src/core/modules/notifications/notifications-sidebar/components/filter-tab/filter-tab.tsx Wires notification filter commits.
assets/js/src/core/modules/notifications/filters/hooks/use-notifications-field-filter-editor.ts Adds field-filter commit handling.
assets/js/src/core/modules/notes-and-events/notes-and-events-sidebar/components/search-filter-tab/search-filters-tab.tsx Wires search and field commits.
assets/js/src/core/modules/notes-and-events/filters/hooks/use-notes-field-filter-editor.ts Adds field-filter commit handling.
assets/js/src/core/modules/notes-and-events/filters/filters.tsx Handles search submission.
assets/js/src/core/modules/element/listing/decorators/general-filters/view-layer/components/sidebar/tabs/filters/filter-container-inner.tsx Unifies listing filter application.
assets/js/src/core/modules/element/listing/decorators/general-filters/view-layer/components/sidebar/tabs/filters/field-filters/use-field-filter-editor.tsx Exposes field-filter commits.
assets/js/src/core/modules/element/listing/decorators/general-filters/view-layer/components/search/search-term-filter.tsx Applies sidebar searches immediately.
assets/js/src/core/components/filters/store/filter-commit-context.tsx Provides commits to rendered controls.
assets/js/src/core/components/filters/store/commit-filter-values.ts Implements whole-draft commits.
assets/js/src/core/components/filters/store/commit-filter-values.test.ts Tests commit merge behavior.
assets/js/src/core/components/filters/index.ts Exports the new commit APIs.
assets/js/src/core/components/filters/adapter.ts Supports query overrides for pending values.
Review details
  • Files reviewed: 21/21 changed files
  • Comments generated: 0
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

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.

🔵 Needs a closer look

The cross-module interaction changes span 21 files and were not browser-verified, warranting final human validation.

Review details

Suppressed comments (1)

assets/js/src/core/components/filters/adapter.ts:32

  • overrides === undefined violates the repository's mandatory type-check convention, which requires lodash guards instead of direct undefined comparisons (.github/copilot-instructions.md:231-233). Defaulting the optional argument and merging it unconditionally avoids the direct comparison without changing the API.
    composeQuery(adapter.descriptors, overrides === undefined ? appliedValues : { ...appliedValues, ...overrides }, context),
  • Files reviewed: 21/22 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

Review feedback: `overrides === undefined` is a direct undefined comparison,
which .github/copilot-instructions.md rules out. Defaulting the optional
argument drops the comparison altogether rather than swapping it for
isUndefined, and keeps the API unchanged. composeQuery only reads values by
key, so the extra shallow copy is behaviour-neutral.

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

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.

🔵 Needs a closer look

The cross-module UI behavior is coherent, but browser verification is still needed across all six hosts.

Review details
  • Files reviewed: 21/22 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@sonarqubecloud

sonarqubecloud Bot commented Sep 9, 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