mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-19 04:41:02 +00:00
feat: add container entity in explore page (#10632)
* feat: add container entity in explore page * fix: adding missing localization keys * fix: adding localization on other languages * feat: add details for entity summary panel * fix: add localization * test: add unit tests for container summary
This commit is contained in:
parent
0fdd58939c
commit
7d91ed9eb2
@ -11,7 +11,7 @@
|
|||||||
* limitations under the License.
|
* 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 { isEmpty, isNil, isUndefined } from 'lodash';
|
||||||
import { action, makeAutoObservable } from 'mobx';
|
import { action, makeAutoObservable } from 'mobx';
|
||||||
import { ClientAuth, NewUser } from 'Models';
|
import { ClientAuth, NewUser } from 'Models';
|
||||||
@ -38,7 +38,7 @@ class AppState {
|
|||||||
nonSecureUserDetails: User = {} as User;
|
nonSecureUserDetails: User = {} as User;
|
||||||
userDetails: User = {} as User;
|
userDetails: User = {} as User;
|
||||||
userDataProfiles: Record<string, User> = {};
|
userDataProfiles: Record<string, User> = {};
|
||||||
entityData: Record<string, EntityData> = {};
|
entityData: Record<string, EntityUnion> = {};
|
||||||
userTeams: Array<UserTeams> = [];
|
userTeams: Array<UserTeams> = [];
|
||||||
userPermissions: ResourcePermission[] = [];
|
userPermissions: ResourcePermission[] = [];
|
||||||
userProfilePics: Array<{
|
userProfilePics: Array<{
|
||||||
|
@ -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 (
|
||||||
|
<SummaryPanelSkeleton loading={Boolean(isLoading)}>
|
||||||
|
<>
|
||||||
|
<Row className="m-md" gutter={[0, 4]}>
|
||||||
|
<Col span={24}>
|
||||||
|
<Row>
|
||||||
|
{entityInfo.map((info) => {
|
||||||
|
const isOwner = info.name === t('label.owner');
|
||||||
|
|
||||||
|
return info.visible?.includes(componentType) ? (
|
||||||
|
<Col key={info.name} span={24}>
|
||||||
|
<Row
|
||||||
|
className={classNames('', {
|
||||||
|
'p-b-md': isOwner,
|
||||||
|
})}
|
||||||
|
gutter={[16, 32]}>
|
||||||
|
{!isOwner ? (
|
||||||
|
<Col data-testid={`${info.name}-label`} span={8}>
|
||||||
|
<Typography.Text className="text-grey-muted">
|
||||||
|
{info.name}
|
||||||
|
</Typography.Text>
|
||||||
|
</Col>
|
||||||
|
) : null}
|
||||||
|
<Col data-testid={`${info.name}-value`} span={16}>
|
||||||
|
{info.isLink ? (
|
||||||
|
<Link
|
||||||
|
target={info.isExternal ? '_blank' : '_self'}
|
||||||
|
to={{ pathname: info.url }}>
|
||||||
|
{info.value}
|
||||||
|
{info.isExternal ? (
|
||||||
|
<SVGIcons
|
||||||
|
alt="external-link"
|
||||||
|
className="m-l-xs"
|
||||||
|
icon="external-link"
|
||||||
|
width="12px"
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<Typography.Text
|
||||||
|
className={classNames('text-grey-muted', {
|
||||||
|
'text-grey-body': !isOwner,
|
||||||
|
})}>
|
||||||
|
{info.value}
|
||||||
|
</Typography.Text>
|
||||||
|
)}
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Col>
|
||||||
|
) : null;
|
||||||
|
})}
|
||||||
|
</Row>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Divider className="m-y-xs" />
|
||||||
|
|
||||||
|
<Row className="m-md" gutter={[0, 16]}>
|
||||||
|
<Col span={24}>
|
||||||
|
<Typography.Text
|
||||||
|
className="text-base text-grey-muted"
|
||||||
|
data-testid="schema-header">
|
||||||
|
{t('label.schema')}
|
||||||
|
</Typography.Text>
|
||||||
|
</Col>
|
||||||
|
<Col span={24}>
|
||||||
|
<SummaryList
|
||||||
|
entityType={SummaryEntityType.COLUMN}
|
||||||
|
formattedEntityData={formattedColumnsData}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</>
|
||||||
|
</SummaryPanelSkeleton>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ContainerSummary;
|
@ -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;
|
||||||
|
}
|
@ -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(() => <div data-testid="SummaryList">SummaryList</div>)
|
||||||
|
);
|
||||||
|
|
||||||
|
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(<ContainerSummary entityDetails={mockEntityDetails} />);
|
||||||
|
});
|
||||||
|
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
});
|
@ -15,6 +15,7 @@ import { CloseOutlined } from '@ant-design/icons';
|
|||||||
import { Col, Drawer, Row } from 'antd';
|
import { Col, Drawer, Row } from 'antd';
|
||||||
import TableDataCardTitle from 'components/common/table-data-card-v2/TableDataCardTitle.component';
|
import TableDataCardTitle from 'components/common/table-data-card-v2/TableDataCardTitle.component';
|
||||||
import { EntityType } from 'enums/entity.enum';
|
import { EntityType } from 'enums/entity.enum';
|
||||||
|
import { Container } from 'generated/entity/data/container';
|
||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { ExplorePageTabs } from '../../../enums/Explore.enum';
|
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 { Pipeline } from '../../../generated/entity/data/pipeline';
|
||||||
import { Table } from '../../../generated/entity/data/table';
|
import { Table } from '../../../generated/entity/data/table';
|
||||||
import { Topic } from '../../../generated/entity/data/topic';
|
import { Topic } from '../../../generated/entity/data/topic';
|
||||||
|
import ContainerSummary from './ContainerSummary/ContainerSummary.component';
|
||||||
import DashboardSummary from './DashboardSummary/DashboardSummary.component';
|
import DashboardSummary from './DashboardSummary/DashboardSummary.component';
|
||||||
import { EntitySummaryPanelProps } from './EntitySummaryPanel.interface';
|
import { EntitySummaryPanelProps } from './EntitySummaryPanel.interface';
|
||||||
import './EntitySummaryPanel.style.less';
|
import './EntitySummaryPanel.style.less';
|
||||||
@ -73,6 +75,15 @@ export default function EntitySummaryPanel({
|
|||||||
<MlModelSummary entityDetails={entityDetails.details as Mlmodel} />
|
<MlModelSummary entityDetails={entityDetails.details as Mlmodel} />
|
||||||
);
|
);
|
||||||
|
|
||||||
|
case ExplorePageTabs.CONTAINERS:
|
||||||
|
setCurrentSearchIndex(EntityType.CONTAINER);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ContainerSummary
|
||||||
|
entityDetails={entityDetails.details as Container}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ import AppliedFilterText from './AppliedFilterText/AppliedFilterText';
|
|||||||
import EntitySummaryPanel from './EntitySummaryPanel/EntitySummaryPanel.component';
|
import EntitySummaryPanel from './EntitySummaryPanel/EntitySummaryPanel.component';
|
||||||
import {
|
import {
|
||||||
EntityDetailsObjectInterface,
|
EntityDetailsObjectInterface,
|
||||||
EntityDetailsType,
|
EntityUnion,
|
||||||
ExploreProps,
|
ExploreProps,
|
||||||
ExploreQuickFilterField,
|
ExploreQuickFilterField,
|
||||||
ExploreSearchIndex,
|
ExploreSearchIndex,
|
||||||
@ -83,7 +83,7 @@ const Explore: React.FC<ExploreProps> = ({
|
|||||||
>([] as ExploreQuickFilterField[]);
|
>([] as ExploreQuickFilterField[]);
|
||||||
const [showSummaryPanel, setShowSummaryPanel] = useState(false);
|
const [showSummaryPanel, setShowSummaryPanel] = useState(false);
|
||||||
const [entityDetails, setEntityDetails] =
|
const [entityDetails, setEntityDetails] =
|
||||||
useState<{ details: EntityDetailsType; entityType: string }>();
|
useState<{ details: EntityUnion; entityType: string }>();
|
||||||
|
|
||||||
const { toggleModal, sqlQuery } = useAdvanceSearch();
|
const { toggleModal, sqlQuery } = useAdvanceSearch();
|
||||||
|
|
||||||
@ -160,7 +160,7 @@ const Explore: React.FC<ExploreProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleSummaryPanelDisplay = useCallback(
|
const handleSummaryPanelDisplay = useCallback(
|
||||||
(details: EntityDetailsType, entityType: string) => {
|
(details: EntityUnion, entityType: string) => {
|
||||||
setShowSummaryPanel(true);
|
setShowSummaryPanel(true);
|
||||||
setEntityDetails({ details, entityType });
|
setEntityDetails({ details, entityType });
|
||||||
},
|
},
|
||||||
@ -231,7 +231,7 @@ const Explore: React.FC<ExploreProps> = ({
|
|||||||
searchResults?.hits?.hits[0]._index === searchIndex
|
searchResults?.hits?.hits[0]._index === searchIndex
|
||||||
) {
|
) {
|
||||||
handleSummaryPanelDisplay(
|
handleSummaryPanelDisplay(
|
||||||
searchResults?.hits?.hits[0]._source as EntityDetailsType,
|
searchResults?.hits?.hits[0]._source as EntityUnion,
|
||||||
tab
|
tab
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -76,6 +76,7 @@ describe('Test Explore component', () => {
|
|||||||
[SearchIndex.DASHBOARD]: 8,
|
[SearchIndex.DASHBOARD]: 8,
|
||||||
[SearchIndex.PIPELINE]: 5,
|
[SearchIndex.PIPELINE]: 5,
|
||||||
[SearchIndex.MLMODEL]: 2,
|
[SearchIndex.MLMODEL]: 2,
|
||||||
|
[SearchIndex.CONTAINER]: 7,
|
||||||
}}
|
}}
|
||||||
onChangeAdvancedSearchQueryFilter={mockFunction}
|
onChangeAdvancedSearchQueryFilter={mockFunction}
|
||||||
onChangePostFilter={mockFunction}
|
onChangePostFilter={mockFunction}
|
||||||
@ -96,6 +97,6 @@ describe('Test Explore component', () => {
|
|||||||
|
|
||||||
expect(searchData).toBeInTheDocument();
|
expect(searchData).toBeInTheDocument();
|
||||||
expect(wrappedContent).toBeInTheDocument();
|
expect(wrappedContent).toBeInTheDocument();
|
||||||
expect(tabs).toHaveLength(5);
|
expect(tabs).toHaveLength(6);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -12,10 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { SearchIndex } from '../../enums/search.enum';
|
import { SearchIndex } from '../../enums/search.enum';
|
||||||
import {
|
import { EntityUnion, ExploreQuickFilterField } from './explore.interface';
|
||||||
EntityDetailsType,
|
|
||||||
ExploreQuickFilterField,
|
|
||||||
} from './explore.interface';
|
|
||||||
|
|
||||||
export interface ExploreQuickFiltersProps {
|
export interface ExploreQuickFiltersProps {
|
||||||
index: SearchIndex;
|
index: SearchIndex;
|
||||||
@ -32,5 +29,5 @@ export interface FilterFieldsMenuItem {
|
|||||||
|
|
||||||
export interface FormattedSuggestResponseObject {
|
export interface FormattedSuggestResponseObject {
|
||||||
text: string;
|
text: string;
|
||||||
source: EntityDetailsType;
|
source: EntityUnion;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ import {
|
|||||||
import { showErrorToast } from '../../utils/ToastUtils';
|
import { showErrorToast } from '../../utils/ToastUtils';
|
||||||
import SearchDropdown from '../SearchDropdown/SearchDropdown';
|
import SearchDropdown from '../SearchDropdown/SearchDropdown';
|
||||||
import { SearchDropdownOption } from '../SearchDropdown/SearchDropdown.interface';
|
import { SearchDropdownOption } from '../SearchDropdown/SearchDropdown.interface';
|
||||||
import { EntityDetailsType } from './explore.interface';
|
import { EntityUnion } from './explore.interface';
|
||||||
import { ExploreQuickFiltersProps } from './ExploreQuickFilters.interface';
|
import { ExploreQuickFiltersProps } from './ExploreQuickFilters.interface';
|
||||||
|
|
||||||
const ExploreQuickFilters: FC<ExploreQuickFiltersProps> = ({
|
const ExploreQuickFilters: FC<ExploreQuickFiltersProps> = ({
|
||||||
@ -100,7 +100,7 @@ const ExploreQuickFilters: FC<ExploreQuickFiltersProps> = ({
|
|||||||
|
|
||||||
const formattedSuggestions = suggestOptions.map((op) => ({
|
const formattedSuggestions = suggestOptions.map((op) => ({
|
||||||
text: op.text,
|
text: op.text,
|
||||||
source: op._source as EntityDetailsType,
|
source: op._source as EntityUnion,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const optionsArray = getOptionsObject(key, formattedSuggestions);
|
const optionsArray = getOptionsObject(key, formattedSuggestions);
|
||||||
|
@ -13,6 +13,9 @@
|
|||||||
|
|
||||||
import { DefaultOptionType } from 'antd/lib/select';
|
import { DefaultOptionType } from 'antd/lib/select';
|
||||||
import { SORT_ORDER } from 'enums/common.enum';
|
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 { SearchIndex } from '../../enums/search.enum';
|
||||||
import { Dashboard } from '../../generated/entity/data/dashboard';
|
import { Dashboard } from '../../generated/entity/data/dashboard';
|
||||||
import { Mlmodel } from '../../generated/entity/data/mlmodel';
|
import { Mlmodel } from '../../generated/entity/data/mlmodel';
|
||||||
@ -33,7 +36,8 @@ export type ExploreSearchIndex =
|
|||||||
| SearchIndex.PIPELINE
|
| SearchIndex.PIPELINE
|
||||||
| SearchIndex.DASHBOARD
|
| SearchIndex.DASHBOARD
|
||||||
| SearchIndex.MLMODEL
|
| SearchIndex.MLMODEL
|
||||||
| SearchIndex.TOPIC;
|
| SearchIndex.TOPIC
|
||||||
|
| SearchIndex.CONTAINER;
|
||||||
|
|
||||||
export type ExploreSearchIndexKey =
|
export type ExploreSearchIndexKey =
|
||||||
| 'TABLE'
|
| 'TABLE'
|
||||||
@ -96,9 +100,18 @@ export interface SearchInputProps {
|
|||||||
handleClear: () => void;
|
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 {
|
export interface EntityDetailsObjectInterface {
|
||||||
details: EntityDetailsType;
|
details: EntityUnion;
|
||||||
entityType: string;
|
entityType: string;
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
import { Button, Divider, Popover, Space, Typography } from 'antd';
|
import { Button, Divider, Popover, Space, Typography } from 'antd';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
|
import { EntityUnion } from 'components/Explore/explore.interface';
|
||||||
import { uniqueId } from 'lodash';
|
import { uniqueId } from 'lodash';
|
||||||
import { EntityTags } from 'Models';
|
import { EntityTags } from 'Models';
|
||||||
import React, { FC, HTMLAttributes, useEffect, useMemo, useState } from 'react';
|
import React, { FC, HTMLAttributes, useEffect, useMemo, useState } from 'react';
|
||||||
@ -31,13 +32,7 @@ import { getEntityName } from 'utils/EntityUtils';
|
|||||||
import AppState from '../../../AppState';
|
import AppState from '../../../AppState';
|
||||||
import { FQN_SEPARATOR_CHAR } from '../../../constants/char.constants';
|
import { FQN_SEPARATOR_CHAR } from '../../../constants/char.constants';
|
||||||
import { EntityType } from '../../../enums/entity.enum';
|
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 { Table } from '../../../generated/entity/data/table';
|
||||||
import { Topic } from '../../../generated/entity/data/topic';
|
|
||||||
import { TagSource } from '../../../generated/type/tagLabel';
|
import { TagSource } from '../../../generated/type/tagLabel';
|
||||||
import SVGIcons from '../../../utils/SvgUtils';
|
import SVGIcons from '../../../utils/SvgUtils';
|
||||||
import {
|
import {
|
||||||
@ -49,15 +44,6 @@ import { showErrorToast } from '../../../utils/ToastUtils';
|
|||||||
import ProfilePicture from '../ProfilePicture/ProfilePicture';
|
import ProfilePicture from '../ProfilePicture/ProfilePicture';
|
||||||
import RichTextEditorPreviewer from '../rich-text-editor/RichTextEditorPreviewer';
|
import RichTextEditorPreviewer from '../rich-text-editor/RichTextEditorPreviewer';
|
||||||
|
|
||||||
export type EntityData =
|
|
||||||
| Table
|
|
||||||
| Topic
|
|
||||||
| Dashboard
|
|
||||||
| Pipeline
|
|
||||||
| Mlmodel
|
|
||||||
| Database
|
|
||||||
| DatabaseSchema;
|
|
||||||
|
|
||||||
interface Props extends HTMLAttributes<HTMLDivElement> {
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
||||||
entityType: string;
|
entityType: string;
|
||||||
entityFQN: string;
|
entityFQN: string;
|
||||||
@ -65,7 +51,7 @@ interface Props extends HTMLAttributes<HTMLDivElement> {
|
|||||||
|
|
||||||
const EntityPopOverCard: FC<Props> = ({ children, entityType, entityFQN }) => {
|
const EntityPopOverCard: FC<Props> = ({ children, entityType, entityFQN }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [entityData, setEntityData] = useState<EntityData>({} as EntityData);
|
const [entityData, setEntityData] = useState<EntityUnion>({} as EntityUnion);
|
||||||
|
|
||||||
const entityTier = useMemo(() => {
|
const entityTier = useMemo(() => {
|
||||||
const tierFQN = getTierTags((entityData as Table).tags || [])?.tagFQN;
|
const tierFQN = getTierTags((entityData as Table).tags || [])?.tagFQN;
|
||||||
@ -83,13 +69,13 @@ const EntityPopOverCard: FC<Props> = ({ children, entityType, entityFQN }) => {
|
|||||||
}, [(entityData as Table).tags]);
|
}, [(entityData as Table).tags]);
|
||||||
|
|
||||||
const getData = () => {
|
const getData = () => {
|
||||||
const setEntityDetails = (entityDetail: EntityData) => {
|
const setEntityDetails = (entityDetail: EntityUnion) => {
|
||||||
AppState.entityData[entityFQN] = entityDetail;
|
AppState.entityData[entityFQN] = entityDetail;
|
||||||
};
|
};
|
||||||
|
|
||||||
const fields = 'tags,owner';
|
const fields = 'tags,owner';
|
||||||
|
|
||||||
let promise: Promise<EntityData> | null = null;
|
let promise: Promise<EntityUnion> | null = null;
|
||||||
|
|
||||||
switch (entityType) {
|
switch (entityType) {
|
||||||
case EntityType.TABLE:
|
case EntityType.TABLE:
|
||||||
|
@ -11,12 +11,12 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { Col, Divider, Row, Typography } from 'antd';
|
import { Col, Divider, Row, Typography } from 'antd';
|
||||||
|
import { EntityUnion } from 'components/Explore/explore.interface';
|
||||||
import TagsViewer from 'components/Tag/TagsViewer/tags-viewer';
|
import TagsViewer from 'components/Tag/TagsViewer/tags-viewer';
|
||||||
import { TagLabel } from 'generated/type/tagLabel';
|
import { TagLabel } from 'generated/type/tagLabel';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ReactComponent as TagIcon } from '../../../assets/svg/tag-grey.svg';
|
import { ReactComponent as TagIcon } from '../../../assets/svg/tag-grey.svg';
|
||||||
import { EntityData } from '../PopOverCard/EntityPopOverCard';
|
|
||||||
import RichTextEditorPreviewer from '../rich-text-editor/RichTextEditorPreviewer';
|
import RichTextEditorPreviewer from '../rich-text-editor/RichTextEditorPreviewer';
|
||||||
|
|
||||||
const SummaryTagsDescription = ({
|
const SummaryTagsDescription = ({
|
||||||
@ -24,7 +24,7 @@ const SummaryTagsDescription = ({
|
|||||||
entityDetail,
|
entityDetail,
|
||||||
}: {
|
}: {
|
||||||
tags: TagLabel[];
|
tags: TagLabel[];
|
||||||
entityDetail: EntityData;
|
entityDetail: EntityUnion;
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
@ -25,14 +25,13 @@ import {
|
|||||||
} from '../../../utils/CommonUtils';
|
} from '../../../utils/CommonUtils';
|
||||||
import { stringToHTML } from '../../../utils/StringsUtils';
|
import { stringToHTML } from '../../../utils/StringsUtils';
|
||||||
import { getEntityLink } from '../../../utils/TableUtils';
|
import { getEntityLink } from '../../../utils/TableUtils';
|
||||||
import { SourceType } from '../../searched-data/SearchedData.interface';
|
|
||||||
import './TableDataCardTitle.less';
|
import './TableDataCardTitle.less';
|
||||||
|
|
||||||
interface TableDataCardTitleProps {
|
interface TableDataCardTitleProps {
|
||||||
dataTestId?: string;
|
dataTestId?: string;
|
||||||
id?: string;
|
id?: string;
|
||||||
searchIndex: SearchIndex | EntityType;
|
searchIndex: SearchIndex | EntityType;
|
||||||
source: SourceType;
|
source: { fullyQualifiedName?: string; displayName?: string };
|
||||||
isPanel?: boolean;
|
isPanel?: boolean;
|
||||||
handleLinkClick?: (e: React.MouseEvent) => void;
|
handleLinkClick?: (e: React.MouseEvent) => void;
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
import { ExclamationCircleOutlined } from '@ant-design/icons';
|
import { ExclamationCircleOutlined } from '@ant-design/icons';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { EntityUnion } from 'components/Explore/explore.interface';
|
||||||
import { 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';
|
||||||
@ -33,7 +34,6 @@ import {
|
|||||||
} from '../../../utils/CommonUtils';
|
} from '../../../utils/CommonUtils';
|
||||||
import { serviceTypeLogo } from '../../../utils/ServiceUtils';
|
import { serviceTypeLogo } from '../../../utils/ServiceUtils';
|
||||||
import { getUsagePercentile } from '../../../utils/TableUtils';
|
import { getUsagePercentile } from '../../../utils/TableUtils';
|
||||||
import { EntityDetailsType } from '../../Explore/explore.interface';
|
|
||||||
import { SearchedDataProps } from '../../searched-data/SearchedData.interface';
|
import { SearchedDataProps } from '../../searched-data/SearchedData.interface';
|
||||||
import '../table-data-card/TableDataCard.style.css';
|
import '../table-data-card/TableDataCard.style.css';
|
||||||
import TableDataCardBody from '../table-data-card/TableDataCardBody';
|
import TableDataCardBody from '../table-data-card/TableDataCardBody';
|
||||||
@ -50,7 +50,7 @@ export interface TableDataCardPropsV2 {
|
|||||||
}[];
|
}[];
|
||||||
searchIndex: SearchIndex | EntityType;
|
searchIndex: SearchIndex | EntityType;
|
||||||
handleSummaryPanelDisplay?: (
|
handleSummaryPanelDisplay?: (
|
||||||
details: EntityDetailsType,
|
details: EntityUnion,
|
||||||
entityType: string
|
entityType: string
|
||||||
) => void;
|
) => void;
|
||||||
}
|
}
|
||||||
@ -133,7 +133,7 @@ const TableDataCardV2: React.FC<TableDataCardPropsV2> = ({
|
|||||||
id={id}
|
id={id}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleSummaryPanelDisplay &&
|
handleSummaryPanelDisplay &&
|
||||||
handleSummaryPanelDisplay(source as EntityDetailsType, tab);
|
handleSummaryPanelDisplay(source as EntityUnion, tab);
|
||||||
}}>
|
}}>
|
||||||
<div>
|
<div>
|
||||||
{'databaseSchema' in source && 'database' in source && (
|
{'databaseSchema' in source && 'database' in source && (
|
||||||
|
@ -21,10 +21,7 @@ import {
|
|||||||
SearchHitBody,
|
SearchHitBody,
|
||||||
TableSearchSource,
|
TableSearchSource,
|
||||||
} from '../../interface/search.interface';
|
} from '../../interface/search.interface';
|
||||||
import {
|
import { EntityUnion, ExploreSearchIndex } from '../Explore/explore.interface';
|
||||||
EntityDetailsType,
|
|
||||||
ExploreSearchIndex,
|
|
||||||
} from '../Explore/explore.interface';
|
|
||||||
|
|
||||||
type Fields =
|
type Fields =
|
||||||
| 'name'
|
| 'name'
|
||||||
@ -75,7 +72,7 @@ export interface SearchedDataProps {
|
|||||||
showOnlyChildren?: boolean;
|
showOnlyChildren?: boolean;
|
||||||
isFilterSelected: boolean;
|
isFilterSelected: boolean;
|
||||||
handleSummaryPanelDisplay?: (
|
handleSummaryPanelDisplay?: (
|
||||||
details: EntityDetailsType,
|
details: EntityUnion,
|
||||||
entityType: string
|
entityType: string
|
||||||
) => void;
|
) => void;
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,6 @@ export const INGESTION_NAME = ':ingestionName';
|
|||||||
export const LOG_ENTITY_NAME = ':logEntityName';
|
export const LOG_ENTITY_NAME = ':logEntityName';
|
||||||
export const KPI_NAME = ':kpiName';
|
export const KPI_NAME = ':kpiName';
|
||||||
export const PLACEHOLDER_ACTION = ':action';
|
export const PLACEHOLDER_ACTION = ':action';
|
||||||
export const PLACEHOLDER_CONTAINER_NAME = ':containerName';
|
|
||||||
|
|
||||||
export const pagingObject = { after: '', before: '', total: 0 };
|
export const pagingObject = { after: '', before: '', total: 0 };
|
||||||
|
|
||||||
@ -257,8 +256,8 @@ export const ROUTES = {
|
|||||||
ADD_KPI: `/data-insights/kpi/add-kpi`,
|
ADD_KPI: `/data-insights/kpi/add-kpi`,
|
||||||
EDIT_KPI: `/data-insights/kpi/edit-kpi/${KPI_NAME}`,
|
EDIT_KPI: `/data-insights/kpi/edit-kpi/${KPI_NAME}`,
|
||||||
|
|
||||||
CONTAINER_DETAILS: `/container/${PLACEHOLDER_CONTAINER_NAME}`,
|
CONTAINER_DETAILS: `/container/${PLACEHOLDER_ROUTE_ENTITY_FQN}`,
|
||||||
CONTAINER_DETAILS_WITH_TAB: `/container/${PLACEHOLDER_CONTAINER_NAME}/${PLACEHOLDER_ROUTE_TAB}`,
|
CONTAINER_DETAILS_WITH_TAB: `/container/${PLACEHOLDER_ROUTE_ENTITY_FQN}/${PLACEHOLDER_ROUTE_TAB}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SOCKET_EVENTS = {
|
export const SOCKET_EVENTS = {
|
||||||
|
@ -27,19 +27,19 @@ export const MAX_RESULT_HITS = 10000;
|
|||||||
// as it is used only in unit tests it's not needed for translation
|
// as it is used only in unit tests it's not needed for translation
|
||||||
export const tableSortingFields: SortingField[] = [
|
export const tableSortingFields: SortingField[] = [
|
||||||
{
|
{
|
||||||
name: 'Last Updated',
|
name: t('label.last-updated'),
|
||||||
value: 'updatedAt',
|
value: 'updatedAt',
|
||||||
},
|
},
|
||||||
{ name: 'Weekly Usage', value: 'usageSummary.weeklyStats.count' },
|
{ name: t('label.weekly-usage'), value: 'usageSummary.weeklyStats.count' },
|
||||||
{ name: 'Relevance', value: '_score' },
|
{ name: t('label.relevance'), value: '_score' },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const entitySortingFields = [
|
export const entitySortingFields = [
|
||||||
{
|
{
|
||||||
name: 'Last Updated',
|
name: t('label.last-updated'),
|
||||||
value: 'updatedAt',
|
value: 'updatedAt',
|
||||||
},
|
},
|
||||||
{ name: 'Relevance', value: '_score' },
|
{ name: t('label.relevance'), value: '_score' },
|
||||||
];
|
];
|
||||||
|
|
||||||
export interface ExploreTabInfo {
|
export interface ExploreTabInfo {
|
||||||
@ -90,4 +90,10 @@ export const tabsInfo: { [K in ExploreSearchIndex]: ExploreTabInfo } = {
|
|||||||
sortField: INITIAL_SORT_FIELD,
|
sortField: INITIAL_SORT_FIELD,
|
||||||
path: 'mlmodels',
|
path: 'mlmodels',
|
||||||
},
|
},
|
||||||
|
[SearchIndex.CONTAINER]: {
|
||||||
|
label: t('label.container-plural'),
|
||||||
|
sortingFields: entitySortingFields,
|
||||||
|
sortField: INITIAL_SORT_FIELD,
|
||||||
|
path: 'containers',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
@ -22,4 +22,5 @@ export enum ExplorePageTabs {
|
|||||||
DASHBOARDS = 'dashboards',
|
DASHBOARDS = 'dashboards',
|
||||||
PIPELINES = 'pipelines',
|
PIPELINES = 'pipelines',
|
||||||
MLMODELS = 'mlmodels',
|
MLMODELS = 'mlmodels',
|
||||||
|
CONTAINERS = 'containers',
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ export enum SearchIndex {
|
|||||||
GLOSSARY = 'glossary_search_index',
|
GLOSSARY = 'glossary_search_index',
|
||||||
MLMODEL = 'mlmodel_search_index',
|
MLMODEL = 'mlmodel_search_index',
|
||||||
TAG = 'tag_search_index',
|
TAG = 'tag_search_index',
|
||||||
|
CONTAINER = 'container_search_index',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const GENERAL_SEARCH_INDEX = [
|
export const GENERAL_SEARCH_INDEX = [
|
||||||
@ -29,4 +30,5 @@ export const GENERAL_SEARCH_INDEX = [
|
|||||||
SearchIndex.TOPIC,
|
SearchIndex.TOPIC,
|
||||||
SearchIndex.PIPELINE,
|
SearchIndex.PIPELINE,
|
||||||
SearchIndex.MLMODEL,
|
SearchIndex.MLMODEL,
|
||||||
|
SearchIndex.CONTAINER,
|
||||||
];
|
];
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Container } from 'generated/entity/data/container';
|
||||||
import { SearchIndex } from '../enums/search.enum';
|
import { SearchIndex } from '../enums/search.enum';
|
||||||
import { Tag } from '../generated/entity/classification/tag';
|
import { Tag } from '../generated/entity/classification/tag';
|
||||||
import { Dashboard } from '../generated/entity/data/dashboard';
|
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 TeamSearchSource extends SearchSourceBase, Team {} // extends EntityInterface
|
||||||
|
|
||||||
|
export interface ContainerSearchSource extends SearchSourceBase, Container {} // extends EntityInterface
|
||||||
|
|
||||||
export interface TagClassSearchSource extends SearchSourceBase, Tag {
|
export interface TagClassSearchSource extends SearchSourceBase, Tag {
|
||||||
id: string; // Tag is generated with the `id` field as optional, which is should not
|
id: string; // Tag is generated with the `id` field as optional, which is should not
|
||||||
} // extends EntityInterface
|
} // extends EntityInterface
|
||||||
@ -78,7 +81,8 @@ export type ExploreSearchSource =
|
|||||||
| DashboardSearchSource
|
| DashboardSearchSource
|
||||||
| MlmodelSearchSource
|
| MlmodelSearchSource
|
||||||
| TopicSearchSource
|
| TopicSearchSource
|
||||||
| PipelineSearchSource;
|
| PipelineSearchSource
|
||||||
|
| ContainerSearchSource;
|
||||||
|
|
||||||
export type SearchIndexSearchSourceMapping = {
|
export type SearchIndexSearchSourceMapping = {
|
||||||
[SearchIndex.TABLE]: TableSearchSource;
|
[SearchIndex.TABLE]: TableSearchSource;
|
||||||
@ -90,6 +94,7 @@ export type SearchIndexSearchSourceMapping = {
|
|||||||
[SearchIndex.USER]: UserSearchSource;
|
[SearchIndex.USER]: UserSearchSource;
|
||||||
[SearchIndex.TOPIC]: TopicSearchSource;
|
[SearchIndex.TOPIC]: TopicSearchSource;
|
||||||
[SearchIndex.TAG]: TagClassSearchSource;
|
[SearchIndex.TAG]: TagClassSearchSource;
|
||||||
|
[SearchIndex.CONTAINER]: ContainerSearchSource;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SearchRequest<
|
export type SearchRequest<
|
||||||
|
@ -492,6 +492,7 @@
|
|||||||
"notification-plural": "Notifications",
|
"notification-plural": "Notifications",
|
||||||
"november": "November",
|
"november": "November",
|
||||||
"null": "Null",
|
"null": "Null",
|
||||||
|
"number-of-object": "Number of objects",
|
||||||
"number-of-rows": "Number of rows",
|
"number-of-rows": "Number of rows",
|
||||||
"object-store": "Object Store",
|
"object-store": "Object Store",
|
||||||
"object-store-plural": "Object Stores",
|
"object-store-plural": "Object Stores",
|
||||||
@ -599,6 +600,7 @@
|
|||||||
"region-name": "Region Name",
|
"region-name": "Region Name",
|
||||||
"registry": "Registry",
|
"registry": "Registry",
|
||||||
"related-term-plural": "Related Terms",
|
"related-term-plural": "Related Terms",
|
||||||
|
"relevance": "Relevance",
|
||||||
"remove": "Remove",
|
"remove": "Remove",
|
||||||
"remove-entity": "Remove {{entity}}",
|
"remove-entity": "Remove {{entity}}",
|
||||||
"removed": "Removed",
|
"removed": "Removed",
|
||||||
@ -843,6 +845,7 @@
|
|||||||
"webhook-display-text": "Webhook {{displayText}}",
|
"webhook-display-text": "Webhook {{displayText}}",
|
||||||
"wednesday": "Wednesday",
|
"wednesday": "Wednesday",
|
||||||
"week": "Week",
|
"week": "Week",
|
||||||
|
"weekly-usage": "Weekly Usage",
|
||||||
"whats-new": "What's New",
|
"whats-new": "What's New",
|
||||||
"yes": "Yes",
|
"yes": "Yes",
|
||||||
"your-entity": "Your {{entity}}"
|
"your-entity": "Your {{entity}}"
|
||||||
|
@ -492,6 +492,7 @@
|
|||||||
"notification-plural": "Notifications",
|
"notification-plural": "Notifications",
|
||||||
"november": "November",
|
"november": "November",
|
||||||
"null": "Null",
|
"null": "Null",
|
||||||
|
"number-of-object": "Number of objects",
|
||||||
"number-of-rows": "Number of rows",
|
"number-of-rows": "Number of rows",
|
||||||
"object-store": "Object Store",
|
"object-store": "Object Store",
|
||||||
"object-store-plural": "Object Stores",
|
"object-store-plural": "Object Stores",
|
||||||
@ -599,6 +600,7 @@
|
|||||||
"region-name": "Nom de Région",
|
"region-name": "Nom de Région",
|
||||||
"registry": "Registry",
|
"registry": "Registry",
|
||||||
"related-term-plural": "Related Terms",
|
"related-term-plural": "Related Terms",
|
||||||
|
"relevance": "Relevance",
|
||||||
"remove": "Enlever",
|
"remove": "Enlever",
|
||||||
"remove-entity": "Supprimer {{entity}}",
|
"remove-entity": "Supprimer {{entity}}",
|
||||||
"removed": "Removed",
|
"removed": "Removed",
|
||||||
@ -843,6 +845,7 @@
|
|||||||
"webhook-display-text": "Webhook {{displayText}}",
|
"webhook-display-text": "Webhook {{displayText}}",
|
||||||
"wednesday": "Wednesday",
|
"wednesday": "Wednesday",
|
||||||
"week": "Week",
|
"week": "Week",
|
||||||
|
"weekly-usage": "Weekly Usage",
|
||||||
"whats-new": "Nouveau",
|
"whats-new": "Nouveau",
|
||||||
"yes": "Yes",
|
"yes": "Yes",
|
||||||
"your-entity": "Your {{entity}}"
|
"your-entity": "Your {{entity}}"
|
||||||
|
@ -492,6 +492,7 @@
|
|||||||
"notification-plural": "Notifications",
|
"notification-plural": "Notifications",
|
||||||
"november": "November",
|
"november": "November",
|
||||||
"null": "Null",
|
"null": "Null",
|
||||||
|
"number-of-object": "Number of objects",
|
||||||
"number-of-rows": "Number of rows",
|
"number-of-rows": "Number of rows",
|
||||||
"object-store": "Object Store",
|
"object-store": "Object Store",
|
||||||
"object-store-plural": "Object Stores",
|
"object-store-plural": "Object Stores",
|
||||||
@ -599,6 +600,7 @@
|
|||||||
"region-name": "Region Name",
|
"region-name": "Region Name",
|
||||||
"registry": "注册",
|
"registry": "注册",
|
||||||
"related-term-plural": "Related Terms",
|
"related-term-plural": "Related Terms",
|
||||||
|
"relevance": "Relevance",
|
||||||
"remove": "删除",
|
"remove": "删除",
|
||||||
"remove-entity": "删除 {{entity}}",
|
"remove-entity": "删除 {{entity}}",
|
||||||
"removed": "Removed",
|
"removed": "Removed",
|
||||||
@ -843,6 +845,7 @@
|
|||||||
"webhook-display-text": "Webhook {{displayText}}",
|
"webhook-display-text": "Webhook {{displayText}}",
|
||||||
"wednesday": "Wednesday",
|
"wednesday": "Wednesday",
|
||||||
"week": "Week",
|
"week": "Week",
|
||||||
|
"weekly-usage": "Weekly Usage",
|
||||||
"whats-new": "What's new",
|
"whats-new": "What's new",
|
||||||
"yes": "是",
|
"yes": "是",
|
||||||
"your-entity": "Your {{entity}}"
|
"your-entity": "Your {{entity}}"
|
||||||
|
@ -88,8 +88,8 @@ const ContainerPage = () => {
|
|||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { getEntityPermissionByFqn } = usePermissionProvider();
|
const { getEntityPermissionByFqn } = usePermissionProvider();
|
||||||
const { containerName, tab = CONTAINER_DETAILS_TABS.SCHEME } =
|
const { entityFQN: containerName, tab = CONTAINER_DETAILS_TABS.SCHEME } =
|
||||||
useParams<{ containerName: string; tab: CONTAINER_DETAILS_TABS }>();
|
useParams<{ entityFQN: string; tab: CONTAINER_DETAILS_TABS }>();
|
||||||
|
|
||||||
// Local states
|
// Local states
|
||||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||||
|
@ -202,6 +202,7 @@ const ExplorePage: FunctionComponent = () => {
|
|||||||
SearchIndex.DASHBOARD,
|
SearchIndex.DASHBOARD,
|
||||||
SearchIndex.PIPELINE,
|
SearchIndex.PIPELINE,
|
||||||
SearchIndex.MLMODEL,
|
SearchIndex.MLMODEL,
|
||||||
|
SearchIndex.CONTAINER,
|
||||||
].map((index) =>
|
].map((index) =>
|
||||||
searchQuery({
|
searchQuery({
|
||||||
query: searchQueryParam,
|
query: searchQueryParam,
|
||||||
@ -221,6 +222,7 @@ const ExplorePage: FunctionComponent = () => {
|
|||||||
dashboardResponse,
|
dashboardResponse,
|
||||||
pipelineResponse,
|
pipelineResponse,
|
||||||
mlmodelResponse,
|
mlmodelResponse,
|
||||||
|
containerResponse,
|
||||||
]) => {
|
]) => {
|
||||||
setSearchHitCounts({
|
setSearchHitCounts({
|
||||||
[SearchIndex.TABLE]: tableResponse.hits.total.value,
|
[SearchIndex.TABLE]: tableResponse.hits.total.value,
|
||||||
@ -228,6 +230,7 @@ const ExplorePage: FunctionComponent = () => {
|
|||||||
[SearchIndex.DASHBOARD]: dashboardResponse.hits.total.value,
|
[SearchIndex.DASHBOARD]: dashboardResponse.hits.total.value,
|
||||||
[SearchIndex.PIPELINE]: pipelineResponse.hits.total.value,
|
[SearchIndex.PIPELINE]: pipelineResponse.hits.total.value,
|
||||||
[SearchIndex.MLMODEL]: mlmodelResponse.hits.total.value,
|
[SearchIndex.MLMODEL]: mlmodelResponse.hits.total.value,
|
||||||
|
[SearchIndex.CONTAINER]: containerResponse.hits.total.value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
@ -52,6 +52,7 @@ const exploreCount = {
|
|||||||
[SearchIndex.DASHBOARD]: 0,
|
[SearchIndex.DASHBOARD]: 0,
|
||||||
[SearchIndex.PIPELINE]: 0,
|
[SearchIndex.PIPELINE]: 0,
|
||||||
[SearchIndex.MLMODEL]: 0,
|
[SearchIndex.MLMODEL]: 0,
|
||||||
|
[SearchIndex.CONTAINER]: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const TourPage = () => {
|
const TourPage = () => {
|
||||||
|
@ -25,6 +25,7 @@ export type SearchEntityHits = SearchResponse<
|
|||||||
| SearchIndex.TABLE
|
| SearchIndex.TABLE
|
||||||
| SearchIndex.MLMODEL
|
| SearchIndex.MLMODEL
|
||||||
| SearchIndex.TOPIC
|
| SearchIndex.TOPIC
|
||||||
|
| SearchIndex.CONTAINER
|
||||||
>['hits']['hits'];
|
>['hits']['hits'];
|
||||||
|
|
||||||
// if more value is added, also update its interface file at -> interface/types.d.ts
|
// if more value is added, also update its interface file at -> interface/types.d.ts
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import {
|
import {
|
||||||
PLACEHOLDER_CONTAINER_NAME,
|
PLACEHOLDER_ROUTE_ENTITY_FQN,
|
||||||
PLACEHOLDER_ROUTE_TAB,
|
PLACEHOLDER_ROUTE_TAB,
|
||||||
ROUTES,
|
ROUTES,
|
||||||
} from 'constants/constants';
|
} from 'constants/constants';
|
||||||
@ -22,7 +22,7 @@ import { EntityTags, TagOption } from 'Models';
|
|||||||
|
|
||||||
export const getContainerDetailPath = (containerFQN: string, tab?: string) => {
|
export const getContainerDetailPath = (containerFQN: string, tab?: string) => {
|
||||||
let path = tab ? ROUTES.CONTAINER_DETAILS_WITH_TAB : ROUTES.CONTAINER_DETAILS;
|
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) {
|
if (tab) {
|
||||||
path = path.replace(PLACEHOLDER_ROUTE_TAB, tab);
|
path = path.replace(PLACEHOLDER_ROUTE_TAB, tab);
|
||||||
|
@ -12,14 +12,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Popover } from 'antd';
|
import { Popover } from 'antd';
|
||||||
import { EntityData } from 'components/common/PopOverCard/EntityPopOverCard';
|
|
||||||
import ProfilePicture from 'components/common/ProfilePicture/ProfilePicture';
|
import ProfilePicture from 'components/common/ProfilePicture/ProfilePicture';
|
||||||
import {
|
import {
|
||||||
LeafNodes,
|
LeafNodes,
|
||||||
LineagePos,
|
LineagePos,
|
||||||
} from 'components/EntityLineage/EntityLineage.interface';
|
} from 'components/EntityLineage/EntityLineage.interface';
|
||||||
|
import { EntityUnion } from 'components/Explore/explore.interface';
|
||||||
import { ResourceEntity } from 'components/PermissionProvider/PermissionProvider.interface';
|
import { ResourceEntity } from 'components/PermissionProvider/PermissionProvider.interface';
|
||||||
import { ExplorePageTabs } from 'enums/Explore.enum';
|
import { ExplorePageTabs } from 'enums/Explore.enum';
|
||||||
|
import { Container } from 'generated/entity/data/container';
|
||||||
import { Mlmodel } from 'generated/entity/data/mlmodel';
|
import { Mlmodel } from 'generated/entity/data/mlmodel';
|
||||||
import i18next from 'i18next';
|
import i18next from 'i18next';
|
||||||
import { isEmpty, isNil, isUndefined, lowerCase, startCase } from 'lodash';
|
import { isEmpty, isNil, isUndefined, lowerCase, startCase } from 'lodash';
|
||||||
@ -125,7 +126,7 @@ export const getOwnerNameWithProfilePic = (
|
|||||||
|
|
||||||
export const getEntityOverview = (
|
export const getEntityOverview = (
|
||||||
type: string,
|
type: string,
|
||||||
entityDetail: EntityData
|
entityDetail: EntityUnion
|
||||||
): Array<{
|
): Array<{
|
||||||
name: string;
|
name: string;
|
||||||
value: string | number | React.ReactNode;
|
value: string | number | React.ReactNode;
|
||||||
@ -428,6 +429,35 @@ export const getEntityOverview = (
|
|||||||
|
|
||||||
return overview;
|
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:
|
default:
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
@ -247,6 +247,7 @@ export const getEntityLink = (
|
|||||||
return getMlModelPath(fullyQualifiedName);
|
return getMlModelPath(fullyQualifiedName);
|
||||||
|
|
||||||
case EntityType.CONTAINER:
|
case EntityType.CONTAINER:
|
||||||
|
case SearchIndex.CONTAINER:
|
||||||
return getContainerDetailPath(fullyQualifiedName);
|
return getContainerDetailPath(fullyQualifiedName);
|
||||||
|
|
||||||
case SearchIndex.TABLE:
|
case SearchIndex.TABLE:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user