mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-09-27 09:55:36 +00:00
Fix(UI): Explore page bugs (#8607)
* - Made changes to show more information about tables in data card on explore page - Fixed bugs related to entity summary panel * Replaced Space components for vertical flex with Row and Col for ColumnSummary
This commit is contained in:
parent
3e3cf971c2
commit
a6822aa094
@ -11,10 +11,11 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Divider, Space, Typography } from 'antd';
|
import { Col, Divider, Row, Space, Typography } from 'antd';
|
||||||
import { toLower } from 'lodash';
|
import { toLower } from 'lodash';
|
||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { MAX_CHAR_LIMIT_ENTITY_SUMMARY } from '../../../constants/constants';
|
||||||
import { getTagValue } from '../../../utils/CommonUtils';
|
import { getTagValue } from '../../../utils/CommonUtils';
|
||||||
import SVGIcons from '../../../utils/SvgUtils';
|
import SVGIcons from '../../../utils/SvgUtils';
|
||||||
import RichTextEditorPreviewer from '../../common/rich-text-editor/RichTextEditorPreviewer';
|
import RichTextEditorPreviewer from '../../common/rich-text-editor/RichTextEditorPreviewer';
|
||||||
@ -38,16 +39,21 @@ export default function ColumnSummary({ columns }: ColumnSummaryProps) {
|
|||||||
}, [columns]);
|
}, [columns]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Space direction="vertical">
|
<Row>
|
||||||
{columns &&
|
{columns &&
|
||||||
formattedColumnsData.map((column) => (
|
formattedColumnsData.map((column) => (
|
||||||
<React.Fragment key={column.name}>
|
<Col key={column.name} span={24}>
|
||||||
<Space direction="vertical" size={0}>
|
<Row>
|
||||||
|
<Col span={24}>
|
||||||
<Text className="column-name">{column.name}</Text>
|
<Text className="column-name">{column.name}</Text>
|
||||||
|
</Col>
|
||||||
|
<Col span={24}>
|
||||||
<Space className="text-xs" size={4}>
|
<Space className="text-xs" size={4}>
|
||||||
<Space size={4}>
|
<Space size={4}>
|
||||||
<Text className="text-gray">{`${t('label.type')}:`}</Text>
|
<Text className="text-gray">{`${t('label.type')}:`}</Text>
|
||||||
<Text className="text-semi-bold">{toLower(column.type)}</Text>
|
<Text className="text-semi-bold">
|
||||||
|
{toLower(column.type)}
|
||||||
|
</Text>
|
||||||
</Space>
|
</Space>
|
||||||
{column.tags?.length !== 0 && (
|
{column.tags?.length !== 0 && (
|
||||||
<>
|
<>
|
||||||
@ -69,19 +75,23 @@ export default function ColumnSummary({ columns }: ColumnSummaryProps) {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Space>
|
</Space>
|
||||||
|
</Col>
|
||||||
|
<Col span={24}>
|
||||||
<Paragraph className="text-gray">
|
<Paragraph className="text-gray">
|
||||||
{column.description ? (
|
{column.description ? (
|
||||||
<RichTextEditorPreviewer
|
<RichTextEditorPreviewer
|
||||||
markdown={column.description || ''}
|
markdown={column.description || ''}
|
||||||
|
maxLength={MAX_CHAR_LIMIT_ENTITY_SUMMARY}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
t('label.no-description')
|
t('label.no-description')
|
||||||
)}
|
)}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
</Space>
|
</Col>
|
||||||
|
</Row>
|
||||||
<Divider />
|
<Divider />
|
||||||
</React.Fragment>
|
</Col>
|
||||||
))}
|
))}
|
||||||
</Space>
|
</Row>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { CloseOutlined } from '@ant-design/icons';
|
import { CloseOutlined } from '@ant-design/icons';
|
||||||
import { Col, Divider, Row, Space, Typography } from 'antd';
|
import { Col, Divider, Row, Typography } from 'antd';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -46,13 +46,15 @@ export default function EntitySummaryPanel({
|
|||||||
'summary-panel-container',
|
'summary-panel-container',
|
||||||
showPanel ? 'show-panel' : ''
|
showPanel ? 'show-panel' : ''
|
||||||
)}>
|
)}>
|
||||||
<Space
|
<Row className={classNames('m-md')}>
|
||||||
className={classNames('basic-info-container m-md')}
|
<Col span={24}>
|
||||||
direction="vertical">
|
|
||||||
<Typography.Title level={5}>{entityDetails.name}</Typography.Title>
|
<Typography.Title level={5}>{entityDetails.name}</Typography.Title>
|
||||||
<Space className={classNames('w-full')} direction="vertical">
|
</Col>
|
||||||
|
<Col span={24}>
|
||||||
|
<Row>
|
||||||
{Object.keys(basicTableInfo).map((fieldName) => (
|
{Object.keys(basicTableInfo).map((fieldName) => (
|
||||||
<Row gutter={16} key={fieldName}>
|
<Col key={fieldName} span={24}>
|
||||||
|
<Row gutter={16}>
|
||||||
<Col className="text-gray" span={10}>
|
<Col className="text-gray" span={10}>
|
||||||
{fieldName}
|
{fieldName}
|
||||||
</Col>
|
</Col>
|
||||||
@ -60,21 +62,29 @@ export default function EntitySummaryPanel({
|
|||||||
{basicTableInfo[fieldName as keyof BasicTableInfo]}
|
{basicTableInfo[fieldName as keyof BasicTableInfo]}
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
</Col>
|
||||||
))}
|
))}
|
||||||
</Space>
|
</Row>
|
||||||
</Space>
|
</Col>
|
||||||
|
</Row>
|
||||||
<Divider className="m-0" />
|
<Divider className="m-0" />
|
||||||
<Space className={classNames('m-md')} direction="vertical">
|
<Row className={classNames('m-md')} gutter={[0, 16]}>
|
||||||
|
<Col span={24}>
|
||||||
<Typography.Text className="section-header">
|
<Typography.Text className="section-header">
|
||||||
{t('label.profiler-amp-data-quality')}
|
{t('label.profiler-amp-data-quality')}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
|
</Col>
|
||||||
|
<Col span={24}>
|
||||||
<Row gutter={[16, 16]}>
|
<Row gutter={[16, 16]}>
|
||||||
{overallSummery.map((field) => (
|
{overallSummery.map((field) => (
|
||||||
<Col key={field.title} span={10}>
|
<Col key={field.title} span={10}>
|
||||||
<Space direction="vertical" size={6}>
|
<Row>
|
||||||
|
<Col span={24}>
|
||||||
<Typography.Text className="text-gray">
|
<Typography.Text className="text-gray">
|
||||||
{field.title}
|
{field.title}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
|
</Col>
|
||||||
|
<Col span={24}>
|
||||||
<Typography.Text
|
<Typography.Text
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'tw-text-2xl tw-font-semibold',
|
'tw-text-2xl tw-font-semibold',
|
||||||
@ -82,18 +92,24 @@ export default function EntitySummaryPanel({
|
|||||||
)}>
|
)}>
|
||||||
{field.value}
|
{field.value}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
</Space>
|
</Col>
|
||||||
|
</Row>
|
||||||
</Col>
|
</Col>
|
||||||
))}
|
))}
|
||||||
</Row>
|
</Row>
|
||||||
</Space>
|
</Col>
|
||||||
|
</Row>
|
||||||
<Divider className="m-0" />
|
<Divider className="m-0" />
|
||||||
<Space className={classNames('m-md')} direction="vertical">
|
<Row className={classNames('m-md')} gutter={[0, 16]}>
|
||||||
|
<Col span={24}>
|
||||||
<Typography.Text className="section-header">
|
<Typography.Text className="section-header">
|
||||||
{t('label.schema')}
|
{t('label.schema')}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
|
</Col>
|
||||||
|
<Col span={24}>
|
||||||
<ColumnSummary columns={columns} />
|
<ColumnSummary columns={columns} />
|
||||||
</Space>
|
</Col>
|
||||||
|
</Row>
|
||||||
<CloseOutlined className="close-icon" onClick={handleClosePanel} />
|
<CloseOutlined className="close-icon" onClick={handleClosePanel} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -37,10 +37,6 @@
|
|||||||
-ms-overflow-style: none;
|
-ms-overflow-style: none;
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
|
|
||||||
.basic-info-container {
|
|
||||||
width: calc(100% - 32px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-gray {
|
.text-gray {
|
||||||
color: @label-color;
|
color: @label-color;
|
||||||
}
|
}
|
||||||
@ -64,7 +60,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ant-divider-horizontal {
|
.ant-divider-horizontal {
|
||||||
margin: 8px 0px;
|
margin: 16px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.ant-typography {
|
div.ant-typography {
|
||||||
|
@ -16,10 +16,18 @@ import {
|
|||||||
faSortAmountUpAlt,
|
faSortAmountUpAlt,
|
||||||
} from '@fortawesome/free-solid-svg-icons';
|
} from '@fortawesome/free-solid-svg-icons';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { Card, Space, Tabs } from 'antd';
|
import { Card, Tabs } from 'antd';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
import unique from 'fork-ts-checker-webpack-plugin/lib/utils/array/unique';
|
import unique from 'fork-ts-checker-webpack-plugin/lib/utils/array/unique';
|
||||||
import { isNil, isNumber, lowerCase, noop, omit, toUpper } from 'lodash';
|
import {
|
||||||
|
isNil,
|
||||||
|
isNumber,
|
||||||
|
lowerCase,
|
||||||
|
noop,
|
||||||
|
omit,
|
||||||
|
toLower,
|
||||||
|
toUpper,
|
||||||
|
} from 'lodash';
|
||||||
import { EntityType } from 'Models';
|
import { EntityType } from 'Models';
|
||||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -43,6 +51,7 @@ import {
|
|||||||
import { updateTestResults } from '../../utils/DataQualityAndProfilerUtils';
|
import { updateTestResults } from '../../utils/DataQualityAndProfilerUtils';
|
||||||
import { generateEntityLink } from '../../utils/TableUtils';
|
import { generateEntityLink } from '../../utils/TableUtils';
|
||||||
import { showErrorToast } from '../../utils/ToastUtils';
|
import { showErrorToast } from '../../utils/ToastUtils';
|
||||||
|
import { Entities } from '../AddWebhook/WebhookConstants';
|
||||||
import AdvancedSearch from '../AdvancedSearch/AdvancedSearch.component';
|
import AdvancedSearch from '../AdvancedSearch/AdvancedSearch.component';
|
||||||
import { FacetFilterProps } from '../common/facetfilter/facetFilter.interface';
|
import { FacetFilterProps } from '../common/facetfilter/facetFilter.interface';
|
||||||
import PageLayoutV1 from '../containers/PageLayoutV1';
|
import PageLayoutV1 from '../containers/PageLayoutV1';
|
||||||
@ -293,6 +302,7 @@ const Explore: React.FC<ExploreProps> = ({
|
|||||||
}
|
}
|
||||||
onChange={(tab) => {
|
onChange={(tab) => {
|
||||||
tab && onChangeSearchIndex(tab as ExploreSearchIndex);
|
tab && onChangeSearchIndex(tab as ExploreSearchIndex);
|
||||||
|
setShowSummaryPanel(false);
|
||||||
}}>
|
}}>
|
||||||
{Object.entries(tabsInfo).map(([tabSearchIndex, tabDetail]) => (
|
{Object.entries(tabsInfo).map(([tabSearchIndex, tabDetail]) => (
|
||||||
<Tabs.TabPane
|
<Tabs.TabPane
|
||||||
@ -314,10 +324,9 @@ const Explore: React.FC<ExploreProps> = ({
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Tabs>
|
</Tabs>
|
||||||
<Space>
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
marginRight: showSummaryPanel ? '380px' : '',
|
marginRight: showSummaryPanel ? '390px' : '',
|
||||||
}}>
|
}}>
|
||||||
<AdvancedSearch
|
<AdvancedSearch
|
||||||
jsonTree={advancedSearchJsonTree}
|
jsonTree={advancedSearchJsonTree}
|
||||||
@ -333,7 +342,11 @@ const Explore: React.FC<ExploreProps> = ({
|
|||||||
showResultCount
|
showResultCount
|
||||||
currentPage={page}
|
currentPage={page}
|
||||||
data={searchResults?.hits.hits ?? []}
|
data={searchResults?.hits.hits ?? []}
|
||||||
handleSummaryPanelDisplay={handleSummaryPanelDisplay}
|
handleSummaryPanelDisplay={
|
||||||
|
tab === toLower(Entities.table)
|
||||||
|
? handleSummaryPanelDisplay
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
paginate={(value) => {
|
paginate={(value) => {
|
||||||
if (isNumber(value)) {
|
if (isNumber(value)) {
|
||||||
onChangePage(value);
|
onChangePage(value);
|
||||||
@ -347,13 +360,14 @@ const Explore: React.FC<ExploreProps> = ({
|
|||||||
<Loader />
|
<Loader />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{tab === toLower(Entities.table) && (
|
||||||
<EntitySummaryPanel
|
<EntitySummaryPanel
|
||||||
entityDetails={entityDetails || ({} as Table)}
|
entityDetails={entityDetails || ({} as Table)}
|
||||||
handleClosePanel={handleClosePanel}
|
handleClosePanel={handleClosePanel}
|
||||||
overallSummery={overallSummery}
|
overallSummery={overallSummery}
|
||||||
showPanel={showSummaryPanel}
|
showPanel={showSummaryPanel}
|
||||||
/>
|
/>
|
||||||
</Space>
|
)}
|
||||||
</PageLayoutV1>
|
</PageLayoutV1>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -219,7 +219,10 @@ const EntitySummaryDetails = ({
|
|||||||
data-testid="owner-link"
|
data-testid="owner-link"
|
||||||
href={data.value as string}
|
href={data.value as string}
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
target={data.openInNewTab ? '_blank' : '_self'}>
|
target={data.openInNewTab ? '_blank' : '_self'}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
}}>
|
||||||
{displayVal}
|
{displayVal}
|
||||||
{data.openInNewTab && (
|
{data.openInNewTab && (
|
||||||
<>
|
<>
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
import { faExclamationCircle } from '@fortawesome/free-solid-svg-icons';
|
import { faExclamationCircle } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { isNil, isString, startCase, uniqueId } from 'lodash';
|
import { isString, startCase, uniqueId } from 'lodash';
|
||||||
import { ExtraInfo } from 'Models';
|
import { ExtraInfo } from 'Models';
|
||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { Link, useLocation } from 'react-router-dom';
|
import { Link, useLocation } from 'react-router-dom';
|
||||||
@ -49,7 +49,7 @@ export interface TableDataCardPropsV2 {
|
|||||||
value: number;
|
value: number;
|
||||||
}[];
|
}[];
|
||||||
searchIndex: SearchIndex | EntityType;
|
searchIndex: SearchIndex | EntityType;
|
||||||
handleSummaryPanelDisplay: (source: Table) => void;
|
handleSummaryPanelDisplay?: (source: Table) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TableDataCardV2: React.FC<TableDataCardPropsV2> = ({
|
const TableDataCardV2: React.FC<TableDataCardPropsV2> = ({
|
||||||
@ -62,19 +62,8 @@ const TableDataCardV2: React.FC<TableDataCardPropsV2> = ({
|
|||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
const otherDetails = useMemo(() => {
|
const otherDetails = useMemo(() => {
|
||||||
const _otherDetails: ExtraInfo[] = [];
|
const _otherDetails: ExtraInfo[] = [
|
||||||
|
{
|
||||||
if ('tier' in source && !isNil(source.tier)) {
|
|
||||||
_otherDetails.push({
|
|
||||||
key: 'Tier',
|
|
||||||
value: isString(source.tier)
|
|
||||||
? source.tier
|
|
||||||
: source.tier.tagFQN.split(FQN_SEPARATOR_CHAR)[1],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('owner' in source && !isNil(source.owner)) {
|
|
||||||
_otherDetails.push({
|
|
||||||
key: 'Owner',
|
key: 'Owner',
|
||||||
value: getOwnerValue(source.owner as EntityReference),
|
value: getOwnerValue(source.owner as EntityReference),
|
||||||
placeholderText: getEntityPlaceHolder(
|
placeholderText: getEntityPlaceHolder(
|
||||||
@ -89,8 +78,16 @@ const TableDataCardV2: React.FC<TableDataCardPropsV2> = ({
|
|||||||
source.owner?.type === OwnerType.USER
|
source.owner?.type === OwnerType.USER
|
||||||
? source.owner?.name
|
? source.owner?.name
|
||||||
: undefined,
|
: undefined,
|
||||||
});
|
},
|
||||||
}
|
{
|
||||||
|
key: 'Tier',
|
||||||
|
value: source.tier
|
||||||
|
? isString(source.tier)
|
||||||
|
? source.tier
|
||||||
|
: source.tier?.tagFQN.split(FQN_SEPARATOR_CHAR)[1]
|
||||||
|
: '',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
if ('usageSummary' in source) {
|
if ('usageSummary' in source) {
|
||||||
_otherDetails.push({
|
_otherDetails.push({
|
||||||
@ -110,7 +107,8 @@ const TableDataCardV2: React.FC<TableDataCardPropsV2> = ({
|
|||||||
return _otherDetails;
|
return _otherDetails;
|
||||||
}, [source]);
|
}, [source]);
|
||||||
|
|
||||||
const handleLinkClick = () => {
|
const handleLinkClick = (e: React.MouseEvent) => {
|
||||||
|
e.stopPropagation();
|
||||||
if (location.pathname.includes(ROUTES.TOUR)) {
|
if (location.pathname.includes(ROUTES.TOUR)) {
|
||||||
AppState.currentTourPage = CurrentTourPageType.DATASET_PAGE;
|
AppState.currentTourPage = CurrentTourPageType.DATASET_PAGE;
|
||||||
}
|
}
|
||||||
@ -145,7 +143,9 @@ const TableDataCardV2: React.FC<TableDataCardPropsV2> = ({
|
|||||||
<div
|
<div
|
||||||
className="tw-bg-white tw-p-3 tw-border tw-border-main tw-rounded-md"
|
className="tw-bg-white tw-p-3 tw-border tw-border-main tw-rounded-md"
|
||||||
data-testid="table-data-card"
|
data-testid="table-data-card"
|
||||||
onClick={() => handleSummaryPanelDisplay(source as Table)}>
|
onClick={() => {
|
||||||
|
handleSummaryPanelDisplay && handleSummaryPanelDisplay(source as Table);
|
||||||
|
}}>
|
||||||
<div>
|
<div>
|
||||||
{'databaseSchema' in source && 'database' in source && (
|
{'databaseSchema' in source && 'database' in source && (
|
||||||
<span
|
<span
|
||||||
|
@ -68,5 +68,5 @@ export interface SearchedDataProps {
|
|||||||
showOnboardingTemplate?: boolean;
|
showOnboardingTemplate?: boolean;
|
||||||
showOnlyChildren?: boolean;
|
showOnlyChildren?: boolean;
|
||||||
isFilterSelected: boolean;
|
isFilterSelected: boolean;
|
||||||
handleSummaryPanelDisplay: (source: Table) => void;
|
handleSummaryPanelDisplay?: (source: Table) => void;
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ export const ADD_USER_CONTAINER_HEIGHT = 250;
|
|||||||
export const INGESTION_PROGRESS_START_VAL = 20;
|
export const INGESTION_PROGRESS_START_VAL = 20;
|
||||||
export const INGESTION_PROGRESS_END_VAL = 80;
|
export const INGESTION_PROGRESS_END_VAL = 80;
|
||||||
export const DEPLOYED_PROGRESS_VAL = 100;
|
export const DEPLOYED_PROGRESS_VAL = 100;
|
||||||
|
export const MAX_CHAR_LIMIT_ENTITY_SUMMARY = 130;
|
||||||
export const LOCALSTORAGE_RECENTLY_VIEWED = `recentlyViewedData_${COOKIE_VERSION}`;
|
export const LOCALSTORAGE_RECENTLY_VIEWED = `recentlyViewedData_${COOKIE_VERSION}`;
|
||||||
export const LOCALSTORAGE_RECENTLY_SEARCHED = `recentlySearchedData_${COOKIE_VERSION}`;
|
export const LOCALSTORAGE_RECENTLY_SEARCHED = `recentlySearchedData_${COOKIE_VERSION}`;
|
||||||
export const LOCALSTORAGE_USER_PROFILES = 'userProfiles';
|
export const LOCALSTORAGE_USER_PROFILES = 'userProfiles';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user