diff --git a/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/DataAssetsHeader/DataAssetsHeader.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/DataAssetsHeader/DataAssetsHeader.component.tsx index 012f70d537f..cba538bb029 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/DataAssetsHeader/DataAssetsHeader.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/DataAssets/DataAssetsHeader/DataAssetsHeader.component.tsx @@ -20,7 +20,6 @@ import QueryString from 'qs'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Link, useHistory, useParams } from 'react-router-dom'; -import { ReactComponent as IconExternalLink } from '../../../assets/svg/external-links.svg'; import { ReactComponent as RedAlertIcon } from '../../../assets/svg/ic-alert-red.svg'; import { ReactComponent as TaskOpenIcon } from '../../../assets/svg/ic-open-task.svg'; import { ReactComponent as VersionIcon } from '../../../assets/svg/ic-version.svg'; @@ -32,7 +31,6 @@ import { OwnerLabel } from '../../../components/common/OwnerLabel/OwnerLabel.com import TierCard from '../../../components/common/TierCard/TierCard'; import EntityHeaderTitle from '../../../components/Entity/EntityHeaderTitle/EntityHeaderTitle.component'; import { AUTO_PILOT_APP_NAME } from '../../../constants/Applications.constant'; -import { DATA_ASSET_ICON_DIMENSION } from '../../../constants/constants'; import { SERVICE_TYPES } from '../../../constants/Services.constant'; import { TAG_START_WITH } from '../../../constants/Tag.constants'; import { useTourProvider } from '../../../context/TourProvider/TourProvider'; @@ -53,6 +51,7 @@ import { getActiveAnnouncement } from '../../../rest/feedsAPI'; import { getDataQualityLineage } from '../../../rest/lineageAPI'; import { getContainerByName } from '../../../rest/storageAPI'; import { + ExtraInfoLabel, getDataAssetsHeaderInfo, getEntityExtraInfoLength, isDataAssetsWithServiceField, @@ -91,89 +90,6 @@ import { EntitiesWithDomainField, } from './DataAssetsHeader.interface'; -export const ExtraInfoLabel = ({ - label, - value, - dataTestId, - inlineLayout = false, -}: { - label: string; - value: string | number | React.ReactNode; - dataTestId?: string; - inlineLayout?: boolean; -}) => { - if (inlineLayout) { - return ( - <> - - - {!isEmpty(label) && ( - {`${label}: `} - )} - {value} - - - ); - } - - return ( -
- - {!isEmpty(label) && ( - {label} - )} -
- {value} -
-
-
- ); -}; - -export const ExtraInfoLink = ({ - label, - value, - href, - newTab = false, - ellipsis = false, -}: { - label: string; - value: string | number; - href: string; - newTab?: boolean; - ellipsis?: boolean; -}) => ( -
- {!isEmpty(label) && ( - {label} - )} -
- - - {value} - - - -
-
-); - export const DataAssetsHeader = ({ allowSoftDelete = true, showDomain = true, @@ -298,9 +214,7 @@ export const DataAssetsHeader = ({ }; const alertBadge = useMemo(() => { - return tableClassBase.getAlertEnableStatus() && - dqFailureCount > 0 && - isDqAlertSupported ? ( + const renderAlertBadgeWithDq = () => ( {badge} @@ -320,9 +234,16 @@ export const DataAssetsHeader = ({ - ) : ( - badge ); + if ( + isDqAlertSupported && + tableClassBase.getAlertEnableStatus() && + dqFailureCount > 0 + ) { + return renderAlertBadgeWithDq(); + } + + return badge; }, [dqFailureCount, dataAsset?.fullyQualifiedName, entityType, badge]); const fetchActiveAnnouncement = async () => { @@ -551,7 +472,7 @@ export const DataAssetsHeader = ({ )} /> - + - + ({ })), getEntityExtraInfoLength: jest.fn().mockImplementation(() => 0), isDataAssetsWithServiceField: jest.fn().mockImplementation(() => true), + ExtraInfoLabel: jest.fn().mockImplementation(({ label, value }) => ( +
+ {label && {label}} + {value} +
+ )), + ExtraInfoLink: jest.fn().mockImplementation(({ value, href, newTab }) => { + const props = { + href, + ...(newTab ? { target: '_blank', rel: 'noopener noreferrer' } : {}), + }; + + return {value}; + }), })); jest.mock('../../common/CertificationTag/CertificationTag', () => { @@ -293,8 +309,6 @@ describe('DataAssetsHeader component', () => { expect(sourceUrlLink).toHaveAttribute('href', mockSourceUrl); expect(sourceUrlLink).toHaveAttribute('target', '_blank'); expect(screen.getByText('label.view-in-service-type')).toBeInTheDocument(); - - ``; }); it('should not render source URL button when sourceUrl is not present', () => { diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Database/RetentionPeriod/RetentionPeriod.component.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Database/RetentionPeriod/RetentionPeriod.component.test.tsx index 69279fdf337..df8e4a5909f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Database/RetentionPeriod/RetentionPeriod.component.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Database/RetentionPeriod/RetentionPeriod.component.test.tsx @@ -21,12 +21,9 @@ jest.mock('../../../utils/ToastUtils', () => ({ showErrorToast: jest.fn(), })); -jest.mock( - '../../DataAssets/DataAssetsHeader/DataAssetsHeader.component', - () => ({ - ExtraInfoLabel: jest.fn().mockImplementation(({ value }) => value), - }) -); +jest.mock('../../../utils/DataAssetsHeader.utils', () => ({ + ExtraInfoLabel: jest.fn().mockImplementation(({ value }) => value), +})); const mockOnUpdate = jest.fn(); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityHeaderTitle/EntityHeaderTitle.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityHeaderTitle/EntityHeaderTitle.component.tsx index 93a0af11eb4..f529e9fe708 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityHeaderTitle/EntityHeaderTitle.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityHeaderTitle/EntityHeaderTitle.component.tsx @@ -112,8 +112,8 @@ const EntityHeaderTitle = ({ wrap={false}> {icon && {icon}} {/* If we do not have displayName name only be shown in the bold from the below code */} {!isEmpty(displayName) && showName ? ( diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityHeaderTitle/entity-header-title.less b/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityHeaderTitle/entity-header-title.less index 28d2c0c6935..7203dffda8c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityHeaderTitle/entity-header-title.less +++ b/openmetadata-ui/src/main/resources/ui/src/components/Entity/EntityHeaderTitle/entity-header-title.less @@ -13,19 +13,16 @@ @import (reference) url('../../../styles/variables.less'); .entity-header-title { + flex: 1; .ant-typography-ellipsis.entity-header-name { margin-bottom: 0px; display: block; color: @grey-900; - max-width: 500px; + min-width: 0; } .ant-typography-ellipsis.entity-header-display-name { font-size: 16px; color: @grey-700; - max-width: 500px; - } - .ant-col.entity-header-content { - max-width: calc(100% - 100px); } } diff --git a/openmetadata-ui/src/main/resources/ui/src/constants/Services.constant.ts b/openmetadata-ui/src/main/resources/ui/src/constants/Services.constant.ts index 86e6da8b659..0d2d9b43944 100644 --- a/openmetadata-ui/src/main/resources/ui/src/constants/Services.constant.ts +++ b/openmetadata-ui/src/main/resources/ui/src/constants/Services.constant.ts @@ -417,18 +417,10 @@ export const SERVICE_TYPES_ENUM = { }; export const BETA_SERVICES = [ - DatabaseServiceType.BigTable, - DatabaseServiceType.SAS, - PipelineServiceType.Spline, PipelineServiceType.OpenLineage, - PipelineServiceType.Flink, PipelineServiceType.Wherescape, - DatabaseServiceType.Teradata, - StorageServiceType.Gcs, - DatabaseServiceType.SapERP, DatabaseServiceType.Cassandra, MetadataServiceType.AlationSink, - DatabaseServiceType.Synapse, DatabaseServiceType.Cockroach, SearchServiceType.OpenSearch, ]; diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/AlertDetailsPage/AlertDetailsPage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/AlertDetailsPage/AlertDetailsPage.test.tsx index 20a3ac39a43..9d23c42f088 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/AlertDetailsPage/AlertDetailsPage.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/AlertDetailsPage/AlertDetailsPage.test.tsx @@ -127,14 +127,9 @@ jest.mock('../../components/common/OwnerLabel/OwnerLabel.component', () => ({ )), })); -jest.mock( - '../../components/DataAssets/DataAssetsHeader/DataAssetsHeader.component', - () => ({ - ExtraInfoLabel: jest - .fn() - .mockImplementation(() =>
ExtraInfoLabel
), - }) -); +jest.mock('../../utils/DataAssetsHeader.utils', () => ({ + ExtraInfoLabel: jest.fn().mockImplementation(() =>
ExtraInfoLabel
), +})); jest.mock('../../components/PageLayoutV1/PageLayoutV1', () => jest.fn().mockImplementation(({ children }) =>
{children}
) diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/TagPage/TagPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/TagPage/TagPage.tsx index 76af77525e2..98b17379129 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/TagPage/TagPage.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/TagPage/TagPage.tsx @@ -343,6 +343,12 @@ const TagPage = () => { setPreviewAsset(undefined); } } catch (error) { + showErrorToast( + error as AxiosError, + t('server.entity-fetch-error', { + entity: t('label.asset-plural'), + }) + ); setAssetCount(0); } }; @@ -593,7 +599,7 @@ const TagPage = () => { className="data-classification" data-testid="data-classification" gutter={[0, 12]}> - + { @@ -265,6 +265,13 @@ export const searchEntity = async ({ 'label' ); } catch (error) { + showErrorToast( + error as AxiosError, + t('server.entity-fetch-error', { + entity: t('label.search'), + }) + ); + return []; } }; @@ -352,26 +359,24 @@ export const getSupportedFilterOptions = ( })); export const getConnectionTimeoutField = () => ( - <> - - {`${t('label.connection-timeout')} (${t( - 'label.second-plural' - )})`} - : - - - - - - - + + {`${t('label.connection-timeout')} (${t( + 'label.second-plural' + )})`} + : + + + + + + ); export const getReadTimeoutField = () => ( diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/DataAssetsHeader.utils.test.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/DataAssetsHeader.utils.test.tsx index 36082c909d5..79f130bd9e8 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/DataAssetsHeader.utils.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/DataAssetsHeader.utils.test.tsx @@ -39,15 +39,11 @@ import { getEntityExtraInfoLength, } from './DataAssetsHeader.utils'; -jest.mock( - '../components/DataAssets/DataAssetsHeader/DataAssetsHeader.component', - () => ({ - ExtraInfoLabel: jest.fn().mockImplementation(({ value }) => { - value; - }), - ExtraInfoLink: jest.fn().mockImplementation(({ value }) => value), - }) -); +jest.mock('./DataAssetsHeader.utils', () => ({ + ...jest.requireActual('./DataAssetsHeader.utils'), + ExtraInfoLabel: jest.fn().mockImplementation(({ value }) => value), + ExtraInfoLink: jest.fn().mockImplementation(({ value }) => value), +})); jest.mock('./EntityUtils', () => ({ getEntityName: jest.fn().mockReturnValue('entityName'), getEntityBreadcrumbs: jest.fn().mockReturnValue([ diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/DataAssetsHeader.utils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/DataAssetsHeader.utils.tsx index 253ac199e3a..4531e23a374 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/DataAssetsHeader.utils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/DataAssetsHeader.utils.tsx @@ -12,21 +12,23 @@ * limitations under the License. */ -import { Divider } from 'antd'; +import Icon from '@ant-design/icons'; +import { Divider, Tooltip, Typography } from 'antd'; +import classNames from 'classnames'; import { t } from 'i18next'; -import { isArray, isObject, isUndefined } from 'lodash'; +import { isArray, isEmpty, isObject, isUndefined } from 'lodash'; import React, { ReactNode } from 'react'; -import { - ExtraInfoLabel, - ExtraInfoLink, -} from '../components/DataAssets/DataAssetsHeader/DataAssetsHeader.component'; +import { ReactComponent as IconExternalLink } from '../assets/svg/external-links.svg'; import { DataAssetHeaderInfo, DataAssetsHeaderProps, DataAssetsType, DataAssetsWithServiceField, } from '../components/DataAssets/DataAssetsHeader/DataAssetsHeader.interface'; -import { NO_DATA_PLACEHOLDER } from '../constants/constants'; +import { + DATA_ASSET_ICON_DIMENSION, + NO_DATA_PLACEHOLDER, +} from '../constants/constants'; import { EntityType } from '../enums/entity.enum'; import { APICollection } from '../generated/entity/data/apiCollection'; import { APIEndpoint } from '../generated/entity/data/apiEndpoint'; @@ -64,6 +66,89 @@ import { getEntityDetailsPath } from './RouterUtils'; import { bytesToSize } from './StringsUtils'; import { getUsagePercentile } from './TableUtils'; +export const ExtraInfoLabel = ({ + label, + value, + dataTestId, + inlineLayout = false, +}: { + label: string; + value: string | number | React.ReactNode; + dataTestId?: string; + inlineLayout?: boolean; +}) => { + if (inlineLayout) { + return ( + <> + + + {!isEmpty(label) && ( + {`${label}: `} + )} + {value} + + + ); + } + + return ( +
+ + {!isEmpty(label) && ( + {label} + )} +
+ {value} +
+
+
+ ); +}; + +export const ExtraInfoLink = ({ + label, + value, + href, + newTab = false, + ellipsis = false, +}: { + label: string; + value: string | number; + href: string; + newTab?: boolean; + ellipsis?: boolean; +}) => ( +
+ {!isEmpty(label) && ( + {label} + )} +
+ + + {value} + + + +
+
+); + export const getDataAssetsHeaderInfo = ( entityType: DataAssetsHeaderProps['entityType'], dataAsset: DataAssetsHeaderProps['dataAsset'],