diff --git a/openmetadata-ui/src/main/resources/ui/src/AppState.ts b/openmetadata-ui/src/main/resources/ui/src/AppState.ts index 79cb43376ac..ca7c5ab1582 100644 --- a/openmetadata-ui/src/main/resources/ui/src/AppState.ts +++ b/openmetadata-ui/src/main/resources/ui/src/AppState.ts @@ -11,7 +11,7 @@ * limitations under the License. */ -import { EntityData } from 'components/common/PopOverCard/EntityPopOverCard'; +import { EntityUnion } from 'components/Explore/explore.interface'; import { isEmpty, isNil, isUndefined } from 'lodash'; import { action, makeAutoObservable } from 'mobx'; import { ClientAuth, NewUser } from 'Models'; @@ -38,7 +38,7 @@ class AppState { nonSecureUserDetails: User = {} as User; userDetails: User = {} as User; userDataProfiles: Record = {}; - entityData: Record = {}; + entityData: Record = {}; userTeams: Array = []; userPermissions: ResourcePermission[] = []; userProfilePics: Array<{ diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/ContainerSummary/ContainerSummary.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/ContainerSummary/ContainerSummary.component.tsx new file mode 100644 index 00000000000..0f654f623ef --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/ContainerSummary/ContainerSummary.component.tsx @@ -0,0 +1,131 @@ +/* + * 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 { Col, Divider, Row, Typography } from 'antd'; +import classNames from 'classnames'; +import SummaryPanelSkeleton from 'components/Skeleton/SummaryPanelSkeleton/SummaryPanelSkeleton.component'; +import { SummaryEntityType } from 'enums/EntitySummary.enum'; +import { ExplorePageTabs } from 'enums/Explore.enum'; +import React, { useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Link } from 'react-router-dom'; +import { getFormattedEntityData } from 'utils/EntitySummaryPanelUtils'; +import { + DRAWER_NAVIGATION_OPTIONS, + getEntityOverview, +} from 'utils/EntityUtils'; +import SVGIcons from 'utils/SvgUtils'; +import SummaryList from '../SummaryList/SummaryList.component'; +import { BasicEntityInfo } from '../SummaryList/SummaryList.interface'; +import { ContainerSummaryProps } from './ContainerSummary.interface'; + +function ContainerSummary({ + entityDetails, + componentType = DRAWER_NAVIGATION_OPTIONS.explore, + isLoading, +}: ContainerSummaryProps) { + const { t } = useTranslation(); + + console.log(entityDetails); + + const entityInfo = useMemo( + () => getEntityOverview(ExplorePageTabs.CONTAINERS, entityDetails), + [entityDetails] + ); + + const formattedColumnsData: BasicEntityInfo[] = useMemo( + () => + getFormattedEntityData( + SummaryEntityType.COLUMN, + entityDetails.dataModel?.columns + ), + [entityDetails] + ); + + return ( + + <> + + + + {entityInfo.map((info) => { + const isOwner = info.name === t('label.owner'); + + return info.visible?.includes(componentType) ? ( + + + {!isOwner ? ( + + + {info.name} + + + ) : null} + + {info.isLink ? ( + + {info.value} + {info.isExternal ? ( + + ) : null} + + ) : ( + + {info.value} + + )} + + + + ) : null; + })} + + + + + + + + + {t('label.schema')} + + + + + + + + + ); +} + +export default ContainerSummary; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/ContainerSummary/ContainerSummary.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/ContainerSummary/ContainerSummary.interface.ts new file mode 100644 index 00000000000..efa47e02e5a --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/ContainerSummary/ContainerSummary.interface.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ +import { Container } from 'generated/entity/data/container'; +import { TagLabel } from 'generated/type/tagLabel'; + +export interface ContainerSummaryProps { + entityDetails: Container; + componentType?: string; + tags?: TagLabel[]; + isLoading?: boolean; +} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/ContainerSummary/ContainerSummary.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/ContainerSummary/ContainerSummary.test.tsx new file mode 100644 index 00000000000..544f798d764 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/EntitySummaryPanel/ContainerSummary/ContainerSummary.test.tsx @@ -0,0 +1,112 @@ +/* + * 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. + */ + +import { act, render, screen } from '@testing-library/react'; +import { + Constraint, + Container, + DataType, + FileFormat, + ObjectStoreServiceType, +} from 'generated/entity/data/container'; +import React from 'react'; +import ContainerSummary from './ContainerSummary.component'; + +jest.mock('../SummaryList/SummaryList.component', () => + jest + .fn() + .mockImplementation(() =>
SummaryList
) +); + +const mockEntityDetails: Container = { + id: '63be99e5-8ebf-44b6-8247-0f4faed00798', + name: 'transactions', + fullyQualifiedName: 's3_object_store_sample.transactions', + displayName: 'Company Transactions', + description: "Bucket containing all the company's transactions", + version: 0.1, + updatedAt: 1678969800877, + updatedBy: 'admin', + href: 'http://openmetadata-server:8585/api/v1/containers/63be99e5-8ebf-44b6-8247-0f4faed00798', + service: { + id: '7ab99e67-b578-4361-bad2-9076a52b341d', + type: 'objectStoreService', + name: 's3_object_store_sample', + fullyQualifiedName: 's3_object_store_sample', + deleted: false, + href: 'http://openmetadata-server:8585/api/v1/services/objectstoreServices/7ab99e67-b578-4361-bad2-9076a52b341d', + }, + dataModel: { + isPartitioned: true, + columns: [ + { + name: 'transaction_id', + dataType: DataType.Numeric, + dataTypeDisplay: 'numeric', + description: + 'The ID of the executed transaction. This column is the primary key for this table.', + fullyQualifiedName: + 's3_object_store_sample.transactions.transaction_id', + tags: [], + constraint: Constraint.PrimaryKey, + ordinalPosition: 1, + }, + { + name: 'merchant', + dataType: DataType.Varchar, + dataLength: 100, + dataTypeDisplay: 'varchar', + description: 'The merchant for this transaction.', + fullyQualifiedName: 's3_object_store_sample.transactions.merchant', + tags: [], + ordinalPosition: 2, + }, + { + name: 'transaction_time', + dataType: DataType.Timestamp, + dataTypeDisplay: 'timestamp', + description: 'The time the transaction took place.', + fullyQualifiedName: + 's3_object_store_sample.transactions.transaction_time', + tags: [], + ordinalPosition: 3, + }, + ], + }, + prefix: '/transactions/', + numberOfObjects: 50, + size: 102400, + fileFormats: [FileFormat.Parquet], + serviceType: ObjectStoreServiceType.S3, + deleted: false, + tags: [], + followers: [], +}; + +describe('ContainerSummary component tests', () => { + it('Component should render properly, when loaded in the Explore page.', async () => { + await act(async () => { + render(); + }); + + const numberOfObjects = screen.getByTestId('label.number-of-object-value'); + const serviceType = screen.getByTestId('label.service-type-value'); + const colsLength = screen.getByTestId('label.column-plural-value'); + const summaryList = screen.getByTestId('SummaryList'); + + expect(numberOfObjects).toBeInTheDocument(); + expect(serviceType).toBeInTheDocument(); + expect(colsLength).toBeInTheDocument(); + expect(summaryList).toBeInTheDocument(); + }); +}); 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 index 25434e20718..55335a372e7 100644 --- 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 @@ -15,6 +15,7 @@ import { CloseOutlined } from '@ant-design/icons'; import { Col, Drawer, Row } from 'antd'; import TableDataCardTitle from 'components/common/table-data-card-v2/TableDataCardTitle.component'; import { EntityType } from 'enums/entity.enum'; +import { Container } from 'generated/entity/data/container'; import React, { useMemo, useState } from 'react'; import { useParams } from 'react-router-dom'; import { ExplorePageTabs } from '../../../enums/Explore.enum'; @@ -23,6 +24,7 @@ import { Mlmodel } from '../../../generated/entity/data/mlmodel'; import { Pipeline } from '../../../generated/entity/data/pipeline'; import { Table } from '../../../generated/entity/data/table'; import { Topic } from '../../../generated/entity/data/topic'; +import ContainerSummary from './ContainerSummary/ContainerSummary.component'; import DashboardSummary from './DashboardSummary/DashboardSummary.component'; import { EntitySummaryPanelProps } from './EntitySummaryPanel.interface'; import './EntitySummaryPanel.style.less'; @@ -73,6 +75,15 @@ export default function EntitySummaryPanel({ ); + case ExplorePageTabs.CONTAINERS: + setCurrentSearchIndex(EntityType.CONTAINER); + + return ( + + ); + default: return null; } 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 caec04bf38c..d8498721f34 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 @@ -47,7 +47,7 @@ import AppliedFilterText from './AppliedFilterText/AppliedFilterText'; import EntitySummaryPanel from './EntitySummaryPanel/EntitySummaryPanel.component'; import { EntityDetailsObjectInterface, - EntityDetailsType, + EntityUnion, ExploreProps, ExploreQuickFilterField, ExploreSearchIndex, @@ -83,7 +83,7 @@ const Explore: React.FC = ({ >([] as ExploreQuickFilterField[]); const [showSummaryPanel, setShowSummaryPanel] = useState(false); const [entityDetails, setEntityDetails] = - useState<{ details: EntityDetailsType; entityType: string }>(); + useState<{ details: EntityUnion; entityType: string }>(); const { toggleModal, sqlQuery } = useAdvanceSearch(); @@ -160,7 +160,7 @@ const Explore: React.FC = ({ }; const handleSummaryPanelDisplay = useCallback( - (details: EntityDetailsType, entityType: string) => { + (details: EntityUnion, entityType: string) => { setShowSummaryPanel(true); setEntityDetails({ details, entityType }); }, @@ -231,7 +231,7 @@ const Explore: React.FC = ({ searchResults?.hits?.hits[0]._index === searchIndex ) { handleSummaryPanelDisplay( - searchResults?.hits?.hits[0]._source as EntityDetailsType, + searchResults?.hits?.hits[0]._source as EntityUnion, tab ); } else { 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 03aecb851c6..2a09d2b0c7c 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 @@ -76,6 +76,7 @@ describe('Test Explore component', () => { [SearchIndex.DASHBOARD]: 8, [SearchIndex.PIPELINE]: 5, [SearchIndex.MLMODEL]: 2, + [SearchIndex.CONTAINER]: 7, }} onChangeAdvancedSearchQueryFilter={mockFunction} onChangePostFilter={mockFunction} @@ -96,6 +97,6 @@ describe('Test Explore component', () => { expect(searchData).toBeInTheDocument(); expect(wrappedContent).toBeInTheDocument(); - expect(tabs).toHaveLength(5); + expect(tabs).toHaveLength(6); }); }); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExploreQuickFilters.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExploreQuickFilters.interface.ts index 72578a76af2..480265b17d9 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExploreQuickFilters.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExploreQuickFilters.interface.ts @@ -12,10 +12,7 @@ */ import { SearchIndex } from '../../enums/search.enum'; -import { - EntityDetailsType, - ExploreQuickFilterField, -} from './explore.interface'; +import { EntityUnion, ExploreQuickFilterField } from './explore.interface'; export interface ExploreQuickFiltersProps { index: SearchIndex; @@ -32,5 +29,5 @@ export interface FilterFieldsMenuItem { export interface FormattedSuggestResponseObject { text: string; - source: EntityDetailsType; + source: EntityUnion; } diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExploreQuickFilters.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExploreQuickFilters.tsx index 78e5c348a1f..63204dda3ef 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExploreQuickFilters.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExploreQuickFilters.tsx @@ -34,7 +34,7 @@ import { import { showErrorToast } from '../../utils/ToastUtils'; import SearchDropdown from '../SearchDropdown/SearchDropdown'; import { SearchDropdownOption } from '../SearchDropdown/SearchDropdown.interface'; -import { EntityDetailsType } from './explore.interface'; +import { EntityUnion } from './explore.interface'; import { ExploreQuickFiltersProps } from './ExploreQuickFilters.interface'; const ExploreQuickFilters: FC = ({ @@ -100,7 +100,7 @@ const ExploreQuickFilters: FC = ({ const formattedSuggestions = suggestOptions.map((op) => ({ text: op.text, - source: op._source as EntityDetailsType, + source: op._source as EntityUnion, })); const optionsArray = getOptionsObject(key, formattedSuggestions); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/explore.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/Explore/explore.interface.ts index b9b8354efbd..1d817d444cd 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Explore/explore.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/explore.interface.ts @@ -13,6 +13,9 @@ import { DefaultOptionType } from 'antd/lib/select'; import { SORT_ORDER } from 'enums/common.enum'; +import { Container } from 'generated/entity/data/container'; +import { Database } from 'generated/entity/data/database'; +import { DatabaseSchema } from 'generated/entity/data/databaseSchema'; import { SearchIndex } from '../../enums/search.enum'; import { Dashboard } from '../../generated/entity/data/dashboard'; import { Mlmodel } from '../../generated/entity/data/mlmodel'; @@ -33,7 +36,8 @@ export type ExploreSearchIndex = | SearchIndex.PIPELINE | SearchIndex.DASHBOARD | SearchIndex.MLMODEL - | SearchIndex.TOPIC; + | SearchIndex.TOPIC + | SearchIndex.CONTAINER; export type ExploreSearchIndexKey = | 'TABLE' @@ -96,9 +100,18 @@ export interface SearchInputProps { handleClear: () => void; } -export type EntityDetailsType = Table | Topic | Dashboard | Pipeline | Mlmodel; +// Type for all the explore tab entities +export type EntityUnion = + | Table + | Topic + | Dashboard + | Pipeline + | Mlmodel + | Container + | DatabaseSchema + | Database; export interface EntityDetailsObjectInterface { - details: EntityDetailsType; + details: EntityUnion; entityType: string; } diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/PopOverCard/EntityPopOverCard.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/PopOverCard/EntityPopOverCard.tsx index f7bd81ab6c5..3bda3fe5be8 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/PopOverCard/EntityPopOverCard.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/PopOverCard/EntityPopOverCard.tsx @@ -13,6 +13,7 @@ import { Button, Divider, Popover, Space, Typography } from 'antd'; import { AxiosError } from 'axios'; +import { EntityUnion } from 'components/Explore/explore.interface'; import { uniqueId } from 'lodash'; import { EntityTags } from 'Models'; import React, { FC, HTMLAttributes, useEffect, useMemo, useState } from 'react'; @@ -31,13 +32,7 @@ import { getEntityName } from 'utils/EntityUtils'; import AppState from '../../../AppState'; import { FQN_SEPARATOR_CHAR } from '../../../constants/char.constants'; import { EntityType } from '../../../enums/entity.enum'; -import { Dashboard } from '../../../generated/entity/data/dashboard'; -import { Database } from '../../../generated/entity/data/database'; -import { DatabaseSchema } from '../../../generated/entity/data/databaseSchema'; -import { Mlmodel } from '../../../generated/entity/data/mlmodel'; -import { Pipeline } from '../../../generated/entity/data/pipeline'; import { Table } from '../../../generated/entity/data/table'; -import { Topic } from '../../../generated/entity/data/topic'; import { TagSource } from '../../../generated/type/tagLabel'; import SVGIcons from '../../../utils/SvgUtils'; import { @@ -49,15 +44,6 @@ import { showErrorToast } from '../../../utils/ToastUtils'; import ProfilePicture from '../ProfilePicture/ProfilePicture'; import RichTextEditorPreviewer from '../rich-text-editor/RichTextEditorPreviewer'; -export type EntityData = - | Table - | Topic - | Dashboard - | Pipeline - | Mlmodel - | Database - | DatabaseSchema; - interface Props extends HTMLAttributes { entityType: string; entityFQN: string; @@ -65,7 +51,7 @@ interface Props extends HTMLAttributes { const EntityPopOverCard: FC = ({ children, entityType, entityFQN }) => { const { t } = useTranslation(); - const [entityData, setEntityData] = useState({} as EntityData); + const [entityData, setEntityData] = useState({} as EntityUnion); const entityTier = useMemo(() => { const tierFQN = getTierTags((entityData as Table).tags || [])?.tagFQN; @@ -83,13 +69,13 @@ const EntityPopOverCard: FC = ({ children, entityType, entityFQN }) => { }, [(entityData as Table).tags]); const getData = () => { - const setEntityDetails = (entityDetail: EntityData) => { + const setEntityDetails = (entityDetail: EntityUnion) => { AppState.entityData[entityFQN] = entityDetail; }; const fields = 'tags,owner'; - let promise: Promise | null = null; + let promise: Promise | null = null; switch (entityType) { case EntityType.TABLE: diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/SummaryTagsDescription/SummaryTagsDescription.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/SummaryTagsDescription/SummaryTagsDescription.component.tsx index bae356f4cc9..d5288b4a481 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/SummaryTagsDescription/SummaryTagsDescription.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/SummaryTagsDescription/SummaryTagsDescription.component.tsx @@ -11,12 +11,12 @@ * limitations under the License. */ import { Col, Divider, Row, Typography } from 'antd'; +import { EntityUnion } from 'components/Explore/explore.interface'; import TagsViewer from 'components/Tag/TagsViewer/tags-viewer'; import { TagLabel } from 'generated/type/tagLabel'; import React from 'react'; import { useTranslation } from 'react-i18next'; import { ReactComponent as TagIcon } from '../../../assets/svg/tag-grey.svg'; -import { EntityData } from '../PopOverCard/EntityPopOverCard'; import RichTextEditorPreviewer from '../rich-text-editor/RichTextEditorPreviewer'; const SummaryTagsDescription = ({ @@ -24,7 +24,7 @@ const SummaryTagsDescription = ({ entityDetail, }: { tags: TagLabel[]; - entityDetail: EntityData; + entityDetail: EntityUnion; }) => { const { t } = useTranslation(); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/table-data-card-v2/TableDataCardTitle.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/table-data-card-v2/TableDataCardTitle.component.tsx index fb2044d282b..5089b2e6962 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/table-data-card-v2/TableDataCardTitle.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/table-data-card-v2/TableDataCardTitle.component.tsx @@ -25,14 +25,13 @@ import { } from '../../../utils/CommonUtils'; import { stringToHTML } from '../../../utils/StringsUtils'; import { getEntityLink } from '../../../utils/TableUtils'; -import { SourceType } from '../../searched-data/SearchedData.interface'; import './TableDataCardTitle.less'; interface TableDataCardTitleProps { dataTestId?: string; id?: string; searchIndex: SearchIndex | EntityType; - source: SourceType; + source: { fullyQualifiedName?: string; displayName?: string }; isPanel?: boolean; handleLinkClick?: (e: React.MouseEvent) => void; } diff --git a/openmetadata-ui/src/main/resources/ui/src/components/common/table-data-card-v2/TableDataCardV2.tsx b/openmetadata-ui/src/main/resources/ui/src/components/common/table-data-card-v2/TableDataCardV2.tsx index bbee18e221d..87871f14e65 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/common/table-data-card-v2/TableDataCardV2.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/common/table-data-card-v2/TableDataCardV2.tsx @@ -13,6 +13,7 @@ import { ExclamationCircleOutlined } from '@ant-design/icons'; import classNames from 'classnames'; +import { EntityUnion } from 'components/Explore/explore.interface'; import { isString, startCase, uniqueId } from 'lodash'; import { ExtraInfo } from 'Models'; import React, { useMemo } from 'react'; @@ -33,7 +34,6 @@ import { } from '../../../utils/CommonUtils'; import { serviceTypeLogo } from '../../../utils/ServiceUtils'; import { getUsagePercentile } from '../../../utils/TableUtils'; -import { EntityDetailsType } from '../../Explore/explore.interface'; import { SearchedDataProps } from '../../searched-data/SearchedData.interface'; import '../table-data-card/TableDataCard.style.css'; import TableDataCardBody from '../table-data-card/TableDataCardBody'; @@ -50,7 +50,7 @@ export interface TableDataCardPropsV2 { }[]; searchIndex: SearchIndex | EntityType; handleSummaryPanelDisplay?: ( - details: EntityDetailsType, + details: EntityUnion, entityType: string ) => void; } @@ -133,7 +133,7 @@ const TableDataCardV2: React.FC = ({ id={id} onClick={() => { handleSummaryPanelDisplay && - handleSummaryPanelDisplay(source as EntityDetailsType, tab); + handleSummaryPanelDisplay(source as EntityUnion, tab); }}>
{'databaseSchema' in source && 'database' in source && ( 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 835f3823bfa..f3e882522ea 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 @@ -21,10 +21,7 @@ import { SearchHitBody, TableSearchSource, } from '../../interface/search.interface'; -import { - EntityDetailsType, - ExploreSearchIndex, -} from '../Explore/explore.interface'; +import { EntityUnion, ExploreSearchIndex } from '../Explore/explore.interface'; type Fields = | 'name' @@ -75,7 +72,7 @@ export interface SearchedDataProps { showOnlyChildren?: boolean; isFilterSelected: boolean; handleSummaryPanelDisplay?: ( - details: EntityDetailsType, + details: EntityUnion, entityType: string ) => void; } diff --git a/openmetadata-ui/src/main/resources/ui/src/constants/constants.ts b/openmetadata-ui/src/main/resources/ui/src/constants/constants.ts index 5e2ced50a55..d1ca57275a1 100644 --- a/openmetadata-ui/src/main/resources/ui/src/constants/constants.ts +++ b/openmetadata-ui/src/main/resources/ui/src/constants/constants.ts @@ -119,7 +119,6 @@ export const INGESTION_NAME = ':ingestionName'; export const LOG_ENTITY_NAME = ':logEntityName'; export const KPI_NAME = ':kpiName'; export const PLACEHOLDER_ACTION = ':action'; -export const PLACEHOLDER_CONTAINER_NAME = ':containerName'; export const pagingObject = { after: '', before: '', total: 0 }; @@ -257,8 +256,8 @@ export const ROUTES = { ADD_KPI: `/data-insights/kpi/add-kpi`, EDIT_KPI: `/data-insights/kpi/edit-kpi/${KPI_NAME}`, - CONTAINER_DETAILS: `/container/${PLACEHOLDER_CONTAINER_NAME}`, - CONTAINER_DETAILS_WITH_TAB: `/container/${PLACEHOLDER_CONTAINER_NAME}/${PLACEHOLDER_ROUTE_TAB}`, + CONTAINER_DETAILS: `/container/${PLACEHOLDER_ROUTE_ENTITY_FQN}`, + CONTAINER_DETAILS_WITH_TAB: `/container/${PLACEHOLDER_ROUTE_ENTITY_FQN}/${PLACEHOLDER_ROUTE_TAB}`, }; export const SOCKET_EVENTS = { diff --git a/openmetadata-ui/src/main/resources/ui/src/constants/explore.constants.ts b/openmetadata-ui/src/main/resources/ui/src/constants/explore.constants.ts index c7a21aa9bf2..d4238b4156f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/constants/explore.constants.ts +++ b/openmetadata-ui/src/main/resources/ui/src/constants/explore.constants.ts @@ -27,19 +27,19 @@ export const MAX_RESULT_HITS = 10000; // as it is used only in unit tests it's not needed for translation export const tableSortingFields: SortingField[] = [ { - name: 'Last Updated', + name: t('label.last-updated'), value: 'updatedAt', }, - { name: 'Weekly Usage', value: 'usageSummary.weeklyStats.count' }, - { name: 'Relevance', value: '_score' }, + { name: t('label.weekly-usage'), value: 'usageSummary.weeklyStats.count' }, + { name: t('label.relevance'), value: '_score' }, ]; export const entitySortingFields = [ { - name: 'Last Updated', + name: t('label.last-updated'), value: 'updatedAt', }, - { name: 'Relevance', value: '_score' }, + { name: t('label.relevance'), value: '_score' }, ]; export interface ExploreTabInfo { @@ -90,4 +90,10 @@ export const tabsInfo: { [K in ExploreSearchIndex]: ExploreTabInfo } = { sortField: INITIAL_SORT_FIELD, path: 'mlmodels', }, + [SearchIndex.CONTAINER]: { + label: t('label.container-plural'), + sortingFields: entitySortingFields, + sortField: INITIAL_SORT_FIELD, + path: 'containers', + }, }; diff --git a/openmetadata-ui/src/main/resources/ui/src/enums/Explore.enum.ts b/openmetadata-ui/src/main/resources/ui/src/enums/Explore.enum.ts index ac1ef1c0a43..e9e45228b68 100644 --- a/openmetadata-ui/src/main/resources/ui/src/enums/Explore.enum.ts +++ b/openmetadata-ui/src/main/resources/ui/src/enums/Explore.enum.ts @@ -22,4 +22,5 @@ export enum ExplorePageTabs { DASHBOARDS = 'dashboards', PIPELINES = 'pipelines', MLMODELS = 'mlmodels', + CONTAINERS = 'containers', } diff --git a/openmetadata-ui/src/main/resources/ui/src/enums/search.enum.ts b/openmetadata-ui/src/main/resources/ui/src/enums/search.enum.ts index 0c3269a78a5..c85a922a83b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/enums/search.enum.ts +++ b/openmetadata-ui/src/main/resources/ui/src/enums/search.enum.ts @@ -21,6 +21,7 @@ export enum SearchIndex { GLOSSARY = 'glossary_search_index', MLMODEL = 'mlmodel_search_index', TAG = 'tag_search_index', + CONTAINER = 'container_search_index', } export const GENERAL_SEARCH_INDEX = [ @@ -29,4 +30,5 @@ export const GENERAL_SEARCH_INDEX = [ SearchIndex.TOPIC, SearchIndex.PIPELINE, SearchIndex.MLMODEL, + SearchIndex.CONTAINER, ]; diff --git a/openmetadata-ui/src/main/resources/ui/src/interface/search.interface.ts b/openmetadata-ui/src/main/resources/ui/src/interface/search.interface.ts index b4ce20dadca..a044f5a4907 100644 --- a/openmetadata-ui/src/main/resources/ui/src/interface/search.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/interface/search.interface.ts @@ -11,6 +11,7 @@ * limitations under the License. */ +import { Container } from 'generated/entity/data/container'; import { SearchIndex } from '../enums/search.enum'; import { Tag } from '../generated/entity/classification/tag'; import { Dashboard } from '../generated/entity/data/dashboard'; @@ -67,6 +68,8 @@ export interface UserSearchSource extends SearchSourceBase, User {} // extends E export interface TeamSearchSource extends SearchSourceBase, Team {} // extends EntityInterface +export interface ContainerSearchSource extends SearchSourceBase, Container {} // extends EntityInterface + export interface TagClassSearchSource extends SearchSourceBase, Tag { id: string; // Tag is generated with the `id` field as optional, which is should not } // extends EntityInterface @@ -78,7 +81,8 @@ export type ExploreSearchSource = | DashboardSearchSource | MlmodelSearchSource | TopicSearchSource - | PipelineSearchSource; + | PipelineSearchSource + | ContainerSearchSource; export type SearchIndexSearchSourceMapping = { [SearchIndex.TABLE]: TableSearchSource; @@ -90,6 +94,7 @@ export type SearchIndexSearchSourceMapping = { [SearchIndex.USER]: UserSearchSource; [SearchIndex.TOPIC]: TopicSearchSource; [SearchIndex.TAG]: TagClassSearchSource; + [SearchIndex.CONTAINER]: ContainerSearchSource; }; export type SearchRequest< diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json index a885c4853f1..11fdd2fd94c 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json @@ -492,6 +492,7 @@ "notification-plural": "Notifications", "november": "November", "null": "Null", + "number-of-object": "Number of objects", "number-of-rows": "Number of rows", "object-store": "Object Store", "object-store-plural": "Object Stores", @@ -599,6 +600,7 @@ "region-name": "Region Name", "registry": "Registry", "related-term-plural": "Related Terms", + "relevance": "Relevance", "remove": "Remove", "remove-entity": "Remove {{entity}}", "removed": "Removed", @@ -843,6 +845,7 @@ "webhook-display-text": "Webhook {{displayText}}", "wednesday": "Wednesday", "week": "Week", + "weekly-usage": "Weekly Usage", "whats-new": "What's New", "yes": "Yes", "your-entity": "Your {{entity}}" diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json index ca8d4ccd931..b96cd17c9a9 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json @@ -492,6 +492,7 @@ "notification-plural": "Notifications", "november": "November", "null": "Null", + "number-of-object": "Number of objects", "number-of-rows": "Number of rows", "object-store": "Object Store", "object-store-plural": "Object Stores", @@ -599,6 +600,7 @@ "region-name": "Nom de Région", "registry": "Registry", "related-term-plural": "Related Terms", + "relevance": "Relevance", "remove": "Enlever", "remove-entity": "Supprimer {{entity}}", "removed": "Removed", @@ -843,6 +845,7 @@ "webhook-display-text": "Webhook {{displayText}}", "wednesday": "Wednesday", "week": "Week", + "weekly-usage": "Weekly Usage", "whats-new": "Nouveau", "yes": "Yes", "your-entity": "Your {{entity}}" diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json index d6b4dde237d..4dabdfb73a9 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json @@ -492,6 +492,7 @@ "notification-plural": "Notifications", "november": "November", "null": "Null", + "number-of-object": "Number of objects", "number-of-rows": "Number of rows", "object-store": "Object Store", "object-store-plural": "Object Stores", @@ -599,6 +600,7 @@ "region-name": "Region Name", "registry": "注册", "related-term-plural": "Related Terms", + "relevance": "Relevance", "remove": "删除", "remove-entity": "删除 {{entity}}", "removed": "Removed", @@ -843,6 +845,7 @@ "webhook-display-text": "Webhook {{displayText}}", "wednesday": "Wednesday", "week": "Week", + "weekly-usage": "Weekly Usage", "whats-new": "What's new", "yes": "是", "your-entity": "Your {{entity}}" diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/ContainerPage/ContainerPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/ContainerPage/ContainerPage.tsx index e7f938d56f3..d841f7b4737 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/ContainerPage/ContainerPage.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/ContainerPage/ContainerPage.tsx @@ -88,8 +88,8 @@ const ContainerPage = () => { const history = useHistory(); const { t } = useTranslation(); const { getEntityPermissionByFqn } = usePermissionProvider(); - const { containerName, tab = CONTAINER_DETAILS_TABS.SCHEME } = - useParams<{ containerName: string; tab: CONTAINER_DETAILS_TABS }>(); + const { entityFQN: containerName, tab = CONTAINER_DETAILS_TABS.SCHEME } = + useParams<{ entityFQN: string; tab: CONTAINER_DETAILS_TABS }>(); // Local states const [isLoading, setIsLoading] = useState(false); diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/explore/ExplorePage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/explore/ExplorePage.component.tsx index c59368805f2..7df95684484 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/explore/ExplorePage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/explore/ExplorePage.component.tsx @@ -202,6 +202,7 @@ const ExplorePage: FunctionComponent = () => { SearchIndex.DASHBOARD, SearchIndex.PIPELINE, SearchIndex.MLMODEL, + SearchIndex.CONTAINER, ].map((index) => searchQuery({ query: searchQueryParam, @@ -221,6 +222,7 @@ const ExplorePage: FunctionComponent = () => { dashboardResponse, pipelineResponse, mlmodelResponse, + containerResponse, ]) => { setSearchHitCounts({ [SearchIndex.TABLE]: tableResponse.hits.total.value, @@ -228,6 +230,7 @@ const ExplorePage: FunctionComponent = () => { [SearchIndex.DASHBOARD]: dashboardResponse.hits.total.value, [SearchIndex.PIPELINE]: pipelineResponse.hits.total.value, [SearchIndex.MLMODEL]: mlmodelResponse.hits.total.value, + [SearchIndex.CONTAINER]: containerResponse.hits.total.value, }); } ), diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/tour-page/TourPage.component.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/tour-page/TourPage.component.tsx index c1005af2c55..247945a1c74 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/tour-page/TourPage.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/tour-page/TourPage.component.tsx @@ -52,6 +52,7 @@ const exploreCount = { [SearchIndex.DASHBOARD]: 0, [SearchIndex.PIPELINE]: 0, [SearchIndex.MLMODEL]: 0, + [SearchIndex.CONTAINER]: 0, }; const TourPage = () => { diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/APIUtils.ts b/openmetadata-ui/src/main/resources/ui/src/utils/APIUtils.ts index e878d6d51f5..6d481519b55 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/APIUtils.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/APIUtils.ts @@ -25,6 +25,7 @@ export type SearchEntityHits = SearchResponse< | SearchIndex.TABLE | SearchIndex.MLMODEL | SearchIndex.TOPIC + | SearchIndex.CONTAINER >['hits']['hits']; // if more value is added, also update its interface file at -> interface/types.d.ts diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/ContainerDetailUtils.ts b/openmetadata-ui/src/main/resources/ui/src/utils/ContainerDetailUtils.ts index 9f045423854..dc12aacf2ef 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/ContainerDetailUtils.ts +++ b/openmetadata-ui/src/main/resources/ui/src/utils/ContainerDetailUtils.ts @@ -11,7 +11,7 @@ * limitations under the License. */ import { - PLACEHOLDER_CONTAINER_NAME, + PLACEHOLDER_ROUTE_ENTITY_FQN, PLACEHOLDER_ROUTE_TAB, ROUTES, } from 'constants/constants'; @@ -22,7 +22,7 @@ import { EntityTags, TagOption } from 'Models'; export const getContainerDetailPath = (containerFQN: string, tab?: string) => { let path = tab ? ROUTES.CONTAINER_DETAILS_WITH_TAB : ROUTES.CONTAINER_DETAILS; - path = path.replace(PLACEHOLDER_CONTAINER_NAME, containerFQN); + path = path.replace(PLACEHOLDER_ROUTE_ENTITY_FQN, containerFQN); if (tab) { path = path.replace(PLACEHOLDER_ROUTE_TAB, tab); diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx index 527761f828a..11a527178c7 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/EntityUtils.tsx @@ -12,14 +12,15 @@ */ import { Popover } from 'antd'; -import { EntityData } from 'components/common/PopOverCard/EntityPopOverCard'; import ProfilePicture from 'components/common/ProfilePicture/ProfilePicture'; import { LeafNodes, LineagePos, } from 'components/EntityLineage/EntityLineage.interface'; +import { EntityUnion } from 'components/Explore/explore.interface'; import { ResourceEntity } from 'components/PermissionProvider/PermissionProvider.interface'; import { ExplorePageTabs } from 'enums/Explore.enum'; +import { Container } from 'generated/entity/data/container'; import { Mlmodel } from 'generated/entity/data/mlmodel'; import i18next from 'i18next'; import { isEmpty, isNil, isUndefined, lowerCase, startCase } from 'lodash'; @@ -125,7 +126,7 @@ export const getOwnerNameWithProfilePic = ( export const getEntityOverview = ( type: string, - entityDetail: EntityData + entityDetail: EntityUnion ): Array<{ name: string; value: string | number | React.ReactNode; @@ -428,6 +429,35 @@ export const getEntityOverview = ( return overview; } + case ExplorePageTabs.CONTAINERS: { + const { numberOfObjects, serviceType, dataModel } = + entityDetail as Container; + + const overview = [ + { + name: i18next.t('label.number-of-object'), + value: numberOfObjects, + isLink: false, + visible: [DRAWER_NAVIGATION_OPTIONS.explore], + }, + { + name: i18next.t('label.service-type'), + value: serviceType, + isLink: false, + visible: [DRAWER_NAVIGATION_OPTIONS.explore], + }, + { + name: i18next.t('label.column-plural'), + value: + dataModel && dataModel.columns ? dataModel.columns.length : NO_DATA, + isLink: false, + visible: [DRAWER_NAVIGATION_OPTIONS.explore], + }, + ]; + + return overview; + } + default: return []; } diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.tsx index 3abc429b0c1..77e4944a1f4 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.tsx @@ -247,6 +247,7 @@ export const getEntityLink = ( return getMlModelPath(fullyQualifiedName); case EntityType.CONTAINER: + case SearchIndex.CONTAINER: return getContainerDetailPath(fullyQualifiedName); case SearchIndex.TABLE: