diff --git a/.github/playwright/impact-map.generated.json b/.github/playwright/impact-map.generated.json index 8ec9320b680b..60da398e6fed 100644 --- a/.github/playwright/impact-map.generated.json +++ b/.github/playwright/impact-map.generated.json @@ -6969,16 +6969,6 @@ "playwright/e2e/Pages/Lineage/LineageInteraction.spec.ts" ] }, - { - "sources": [ - "openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityLineage/LineageConfigModal.tsx" - ], - "specs": [ - "playwright/e2e/Features/ProfilePlatformSettings.spec.ts", - "playwright/e2e/Flow/LineageSettings.spec.ts", - "playwright/e2e/Pages/Lineage/PlatformLineage.spec.ts" - ] - }, { "sources": [ "openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityLineage/LineageControlButtons/LineageControlButtons.tsx" @@ -7645,14 +7635,6 @@ "playwright/e2e/Pages/Tag.spec.ts" ] }, - { - "sources": [ - "openmetadata-ui/src/main/resources/ui/src/components/Modals/ModalWithFunctionEditor/ModalWithFunctionEditor.tsx" - ], - "specs": [ - "playwright/e2e/Pages/Lineage/LineageInteraction.spec.ts" - ] - }, { "sources": [ "openmetadata-ui/src/main/resources/ui/src/components/Modals/ModalWithMarkdownEditor/ModalWithMarkdownEditor.tsx" @@ -8116,14 +8098,6 @@ "playwright/e2e/Pages/SearchSettings.spec.ts" ] }, - { - "sources": [ - "openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/FieldValueBoostModal/FieldValueBoostModal.tsx" - ], - "specs": [ - "playwright/e2e/Pages/SearchSettings.spec.ts" - ] - }, { "sources": [ "openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/SearchPreview/SearchPreview.tsx" @@ -8363,8 +8337,7 @@ "openmetadata-ui/src/main/resources/ui/src/components/Settings/Email/EmailConfigForm/EmailConfigForm.component.tsx" ], "specs": [ - "playwright/e2e/Features/ProfilePlatformSettings.spec.ts", - "playwright/e2e/Pages/EmailConfiguration.spec.ts" + "playwright/e2e/Features/ProfilePlatformSettings.spec.ts" ] }, { @@ -8615,17 +8588,11 @@ "openmetadata-ui/src/main/resources/ui/src/components/Settings/Users/CreateUser/CreateUser.component.tsx" ], "specs": [ - "playwright/e2e/Features/ContextCenterPermission.spec.ts", - "playwright/e2e/Features/Glossary/GlossaryDisplayNameEdit.spec.ts", "playwright/e2e/Features/QueryEntity.spec.ts", "playwright/e2e/Flow/AddRoleAndAssignToUser.spec.ts", - "playwright/e2e/Flow/PersonaFlow.spec.ts", "playwright/e2e/Pages/AIProfile/ProfileMembers.spec.ts", "playwright/e2e/Pages/AIProfile/ProfileUser.spec.ts", - "playwright/e2e/Pages/BotsProfile.spec.ts", - "playwright/e2e/Pages/DataContracts.spec.ts", - "playwright/e2e/Pages/EditClassification.spec.ts", - "playwright/e2e/Pages/Tags.spec.ts" + "playwright/e2e/Pages/DataContracts.spec.ts" ] }, { @@ -10893,6 +10860,14 @@ "playwright/e2e/Pages/SearchSettings.spec.ts" ] }, + { + "sources": [ + "openmetadata-ui/src/main/resources/ui/src/components/discovery/personal-space/Profile/tabs/platform-settings/search/FieldValueBoostDialog.tsx" + ], + "specs": [ + "playwright/e2e/Pages/SearchSettings.spec.ts" + ] + }, { "sources": [ "openmetadata-ui/src/main/resources/ui/src/components/discovery/personal-space/Profile/tabs/platform-settings/search/FieldValueBoostTable.tsx" @@ -12464,14 +12439,6 @@ "playwright/e2e/Pages/DataProducts.spec.ts" ] }, - { - "sources": [ - "openmetadata-ui/src/main/resources/ui/src/pages/Configuration/EditUrlConfiguration/EditUrlConfigurationPage.tsx" - ], - "specs": [ - "playwright/e2e/Pages/OmdURLConfiguration.spec.ts" - ] - }, { "sources": [ "openmetadata-ui/src/main/resources/ui/src/pages/Configuration/LoginConfigurationDetails/LoginConfigurationPage.tsx" @@ -12713,36 +12680,6 @@ "playwright/e2e/Pages/IntakeForm.spec.ts" ] }, - { - "sources": [ - "openmetadata-ui/src/main/resources/ui/src/pages/KPIPage/AddKPIPage.tsx" - ], - "specs": [ - "playwright/e2e/Features/ContextCenterPermission.spec.ts", - "playwright/e2e/Features/DataQuality/ProfilerSettingsAfterReindex.spec.ts", - "playwright/e2e/Features/Glossary/GlossaryDisplayNameEdit.spec.ts", - "playwright/e2e/Flow/AddRoleAndAssignToUser.spec.ts", - "playwright/e2e/Flow/PersonaFlow.spec.ts", - "playwright/e2e/Pages/BotsProfile.spec.ts", - "playwright/e2e/Pages/EditClassification.spec.ts", - "playwright/e2e/Pages/Tags.spec.ts" - ] - }, - { - "sources": [ - "openmetadata-ui/src/main/resources/ui/src/pages/KPIPage/EditKPIPage.tsx" - ], - "specs": [ - "playwright/e2e/Features/ContextCenterPermission.spec.ts", - "playwright/e2e/Features/DataQuality/ProfilerSettingsAfterReindex.spec.ts", - "playwright/e2e/Features/Glossary/GlossaryDisplayNameEdit.spec.ts", - "playwright/e2e/Flow/AddRoleAndAssignToUser.spec.ts", - "playwright/e2e/Flow/PersonaFlow.spec.ts", - "playwright/e2e/Pages/BotsProfile.spec.ts", - "playwright/e2e/Pages/EditClassification.spec.ts", - "playwright/e2e/Pages/Tags.spec.ts" - ] - }, { "sources": [ "openmetadata-ui/src/main/resources/ui/src/pages/KnowledgeCenterFilterPage/KnowledgeCenterFilterPage.tsx" @@ -12756,10 +12693,6 @@ "openmetadata-ui/src/main/resources/ui/src/pages/LearningResourcesPage/LearningResourceForm.component.tsx" ], "specs": [ - "playwright/e2e/Features/IncidentManager.spec.ts", - "playwright/e2e/Features/ProfileGovernance.spec.ts", - "playwright/e2e/Features/ProfilePlatformSettings.spec.ts", - "playwright/e2e/Pages/GlossaryTermRelationSettings.spec.ts", "playwright/e2e/Pages/LearningResources.spec.ts" ] }, @@ -12779,8 +12712,7 @@ "specs": [ "playwright/e2e/Features/MetricHierarchy.spec.ts", "playwright/e2e/Features/ProfilePlatformSettings.spec.ts", - "playwright/e2e/Flow/LineageSettings.spec.ts", - "playwright/e2e/Pages/Lineage/PlatformLineage.spec.ts" + "playwright/e2e/Flow/LineageSettings.spec.ts" ] }, { @@ -12858,8 +12790,7 @@ "openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/AddPolicyPage/AddPolicyPage.tsx" ], "specs": [ - "playwright/e2e/Features/AccessControlSettings.spec.ts", - "playwright/e2e/Pages/Policies.spec.ts" + "playwright/e2e/Features/AccessControlSettings.spec.ts" ] }, { @@ -12881,15 +12812,6 @@ "playwright/e2e/Pages/Policies.spec.ts" ] }, - { - "sources": [ - "openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/RuleForm/RuleForm.tsx" - ], - "specs": [ - "playwright/e2e/Features/AccessControlSettings.spec.ts", - "playwright/e2e/Pages/Policies.spec.ts" - ] - }, { "sources": [ "openmetadata-ui/src/main/resources/ui/src/pages/ProfilerConfigurationPage/ProfilerConfigurationPage.tsx" @@ -12914,20 +12836,8 @@ ], "specs": [ "playwright/e2e/Features/AccessControlSettings.spec.ts", - "playwright/e2e/Features/EntityRenameConsolidation.spec.ts", - "playwright/e2e/Features/Glossary/GlossaryMiscOperations.spec.ts", - "playwright/e2e/Features/Glossary/GlossaryMutualExclusivityDataProductTree.spec.ts", - "playwright/e2e/Features/MetricCustomUnitFlow.spec.ts", - "playwright/e2e/Features/MetricHierarchy.spec.ts", - "playwright/e2e/Features/MultipleRename.spec.ts", "playwright/e2e/Flow/AddRoleAndAssignToUser.spec.ts", - "playwright/e2e/Flow/PersonaFlow.spec.ts", - "playwright/e2e/Pages/AIProfile/ProfileTeam.spec.ts", - "playwright/e2e/Pages/DataProductAndSubdomains.spec.ts", - "playwright/e2e/Pages/EditClassification.spec.ts", - "playwright/e2e/Pages/IntakeForm.spec.ts", "playwright/e2e/Pages/Roles.spec.ts", - "playwright/e2e/Pages/Tags.spec.ts", "playwright/e2e/Pages/Teams.spec.ts" ] }, @@ -13181,30 +13091,6 @@ "playwright/e2e/Pages/GlossaryImportExport.spec.ts" ] }, - { - "sources": [ - "openmetadata-ui/src/main/resources/ui/src/pages/TeamsPage/AddTeamForm.tsx" - ], - "specs": [ - "playwright/e2e/Features/AIMode/Observability.spec.ts", - "playwright/e2e/Features/DataQuality/TestLibrary.spec.ts", - "playwright/e2e/Features/EntityRenameConsolidation.spec.ts", - "playwright/e2e/Features/Glossary/GlossaryMiscOperations.spec.ts", - "playwright/e2e/Features/Glossary/GlossaryMutualExclusivityDataProductTree.spec.ts", - "playwright/e2e/Features/MetricCustomUnitFlow.spec.ts", - "playwright/e2e/Features/MetricHierarchy.spec.ts", - "playwright/e2e/Features/MultipleRename.spec.ts", - "playwright/e2e/Flow/AddRoleAndAssignToUser.spec.ts", - "playwright/e2e/Flow/PersonaFlow.spec.ts", - "playwright/e2e/Pages/AIProfile/ProfileTeam.spec.ts", - "playwright/e2e/Pages/AIProfile/ProfileUser.spec.ts", - "playwright/e2e/Pages/BotsProfile.spec.ts", - "playwright/e2e/Pages/DataProductAndSubdomains.spec.ts", - "playwright/e2e/Pages/EditClassification.spec.ts", - "playwright/e2e/Pages/IntakeForm.spec.ts", - "playwright/e2e/Pages/Tags.spec.ts" - ] - }, { "sources": [ "openmetadata-ui/src/main/resources/ui/src/pages/TestSuiteDetailsPage/TestSuiteDetailsPage.component.tsx" diff --git a/openmetadata-ui/src/main/resources/ui/eslint-rules/openmetadata-antd.test.mjs b/openmetadata-ui/src/main/resources/ui/eslint-rules/openmetadata-antd.test.mjs index 4aaec83d0924..3e2b3b9d6881 100644 --- a/openmetadata-ui/src/main/resources/ui/eslint-rules/openmetadata-antd.test.mjs +++ b/openmetadata-ui/src/main/resources/ui/eslint-rules/openmetadata-antd.test.mjs @@ -163,7 +163,7 @@ test('the app config never suppresses a migrated component', async () => { // Exact, so re-running --suppress-rule cannot quietly absorb new antd usage. // Lower this when a PR removes antd imports and prunes the baseline. - const EXPECTED_SUPPRESSED_ANTD_SYMBOLS = 357; + const EXPECTED_SUPPRESSED_ANTD_SYMBOLS = 346; const suppressedSymbols = Object.values(suppressions).reduce( (total, rules) => total + (rules['openmetadata-antd/no-antd-import']?.count ?? 0), diff --git a/openmetadata-ui/src/main/resources/ui/eslint-suppressions.json b/openmetadata-ui/src/main/resources/ui/eslint-suppressions.json index 81e5b566de3c..f7aeba39f4ae 100644 --- a/openmetadata-ui/src/main/resources/ui/eslint-suppressions.json +++ b/openmetadata-ui/src/main/resources/ui/eslint-suppressions.json @@ -1008,21 +1008,6 @@ "count": 1 } }, - "src/components/Database/TableQueries/QueryCard.tsx": { - "openmetadata-antd/no-antd-import": { - "count": 1 - } - }, - "src/components/Database/TableQueries/QueryUsedByOtherTable/QueryUsedByOtherTable.component.tsx": { - "openmetadata-antd/no-antd-import": { - "count": 1 - } - }, - "src/components/Database/TableQueries/TableQueries.interface.ts": { - "openmetadata-antd/no-antd-import": { - "count": 1 - } - }, "src/components/Database/TableQueries/TableQueries.tsx": { "openmetadata-antd/no-antd-import": { "count": 3 @@ -1188,11 +1173,6 @@ "count": 1 } }, - "src/components/SearchSettings/TermBoost/TermBoost.tsx": { - "openmetadata-antd/no-antd-import": { - "count": 3 - } - }, "src/components/ServiceInsights/AgentsStatusWidget/AgentsStatusWidget.tsx": { "openmetadata-antd/no-antd-import": { "count": 1 @@ -1343,11 +1323,6 @@ "count": 1 } }, - "src/components/common/ColorPicker/ColorPicker.component.tsx": { - "openmetadata-antd/no-antd-import": { - "count": 2 - } - }, "src/components/common/DatePicker/DatePicker.tsx": { "openmetadata-antd/no-antd-import": { "count": 2 @@ -1483,11 +1458,6 @@ "count": 1 } }, - "src/components/common/TeamTypeSelect/TeamTypeSelect.component.tsx": { - "openmetadata-antd/no-antd-import": { - "count": 3 - } - }, "src/components/common/UserTeamSelectableListSearchInput/UserTeamSelectableListSearchInput.component.tsx": { "openmetadata-antd/no-antd-import": { "count": 1 diff --git a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/QueryEntity.spec.ts b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/QueryEntity.spec.ts index 15cab5e4b0c9..3f2db964702b 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/QueryEntity.spec.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/QueryEntity.spec.ts @@ -201,14 +201,18 @@ test('Query Entity', async ({ page }) => { await page.click(CODE_EDITOR_LINE, { clickCount: 3 }); await page.keyboard.press('Backspace'); await page.keyboard.type(`${queryData.queryUsedIn.table1}`); - await page.click('[data-testid="edit-query-used-in"]'); const tableSearchResponse = page.waitForResponse( - '/api/v1/search/query?q=*&index=table*' + (response) => + response.url().includes('/api/v1/search/query') && + response.url().includes('index=table') ); - await page.keyboard.type(queryData.queryUsedIn.table2); + await page + .getByTestId('edit-query-used-in') + .getByRole('combobox') + .fill(queryData.queryUsedIn.table2); await tableSearchResponse; await page - .locator('.ant-select-dropdown:visible .ant-select-item-option') + .getByRole('option') .filter({ has: page.getByText(queryData.queryUsedIn.table2, { exact: true }), }) diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/QueryCard.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/QueryCard.tsx index 30f5e471682a..f9902026ea8f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/QueryCard.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/QueryCard.tsx @@ -21,7 +21,6 @@ import { Typography, } from '@openmetadata/ui-core-components'; import { Copy01 } from '@openmetadata/ui-core-components/icons'; -import { DefaultOptionType } from 'antd/lib/select'; import classNames from 'classnames'; import { isUndefined, split } from 'lodash'; import { Duration } from 'luxon'; @@ -41,6 +40,7 @@ import { } from '../../../constants/Query.constant'; import { CSMode } from '../../../enums/codemirror.enum'; import { EntityTabs, EntityType } from '../../../enums/entity.enum'; +import { EntityReference } from '../../../generated/type/entityReference'; import { useClipboard } from '../../../hooks/useClipBoard'; import useCustomLocation from '../../../hooks/useCustomLocation/useCustomLocation'; import { useFqn } from '../../../hooks/useFqn'; @@ -86,7 +86,7 @@ const QueryCard: FC = ({ query: query.query, isLoading: false, }); - const [selectedTables, setSelectedTables] = useState(); + const [selectedTables, setSelectedTables] = useState(); const { isAllowExpand, queryDate } = useMemo(() => { const queryArr = split(query.query, '\n'); @@ -130,21 +130,7 @@ const QueryCard: FC = ({ const updatedData = { ...query, query: query.query !== sqlQuery.query ? sqlQuery.query : query.query, - queryUsedIn: isUndefined(selectedTables) - ? query.queryUsedIn - : selectedTables.map((option) => { - const existingTable = query.queryUsedIn?.find( - (table) => table.id === option.value - ); - - return ( - existingTable ?? { - id: (option.value as string) ?? '', - displayName: option.labelName as string, - type: EntityType.TABLE, - } - ); - }), + queryUsedIn: selectedTables ?? query.queryUsedIn, }; if (query.query !== sqlQuery.query || !isUndefined(selectedTables)) { await onQueryUpdate(updatedData, 'query'); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/QueryUsedByOtherTable/QueryUsedByOtherTable.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/QueryUsedByOtherTable/QueryUsedByOtherTable.component.tsx index 455ef5e6b9af..6325944d50f9 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/QueryUsedByOtherTable/QueryUsedByOtherTable.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/QueryUsedByOtherTable/QueryUsedByOtherTable.component.tsx @@ -17,25 +17,17 @@ import { PopoverTrigger, Typography, } from '@openmetadata/ui-core-components'; - -import { DefaultOptionType } from 'antd/lib/select'; -import { isArray, isUndefined, slice, uniqBy } from 'lodash'; +import { isUndefined, slice } from 'lodash'; import { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Link } from 'react-router-dom'; -import { - INITIAL_PAGING_VALUE, - PAGE_SIZE_MEDIUM, -} from '../../../../constants/constants'; import { QUERY_USED_BY_TABLE_VIEW_CAP } from '../../../../constants/Query.constant'; import { EntityType } from '../../../../enums/entity.enum'; import { SearchIndex } from '../../../../enums/search.enum'; -import { searchQuery } from '../../../../rest/searchAPI'; import { getEntityName } from '../../../../utils/EntityNameUtils'; import { getEntityDetailsPath } from '../../../../utils/RouterUtils'; -import { AsyncSelect } from '../../../common/AsyncSelect/AsyncSelect'; -import Loader from '../../../common/Loader/Loader'; -import getEntityLabel from '../../../Entity/EntityLabel/EntityLabel.component'; +import DataAssetAsyncSelectList from '../../../DataAssets/DataAssetAsyncSelectList/DataAssetAsyncSelectList'; +import { DataAssetOption } from '../../../DataAssets/DataAssetAsyncSelectList/DataAssetAsyncSelectList.interface'; import { QueryUsedByOtherTableProps, QueryUsedByTable, @@ -47,8 +39,6 @@ const QueryUsedByOtherTable = ({ onChange, }: QueryUsedByOtherTableProps) => { const { t } = useTranslation(); - const [initialOptions, setInitialOptions] = useState([]); - const [isLoading, setIsLoading] = useState(false); const { topThreeTable, remainingTable } = useMemo(() => { const { queryUsedIn } = query; @@ -131,85 +121,43 @@ const QueryUsedByOtherTable = ({ [topThreeTable, remainingTable] ); - const handleOnChange = ( - _: string[], - options?: DefaultOptionType | DefaultOptionType[] - ) => { - if (isArray(options)) { - onChange(options); - } - }; - - const fetchTableEntity = async ( - searchValue = '' - ): Promise => { - try { - const response = await searchQuery({ - query: searchValue, - pageNumber: INITIAL_PAGING_VALUE, - pageSize: PAGE_SIZE_MEDIUM, - searchIndex: SearchIndex.TABLE, - }); - - return response.hits.hits.map((value) => ({ - label: getEntityLabel(value._source), - value: value._source.id, - labelName: getEntityName(value._source), - })); - } catch (error) { - return []; - } - }; - - const fetchInitialOptions = async () => { - setIsLoading(true); - try { - const options = await fetchTableEntity(); - const { queryUsedIn = [] } = query; - const selectedValue = queryUsedIn.map((table) => ({ - label: getEntityLabel(table), - value: table.id, - labelName: getEntityName(table), - })); - - setInitialOptions(uniqBy([...selectedValue, ...options], 'labelName')); - } catch (error) { - setInitialOptions([]); - } finally { - setIsLoading(false); - } - }; - - const selectList = useMemo(() => { - const { queryUsedIn = [] } = query; - - const defaultValue = queryUsedIn.map((table) => table.id); + const initialOptions = useMemo( + () => + (query.queryUsedIn ?? []).map((table) => ({ + value: table.fullyQualifiedName, + displayName: getEntityName(table), + reference: table, + })), + [query.queryUsedIn] + ); + // The picker is controlled, so it must be fed the user's picks rather than + // the saved tables, or each re-render would reset the selection. + const [selectedOptions, setSelectedOptions] = useState(initialOptions); - return isLoading ? ( - - ) : ( - { + setSelectedOptions(initialOptions); + }, [initialOptions]); + + const selectList = ( +
+ { + const next = Array.isArray(options) ? options : []; + setSelectedOptions(next); + onChange(next.map((option) => option.reference)); + }} /> - ); - }, [query, initialOptions, isLoading, fetchTableEntity, handleOnChange]); - - useEffect(() => { - if (isEditMode) { - fetchInitialOptions(); - } - }, [isEditMode]); +
+ ); return ( diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/QueryUsedByOtherTable/QueryUsedByOtherTable.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/QueryUsedByOtherTable/QueryUsedByOtherTable.test.tsx index 14e9e991b4e4..909e5e23813c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/QueryUsedByOtherTable/QueryUsedByOtherTable.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/QueryUsedByOtherTable/QueryUsedByOtherTable.test.tsx @@ -11,22 +11,23 @@ * limitations under the License. */ -import { render, screen } from '@testing-library/react'; +import { act, render, screen } from '@testing-library/react'; import { MemoryRouter } from 'react-router-dom'; +import { SearchIndex } from '../../../../enums/search.enum'; import { Query } from '../../../../generated/entity/data/query'; import { MOCK_QUERIES } from '../../../../mocks/Queries.mock'; -import { searchQuery } from '../../../../rest/searchAPI'; -import { MOCK_EXPLORE_SEARCH_RESULTS } from '../../../Explore/Explore.mock'; +import { DataAssetAsyncSelectListProps } from '../../../DataAssets/DataAssetAsyncSelectList/DataAssetAsyncSelectList.interface'; import { QueryUsedByOtherTableProps } from '../TableQueries.interface'; import QueryUsedByOtherTable from './QueryUsedByOtherTable.component'; -jest.mock('../../../common/AsyncSelect/AsyncSelect', () => ({ - AsyncSelect: jest - .fn() - .mockImplementation(() =>
AsyncSelect.component
), -})); +const mockDataAssetSelect = jest + .fn() + .mockImplementation(() =>
DataAssetAsyncSelectList
); -jest.mock('../../../../rest/searchAPI'); +jest.mock( + '../../../DataAssets/DataAssetAsyncSelectList/DataAssetAsyncSelectList', + () => (props: DataAssetAsyncSelectListProps) => mockDataAssetSelect(props) +); const mockProps: QueryUsedByOtherTableProps = { query: MOCK_QUERIES[0] as Query, @@ -35,10 +36,6 @@ const mockProps: QueryUsedByOtherTableProps = { }; describe('QueryUsedByOtherTable test', () => { - beforeEach(() => { - (searchQuery as jest.Mock).mockResolvedValue(MOCK_EXPLORE_SEARCH_RESULTS); - }); - it('Component should render', async () => { render(, { wrapper: MemoryRouter, @@ -71,40 +68,67 @@ describe('QueryUsedByOtherTable test', () => { ); }); - it('Should display select box if edit mode is true', async () => { + it('Should search tables and preselect the current ones in edit mode', async () => { render(, { wrapper: MemoryRouter, }); - const selectField = await screen.findByText('AsyncSelect.component'); - expect(selectField).toBeInTheDocument(); + expect( + await screen.findByText('DataAssetAsyncSelectList') + ).toBeInTheDocument(); + + const props = mockDataAssetSelect.mock.calls[0][0]; + const usedIn = MOCK_QUERIES[0].queryUsedIn ?? []; + + expect(props.searchIndex).toBe(SearchIndex.TABLE); + expect(props.multiple).toBe(true); + expect( + props.value.map((option: { value?: string }) => option.value) + ).toEqual(usedIn.map((t) => t.fullyQualifiedName)); }); - it('Should fetch initial dropdown list in edit mode', async () => { - const mockSearchQuery = searchQuery as jest.Mock; - render(, { - wrapper: MemoryRouter, - }); - const selectField = await screen.findByText('AsyncSelect.component'); - - expect(selectField).toBeInTheDocument(); - expect(mockSearchQuery).toHaveBeenCalledWith({ - query: '', - pageNumber: 1, - pageSize: 25, - searchIndex: 'table', - }); + it('Should report the picked tables as entity references', async () => { + const onChange = jest.fn(); + render( + , + { wrapper: MemoryRouter } + ); + await screen.findByText('DataAssetAsyncSelectList'); + + const reference = { id: 'table-id', type: 'table', name: 'orders' }; + mockDataAssetSelect.mock.calls[0][0].onChange([ + { displayName: 'orders', value: 'db.orders', reference }, + ]); + + expect(onChange).toHaveBeenCalledWith([reference]); }); - it('Loader should be visible while loading the initial options', async () => { - render(, { - wrapper: MemoryRouter, - }); + it('Should keep the picked tables when the parent re-renders', async () => { + const { rerender } = render( + , + { wrapper: MemoryRouter } + ); + await screen.findByText('DataAssetAsyncSelectList'); - expect(screen.getByTestId('loader')).toBeInTheDocument(); + const picked = [ + { + displayName: 'orders', + value: 'db.orders', + reference: { id: 'orders-id', type: 'table' }, + }, + ]; + act(() => { + mockDataAssetSelect.mock.calls[0][0].onChange(picked); + }); + rerender( + + ); - const selectField = await screen.findByText('AsyncSelect.component'); + const lastProps = + mockDataAssetSelect.mock.calls[ + mockDataAssetSelect.mock.calls.length - 1 + ][0]; - expect(selectField).toBeInTheDocument(); + expect(lastProps.value).toEqual(picked); }); }); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/TableQueries.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/TableQueries.interface.ts index f417f6086467..9aed7922c293 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/TableQueries.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/TableQueries.interface.ts @@ -11,7 +11,6 @@ * limitations under the License. */ -import type { DefaultOptionType } from 'antd/lib/select'; import { HTMLAttributes } from 'react'; import { OperationPermission } from '../../../context/PermissionProvider/PermissionProvider.interface'; import { SORT_ORDER } from '../../../enums/common.enum'; @@ -60,7 +59,7 @@ export type QueryUsedByTable = { export interface QueryUsedByOtherTableProps { query: Query; isEditMode: boolean; - onChange: (value: DefaultOptionType[]) => void; + onChange: (tables: EntityReference[]) => void; } export type QuerySearchParams = { diff --git a/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/EntitySeachSettings/EntitySearchSettings.tsx b/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/EntitySeachSettings/EntitySearchSettings.tsx index 18cdcc17fb33..0289c9967bc1 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/EntitySeachSettings/EntitySearchSettings.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/EntitySeachSettings/EntitySearchSettings.tsx @@ -1044,7 +1044,6 @@ const EntitySearchSettings = () => { handleDeleteTermBoost={handleDeleteTermBoost} handleTermBoostChange={handleTermBoostChange} showNewTermBoost={showNewTermBoost} - termBoostCardClassName="term-boost-card" termBoosts={searchSettings.termBoosts ?? []} /> diff --git a/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/EntitySeachSettings/entity-search-settings.less b/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/EntitySeachSettings/entity-search-settings.less index d0ff0c1f29e0..385b13e3b476 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/EntitySeachSettings/entity-search-settings.less +++ b/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/EntitySeachSettings/entity-search-settings.less @@ -98,10 +98,6 @@ } } -.term-boost-card { - min-width: 100%; -} - .ranking-configuration-container { .ranking-configuration { display: flex; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/TermBoost/TermBoost.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/TermBoost/TermBoost.test.tsx deleted file mode 100644 index 6e69cb31d573..000000000000 --- a/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/TermBoost/TermBoost.test.tsx +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2025 Collate. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { fireEvent, render, screen, waitFor } from '@testing-library/react'; -import { TermBoost } from '../../../generated/configuration/searchSettings'; -import tagClassBase from '../../../utils/TagClassBase'; -import TermBoostComponent from './TermBoost'; - -jest.mock('react-i18next', () => ({ - useTranslation: () => ({ - t: (str: string) => str, - }), -})); - -jest.mock('../../../utils/TagClassBase', () => ({ - getTags: jest.fn(), -})); - -jest.mock('../../common/AsyncSelect/AsyncSelect', () => ({ - AsyncSelect: jest.fn().mockImplementation(({ api }) => ( -
-

AsyncSelect

- api('test')} - /> -
- )), -})); - -const mockTermBoost: TermBoost = { - field: 'tags.tagFQN', - value: 'PII.Sensitive', - boost: 5, -}; - -const mockProps = { - termBoost: mockTermBoost, - onTermBoostChange: jest.fn(), - onDeleteBoost: jest.fn(), -}; - -const mockTagResponse = { - data: [ - { - data: { - name: 'Sensitive', - displayName: 'Sensitive', - fullyQualifiedName: 'PII.Sensitive', - }, - }, - ], - paging: { - total: 1, - }, -}; - -describe('TermBoost Component', () => { - beforeEach(() => { - jest.clearAllMocks(); - (tagClassBase.getTags as jest.Mock).mockResolvedValue(mockTagResponse); - }); - - it('Should render component with initial values', () => { - render(); - - expect(screen.getByTestId('term-boost-impact-label')).toBeInTheDocument(); - expect(screen.getByTestId('term-boost-value')).toBeInTheDocument(); - expect(screen.getByTestId('term-boost-slider')).toBeInTheDocument(); - expect(screen.getByTestId('term-boost-select')).toBeInTheDocument(); - }); - - it('Should handle tag selection', async () => { - render(); - - const select = screen.getByTestId('term-boost-select'); - fireEvent.click(select); - - await waitFor(() => { - expect(tagClassBase.getTags).toHaveBeenCalledWith('test', 1, true); - }); - }); - - it('Should handle delete tag boost', () => { - render(); - - const deleteIcon = screen.getByTestId('delete-term-boost'); - fireEvent.click(deleteIcon); - - expect(mockProps.onDeleteBoost).toHaveBeenCalledWith('PII.Sensitive'); - }); -}); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/TermBoost/TermBoost.tsx b/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/TermBoost/TermBoost.tsx deleted file mode 100644 index a57d4e25872e..000000000000 --- a/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/TermBoost/TermBoost.tsx +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright 2025 Collate. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import Icon, { DownOutlined } from '@ant-design/icons'; -import { - Box, - Button, - Divider, - Typography, -} from '@openmetadata/ui-core-components'; -import { Slider } from 'antd'; -import { AxiosError } from 'axios'; -import classNames from 'classnames'; -import { ComponentProps, useEffect, useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import { ReactComponent as Delete } from '../../../assets/svg/delete-colored.svg'; -import { TermBoost } from '../../../generated/configuration/searchSettings'; -import { getFilterOptions } from '../../../utils/SearchSettingsUtils'; -import tagClassBase from '../../../utils/TagClassBase'; -import { showErrorToast } from '../../../utils/ToastUtils'; -import { AsyncSelect } from '../../common/AsyncSelect/AsyncSelect'; -import './term-boost.less'; - -interface TermBoostProps { - className?: string; - termBoost: TermBoost; - onTermBoostChange: (termBoost: TermBoost) => void; - onDeleteBoost: (termValue: string) => void; - showNewTermBoost?: boolean; -} - -const TermBoostComponent: React.FC = ({ - className, - termBoost, - onTermBoostChange, - onDeleteBoost, - showNewTermBoost, -}) => { - const { t } = useTranslation(); - const [termBoostData, setTermBoostData] = useState({ - field: '', - value: '', - boost: 0, - }); - - const isNewBoost = showNewTermBoost || (!termBoost.field && !termBoost.value); - - useEffect(() => { - if (!isNewBoost) { - setTermBoostData({ - field: termBoost.field, - value: termBoost.value, - boost: termBoost.boost, - }); - } - }, [termBoost, isNewBoost]); - - const fetchTags = async (searchText: string, page = 1) => { - try { - const response = await tagClassBase.getTags(searchText, page, true); - - const formattedOptions = response.data.map((item) => { - const fqn = item.data.fullyQualifiedName; - let field = 'tags.tagFQN'; // default field - - // Determine field based on FQN pattern - if (fqn?.startsWith('Certification.')) { - field = 'certification.tagLabel.tagFQN'; - } else if (fqn?.startsWith('Tier.')) { - field = 'tier.tagFQN'; - } - - return { - label: ( -
- - {item.data.displayName ?? item.data.name} - - - {fqn} - -
- ), - value: fqn, - field: field, - }; - }); - - // Return PagingResponse structure for infinite scroll support - return { - data: formattedOptions, - paging: response.paging, - }; - } catch (error) { - showErrorToast(error as AxiosError); - - // Return empty PagingResponse structure on error - return { - data: [], - paging: { total: 0 }, - }; - } - }; - - const handleTagChange: NonNullable< - ComponentProps['onChange'] - > = (value, option) => { - const selectedOption = Array.isArray(option) ? option[0] : option; - const updatedData = { - ...termBoostData, - field: selectedOption?.field, - value: value as string, - }; - - setTermBoostData(updatedData); - onTermBoostChange(updatedData); - }; - - const handleBoostChange = (value: number) => { - const updatedData = { ...termBoostData, boost: value }; - - setTermBoostData(updatedData); - onTermBoostChange(updatedData); - }; - - return ( -
- - - } - value={termBoostData.value || undefined} - onChange={handleTagChange} - /> - - -
- - {t('label.boost')} - - - {termBoostData.boost} - -
-
- -
- -
- -
- ); -}; - -export default TermBoostComponent; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/TermBoost/term-boost.less b/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/TermBoost/term-boost.less deleted file mode 100644 index 8f6c1ebeeaba..000000000000 --- a/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/TermBoost/term-boost.less +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2025 Collate. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -@import '../../../styles/variables.less'; - -.term-boost { - background-color: var(--tw-color-bg-primary); - border: 1px solid @grey-100; - border-radius: var(--om-radius-xl); -} - -.delete-term-boost { - color: @red-12; - background-color: @red-9; - border: 1px solid @red-13; - border-radius: var(--om-radius-lg); - &:hover { - color: @red-12; - background-color: @red-9; - border: 1px solid @red-13; - } -} - -.boost-value { - color: @blue-3; -} - -.config-section-content { - border: 1px solid @border-color-4; -} - -.custom-select { - .ant-select-selector { - padding-left: 0; - padding-right: 0; - border: none !important; - } - - .ant-select-focused .ant-select-selector, - .ant-select-selector:focus, - .ant-select-selector:active, - .ant-select-open .ant-select-selector { - border: none; - box-shadow: none; - } - - &.ant-select-focused:not(.ant-select-disabled):not( - .ant-select-customize-input - ):not(.ant-select-borderless) - .ant-select-selector { - border: none; - box-shadow: none; - } - - &.ant-select-disabled { - .ant-select-selector { - background-color: transparent; - color: @black; - } - } -} - -.config-section-content - .ant-select-disabled.ant-select:not(.ant-select-customize-input) - .ant-select-selector { - background-color: transparent; - color: @black; - cursor: default; -} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/TermBoostList/TermBoostList.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/TermBoostList/TermBoostList.test.tsx index e07fb454378c..cff0e42b55d0 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/TermBoostList/TermBoostList.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/TermBoostList/TermBoostList.test.tsx @@ -30,37 +30,42 @@ const mockTermBoosts: TermBoost[] = [ const mockHandleDeleteTermBoost = jest.fn(); const mockHandleTermBoostChange = jest.fn(); -jest.mock('../TermBoost/TermBoost', () => { - return jest - .fn() - .mockImplementation( - ({ termBoost, showNewTermBoost, onDeleteBoost, onTermBoostChange }) => ( -
- {termBoost.value || 'New Term Boost'} - - -
- ) - ); -}); + {termBoost?.value || 'New Term Boost'} + + + + ) + ); + } +); describe('TermBoostList', () => { beforeEach(() => { diff --git a/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/TermBoostList/TermBoostList.tsx b/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/TermBoostList/TermBoostList.tsx index cdf9234ce20e..120fa2681bdb 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/TermBoostList/TermBoostList.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/SearchSettings/TermBoostList/TermBoostList.tsx @@ -12,12 +12,11 @@ */ import classNames from 'classnames'; import { TermBoost } from '../../../generated/configuration/searchSettings'; -import TermBoostComponent from '../TermBoost/TermBoost'; +import TermBoostCard from '../../discovery/personal-space/Profile/tabs/platform-settings/search/TermBoostCard'; import './term-boost-list.less'; interface TermBoostListProps { className?: string; - termBoostCardClassName?: string; termBoosts: TermBoost[]; showNewTermBoost?: boolean; handleDeleteTermBoost: (value: string) => void; @@ -26,7 +25,6 @@ interface TermBoostListProps { const TermBoostList = ({ className, - termBoostCardClassName, termBoosts, showNewTermBoost, handleDeleteTermBoost, @@ -39,21 +37,17 @@ const TermBoostList = ({ 'd-flex items-center gap-2 flex-wrap m-b-xs term-boosts-container' )}> {termBoosts.map((termBoost) => ( - ))} {showNewTermBoost && ( - handleDeleteTermBoost('')} - onTermBoostChange={handleTermBoostChange} + handleDeleteTermBoost('')} /> )} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/ColorPicker/ColorPicker.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/ColorPicker/ColorPicker.component.tsx index 9a089da92a0f..118b78cdd461 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/ColorPicker/ColorPicker.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/ColorPicker/ColorPicker.component.tsx @@ -10,30 +10,53 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Input, InputProps } from 'antd'; +import { Box, Input } from '@openmetadata/ui-core-components'; import { useTranslation } from 'react-i18next'; -import './color-picker.style.less'; -const ColorPicker = (props: InputProps) => { +export interface ColorPickerProps { + id?: string; + /** Names both controls, so each theme colour is distinguishable. */ + label: string; + value?: string; + onBlur?: () => void; + onChange?: (value: string) => void; +} + +const ColorPicker = ({ + id, + label, + value = '', + onBlur, + onChange, +}: ColorPickerProps) => { const { t } = useTranslation(); - const { id, ...rest } = props; + const testId = id ? `${id}-color` : 'color'; return ( - - + {/* Core has no colour swatch control; a core Input squeezes the native + swatch into a thin stripe, so the swatch stays a native colour input. */} + onChange?.(e.target.value)} /> - - + + + +
); }; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/ColorPicker/ColorPicker.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/ColorPicker/ColorPicker.test.tsx index b34b5fc6ab61..d4ff13dbead2 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/ColorPicker/ColorPicker.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/ColorPicker/ColorPicker.test.tsx @@ -10,21 +10,50 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { render, screen } from '@testing-library/react'; +import { fireEvent, render, screen } from '@testing-library/react'; import ColorPicker from './ColorPicker.component'; describe('ColorPicker component', () => { it('component should render', async () => { - render(); + render(); expect(await screen.findByTestId('color-picker')).toBeInTheDocument(); expect(await screen.findByTestId('color-input')).toBeInTheDocument(); }); it('Should have same value in color picker and input box', async () => { - render(); + render(); expect(await screen.findByTestId('color-picker')).toHaveValue('#000000'); expect(await screen.findByTestId('color-input')).toHaveValue('#000000'); }); + + it('reports a typed hex code as a plain string', () => { + const onChange = jest.fn(); + render( + + ); + + fireEvent.change(screen.getByTestId('primaryColor-color-input'), { + target: { value: '#123456' }, + }); + + expect(onChange).toHaveBeenCalledWith('#123456'); + }); + + it('names the hex box and the swatch after the field', () => { + render(); + + expect(screen.getByTestId('color-input')).toHaveAccessibleName( + 'Primary Color' + ); + expect(screen.getByTestId('color-picker')).toHaveAccessibleName( + 'label.select-field' + ); + }); }); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/ColorPicker/color-picker.style.less b/openmetadata-ui/src/main/resources/ui/src/components/common/ColorPicker/color-picker.style.less deleted file mode 100644 index 49b340eb0766..000000000000 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/ColorPicker/color-picker.style.less +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2023 Collate. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -.ant-input-group .ant-input.style-color-picker { - width: 15%; -} -.ant-input-group .ant-input.style-color-input { - width: 85%; -} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/TeamTypeSelect/TeamTypeSelect.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/TeamTypeSelect/TeamTypeSelect.component.tsx index 971716fe203b..c3d95a51a34b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/TeamTypeSelect/TeamTypeSelect.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/TeamTypeSelect/TeamTypeSelect.component.tsx @@ -11,10 +11,10 @@ * limitations under the License. */ -import { CheckOutlined, CloseOutlined } from '@ant-design/icons'; -import { Box, Button } from '@openmetadata/ui-core-components'; -import { Select } from 'antd'; +import { Box, Button, Select } from '@openmetadata/ui-core-components'; +import { Check, XClose } from '@openmetadata/ui-core-components/icons'; import { useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { TeamType } from '../../../generated/entity/teams/team'; import { getTeamOptionsFromType } from '../../../utils/TeamUtils'; import { TeamTypeSelectProps } from './TeamTypeSelect.interface'; @@ -26,12 +26,9 @@ function TeamTypeSelect({ updateTeamType, parentTeamType, }: TeamTypeSelectProps) { + const { t } = useTranslation(); const [value, setValue] = useState(teamType); - const handleSelect = (type: TeamType) => { - setValue(type); - }; - const handleCancel = () => { handleShowTypeSelector(false); }; @@ -42,13 +39,13 @@ function TeamTypeSelect({ const options = useMemo(() => { const options = getTeamOptionsFromType(parentTeamType).map((type) => ({ + id: type, label: type, - value: type, })); return showGroupOption ? options - : options.filter((opt) => opt.value !== TeamType.Group); + : options.filter((opt) => opt.id !== TeamType.Group); }, [parentTeamType, showGroupOption]); // Editing the team type must not toggle its parent collapsible panel. @@ -62,11 +59,13 @@ function TeamTypeSelect({ itemClassName="layout-space-item" onClick={(e) => e.stopPropagation()}> + onClick={handleCancel} + /> + onClick={handleSubmit} + /> ); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/TeamTypeSelect/TeamTypeSelect.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/TeamTypeSelect/TeamTypeSelect.test.tsx index 9e36eeaba3a2..d0fbbb0d7749 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/TeamTypeSelect/TeamTypeSelect.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/TeamTypeSelect/TeamTypeSelect.test.tsx @@ -10,7 +10,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { fireEvent, render } from '@testing-library/react'; +import { act, fireEvent, render, screen } from '@testing-library/react'; import { TeamType } from '../../../generated/entity/teams/team'; import TeamTypeSelect from './TeamTypeSelect.component'; @@ -26,12 +26,9 @@ const mockProps = { }; jest.mock('../../../utils/TeamUtils', () => ({ - getTeamOptionsFromType: jest.fn().mockReturnValue([ - { label: 'BusinessUnit', value: 'BusinessUnit' }, - { label: 'Division', value: 'Division' }, - { label: 'Department', value: 'Department' }, - { label: 'Group', value: 'Group' }, - ]), + getTeamOptionsFromType: jest + .fn() + .mockReturnValue(['BusinessUnit', 'Division', 'Department', 'Group']), })); describe('TeamTypeSelect', () => { @@ -55,4 +52,31 @@ describe('TeamTypeSelect', () => { expect(updateTeamType).toHaveBeenCalled(); }); + + it('should save the team type picked from the list', async () => { + render(); + + await act(async () => { + fireEvent.click(screen.getByRole('button', { name: /team-type/ })); + }); + await act(async () => { + fireEvent.click(screen.getByRole('option', { name: 'Division' })); + }); + fireEvent.click(screen.getByTestId('save-btn')); + + expect(updateTeamType).toHaveBeenCalledWith(TeamType.Division); + }); + + it('should not offer Group when the group option is hidden', async () => { + render(); + + await act(async () => { + fireEvent.click(screen.getByRole('button', { name: /team-type/ })); + }); + + expect(screen.queryByRole('option', { name: 'Group' })).toBeNull(); + expect( + screen.getByRole('option', { name: 'Division' }) + ).toBeInTheDocument(); + }); }); diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/AppearanceConfigSettingsPage/AppearanceConfigSettingsPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/AppearanceConfigSettingsPage/AppearanceConfigSettingsPage.tsx index 9a047b150132..5de1b713dd1f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/AppearanceConfigSettingsPage/AppearanceConfigSettingsPage.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/AppearanceConfigSettingsPage/AppearanceConfigSettingsPage.tsx @@ -351,11 +351,10 @@ const AppearanceConfigSettingsPage = () => { - control.onChange(e.target.value) - } + onChange={control.onChange} /> {fieldState.error && ( diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/SearchSettingsPage/SearchSettingsPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/SearchSettingsPage/SearchSettingsPage.tsx index 7b5cc1d0c5e0..cb81c5bcd3c2 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/SearchSettingsPage/SearchSettingsPage.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/SearchSettingsPage/SearchSettingsPage.tsx @@ -142,7 +142,6 @@ const SearchBoostsSection = ({ handleDeleteTermBoost={onDeleteTermBoost} handleTermBoostChange={onTermBoostChange} showNewTermBoost={showNewTermBoost} - termBoostCardClassName="settings-term-boost-card" termBoosts={searchConfig?.globalSettings?.termBoosts ?? []} /> diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/SearchSettingsPage/search-settings.less b/openmetadata-ui/src/main/resources/ui/src/pages/SearchSettingsPage/search-settings.less index c0f26cfac2f7..1a4f612bc6fd 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/SearchSettingsPage/search-settings.less +++ b/openmetadata-ui/src/main/resources/ui/src/pages/SearchSettingsPage/search-settings.less @@ -163,6 +163,3 @@ } } -.settings-term-boost-card { - min-width: 300px; -} diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/formUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/formUtils.tsx index 3d6295fcabf2..762701adbbd7 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/formUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/formUtils.tsx @@ -36,7 +36,6 @@ import { ComponentProps, Fragment, ReactNode } from 'react'; import type { Placement } from 'react-aria'; import AsyncSelectList from '../components/common/AsyncSelectList/AsyncSelectList'; import { AsyncSelectListProps } from '../components/common/AsyncSelectList/AsyncSelectList.interface'; -import ColorPicker from '../components/common/ColorPicker/ColorPicker.component'; import DomainSelectableList from '../components/common/DomainSelectableList/DomainSelectableList.component'; import { DomainSelectableListProps } from '../components/common/DomainSelectableList/DomainSelectableList.interface'; import FilterPattern from '../components/common/FilterPattern/FilterPattern'; @@ -193,9 +192,6 @@ const FIELD_ELEMENT_RENDERERS: Partial< ), }; }, - [FieldTypes.COLOR_PICKER]: ({ props }) => ({ - element: , - }), [FieldTypes.COMPONENT]: ({ props }) => ({ element: props.children, }),