EnxDev commented on PR #43277:
URL: https://github.com/apache/superset/pull/43277#issuecomment-5339622296
## EnxDev's Review Agent — apache/superset#43277 · HEAD 3c64e55
**request changes** — the `useFilters()` change silently regresses every
existing dashboard (filter-bar dividers disappear, "Clear all" skips canvas
filters, required filters stop gating), and two advertised controls are wired
up but never read.
Context: reviewed the full 3.3k-line diff against `master` @ 097c99b. Linked
issue #41498 is referenced but has no design doc I could read. Note that **CI
has not run the real gates on this PR** — only `labeler` succeeded; frontend
lint, `tsc`, and Jest were never executed, so none of the below is
machine-checked. The prior CodeAnt/Bito comments partly target files that no
longer exist in this diff (`CustomControlsFilterPlugin.tsx`,
`DraggableFilter.tsx`) — I re-derived everything from the current head.
### 🔴 Functional
- **`FilterBar/state.ts:61`** · _High_ — `useFilters()` now drops every
entry with `type !== 'DIVIDER'`. `useFilterControlFactory` builds its list from
`useFilters()` and branches on `isFilterDivider(filter)` to render
`<FilterDivider>` (`NativeFilterType.Divider === 'DIVIDER'`), so **all
native-filter dividers vanish from the filter bar on every dashboard** —
unconditionally, no feature flag, whether or not anyone uses a Filter Card.
Restrict the predicate to `!canvasFilterIds.has(filter.id)` and keep dividers.
**regression test:** render `FilterBar` with a config containing a `DIVIDER`
entry; assert the divider still renders.
- **`FilterBar/index.tsx:512`** · _High_ — `handleClearAll` iterates
`nativeFilterValues`, derived from `useFilters()`. Canvas-bound filters are
excluded there, so **"Clear all" silently leaves them applied** while the UI
reports everything cleared; charts stay filtered. Keep canvas filters in the
lifecycle data and exclude them only from the bar's rendering. **regression
test:** bind a filter to a `FilterHolder`, set a value, click Clear all, assert
its `dataMask` is cleared.
- **`DashboardBuilder/state.ts:99`** · _High_ — same root cause:
`requiredFirstFilter` / `missingInitialFilters` come from `useFilters()`. Once
a `requiredFirst` filter is bound to a Filter Card it drops out of that set, so
**the dashboard renders charts without the mandatory value** instead of showing
the "select a value first" gate. **regression test:** `requiredFirst` filter
bound to a canvas component → `showDashboard` stays false until a value is set.
- **`DateTimeFilter/DateTimeFilterPlugin.tsx:637`** · _High_ — in
`emitFilter`, when `col` is set but `fetchTimeRange` errors or returns fewer
than 2 date matches, `extra` stays `{}` while `filterState` is still published
as `{ value: rangeStr, label: rangeStr }`. The filter renders as applied with
the range label, but **no filtering happens** — a silent no-op the user cannot
distinguish from success. The `catch` has the same gap (it only repairs the
`!col` branch). Set `validateStatus: 'error'` and skip publishing a success
label when resolution fails. **regression test:** mock `fetchTimeRange` to
reject with `col` set; assert no mask claiming an applied range.
- **`CheckboxRadio/controlPanel.ts:87` and
`DateTimeFilter/controlPanel.ts:52`** · _High_ — both plugins expose "Filter
value is required" (`enableEmptyFilter`), and neither ever reads it.
`CheckboxRadio/transformProps.ts` doesn't forward it; `DateTimeFilterPlugin`
never touches `formData.enableEmptyFilter`. Compare
`SelectFilterPlugin.tsx:220`, which computes `emptyFilter` and drives
`validateStatus`. **Marking these filters required does nothing** — empty
selections apply and clear the filter. Implement it or remove the control.
**regression test:** `enableEmptyFilter: true` + empty value → emitted mask
carries `validateStatus: 'error'` and empty `extraFormData`.
- **`FilterHolder.tsx:186`** · _Medium_ — `handleClearStagedFilter`
dispatches `updateDataMask` straight to Redux, but it only renders when
`applyMode === 'manual'`, where ordinary selections stage in `stagedDataMask`
until Apply. **Clear bypasses the manual-apply workflow** and refreshes charts
before the user clicks Apply. Stage the cleared mask and commit it through
Apply. **regression test:** manual mode, set a value, click Clear → Redux
`dataMask` unchanged until Apply.
- **`CheckboxRadio/CheckboxRadioFilterPlugin.tsx:166`** · _Medium_ — the
sync effect guards on `filterState?.value !== undefined`, so an external reset
to `undefined` (Clear all, `getInitialDataMask`) never reaches `localValue`.
**The boxes stay visually checked while the filter is actually cleared.** Sync
unconditionally. **regression test:** rerender with `filterState.value ===
undefined`; assert no option is checked.
### 🟡 Should-fix
- **`packages/superset-core/src/theme/GlobalStyles.tsx:96-125`** — a global
`!important` block on `.ant-select-dropdown`, `.ant-picker-dropdown`,
`.ant-dropdown-menu` forces background, shadow, a new 1px border, and
`font-weight: 600` on selected options for **every dropdown in the app** (SQL
Lab, Explore, list views), and makes them un-overridable by any component that
themes its own popup. Scope this to the filter-card subtree, or fix the
underlying token instead of blanket `!important`.
-
**`packages/superset-ui-core/src/components/PopoverDropdown/index.tsx:96`** —
`theme.zIndexBase` (0) → `theme.zIndexPopupBase` (1000) changes stacking for
every `PopoverDropdown` consumer, not just this feature. The `|| 3100` fallback
is dead — `zIndexPopupBase` is always 1000. Confirm no consumer relied on these
sitting below other layers.
- **No feature flag** — a new dashboard layout element plus two plugins
registered in `MainPreset.ts` ship on by default. Convention is
`DEFAULT_FEATURE_FLAGS` in `superset/config.py` with
`docs/static/feature-flags.json` kept in sync; for a change that alters
`useFilters()` for everyone, gating matters.
- **`DateTimeFilter/index.ts:35`** — `datasourceCount: 1` with no
`buildQuery`. `FilterValue` fires `getChartDataRequest` whenever a dataset is
bound, so the default `buildQuery` runs a real query per DateTime filter on
every dashboard load — and the plugin never reads `queriesData`. Use
`datasourceCount: 0` like `TimeFilterPlugin`, or supply a minimal `buildQuery`.
- **`FilterHolder.test.tsx:142`** — the mock renders `data-test`, but Jest
has no global `testIdAttribute` override (only `playwright.config.ts` sets it),
so `getByTestId` looks for `data-testid` and this test fails.
`NewFilterComponent.test.tsx` sets both attributes; this file doesn't. Confirms
the earlier CodeAnt comment.
- **Test coverage** — ~1,600 new lines across `CheckboxRadio/*` and
`DateTimeFilter/*` ship with zero tests, and the ~140 new lines in
`getControlItemsMap.tsx` (Select/Text rendering, `visibility` evaluation) add
nothing to the existing `getControlItemsMap.test.tsx`. At minimum: `emitFilter`
failure path, `enableEmptyFilter`, and the canvas/bar rendering split.
- **`FilterHolder.tsx:168`** — canvas selections dispatch the raw mask,
keeping `validateStatus`. `FilterBar`'s own handler strips it first ("UI-only
state and shouldn't persist in Redux"); this path leaks it into `dataMask` and
anything derived from it.
- **`getControlItemsMap.tsx:187`** and **`DateTimeFilter/types.ts:42`** —
`as any` casts to synthesize the `visibility()` argument, and `datasource?:
any`. The repo bans `any`; use a typed partial and the core `Datasource` type.
### 🔵 Nits
- `DateTimeFilterPlugin.tsx:443` — `hasTime`'s third branch returns `true`
and so does the fallback; the `includes(':')` check is dead.
- `DateTimeFilterPlugin.tsx:716` — the mount effect re-emits the filter and
re-fetches the time range on every remount, with `exhaustive-deps` suppressed.
- `DateTimeFilterPlugin.tsx:1032` — `t(label)` over a `TAB_CONFIG` variable
won't be picked up by the i18n extractor; wrap the strings at definition
(`:59`).
- Hardcoded px throughout both plugins (`gap: 8px`, `font-size: 11px`,
`min-height: 290px`) instead of `theme.sizeUnit * n` / `theme.fontSizeSM`, plus
many inline `style={{…}}` props (`DateTimeFilterPlugin.tsx:834, 846, 1041`;
`CheckboxRadioFilterPlugin.tsx:224`) and raw `<input className="ant-input">` /
`<button>` where core `Input`/`Button` exist.
- `FilterBar/state.ts:78` — `useAllFilters` is exported and never called;
`DateTimeFilterPlugin.tsx:45` imports `useLocale`/`dayjs` after relative
imports. Also worth running Prettier locally —
`CheckboxRadio/transformProps.ts:87` and `types.ts` look unformatted, and lint
never ran here.
### 🙌 Praise
- `FILTER_TYPE` is threaded consistently through every layout util —
`componentIsResizable`, `getDetailedComponentWidth`, `isValidChild`,
`isDashboardEmpty`, `newComponentFactory` — with tests added for the resizable
and width paths. That's the easy half to miss.
- `FiltersConfigForm/utils.ts` — the `doesColumnMatchFilterType` rewrite
correctly handles temporal-only filter types via `is_dttm`, with four new tests
covering both directions.
<!-- enxdev-review-agent:3c64e55 -->
_Reviewed by EnxDev's Review Agent — @EnxDev · HEAD 3c64e55._
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]