Skip to content

Commit f3ae6cf

Browse files
authored
fix: extend enum in all (#27265)
1 parent 2ca0109 commit f3ae6cf

2 files changed

Lines changed: 104 additions & 4 deletions

File tree

openmetadata-ui/src/main/resources/ui/src/components/common/Form/JSONSchema/JsonSchemaWidgets/TreeSelectWidget.test.tsx

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ const mockProps = {
3737
};
3838

3939
describe('Test TreeSelectWidget Component', () => {
40+
beforeEach(() => {
41+
jest.clearAllMocks();
42+
});
43+
4044
it('Should render tree select component', async () => {
4145
render(<TreeSelectWidget {...mockProps} />);
4246

@@ -96,4 +100,72 @@ describe('Test TreeSelectWidget Component', () => {
96100

97101
expect(mockOnChange).toHaveBeenCalledTimes(1);
98102
});
103+
104+
it('Should pass through "all" when expandAllValue is not set', async () => {
105+
const passThroughProps = {
106+
...mockProps,
107+
value: [],
108+
};
109+
110+
render(<TreeSelectWidget {...passThroughProps} />);
111+
112+
const treeSelectInput = await findByRole(
113+
screen.getByTestId('tree-select-widget'),
114+
'combobox'
115+
);
116+
117+
await act(async () => {
118+
userEvent.click(treeSelectInput);
119+
});
120+
121+
await waitFor(() => screen.getByText('All'));
122+
123+
await act(async () => {
124+
fireEvent.click(screen.getByText('All'));
125+
});
126+
127+
expect(mockOnChange).toHaveBeenCalledWith(['all']);
128+
});
129+
130+
it('Should expand "all" into individual enum values when expandAllValue is true', async () => {
131+
const expandAllProps = {
132+
...mockProps,
133+
options: {
134+
enumOptions: [
135+
{ label: 'PROFILE', value: 'PROFILE' },
136+
{ label: 'TEST_CASE_RESULTS', value: 'TEST_CASE_RESULTS' },
137+
{ label: 'ENTITY_HISTORY', value: 'ENTITY_HISTORY' },
138+
],
139+
},
140+
schema: {
141+
...mockProps.schema,
142+
expandAllValue: true,
143+
},
144+
value: [],
145+
};
146+
147+
render(<TreeSelectWidget {...expandAllProps} />);
148+
149+
const treeSelectInput = await findByRole(
150+
screen.getByTestId('tree-select-widget'),
151+
'combobox'
152+
);
153+
154+
await act(async () => {
155+
userEvent.click(treeSelectInput);
156+
});
157+
158+
await waitFor(() => screen.getByText('All'));
159+
160+
await act(async () => {
161+
fireEvent.click(screen.getByText('All'));
162+
});
163+
164+
expect(mockOnChange).toHaveBeenCalledWith([
165+
'PROFILE',
166+
'TEST_CASE_RESULTS',
167+
'ENTITY_HISTORY',
168+
]);
169+
expect(mockOnChange).not.toHaveBeenCalledWith(['all']);
170+
});
99171
});

openmetadata-ui/src/main/resources/ui/src/components/common/Form/JSONSchema/JsonSchemaWidgets/TreeSelectWidget.tsx

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ import Icon from '@ant-design/icons/lib/components/Icon';
1414
import { WidgetProps } from '@rjsf/utils';
1515
import { TreeSelect } from 'antd';
1616
import { startCase } from 'lodash';
17-
import { FC, ReactNode, useMemo } from 'react';
17+
import { FC, ReactNode, useCallback, useMemo } from 'react';
1818
import { ReactComponent as ArrowIcon } from '../../../../../assets/svg/ic-arrow-down.svg';
1919
import { TEXT_BODY_COLOR } from '../../../../../constants/constants';
2020

21+
const ALL_VALUE = 'all';
22+
2123
const TreeSelectWidget: FC<WidgetProps> = ({
2224
onFocus,
2325
onBlur,
@@ -28,8 +30,8 @@ const TreeSelectWidget: FC<WidgetProps> = ({
2830
() => [
2931
{
3032
title: 'All',
31-
value: 'all',
32-
key: 'all',
33+
value: ALL_VALUE,
34+
key: ALL_VALUE,
3335
children: rest.options.enumOptions?.map((node) => ({
3436
title: startCase(node.label),
3537
value: node.value,
@@ -40,6 +42,32 @@ const TreeSelectWidget: FC<WidgetProps> = ({
4042
[rest.options.enumOptions]
4143
);
4244

45+
// When `expandAllValue` is set on the schema, the synthetic "all" parent
46+
// node is a UI-only convenience: the backend enum does not include "all",
47+
// so we expand it back into the full list of enum values before submit.
48+
// Without this, selecting "All" would persist a value that violates the
49+
// schema (e.g. MetadataExporterApp eventTypes).
50+
const shouldExpandAll = Boolean(rest.schema.expandAllValue);
51+
52+
const handleChange = useCallback(
53+
(value: unknown) => {
54+
if (
55+
shouldExpandAll &&
56+
Array.isArray(value) &&
57+
value.includes(ALL_VALUE)
58+
) {
59+
const expanded =
60+
rest.options.enumOptions?.map((option) => option.value) ?? [];
61+
onChange(expanded);
62+
63+
return;
64+
}
65+
66+
onChange(value);
67+
},
68+
[onChange, shouldExpandAll, rest.options.enumOptions]
69+
);
70+
4371
return (
4472
<TreeSelect
4573
allowClear
@@ -63,7 +91,7 @@ const TreeSelectWidget: FC<WidgetProps> = ({
6391
}
6492
treeData={treeData}
6593
onBlur={() => onBlur(rest.id, rest.value)}
66-
onChange={(value) => onChange(value)}
94+
onChange={handleChange}
6795
onFocus={() => onFocus(rest.id, rest.value)}
6896
{...rest}>
6997
{rest.children as ReactNode}

0 commit comments

Comments
 (0)