From 7c395a82d4dd2d2496d86ddc04930df45bebc91d Mon Sep 17 00:00:00 2001 From: Aniket Katkar <51777795+aniketkatkar97@users.noreply.github.com> Date: Wed, 9 Nov 2022 11:11:01 +0530 Subject: [PATCH] Feat(UI): Added EntitySummaryPanel in Explore page (#8591) * Added EntitySummaryPanel in Explore page * Worked on comments to optimise code for EntitySummaryPanel * fixed faling unit test for explore component --- .../ColumnSummary/ColumnSummary.component.tsx | 87 +++++ .../ColumnSummary/ColumnSummary.interface.ts | 26 ++ .../EntitySummaryPanel.component.tsx | 100 +++++ .../EntitySummaryPanel.interface.ts | 28 ++ .../EntitySummaryPanel.style.less | 84 ++++ .../components/Explore/Explore.component.tsx | 360 ++++++++++++------ .../src/components/Explore/Explore.test.tsx | 23 -- .../TableDataCardV2.test.tsx | 4 + .../table-data-card-v2/TableDataCardV2.tsx | 6 +- .../table-data-card/TableDataCardBody.tsx | 19 +- .../searched-data/SearchedData.interface.ts | 2 + .../searched-data/SearchedData.test.tsx | 7 + .../components/searched-data/SearchedData.tsx | 2 + .../ui/src/locale/languages/en-us.json | 4 +- .../resources/ui/src/utils/CommonUtils.tsx | 17 + 15 files changed, 619 insertions(+), 150 deletions(-) create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Explore/ColumnSummary/ColumnSummary.component.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Explore/ColumnSummary/ColumnSummary.interface.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/EntitySummaryPanel.component.tsx create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/EntitySummaryPanel.interface.ts create mode 100644 openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/EntitySummaryPanel.style.less diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/ColumnSummary/ColumnSummary.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Explore/ColumnSummary/ColumnSummary.component.tsx new file mode 100644 index 00000000000..385dd13376a --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/ColumnSummary/ColumnSummary.component.tsx @@ -0,0 +1,87 @@ +/* + * Copyright 2022 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 { Divider, Space, Typography } from 'antd'; +import { toLower } from 'lodash'; +import React, { useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; +import { getTagValue } from '../../../utils/CommonUtils'; +import SVGIcons from '../../../utils/SvgUtils'; +import RichTextEditorPreviewer from '../../common/rich-text-editor/RichTextEditorPreviewer'; +import TagsViewer from '../../tags-viewer/tags-viewer'; +import { BasicColumnInfo, ColumnSummaryProps } from './ColumnSummary.interface'; + +const { Text, Paragraph } = Typography; + +export default function ColumnSummary({ columns }: ColumnSummaryProps) { + const { t } = useTranslation(); + + const formattedColumnsData: BasicColumnInfo[] = useMemo(() => { + if (columns) { + return columns.map((column) => ({ + name: column.name, + type: column.dataType, + tags: column.tags, + description: column.description, + })); + } else return []; + }, [columns]); + + return ( + + {columns && + formattedColumnsData.map((column) => ( + + + {column.name} + + + {`${t('label.type')}:`} + {toLower(column.type)} + + {column.tags?.length !== 0 && ( + <> + + + + + + getTagValue(tag) + )} + /> + + + )} + + + {column.description ? ( + + ) : ( + t('label.no-description') + )} + + + + + ))} + + ); +} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/ColumnSummary/ColumnSummary.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/Explore/ColumnSummary/ColumnSummary.interface.ts new file mode 100644 index 00000000000..02e9096dff8 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/ColumnSummary/ColumnSummary.interface.ts @@ -0,0 +1,26 @@ +/* + * Copyright 2022 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 { Column, DataType } from '../../../generated/entity/data/table'; +import { TagLabel } from './../../../generated/type/tagLabel'; + +export interface ColumnSummaryProps { + columns: Column[]; +} + +export interface BasicColumnInfo { + name: string; + type: DataType; + tags?: TagLabel[]; + description?: string; +} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/EntitySummaryPanel.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/EntitySummaryPanel.component.tsx new file mode 100644 index 00000000000..e3cf5cd302b --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/EntitySummaryPanel.component.tsx @@ -0,0 +1,100 @@ +/* + * Copyright 2022 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 { CloseOutlined } from '@ant-design/icons'; +import { Col, Divider, Row, Space, Typography } from 'antd'; +import classNames from 'classnames'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { TableType } from '../../../generated/entity/data/table'; +import ColumnSummary from '../ColumnSummary/ColumnSummary.component'; +import { + BasicTableInfo, + EntitySummaryPanelProps, +} from './EntitySummaryPanel.interface'; +import './EntitySummaryPanel.style.less'; + +export default function EntitySummaryPanel({ + entityDetails, + handleClosePanel, + overallSummery, + showPanel, +}: EntitySummaryPanelProps) { + const { t } = useTranslation(); + + const { tableType, columns, tableQueries } = entityDetails; + + const basicTableInfo: BasicTableInfo = { + Type: tableType || TableType.Regular, + Queries: tableQueries?.length ? `${tableQueries?.length}` : '-', + Columns: columns?.length ? `${columns?.length}` : '-', + }; + + return ( +
+ + {entityDetails.name} + + {Object.keys(basicTableInfo).map((fieldName) => ( + + + {fieldName} + + + {basicTableInfo[fieldName as keyof BasicTableInfo]} + + + ))} + + + + + + {t('label.profiler-amp-data-quality')} + + + {overallSummery.map((field) => ( + + + + {field.title} + + + {field.value} + + + + ))} + + + + + + {t('label.schema')} + + + + +
+ ); +} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/EntitySummaryPanel.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/EntitySummaryPanel.interface.ts new file mode 100644 index 00000000000..db832f0cde2 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/EntitySummaryPanel.interface.ts @@ -0,0 +1,28 @@ +/* + * Copyright 2022 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 { Table, TableType } from '../../../generated/entity/data/table'; +import { OverallTableSummeryType } from '../../TableProfiler/TableProfiler.interface'; + +export interface EntitySummaryPanelProps { + entityDetails: Table; + handleClosePanel: () => void; + overallSummery: OverallTableSummeryType[]; + showPanel: boolean; +} + +export interface BasicTableInfo { + Type: TableType | string; + Queries: string; + Columns: string; +} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/EntitySummaryPanel.style.less b/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/EntitySummaryPanel.style.less new file mode 100644 index 00000000000..8952bfc585c --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/EntitySummaryPanel.style.less @@ -0,0 +1,84 @@ +/* + * Copyright 2022 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. + */ + +@white: #ffffff; +@summary-panel-offset: 118px; // (topnav height) 64px + (margin) 16px + (tabs height) 38px +@label-color: #37352f99; +@succesColor: #28a745; +@failedColor: #cb2431; +@abortedColor: #efae2f; + +.summary-panel-container { + width: 380px; + display: none; + background-color: @white; + height: calc(100vh - @summary-panel-offset); +} + +.show-panel { + display: block; + position: fixed; + top: @summary-panel-offset; + right: 0px; + z-index: 1000; + box-shadow: -2px 2px 4px rgba(0, 0, 0, 0.12); + font-size: 14px; + overflow-y: scroll; + -ms-overflow-style: none; + scrollbar-width: none; + + .basic-info-container { + width: calc(100% - 32px); + } + + .text-gray { + color: @label-color; + } + + .section-header { + font-size: 16px; + } + + .success { + color: @succesColor; + } + .failed { + color: @failedColor; + } + .aborted { + color: @abortedColor; + } + + .column-name { + font-weight: 500; + } + + .ant-divider-horizontal { + margin: 8px 0px; + } + + div.ant-typography { + margin-top: 16px; + margin-bottom: 0px; + } + + .close-icon { + position: absolute; + top: 16px; + right: 16px; + } +} + +.show-panel::-webkit-scrollbar { + display: none; +} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/Explore.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Explore/Explore.component.tsx index f98495f7788..46bedf11034 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Explore/Explore.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/Explore.component.tsx @@ -16,22 +16,42 @@ import { faSortAmountUpAlt, } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { Card, Tabs } from 'antd'; +import { Card, Space, Tabs } from 'antd'; +import { AxiosError } from 'axios'; import unique from 'fork-ts-checker-webpack-plugin/lib/utils/array/unique'; import { isNil, isNumber, lowerCase, noop, omit, toUpper } from 'lodash'; import { EntityType } from 'Models'; -import React, { Fragment, useEffect, useMemo, useRef } from 'react'; +import React, { useEffect, useMemo, useRef, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { useParams } from 'react-router-dom'; +import { getTableDetailsByFQN } from '../../axiosAPIs/tableAPI'; +import { getListTestCase } from '../../axiosAPIs/testAPI'; import FacetFilter from '../../components/common/facetfilter/FacetFilter'; import SearchedData from '../../components/searched-data/SearchedData'; -import { ENTITY_PATH } from '../../constants/constants'; +import { API_RES_MAX_SIZE, ENTITY_PATH } from '../../constants/constants'; import { tabsInfo } from '../../constants/explore.constants'; +import { INITIAL_TEST_RESULT_SUMMARY } from '../../constants/profiler.constant'; +import { TabSpecificField } from '../../enums/entity.enum'; import { SearchIndex } from '../../enums/search.enum'; -import { getCountBadge } from '../../utils/CommonUtils'; +import { Table } from '../../generated/entity/data/table'; +import { Include } from '../../generated/type/include'; +import { + formatNumberWithComma, + formTwoDigitNmber, + getCountBadge, +} from '../../utils/CommonUtils'; +import { updateTestResults } from '../../utils/DataQualityAndProfilerUtils'; +import { generateEntityLink } from '../../utils/TableUtils'; +import { showErrorToast } from '../../utils/ToastUtils'; import AdvancedSearch from '../AdvancedSearch/AdvancedSearch.component'; import { FacetFilterProps } from '../common/facetfilter/facetFilter.interface'; -import PageLayout, { leftPanelAntCardStyle } from '../containers/PageLayout'; +import PageLayoutV1 from '../containers/PageLayoutV1'; import Loader from '../Loader/Loader'; +import { + OverallTableSummeryType, + TableTestsType, +} from '../TableProfiler/TableProfiler.interface'; +import EntitySummaryPanel from './EntitySummaryPanel/EntitySummaryPanel.component'; import { ExploreProps, ExploreSearchIndex, @@ -61,6 +81,17 @@ const Explore: React.FC = ({ }) => { const isMounting = useRef(true); const { tab } = useParams<{ tab: string }>(); + const { t } = useTranslation(); + const [showSummaryPanel, setShowSummaryPanel] = useState(false); + const [entityDetails, setEntityDetails] = useState(); + const [tableTests, setTableTests] = useState({ + tests: [], + results: INITIAL_TEST_RESULT_SUMMARY, + }); + + const handleClosePanel = () => { + setShowSummaryPanel(false); + }; // get entity active tab by URL params const defaultActiveTab = useMemo(() => { @@ -96,6 +127,99 @@ const Explore: React.FC = ({ } }; + const overallSummery: OverallTableSummeryType[] = useMemo(() => { + return [ + { + title: 'Row Count', + value: formatNumberWithComma(entityDetails?.profile?.rowCount ?? 0), + }, + { + title: 'Column Count', + value: entityDetails?.profile?.columnCount ?? 0, + }, + { + title: 'Table Sample %', + value: `${entityDetails?.profile?.profileSample ?? 100}%`, + }, + { + title: 'Tests Passed', + value: formTwoDigitNmber(tableTests.results.success), + className: 'success', + }, + { + title: 'Tests Aborted', + value: formTwoDigitNmber(tableTests.results.aborted), + className: 'aborted', + }, + { + title: 'Tests Failed', + value: formTwoDigitNmber(tableTests.results.failed), + className: 'failed', + }, + ]; + }, [entityDetails, tableTests]); + + const fetchProfilerData = async (source: Table) => { + try { + const res = await getTableDetailsByFQN( + encodeURIComponent(source?.fullyQualifiedName || ''), + `${TabSpecificField.TABLE_PROFILE},${TabSpecificField.TABLE_QUERIES}` + ); + const { profile, tableQueries } = res; + setEntityDetails((prev) => { + if (prev) { + return { ...prev, profile, tableQueries }; + } else { + return {} as Table; + } + }); + } catch { + showErrorToast( + t('message.entity-fetch-error', { + entity: `profile details for table ${source?.name || ''}`, + }) + ); + } + }; + + const fetchAllTests = async (source: Table) => { + try { + const { data } = await getListTestCase({ + fields: 'testCaseResult,entityLink,testDefinition,testSuite', + entityLink: generateEntityLink(source?.fullyQualifiedName || ''), + includeAllTests: true, + limit: API_RES_MAX_SIZE, + include: Include.Deleted, + }); + const tableTests: TableTestsType = { + tests: [], + results: { ...INITIAL_TEST_RESULT_SUMMARY }, + }; + data.forEach((test) => { + if (test.entityFQN === source?.fullyQualifiedName) { + tableTests.tests.push(test); + + updateTestResults( + tableTests.results, + test.testCaseResult?.testCaseStatus || '' + ); + + return; + } + }); + setTableTests(tableTests); + } catch (error) { + showErrorToast(error as AxiosError); + } + }; + + const handleSummaryPanelDisplay = (source: Table) => { + setShowSummaryPanel(true); + fetchAllTests(source); + fetchProfilerData(source); + setEntityDetails(source); + }; + const handleFacetFilterClearFilter: FacetFilterProps['onClearFilter'] = ( key ) => onChangePostFilter(omit(postFilter, key)); @@ -103,114 +227,134 @@ const Explore: React.FC = ({ // alwyas Keep this useEffect at the end... useEffect(() => { isMounting.current = false; + const escapeKeyHandler = (e: KeyboardEvent) => { + if (e.key === 'Escape') { + handleClosePanel(); + } + }; + document.addEventListener('keydown', escapeKeyHandler); + + return () => { + document.removeEventListener('keydown', escapeKeyHandler); + }; }, []); return ( - - - - - - - }> - - - -
- {sortOrder === 'asc' ? ( - - ) : ( - - )} -
- - } - onChange={(tab) => { - tab && onChangeSearchIndex(tab as ExploreSearchIndex); - }}> - {Object.entries(tabsInfo).map(([tabSearchIndex, tabDetail]) => ( - - {tabDetail.label} - - {!isNil(tabCounts) - ? getCountBadge( - tabCounts[tabSearchIndex as ExploreSearchIndex], - '', - tabSearchIndex === searchIndex - ) - : getCountBadge()} - - - } + + + - ))} -
- onChangeAdvancedSearchJsonTree(nTree)} - onChangeQueryFilter={(nQueryFilter) => - onChangeAdvancedSearchQueryFilter(nQueryFilter) - } - /> - {!loading ? ( - { - if (isNumber(value)) { - onChangePage(value); - } else if (!isNaN(Number.parseInt(value))) { - onChangePage(Number.parseInt(value)); - } - }} - totalValue={searchResults?.hits.total.value ?? 0} + + + }> + + + +
+ {sortOrder === 'asc' ? ( + + ) : ( + + )} +
+ + } + onChange={(tab) => { + tab && onChangeSearchIndex(tab as ExploreSearchIndex); + }}> + {Object.entries(tabsInfo).map(([tabSearchIndex, tabDetail]) => ( + + {tabDetail.label} + + {!isNil(tabCounts) + ? getCountBadge( + tabCounts[tabSearchIndex as ExploreSearchIndex], + '', + tabSearchIndex === searchIndex + ) + : getCountBadge()} + + + } /> - ) : ( - - )} -
-
+ ))} + + +
+ onChangeAdvancedSearchJsonTree(nTree)} + onChangeQueryFilter={(nQueryFilter) => + onChangeAdvancedSearchQueryFilter(nQueryFilter) + } + /> + {!loading ? ( + { + if (isNumber(value)) { + onChangePage(value); + } else if (!isNaN(Number.parseInt(value))) { + onChangePage(Number.parseInt(value)); + } + }} + totalValue={searchResults?.hits.total.value ?? 0} + /> + ) : ( + + )} +
+ +
+ ); }; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/Explore.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Explore/Explore.test.tsx index 6eb59601f07..e47625af12f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Explore/Explore.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/Explore.test.tsx @@ -59,27 +59,6 @@ jest.mock('../../components/searched-data/SearchedData', () => { )); }); -jest.mock( - '../containers/PageLayout', - () => - ({ - children, - leftPanel, - rightPanel, - }: { - children: React.ReactNode; - rightPanel: React.ReactNode; - leftPanel: React.ReactNode; - }) => - ( -
-
{leftPanel}
-
{rightPanel}
- {children} -
- ) -); - const mockFunction = jest.fn(); describe('Test Explore component', () => { @@ -110,12 +89,10 @@ describe('Test Explore component', () => { wrapper: MemoryRouter, } ); - const pageContainer = await findByTestId(container, 'PageLayout'); const searchData = await findByTestId(container, 'search-data'); const wrappedContent = await findByTestId(container, 'wrapped-content'); const tabs = await findAllByTestId(container, /tab/i); - expect(pageContainer).toBeInTheDocument(); expect(searchData).toBeInTheDocument(); expect(wrappedContent).toBeInTheDocument(); expect(tabs.length).toBe(5); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/table-data-card-v2/TableDataCardV2.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/table-data-card-v2/TableDataCardV2.test.tsx index c37434fb49a..ae3d7baf5ea 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/table-data-card-v2/TableDataCardV2.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/table-data-card-v2/TableDataCardV2.test.tsx @@ -38,10 +38,13 @@ jest.mock('../table-data-card/TableDataCardBody', () => { return jest.fn().mockReturnValue(

TableDataCardBody

); }); +const mockHandleSummaryPanelDisplay = jest.fn(); + describe('Test TableDataCard Component', () => { it('Component should render', () => { const { getByTestId } = render( { it('Component should render for deleted', () => { const { getByTestId } = render( void; } const TableDataCardV2: React.FC = ({ @@ -55,6 +57,7 @@ const TableDataCardV2: React.FC = ({ source, matches, searchIndex, + handleSummaryPanelDisplay, }) => { const location = useLocation(); @@ -141,7 +144,8 @@ const TableDataCardV2: React.FC = ({ return (
+ data-testid="table-data-card" + onClick={() => handleSummaryPanelDisplay(source as Table)}>
{'databaseSchema' in source && 'database' in source && ( = ({ extraInfo, tags, }: Props) => { - const getTagValue = (tag: string | TagLabel): string | TagLabel => { - if (isString(tag)) { - return tag.startsWith(`Tier${FQN_SEPARATOR_CHAR}Tier`) - ? tag.split(FQN_SEPARATOR_CHAR)[1] - : tag; - } else { - return { - ...tag, - tagFQN: tag.tagFQN.startsWith(`Tier${FQN_SEPARATOR_CHAR}Tier`) - ? tag.tagFQN.split(FQN_SEPARATOR_CHAR)[1] - : tag.tagFQN, - }; - } - }; - return (
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/searched-data/SearchedData.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/searched-data/SearchedData.interface.ts index 8afe0db1008..0750913a96e 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/searched-data/SearchedData.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/searched-data/SearchedData.interface.ts @@ -12,6 +12,7 @@ */ import { ReactNode } from 'react'; +import { Table } from '../../generated/entity/data/table'; import { EntityReference } from '../../generated/entity/type'; import { TagLabel } from '../../generated/type/tagLabel'; import { @@ -67,4 +68,5 @@ export interface SearchedDataProps { showOnboardingTemplate?: boolean; showOnlyChildren?: boolean; isFilterSelected: boolean; + handleSummaryPanelDisplay: (source: Table) => void; } diff --git a/openmetadata-ui/src/main/resources/ui/src/components/searched-data/SearchedData.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/searched-data/SearchedData.test.tsx index 424c0e2dc3a..8efb88b24b2 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/searched-data/SearchedData.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/searched-data/SearchedData.test.tsx @@ -64,6 +64,7 @@ const mockData: SearchedDataProps['data'] = [ ]; const mockPaginate = jest.fn(); +const mockHandleSummaryPanelDisplay = jest.fn(); jest.mock('../common/table-data-card/TableDataCard', () => { return jest @@ -90,6 +91,7 @@ describe('Test SearchedData Component', () => { isFilterSelected currentPage={0} data={mockData} + handleSummaryPanelDisplay={mockHandleSummaryPanelDisplay} paginate={mockPaginate} totalValue={10} />, @@ -109,6 +111,7 @@ describe('Test SearchedData Component', () => { isFilterSelected currentPage={0} data={mockData} + handleSummaryPanelDisplay={mockHandleSummaryPanelDisplay} paginate={mockPaginate} totalValue={10} />, @@ -128,6 +131,7 @@ describe('Test SearchedData Component', () => { isFilterSelected currentPage={0} data={mockData} + handleSummaryPanelDisplay={mockHandleSummaryPanelDisplay} paginate={mockPaginate} totalValue={10}>

hello world

@@ -146,6 +150,7 @@ describe('Test SearchedData Component', () => { isFilterSelected currentPage={0} data={mockData} + handleSummaryPanelDisplay={mockHandleSummaryPanelDisplay} paginate={mockPaginate} totalValue={11}>

hello world

@@ -165,6 +170,7 @@ describe('Test SearchedData Component', () => { showOnboardingTemplate currentPage={0} data={[]} + handleSummaryPanelDisplay={mockHandleSummaryPanelDisplay} paginate={mockPaginate} totalValue={0} />, @@ -182,6 +188,7 @@ describe('Test SearchedData Component', () => { isFilterSelected currentPage={0} data={[]} + handleSummaryPanelDisplay={mockHandleSummaryPanelDisplay} paginate={mockPaginate} totalValue={0} />, diff --git a/openmetadata-ui/src/main/resources/ui/src/components/searched-data/SearchedData.tsx b/openmetadata-ui/src/main/resources/ui/src/components/searched-data/SearchedData.tsx index e72acb9a83b..59699f9718b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/searched-data/SearchedData.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/searched-data/SearchedData.tsx @@ -44,6 +44,7 @@ const SearchedData: React.FC = ({ totalValue, isFilterSelected, searchText, + handleSummaryPanelDisplay, }) => { const highlightSearchResult = () => { return data.map(({ _source: table, highlight, _index }, index) => { @@ -89,6 +90,7 @@ const SearchedData: React.FC = ({ return (
{ getTierFromSearchTableTags((entity.tags || []).map((tag) => tag.tagFQN)) )?.split(FQN_SEPARATOR_CHAR)[1]; }; + +export const getTagValue = (tag: string | TagLabel): string | TagLabel => { + if (isString(tag)) { + return tag.startsWith(`Tier${FQN_SEPARATOR_CHAR}Tier`) + ? tag.split(FQN_SEPARATOR_CHAR)[1] + : tag; + } else { + return { + ...tag, + tagFQN: tag.tagFQN.startsWith(`Tier${FQN_SEPARATOR_CHAR}Tier`) + ? tag.tagFQN.split(FQN_SEPARATOR_CHAR)[1] + : tag.tagFQN, + }; + } +};