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,
+ };
+ }
+};