feat(query-builder): migrate QueryBuilderWidgetV1 from antd to core-components - #29849
feat(query-builder): migrate QueryBuilderWidgetV1 from antd to core-components#29849chirag-madlani wants to merge 101 commits into
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nput Replace @react-awesome-query-builder/antd widgets with core-components. Two new widgets using Input component: - OMTextWidget: string input values - OMNumberWidget: numeric input with type="number" All tests passing, TypeScript strict compilation verified. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…support Implements Task 3 of the query builder migration from Ant Design to openmetadata-ui-core-components. Provides async-capable single-select widget wrapping core Select component. Includes handling for both static list values and async fetch callbacks, with proper TypeScript typing. - Converts listValues (array or object format) to SelectItemType[] - Supports async data loading via asyncFetch callback - Properly disables when readonly - Fully tested with 2 core test cases (render + disabled state) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ith async support Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…and ButtonGroup Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…m core-component widgets Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ate button renderers to core-components - AdvancedSearchClassBase: replace BasicConfig value with OMConfig from QueryBuilderOMConfig; BasicConfig is now type-only - AdvancedSearchUtils: renderAdvanceSearchButtons uses Button (core), X and Trash01 icons from @untitledui/icons; removes @ant-design/icons and antd Button imports - QueryBuilderUtils: renderQueryBuilderFilterButtons and renderJSONLogicQueryBuilderButtons use Button (core) and X/Plus from @untitledui/icons; removes antd and @ant-design/icons imports Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…and button renderers Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…-components, clean up LESS - Replace antd Card/Row/Col/Skeleton/Alert/Button/Divider/Typography with @openmetadata/ui-core-components equivalents - Replace @ant-design/icons InfoCircleOutlined with @untitledui/icons InfoCircle - Remove all .ant-* selectors from LESS; replace Less variable refs with CSS custom properties (--color-*) - Update skeleton test selector from .ant-skeleton.ant-skeleton-active to [aria-hidden="true"] (core Skeleton uses aria-hidden) - Update padding class test from .ant-col/.p-t-sm to .tw\\:pt-2 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Updated 7 test files to import from @react-awesome-query-builder/ui instead of @react-awesome-query-builder/antd, and replaced AntdConfig with BasicConfig. Applied UI checkstyle (organize-imports, lint:fix, prettier) on all modified test files. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…invalid type cast, wire JSONLogicSearchClassBase to OMConfig - OMDateWidget: replace getInputType(operator) with fieldType prop — operator values like "equal"/"less" never contain "time"/"datetime"; fieldType is the correct discriminant - OMDateWidget: fix tw:bg-disabled_subtle → tw:bg-disabled-subtle (underscore → dash matches CSS token) - OMNumberWidget: remove impossible `as number & null` intersection cast; Number(v) is already number - JSONLogicSearchClassBase: import OMConfig and set baseConfig = OMConfig so JSON-logic query builder uses OM-styled widgets consistently with AdvancedSearchClassBase Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ocument native input in OMDateWidget
❌ PR checklist incompleteThis PR cannot be merged until the following are addressed on its linked issue:
The fields live on the linked issue in the Shipping project (open the issue → right sidebar → Projects). After you set them, re-run this check (or push a commit) — issue/project changes do not re-trigger it automatically. Maintainers can bypass this check by adding the |
| async (search: string) => { | ||
| if (!asyncFetch) { | ||
| return; | ||
| } | ||
| const result = await asyncFetch(search); | ||
| setAllItems( | ||
| (result.values as ListItem[]).map((item) => ({ | ||
| id: String(item.value), | ||
| label: String(item.title ?? item.value), | ||
| })) | ||
| ); | ||
| }, | ||
| [asyncFetch] | ||
| ); |
There was a problem hiding this comment.
The multi-select adapter always calls asyncFetch(search) and discards the returned hasMore state. Fetchers such as enum/custom-property autocomplete accept an offset and can return more pages, so values after the first page can never be loaded or selected in the query builder.
| useEffect(() => { | ||
| const currentIds = new Set(selectedItems.items.map((i) => i.id)); | ||
| const targetIds = new Set(valueArray); | ||
|
|
||
| for (const id of targetIds) { | ||
| if (!currentIds.has(id)) { | ||
| const item = allItems.find((i) => i.id === id); | ||
| if (item) { | ||
| selectedItems.append(item); | ||
| } | ||
| } | ||
| } | ||
| for (const item of selectedItems.items) { | ||
| if (!targetIds.has(item.id)) { | ||
| selectedItems.remove(item.id); | ||
| } | ||
| } | ||
| }, [valueArray.join(',')]); |
There was a problem hiding this comment.
When a saved async multiselect filter is rendered, allItems is initially empty, so the sync effect cannot append chips for the current valueArray. After the async options arrive, the effect does not rerun for the same value, leaving persisted owner, tag, tier, or custom-property filters visually unselected even though the tree still contains their values.
| value={value !== null && value !== undefined ? String(value) : ''} | ||
| onChange={(v: string) => setValue(v === '' ? null : Number(v))} |
There was a problem hiding this comment.
Intermediate Numbers Store NaN
Number(v) is stored for every non-empty number-input string. Browser number inputs can emit intermediate values like 1e, -, or ., which convert to NaN; that value then enters the query tree and can produce an invalid or non-matching generated filter.
| value={value !== null && value !== undefined ? String(value) : ''} | |
| onChange={(v: string) => setValue(v === '' ? null : Number(v))} | |
| value={value !== null && value !== undefined ? String(value) : ''} | |
| onChange={(v: string) => { | |
| if (v === '') { | |
| setValue(null); | |
| return; | |
| } | |
| const nextValue = Number(v); | |
| if (Number.isFinite(nextValue)) { | |
| setValue(nextValue); | |
| } | |
| }} |
The selectOption helper already retries for up to 30 s with toPass — each retry re-fills the combobox which triggers a fresh aggregate fetch, so the suite self-heals if ES hasn't indexed the schema yet. The beforeAll block added up to 120 s of shard overhead (2 schemas × 60 s worst-case) that timing-baseline.json doesn't capture, pushing chromium-01 past the 1500 s execution budget and timing out the shard. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The OMSelectWidget aggregate autocomplete queries Elasticsearch; if the chart entity is not yet indexed the aggregate endpoint returns empty buckets, setItems([]) is called, and the value-picker option never appears. This causes "Verify Group functionality for field Chart with AND operator" to fail consistently when it runs early in the shard before ES has caught up. Add a toPass poll (60s, 2s intervals) in beforeAll that waits for each chart displayName to appear in the ES chart aggregate index — mirroring the existing pattern used for databaseSchema fields. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ests run" This reverts commit a038abb.
| const loadAsync = useCallback( | ||
| async (search: string) => { | ||
| if (!asyncFetch) { | ||
| return; |
There was a problem hiding this comment.
loadAsync still only requests the first async page. Enum and custom-property fetchers can return hasMore and use an offset for later pages, but this call always uses the default offset and the result handling only stores the returned values. When a multiselect field has values beyond the first response, users cannot browse or select those later values unless their search text narrows the value into page one. Preserve the pagination state and add a path to request later offsets.
|
| Count | Rule |
|---|---|
| 35 | react-hooks/exhaustive-deps |
| 22 | @typescript-eslint/no-explicit-any |
| 7 | openmetadata-imports/no-lower-layer-page-imports |
| 7 | sonarjs/cyclomatic-complexity |
| 6 | sonarjs/no-duplicate-string |
| 5 | openmetadata-imports/no-impure-pure-utils |
| 4 | jsx-a11y/control-has-associated-label |
| 4 | openmetadata-imports/no-circular-imports |
| 4 | sonarjs/cognitive-complexity |
| 4 | @typescript-eslint/no-non-null-assertion |
All findings
| Location | Rule | Message | |
|---|---|---|---|
| 🟡 | src/components/DataContract/ContractSemanticFormTab/ContractSemanticFormTab.test.tsx:40:6 |
@typescript-eslint/no-explicit-any |
Unexpected any. Specify a different type. |
| 🟡 | src/components/DataContract/ContractSemanticFormTab/ContractSemanticFormTab.test.tsx:110:8 |
@typescript-eslint/no-explicit-any |
Unexpected any. Specify a different type. |
| 🟡 | src/components/DataContract/ContractSemanticFormTab/ContractSemanticFormTab.tsx:99:5 |
react-hooks/exhaustive-deps |
React Hook useCallback has missing dependencies: 'form' and 'onChange'. Either include them or remove the dependency array. If 'onChange' changes too often, fin |
| 🟡 | src/components/DataContract/ContractSemanticFormTab/ContractSemanticFormTab.tsx:158:6 |
react-hooks/exhaustive-deps |
React Hook useEffect has a missing dependency: 'form'. Either include it or remove the dependency array. |
| 🟡 | src/components/DataContract/ContractSemanticFormTab/ContractSemanticFormTab.tsx:181:6 |
react-hooks/exhaustive-deps |
React Hook useEffect has a missing dependency: 'onChange'. Either include it or remove the dependency array. If 'onChange' changes too often, find the parent co |
| 🟡 | src/components/Explore/AdvanceSearchProvider/AdvanceSearchProvider.component.tsx:37:1 |
openmetadata-imports/no-lower-layer-page-imports |
Pages are route-level composition modules. Move the shared implementation/type to a lower layer instead of importing a page from here. |
| 🟡 | src/components/Explore/AdvanceSearchProvider/AdvanceSearchProvider.component.tsx:131:5 |
react-hooks/exhaustive-deps |
React Hook useMemo has a missing dependency: 'config'. Either include it or remove the dependency array. |
| 🟡 | src/components/Explore/AdvanceSearchProvider/AdvanceSearchProvider.component.tsx:160:6 |
react-hooks/exhaustive-deps |
React Hook useMemo has a missing dependency: 'config'. Either include it or remove the dependency array. |
| 🟡 | src/components/Explore/AdvanceSearchProvider/AdvanceSearchProvider.component.tsx:184:6 |
react-hooks/exhaustive-deps |
React Hook useEffect has a missing dependency: 'searchOutputType'. Either include it or remove the dependency array. If 'setConfig' needs the current value of ' |
| 🟡 | src/components/Explore/AdvanceSearchProvider/AdvanceSearchProvider.component.tsx:204:9 |
react-hooks/exhaustive-deps |
The 'toggleModal' function makes the dependencies of useMemo Hook (at line 356) change on every render. Move it inside the useMemo callback. Alternatively, wrap |
| 🟡 | src/components/Explore/AdvanceSearchProvider/AdvanceSearchProvider.component.tsx:308:6 |
react-hooks/exhaustive-deps |
React Hook useEffect has a missing dependency: 'tabsInfo'. Either include it or remove the dependency array. |
| 🟡 | src/components/Explore/AdvanceSearchProvider/AdvanceSearchProvider.component.tsx:312:6 |
react-hooks/exhaustive-deps |
React Hook useEffect has a missing dependency: 'loadData'. Either include it or remove the dependency array. |
| 🟡 | src/components/Explore/AdvanceSearchProvider/AdvanceSearchProvider.component.tsx:325:6 |
react-hooks/exhaustive-deps |
React Hook useEffect has missing dependencies: 'handleReset' and 'loadTree'. Either include them or remove the dependency array. |
| 🟡 | src/components/MyData/Widgets/CuratedAssetsWidget/AdvancedAssetsFilterField/AdvancedAssetsFilterField.component.tsx:68:9 |
react-hooks/exhaustive-deps |
The 'selectedResource' logical expression could make the dependencies of useMemo Hook (at line 77) change on every render. To fix this, wrap the initialization |
| 🟡 | src/components/MyData/Widgets/CuratedAssetsWidget/AdvancedAssetsFilterField/AdvancedAssetsFilterField.component.tsx:68:9 |
react-hooks/exhaustive-deps |
The 'selectedResource' logical expression could make the dependencies of useMemo Hook (at line 135) change on every render. To fix this, wrap the initialization |
| 🟡 | src/components/MyData/Widgets/CuratedAssetsWidget/AdvancedAssetsFilterField/AdvancedAssetsFilterField.component.tsx:68:9 |
react-hooks/exhaustive-deps |
The 'selectedResource' logical expression could make the dependencies of useEffect Hook (at line 154) change on every render. To fix this, wrap the initializati |
| 🟡 | src/components/MyData/Widgets/CuratedAssetsWidget/AdvancedAssetsFilterField/AdvancedAssetsFilterField.component.tsx:121:5 |
react-hooks/exhaustive-deps |
React Hook useCallback has an unnecessary dependency: 'getExpandedResourceList'. Either exclude it or remove the dependency array. Outer scope values like 'getE |
| 🟡 | src/components/MyData/Widgets/CuratedAssetsWidget/AdvancedAssetsFilterField/AdvancedAssetsFilterField.component.tsx:124:37 |
react-hooks/exhaustive-deps |
React Hook useCallback received a function whose dependencies are unknown. Pass an inline function instead. |
| 🟡 | src/components/MyData/Widgets/CuratedAssetsWidget/AdvancedAssetsFilterField/AdvancedAssetsFilterField.component.tsx:172:6 |
react-hooks/exhaustive-deps |
React Hook useEffect has missing dependencies: 'config', 'fqn', 'onTreeUpdate', and 'queryFilter'. Either include them or remove the dependency array. |
| 🟡 | src/components/MyData/Widgets/CuratedAssetsWidget/AdvancedAssetsFilterField/AdvancedAssetsFilterField.component.tsx:187:13 |
jsx-a11y/label-has-for |
Form label must have ALL of the following types of associated control: nesting, id |
| 🟡 | src/components/common/Form/JSONSchema/JsonSchemaWidgets/QueryBuilderWidget/QueryBuilderWidget.tsx:41:1 |
openmetadata-imports/no-lower-layer-page-imports |
Pages are route-level composition modules. Move the shared implementation/type to a lower layer instead of importing a page from here. |
| 🟡 | src/components/common/Form/JSONSchema/JsonSchemaWidgets/QueryBuilderWidget/QueryBuilderWidget.tsx:68:77 |
sonarjs/cyclomatic-complexity |
{"message":"Function has a complexity of 14 which is greater than 10 authorized.","cost":4,"secondaryLocations":[{"line":68,"column":76,"endLine":68,"endColumn" |
| 🟡 | src/components/common/Form/JSONSchema/JsonSchemaWidgets/QueryBuilderWidget/QueryBuilderWidget.tsx:130:5 |
react-hooks/exhaustive-deps |
React Hook useCallback has a missing dependency: 'config'. Either include it or remove the dependency array. |
| 🟡 | src/components/common/Form/JSONSchema/JsonSchemaWidgets/QueryBuilderWidget/QueryBuilderWidget.tsx:144:5 |
react-hooks/exhaustive-deps |
React Hook useMemo has a missing dependency: 'searchResults'. Either include it or remove the dependency array. |
| 🟡 | src/components/common/Form/JSONSchema/JsonSchemaWidgets/QueryBuilderWidget/QueryBuilderWidget.tsx:219:6 |
react-hooks/exhaustive-deps |
React Hook useCallback has missing dependencies: 'debouncedFetchEntityCount', 'defaultField', 'onTreeUpdate', and 'subField'. Either include them or remove the |
| 🟡 | src/components/common/Form/JSONSchema/JsonSchemaWidgets/QueryBuilderWidget/QueryBuilderWidget.tsx:223:6 |
react-hooks/exhaustive-deps |
React Hook useEffect has missing dependencies: 'onChangeSearchIndex' and 'resolvedSearchIndex'. Either include them or remove the dependency array. |
| 🟡 | src/components/common/Form/JSONSchema/JsonSchemaWidgets/QueryBuilderWidget/QueryBuilderWidget.tsx:229:6 |
react-hooks/exhaustive-deps |
React Hook useEffect has a missing dependency: 'loadDefaultValueInTree'. Either include it or remove the dependency array. |
| 🟡 | src/components/common/Form/JSONSchema/JsonSchemaWidgets/QueryBuilderWidget/QueryBuilderWidget.tsx:235:6 |
react-hooks/exhaustive-deps |
React Hook useEffect has a missing dependency: 'props'. Either include it or remove the dependency array. However, 'props' will change when any prop changes, |
| 🟡 | src/components/common/QueryBuilderWidgetV1/QueryBuilderWidgetV1.test.tsx:109:39 |
@typescript-eslint/no-explicit-any |
Unexpected any. Specify a different type. |
| 🟡 | src/components/common/QueryBuilderWidgetV1/QueryBuilderWidgetV1.test.tsx:118:52 |
@typescript-eslint/no-explicit-any |
Unexpected any. Specify a different type. |
| 🟡 | src/components/common/QueryBuilderWidgetV1/QueryBuilderWidgetV1.test.tsx:126:30 |
@typescript-eslint/no-explicit-any |
Unexpected any. Specify a different type. |
| 🟡 | src/components/common/QueryBuilderWidgetV1/QueryBuilderWidgetV1.test.tsx:126:43 |
@typescript-eslint/no-explicit-any |
Unexpected any. Specify a different type. |
| 🟡 | src/components/common/QueryBuilderWidgetV1/QueryBuilderWidgetV1.test.tsx:144:18 |
@typescript-eslint/no-explicit-any |
Unexpected any. Specify a different type. |
| 🟡 | src/components/common/QueryBuilderWidgetV1/QueryBuilderWidgetV1.test.tsx:362:34 |
@typescript-eslint/no-explicit-any |
Unexpected any. Specify a different type. |
| 🟡 | src/components/common/QueryBuilderWidgetV1/QueryBuilderWidgetV1.tsx:49:1 |
openmetadata-imports/no-lower-layer-page-imports |
Pages are route-level composition modules. Move the shared implementation/type to a lower layer instead of importing a page from here. |
| 🟡 | src/components/common/QueryBuilderWidgetV1/QueryBuilderWidgetV1.tsx:200:5 |
react-hooks/exhaustive-deps |
React Hook useCallback has a missing dependency: 'config'. Either include it or remove the dependency array. |
| 🟡 | src/components/common/QueryBuilderWidgetV1/QueryBuilderWidgetV1.tsx:210:7 |
sonarjs/expression-complexity |
Reduce the number of conditional operators (4) used in the expression (maximum allowed 3). |
| 🟡 | src/components/common/QueryBuilderWidgetV1/QueryBuilderWidgetV1.tsx:215:5 |
react-hooks/exhaustive-deps |
React Hook useMemo has a missing dependency: 'searchResults'. Either include it or remove the dependency array. |
| 🟡 | src/components/common/QueryBuilderWidgetV1/QueryBuilderWidgetV1.tsx:261:6 |
react-hooks/exhaustive-deps |
React Hook useEffect has a missing dependency: 'props'. Either include it or remove the dependency array. However, 'props' will change when any prop changes, |
| 🟡 | src/components/common/QueryBuilderWidgetV1/QueryBuilderWidgetV1.tsx:337:13 |
jsx-a11y/control-has-associated-label |
A control must be associated with a text label. |
| 🟡 | src/components/common/TagsSection/TagsSection.test.tsx:143:15 |
jsx-a11y/control-has-associated-label |
A control must be associated with a text label. |
| 🟡 | src/utils/AdvancedSearchClassBase.ts:48:1 |
openmetadata-imports/no-circular-imports |
This runtime import participates in a circular dependency. Extract the shared type/constant/utility or invert the dependency. |
| 🟡 | src/utils/AdvancedSearchClassBase.ts:280:16 |
sonarjs/no-duplicate-string |
Define a constant instead of duplicating this literal 3 times. |
| 🟡 | src/utils/AdvancedSearchClassBase.ts:611:51 |
sonarjs/no-duplicate-string |
Define a constant instead of duplicating this literal 3 times. |
| 🟡 | src/utils/AdvancedSearchClassBase.ts:946:26 |
sonarjs/no-duplicate-string |
Define a constant instead of duplicating this literal 4 times. |
| 🟡 | src/utils/AdvancedSearchClassBase.ts:1360:11 |
sonarjs/cyclomatic-complexity |
{"message":"Function has a complexity of 21 which is greater than 10 authorized.","cost":11,"secondaryLocations":[{"line":1360,"column":10,"endLine":1360,"endCo |
| 🟡 | src/utils/AdvancedSearchPureUtils.ts:16:1 |
openmetadata-imports/no-impure-pure-utils |
Pure utilities must not depend on React, UI, state, hooks, pages, or REST clients. Move orchestration/rendering out or move shared types to a lower layer. |
| 🟡 | src/utils/AdvancedSearchPureUtils.ts:17:1 |
openmetadata-imports/no-impure-pure-utils |
Pure utilities must not depend on React, UI, state, hooks, pages, or REST clients. Move orchestration/rendering out or move shared types to a lower layer. |
| 🟡 | src/utils/AdvancedSearchPureUtils.ts:18:1 |
openmetadata-imports/no-impure-pure-utils |
Pure utilities must not depend on React, UI, state, hooks, pages, or REST clients. Move orchestration/rendering out or move shared types to a lower layer. |
| 🟡 | src/utils/AdvancedSearchUtils.tsx:33:1 |
openmetadata-imports/no-circular-imports |
This runtime import participates in a circular dependency. Extract the shared type/constant/utility or invert the dependency. |
… and 59 more. Run make ui-checkstyle-changed locally for the full list.
Fix locally (fast - only checks files changed in this branch):
make ui-checkstyle-changed| if (!asyncFetch) { | ||
| return; | ||
| } | ||
| const result = await asyncFetch(search); |
There was a problem hiding this comment.
This still only requests the first async page. Enum custom-property fetchers accept an offset and can return hasMore, but this call always uses the default offset and the result handling keeps only result.values. When a multiselect field has values beyond the first response page, users cannot browse or select those later values unless their search narrows the value into page one.
…o-core
advancedSearch.ts — waitForResponse used escapeESReservedCharacters() before
encodeURIComponent(), turning dashes into \- then %5C-, a pattern that never
appears in the actual /api/v1/search/aggregate URL. Switched to
URL.searchParams.get('value') so the comparison is against the decoded value,
matching regardless of how the server percent-encodes the query param.
PersonaAIContext.spec.ts — the OMConjs conjunction toggle uses ButtonGroup →
AriaToggleButtonGroup → AriaToggleButton, which renders as <button> elements
with aria-pressed. Changed getByRole('radio') back to getByRole('button').
The 'radio' selector never matched, causing a 60 s assertion hang on every run.
IntakeForm.spec.ts — input.focus() opened the reference-picker ComboBox
without the pointer-event chain, leaving it in a state where a subsequent
option.click() continuously detached and re-rendered options for the test's
full 3-minute (test.slow()) window. Reverted to input.click({ force: true })
which bypasses the layout-shift stability check while still dispatching the
pointer events needed to activate the popup correctly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| if (!asyncFetch) { | ||
| return; | ||
| } | ||
| const result = await asyncFetch(search); |
There was a problem hiding this comment.
Pagination Still Missing
loadAsync only calls asyncFetch(search) and stores the returned values. It still does not keep hasMore or request a later offset, so async enum and custom-property multiselects can only browse the first result page. When a field has values beyond that first response, users cannot select them unless their search narrows the value into page one.
The UI sends ES-escaped values in the aggregate URL (e.g., dashes become \- which encodeURIComponent turns into %5C-), so the original predicate encodeURIComponent(escapeESReservedCharacters(searchData)) correctly matches the actual API URL. The URL.searchParams.get() approach decoded the %5C- back to \- which never equaled the raw searchData, causing waitForResponse to hang on every fillRule call. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Code Review
|
| Compact |
|
Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source
| if (!asyncFetch) { | ||
| return; | ||
| } | ||
| const result = await asyncFetch(search); |
There was a problem hiding this comment.
loadAsync still requests only the first async page. Enum and custom-property fetchers can return more values through hasMore and a later offset, but this call always uses the default offset and the result handling drops the pagination state. When a multiselect field has values beyond the first response, users cannot browse or select those values unless a search narrows them into page one.
|



Summary
@react-awesome-query-builder/antdimports with@react-awesome-query-builder/ui(API-identical, same version) across 14 production files and 8 test filesOMConfigfromBasicConfigwith new widget factories backed byopenmetadata-ui-core-components, eliminating Ant Design widget rendering inside query builder rulesQueryBuilderWidgetV1outer shell (Card, Alert, Skeleton, Divider, Typography) from antd to core-componentsAdvancedSearchUtilsandQueryBuilderUtilsfrom antdButton+@ant-design/iconsto coreButton+@untitledui/iconsNew widgets (
src/utils/queryBuilderWidgets/)OMTextWidgetInputOMNumberWidgetInput(numeric)OMSelectWidgetSelectwith async adapterOMMultiSelectWidgetMultiSelect+useListDatafromreact-statelyOMBooleanWidgetToggleOMDateWidget<input type="date/datetime-local/time">(coreDateInputis not publicly exported and requires@internationalized/dateobjects incompatible with RAQB string values)OMFieldSelectSelect(field/operator picker)OMConjsButtonGroup(AND/OR conjunction)All assembled into
src/utils/QueryBuilderOMConfig.tsxwhich exportsOMConfig.Test plan
QueryBuilderWidgetV1tests passsrc/utils/queryBuilderWidgets/)🤖 Generated with Claude Code
Greptile Summary
This PR migrates the query builder UI from Ant Design to core components. The main changes are:
OMConfigwiring for the React Awesome Query Builder renderers.Confidence Score: 4/5
This is close, but the async multiselect pagination path should be fixed before merging.
Files Needing Attention: openmetadata-ui/src/main/resources/ui/src/utils/queryBuilderWidgets/OMMultiSelectWidget.tsx
Important Files Changed
itemsto React Aria so async option updates can render.Reviews (36): Last reviewed commit: "fix(playwright): revert advancedSearch.t..." | Re-trigger Greptile
Context used (3)