mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-11-02 11:39:12 +00:00
UI feedbacks (#13651)
* fix: ui feedbacks * fix: add localization * fix: placeholder feedbacks * fix: localization * fix: minor css fix * fix: add domains on teams page * fix: team subscription * fix: minor css --------- Co-authored-by: Chirag Madlani <12962843+chirag-madlani@users.noreply.github.com>
This commit is contained in:
parent
660bf01a5b
commit
65362c7474
@ -17,6 +17,7 @@ import { Dashboard } from '../../../generated/entity/data/dashboard';
|
||||
import { DashboardDataModel } from '../../../generated/entity/data/dashboardDataModel';
|
||||
import { Database } from '../../../generated/entity/data/database';
|
||||
import { DatabaseSchema } from '../../../generated/entity/data/databaseSchema';
|
||||
import { Glossary } from '../../../generated/entity/data/glossary';
|
||||
import { GlossaryTerm } from '../../../generated/entity/data/glossaryTerm';
|
||||
import { Mlmodel } from '../../../generated/entity/data/mlmodel';
|
||||
import { Pipeline } from '../../../generated/entity/data/pipeline';
|
||||
@ -31,6 +32,7 @@ import { MlmodelService } from '../../../generated/entity/services/mlmodelServic
|
||||
import { PipelineService } from '../../../generated/entity/services/pipelineService';
|
||||
import { SearchService } from '../../../generated/entity/services/searchService';
|
||||
import { StorageService } from '../../../generated/entity/services/storageService';
|
||||
import { Team } from '../../../generated/entity/teams/team';
|
||||
|
||||
export interface AssetSelectionModalProps {
|
||||
entityFqn: string;
|
||||
@ -39,6 +41,7 @@ export interface AssetSelectionModalProps {
|
||||
onCancel: () => void;
|
||||
onSave?: () => void;
|
||||
queryFilter?: Record<string, unknown>;
|
||||
emptyPlaceHolderText?: string;
|
||||
}
|
||||
|
||||
export type AssetsUnion =
|
||||
@ -73,6 +76,7 @@ export type MapPatchAPIResponse = {
|
||||
[EntityType.STORED_PROCEDURE]: StoredProcedure;
|
||||
[EntityType.DASHBOARD_DATA_MODEL]: DashboardDataModel;
|
||||
[EntityType.GLOSSARY_TERM]: GlossaryTerm;
|
||||
[EntityType.GLOSSARY]: Glossary;
|
||||
[EntityType.DATABASE_SCHEMA]: DatabaseSchema;
|
||||
[EntityType.DATABASE]: Database;
|
||||
[EntityType.DASHBOARD_SERVICE]: DashboardService;
|
||||
@ -82,4 +86,5 @@ export type MapPatchAPIResponse = {
|
||||
[EntityType.STORAGE_SERVICE]: StorageService;
|
||||
[EntityType.DATABASE_SERVICE]: DatabaseService;
|
||||
[EntityType.SEARCH_SERVICE]: SearchService;
|
||||
[EntityType.TEAM]: Team;
|
||||
};
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Button, List, Modal, Select, Space } from 'antd';
|
||||
import { Button, List, Modal, Select, Space, Typography } from 'antd';
|
||||
import { compare } from 'fast-json-patch';
|
||||
import { map, startCase } from 'lodash';
|
||||
import { EntityDetailUnion } from 'Models';
|
||||
@ -38,6 +38,7 @@ import {
|
||||
getAssetsSearchIndex,
|
||||
getEntityAPIfromSource,
|
||||
} from '../../../utils/Assets/AssetsUtils';
|
||||
import ErrorPlaceHolder from '../../common/error-with-placeholder/ErrorPlaceHolder';
|
||||
import Searchbar from '../../common/searchbar/Searchbar';
|
||||
import TableDataCardV2 from '../../common/table-data-card-v2/TableDataCardV2';
|
||||
import { AssetsOfEntity } from '../../Glossary/GlossaryTerms/tabs/AssetsTabs.interface';
|
||||
@ -53,6 +54,7 @@ export const AssetSelectionModal = ({
|
||||
open,
|
||||
type = AssetsOfEntity.GLOSSARY,
|
||||
queryFilter = {},
|
||||
emptyPlaceHolderText,
|
||||
}: AssetSelectionModalProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [search, setSearch] = useState('');
|
||||
@ -235,7 +237,7 @@ export const AssetSelectionModal = ({
|
||||
entityDetailsResponse.forEach((response) => {
|
||||
if (response.status === 'fulfilled') {
|
||||
const entity = response.value;
|
||||
entity && map.set(entity.fullyQualifiedName, entity.tags);
|
||||
entity && map.set(entity.fullyQualifiedName, (entity as Table).tags);
|
||||
}
|
||||
});
|
||||
const patchAPIPromises = [...(selectedItems?.values() ?? [])]
|
||||
@ -345,26 +347,40 @@ export const AssetSelectionModal = ({
|
||||
searchValue={search}
|
||||
onSearch={setSearch}
|
||||
/>
|
||||
<List loading={{ spinning: isLoading, indicator: <Loader /> }}>
|
||||
<VirtualList
|
||||
data={items}
|
||||
height={500}
|
||||
itemKey="id"
|
||||
onScroll={onScroll}>
|
||||
{({ _source: item }) => (
|
||||
<TableDataCardV2
|
||||
openEntityInNewPage
|
||||
showCheckboxes
|
||||
checked={selectedItems?.has(item.id ?? '')}
|
||||
className="m-b-sm asset-selection-model-card cursor-pointer"
|
||||
handleSummaryPanelDisplay={handleCardClick}
|
||||
id={`tabledatacard-${item.id}`}
|
||||
key={item.id}
|
||||
source={{ ...item, tags: [] }}
|
||||
/>
|
||||
|
||||
{isLoading && <Loader />}
|
||||
|
||||
{!isLoading && items.length > 0 && (
|
||||
<List loading={{ spinning: isLoading, indicator: <Loader /> }}>
|
||||
<VirtualList
|
||||
data={items}
|
||||
height={500}
|
||||
itemKey="id"
|
||||
onScroll={onScroll}>
|
||||
{({ _source: item }) => (
|
||||
<TableDataCardV2
|
||||
openEntityInNewPage
|
||||
showCheckboxes
|
||||
checked={selectedItems?.has(item.id ?? '')}
|
||||
className="m-b-sm asset-selection-model-card cursor-pointer"
|
||||
handleSummaryPanelDisplay={handleCardClick}
|
||||
id={`tabledatacard-${item.id}`}
|
||||
key={item.id}
|
||||
source={{ ...item, tags: [] }}
|
||||
/>
|
||||
)}
|
||||
</VirtualList>
|
||||
</List>
|
||||
)}
|
||||
{!isLoading && items.length === 0 && (
|
||||
<ErrorPlaceHolder>
|
||||
{emptyPlaceHolderText && (
|
||||
<Typography.Paragraph>
|
||||
{emptyPlaceHolderText}
|
||||
</Typography.Paragraph>
|
||||
)}
|
||||
</VirtualList>
|
||||
</List>
|
||||
</ErrorPlaceHolder>
|
||||
)}
|
||||
</Space>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
@ -562,6 +562,9 @@ const DataProductsDetailsPage = ({
|
||||
/>
|
||||
|
||||
<AssetSelectionModal
|
||||
emptyPlaceHolderText={t('message.domain-does-not-have-assets', {
|
||||
name: getEntityName(dataProduct.domain),
|
||||
})}
|
||||
entityFqn={dataProductFqn}
|
||||
open={assetModalVisible}
|
||||
queryFilter={getQueryFilterToIncludeDomain(
|
||||
|
||||
@ -179,10 +179,11 @@ const DomainPage = () => {
|
||||
type={
|
||||
createDomainPermission
|
||||
? ERROR_PLACEHOLDER_TYPE.CREATE
|
||||
: ERROR_PLACEHOLDER_TYPE.NO_DATA
|
||||
: ERROR_PLACEHOLDER_TYPE.CUSTOM
|
||||
}
|
||||
onClick={handleAddDomainClick}
|
||||
/>
|
||||
onClick={handleAddDomainClick}>
|
||||
{t('message.domains-not-configured')}
|
||||
</ErrorPlaceHolder>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@ import {
|
||||
NO_DATA_PLACEHOLDER,
|
||||
} from '../../../constants/constants';
|
||||
import { EntityField } from '../../../constants/Feeds.constants';
|
||||
import { EntityType } from '../../../enums/entity.enum';
|
||||
import { Glossary } from '../../../generated/entity/data/glossary';
|
||||
import {
|
||||
GlossaryTerm,
|
||||
@ -45,6 +46,7 @@ import {
|
||||
getDiffValue,
|
||||
getEntityVersionTags,
|
||||
} from '../../../utils/EntityVersionUtils';
|
||||
import { DomainLabel } from '../../common/DomainLabel/DomainLabel.component';
|
||||
import GlossaryReviewers from './GlossaryReviewers';
|
||||
|
||||
type Props = {
|
||||
@ -199,6 +201,16 @@ const GlossaryDetailsRightPanel = ({
|
||||
|
||||
return (
|
||||
<Row gutter={[0, 40]}>
|
||||
<Col span={24}>
|
||||
<DomainLabel
|
||||
showDomainHeading
|
||||
domain={selectedData.domain}
|
||||
entityFqn={selectedData.fullyQualifiedName ?? ''}
|
||||
entityId={selectedData.id ?? ''}
|
||||
entityType={EntityType.GLOSSARY}
|
||||
hasPermission={permissions.EditAll}
|
||||
/>
|
||||
</Col>
|
||||
<Col data-testid="glossary-owner-name" span="24">
|
||||
<div className="d-flex items-center m-b-xs">
|
||||
<Typography.Text className="right-panel-label">
|
||||
|
||||
@ -102,12 +102,12 @@ import { usePermissionProvider } from '../../PermissionProvider/PermissionProvid
|
||||
import { ResourceEntity } from '../../PermissionProvider/PermissionProvider.interface';
|
||||
import TabsLabel from '../../TabsLabel/TabsLabel.component';
|
||||
import ListEntities from './RolesAndPoliciesList';
|
||||
import { SubscriptionWebhook, TeamsPageTab } from './team.interface';
|
||||
import { TeamsPageTab } from './team.interface';
|
||||
import { getTabs } from './TeamDetailsV1.utils';
|
||||
import TeamHierarchy from './TeamHierarchy';
|
||||
import './teams.less';
|
||||
import TeamsHeadingLabel from './TeamsHeaderSection/TeamsHeadingLabel.component';
|
||||
import TeamsInfo from './TeamsHeaderSection/TeamsInfo.component';
|
||||
import TeamsSubscription from './TeamsHeaderSection/TeamsSubscription.component';
|
||||
import { UserTab } from './UserTab/UserTab.component';
|
||||
|
||||
const TeamDetailsV1 = ({
|
||||
@ -200,12 +200,6 @@ const TeamDetailsV1 = ({
|
||||
|
||||
const addTeam = t('label.add-entity', { entity: t('label.team') });
|
||||
|
||||
const hasEditSubscriptionPermission = useMemo(
|
||||
() =>
|
||||
entityPermissions.EditAll || currentTeam.owner?.id === currentUser?.id,
|
||||
[entityPermissions, currentTeam, currentUser]
|
||||
);
|
||||
|
||||
const teamCount = useMemo(
|
||||
() =>
|
||||
isOrganization && currentTeam && currentTeam.childrenCount
|
||||
@ -339,23 +333,6 @@ const TeamDetailsV1 = ({
|
||||
}
|
||||
};
|
||||
|
||||
const updateTeamSubscription = async (data?: SubscriptionWebhook) => {
|
||||
if (currentTeam) {
|
||||
const updatedData: Team = {
|
||||
...currentTeam,
|
||||
profile: {
|
||||
subscription: isEmpty(data)
|
||||
? undefined
|
||||
: {
|
||||
[data?.webhook ?? '']: { endpoint: data?.endpoint },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
await updateTeamHandler(updatedData);
|
||||
}
|
||||
};
|
||||
|
||||
const handleTeamSearch = (value: string) => {
|
||||
setSearchTerm(value);
|
||||
if (value) {
|
||||
@ -886,60 +863,71 @@ const TeamDetailsV1 = ({
|
||||
|
||||
const teamsCollapseHeader = useMemo(
|
||||
() => (
|
||||
<Space wrap className="w-full justify-between">
|
||||
<Space className="w-full" size="middle">
|
||||
<Avatar className="teams-profile" size={40}>
|
||||
<IconTeams className="text-primary" width={20} />
|
||||
</Avatar>
|
||||
<>
|
||||
<Space wrap className="w-full justify-between">
|
||||
<Space className="w-full" size="middle">
|
||||
<Avatar className="teams-profile" size={40}>
|
||||
<IconTeams className="text-primary" width={20} />
|
||||
</Avatar>
|
||||
|
||||
<Space direction="vertical" size={3}>
|
||||
{!isOrganization && (
|
||||
<TitleBreadcrumb titleLinks={slashedTeamName} />
|
||||
<Space direction="vertical" size={3}>
|
||||
{!isOrganization && (
|
||||
<TitleBreadcrumb titleLinks={slashedTeamName} />
|
||||
)}
|
||||
|
||||
<TeamsHeadingLabel
|
||||
currentTeam={currentTeam}
|
||||
entityPermissions={entityPermissions}
|
||||
updateTeamHandler={updateTeamHandler}
|
||||
/>
|
||||
</Space>
|
||||
</Space>
|
||||
|
||||
<Space align="center">
|
||||
{teamActionButton}
|
||||
{!isOrganization ? (
|
||||
entityPermissions.EditAll && (
|
||||
<ManageButton
|
||||
isRecursiveDelete
|
||||
afterDeleteAction={afterDeleteAction}
|
||||
allowSoftDelete={!currentTeam.deleted}
|
||||
canDelete={entityPermissions.EditAll}
|
||||
entityId={currentTeam.id}
|
||||
entityName={
|
||||
currentTeam.fullyQualifiedName ?? currentTeam.name
|
||||
}
|
||||
entityType="team"
|
||||
extraDropdownContent={extraDropdownContent}
|
||||
hardDeleteMessagePostFix={getDeleteMessagePostFix(
|
||||
currentTeam.fullyQualifiedName ?? currentTeam.name,
|
||||
t('label.permanently-lowercase')
|
||||
)}
|
||||
softDeleteMessagePostFix={getDeleteMessagePostFix(
|
||||
currentTeam.fullyQualifiedName ?? currentTeam.name,
|
||||
t('label.soft-lowercase')
|
||||
)}
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
<ManageButton
|
||||
canDelete={false}
|
||||
entityName={currentTeam.fullyQualifiedName ?? currentTeam.name}
|
||||
extraDropdownContent={[...IMPORT_EXPORT_MENU_ITEM]}
|
||||
/>
|
||||
)}
|
||||
|
||||
<TeamsInfo
|
||||
childTeamsCount={childTeams.length}
|
||||
currentTeam={currentTeam}
|
||||
entityPermissions={entityPermissions}
|
||||
isGroupType={isGroupType}
|
||||
parentTeams={parentTeams}
|
||||
updateTeamHandler={updateTeamHandler}
|
||||
/>
|
||||
</Space>
|
||||
</Space>
|
||||
|
||||
<Space align="center">
|
||||
{teamActionButton}
|
||||
{!isOrganization ? (
|
||||
entityPermissions.EditAll && (
|
||||
<ManageButton
|
||||
isRecursiveDelete
|
||||
afterDeleteAction={afterDeleteAction}
|
||||
allowSoftDelete={!currentTeam.deleted}
|
||||
canDelete={entityPermissions.EditAll}
|
||||
entityId={currentTeam.id}
|
||||
entityName={currentTeam.fullyQualifiedName ?? currentTeam.name}
|
||||
entityType="team"
|
||||
extraDropdownContent={extraDropdownContent}
|
||||
hardDeleteMessagePostFix={getDeleteMessagePostFix(
|
||||
currentTeam.fullyQualifiedName ?? currentTeam.name,
|
||||
t('label.permanently-lowercase')
|
||||
)}
|
||||
softDeleteMessagePostFix={getDeleteMessagePostFix(
|
||||
currentTeam.fullyQualifiedName ?? currentTeam.name,
|
||||
t('label.soft-lowercase')
|
||||
)}
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
<ManageButton
|
||||
canDelete={false}
|
||||
entityName={currentTeam.fullyQualifiedName ?? currentTeam.name}
|
||||
extraDropdownContent={[...IMPORT_EXPORT_MENU_ITEM]}
|
||||
/>
|
||||
)}
|
||||
</Space>
|
||||
</Space>
|
||||
<div className="p-t-md p-l-xss">
|
||||
<TeamsInfo
|
||||
childTeamsCount={childTeams.length}
|
||||
currentTeam={currentTeam}
|
||||
entityPermissions={entityPermissions}
|
||||
isGroupType={isGroupType}
|
||||
parentTeams={parentTeams}
|
||||
updateTeamHandler={updateTeamHandler}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
),
|
||||
[
|
||||
isGroupType,
|
||||
@ -1053,7 +1041,6 @@ const TeamDetailsV1 = ({
|
||||
accordion
|
||||
bordered={false}
|
||||
className="site-collapse-custom-collapse"
|
||||
defaultActiveKey={['1']}
|
||||
expandIconPosition="end">
|
||||
<Collapse.Panel
|
||||
className="site-collapse-custom-panel"
|
||||
@ -1061,18 +1048,6 @@ const TeamDetailsV1 = ({
|
||||
header={teamsCollapseHeader}
|
||||
key="1">
|
||||
<Row>
|
||||
{(currentTeam.owner?.id === currentUser?.id ||
|
||||
entityPermissions.EditAll ||
|
||||
isAlreadyJoinedTeam) && (
|
||||
<Col className="p-md border-top" span={24}>
|
||||
<TeamsSubscription
|
||||
hasEditPermission={hasEditSubscriptionPermission}
|
||||
subscription={currentTeam.profile?.subscription}
|
||||
updateTeamSubscription={updateTeamSubscription}
|
||||
/>
|
||||
</Col>
|
||||
)}
|
||||
|
||||
<Col className="border-top" span={24}>
|
||||
<Card
|
||||
className="ant-card-feed card-body-border-none card-padding-y-0 p-y-sm"
|
||||
|
||||
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* 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 Icon, { CheckOutlined, CloseOutlined } from '@ant-design/icons';
|
||||
import { Button, Input, Space, Tooltip, Typography } from 'antd';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ReactComponent as EditIcon } from '../../../../assets/svg/edit-new.svg';
|
||||
import { Team } from '../../../../generated/entity/teams/team';
|
||||
import { useAuth } from '../../../../hooks/authHooks';
|
||||
import { hasEditAccess } from '../../../../utils/CommonUtils';
|
||||
import { useAuthContext } from '../../../authentication/auth-provider/AuthProvider';
|
||||
import { TeamsHeadingLabelProps } from '../team.interface';
|
||||
|
||||
const TeamsHeadingLabel = ({
|
||||
currentTeam,
|
||||
updateTeamHandler,
|
||||
entityPermissions,
|
||||
}: TeamsHeadingLabelProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [isHeadingEditing, setIsHeadingEditing] = useState(false);
|
||||
const [heading, setHeading] = useState(
|
||||
currentTeam ? currentTeam.displayName : ''
|
||||
);
|
||||
const { isAdminUser } = useAuth();
|
||||
const { isAuthDisabled } = useAuthContext();
|
||||
|
||||
const { owner } = useMemo(() => currentTeam, [currentTeam]);
|
||||
|
||||
const isCurrentTeamOwner = useMemo(
|
||||
() => hasEditAccess(owner?.type ?? '', owner?.id ?? ''),
|
||||
[owner]
|
||||
);
|
||||
|
||||
const { hasEditDisplayNamePermission, hasAccess } = useMemo(
|
||||
() => ({
|
||||
hasEditPermission: entityPermissions.EditAll,
|
||||
hasEditDisplayNamePermission:
|
||||
entityPermissions.EditDisplayName || entityPermissions.EditAll,
|
||||
hasAccess: isAuthDisabled || isAdminUser,
|
||||
}),
|
||||
|
||||
[entityPermissions]
|
||||
);
|
||||
|
||||
const onHeadingSave = async (): Promise<void> => {
|
||||
if (heading && currentTeam) {
|
||||
const updatedData: Team = {
|
||||
...currentTeam,
|
||||
displayName: heading,
|
||||
};
|
||||
|
||||
await updateTeamHandler(updatedData);
|
||||
}
|
||||
setIsHeadingEditing(false);
|
||||
};
|
||||
|
||||
const teamHeadingRender = useMemo(
|
||||
() =>
|
||||
isHeadingEditing ? (
|
||||
<Space>
|
||||
<Input
|
||||
className="w-48"
|
||||
data-testid="team-name-input"
|
||||
placeholder={t('message.enter-comma-separated-field', {
|
||||
field: t('label.term-lowercase'),
|
||||
})}
|
||||
type="text"
|
||||
value={heading}
|
||||
onChange={(e) => setHeading(e.target.value)}
|
||||
/>
|
||||
<Space data-testid="buttons" size={4}>
|
||||
<Button
|
||||
className="rounded-4 text-sm p-xss"
|
||||
data-testid="cancelAssociatedTag"
|
||||
type="primary"
|
||||
onMouseDown={() => setIsHeadingEditing(false)}>
|
||||
<CloseOutlined />
|
||||
</Button>
|
||||
<Button
|
||||
className="rounded-4 text-sm p-xss"
|
||||
data-testid="saveAssociatedTag"
|
||||
type="primary"
|
||||
onMouseDown={onHeadingSave}>
|
||||
<CheckOutlined />
|
||||
</Button>
|
||||
</Space>
|
||||
</Space>
|
||||
) : (
|
||||
<Space align="baseline">
|
||||
<Typography.Title
|
||||
className="m-b-0 w-max-200"
|
||||
data-testid="team-heading"
|
||||
ellipsis={{ tooltip: true }}
|
||||
level={5}>
|
||||
{heading}
|
||||
</Typography.Title>
|
||||
{(hasAccess || isCurrentTeamOwner) && (
|
||||
<Tooltip
|
||||
placement="right"
|
||||
title={
|
||||
hasEditDisplayNamePermission
|
||||
? t('label.edit-entity', {
|
||||
entity: t('label.display-name'),
|
||||
})
|
||||
: t('message.no-permission-for-action')
|
||||
}>
|
||||
<Icon
|
||||
className="align-middle"
|
||||
component={EditIcon}
|
||||
data-testid="edit-team-name"
|
||||
disabled={!hasEditDisplayNamePermission}
|
||||
style={{ fontSize: '16px' }}
|
||||
onClick={() => setIsHeadingEditing(true)}
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Space>
|
||||
),
|
||||
[heading, isHeadingEditing, hasEditDisplayNamePermission]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (currentTeam) {
|
||||
setHeading(currentTeam.displayName ?? currentTeam.name);
|
||||
}
|
||||
}, [currentTeam]);
|
||||
|
||||
return <Space size={4}>{teamHeadingRender}</Space>;
|
||||
};
|
||||
|
||||
export default TeamsHeadingLabel;
|
||||
@ -15,19 +15,21 @@ import Icon from '@ant-design/icons/lib/components/Icon';
|
||||
import { Button, Divider, Form, Input, Space, Tooltip, Typography } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import { isEmpty, last } from 'lodash';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ReactComponent as EditIcon } from '../../../../assets/svg/edit-new.svg';
|
||||
import { NO_DATA_PLACEHOLDER } from '../../../../constants/constants';
|
||||
import { EMAIL_REG_EX } from '../../../../constants/regex.constants';
|
||||
import { EntityType } from '../../../../enums/entity.enum';
|
||||
import { Team, TeamType } from '../../../../generated/entity/teams/team';
|
||||
import { EntityReference } from '../../../../generated/entity/type';
|
||||
import { useAuth } from '../../../../hooks/authHooks';
|
||||
import { hasEditAccess } from '../../../../utils/CommonUtils';
|
||||
import { useAuthContext } from '../../../authentication/auth-provider/AuthProvider';
|
||||
import { DomainLabel } from '../../../common/DomainLabel/DomainLabel.component';
|
||||
import { OwnerLabel } from '../../../common/OwnerLabel/OwnerLabel.component';
|
||||
import TeamTypeSelect from '../../../common/TeamTypeSelect/TeamTypeSelect.component';
|
||||
import { TeamsInfoProps } from '../team.interface';
|
||||
import { SubscriptionWebhook, TeamsInfoProps } from '../team.interface';
|
||||
import TeamsSubscription from './TeamsSubscription.component';
|
||||
|
||||
const TeamsInfo = ({
|
||||
parentTeams,
|
||||
@ -42,47 +44,30 @@ const TeamsInfo = ({
|
||||
const { isAdminUser } = useAuth();
|
||||
const { isAuthDisabled } = useAuthContext();
|
||||
|
||||
const [isHeadingEditing, setIsHeadingEditing] = useState(false);
|
||||
const [isEmailEdit, setIsEmailEdit] = useState<boolean>(false);
|
||||
const [showTypeSelector, setShowTypeSelector] = useState(false);
|
||||
const [heading, setHeading] = useState(
|
||||
currentTeam ? currentTeam.displayName : ''
|
||||
|
||||
const { currentUser } = useAuthContext();
|
||||
|
||||
const { email, owner, teamType, id, fullyQualifiedName } = useMemo(
|
||||
() => currentTeam,
|
||||
[currentTeam]
|
||||
);
|
||||
|
||||
const { email, owner, teamType } = useMemo(() => currentTeam, [currentTeam]);
|
||||
const { hasEditPermission, hasAccess } = useMemo(
|
||||
() => ({
|
||||
hasEditPermission: entityPermissions.EditAll,
|
||||
hasAccess: isAuthDisabled || isAdminUser,
|
||||
}),
|
||||
|
||||
const { hasEditPermission, hasEditDisplayNamePermission, hasAccess } =
|
||||
useMemo(
|
||||
() => ({
|
||||
hasEditPermission: entityPermissions.EditAll,
|
||||
hasEditDisplayNamePermission:
|
||||
entityPermissions.EditDisplayName || entityPermissions.EditAll,
|
||||
hasAccess: isAuthDisabled || isAdminUser,
|
||||
}),
|
||||
|
||||
[entityPermissions]
|
||||
);
|
||||
|
||||
/**
|
||||
* Check if current team is the owner or not
|
||||
* @returns - True true or false based on hasEditAccess response
|
||||
*/
|
||||
const isCurrentTeamOwner = useMemo(
|
||||
() => hasEditAccess(owner?.type ?? '', owner?.id ?? ''),
|
||||
[owner]
|
||||
[entityPermissions]
|
||||
);
|
||||
|
||||
const onHeadingSave = async (): Promise<void> => {
|
||||
if (heading && currentTeam) {
|
||||
const updatedData: Team = {
|
||||
...currentTeam,
|
||||
displayName: heading,
|
||||
};
|
||||
|
||||
await updateTeamHandler(updatedData);
|
||||
}
|
||||
setIsHeadingEditing(false);
|
||||
};
|
||||
const hasEditSubscriptionPermission = useMemo(
|
||||
() =>
|
||||
entityPermissions.EditAll || currentTeam.owner?.id === currentUser?.id,
|
||||
[entityPermissions, currentTeam, currentUser]
|
||||
);
|
||||
|
||||
const onEmailSave = async (data: { email: string }) => {
|
||||
if (currentTeam) {
|
||||
@ -123,70 +108,22 @@ const TeamsInfo = ({
|
||||
}
|
||||
};
|
||||
|
||||
const teamHeadingRender = useMemo(
|
||||
() =>
|
||||
isHeadingEditing ? (
|
||||
<Space>
|
||||
<Input
|
||||
className="w-48"
|
||||
data-testid="team-name-input"
|
||||
placeholder={t('message.enter-comma-separated-field', {
|
||||
field: t('label.term-lowercase'),
|
||||
})}
|
||||
type="text"
|
||||
value={heading}
|
||||
onChange={(e) => setHeading(e.target.value)}
|
||||
/>
|
||||
<Space data-testid="buttons" size={4}>
|
||||
<Button
|
||||
className="rounded-4 text-sm p-xss"
|
||||
data-testid="cancelAssociatedTag"
|
||||
type="primary"
|
||||
onMouseDown={() => setIsHeadingEditing(false)}>
|
||||
<CloseOutlined />
|
||||
</Button>
|
||||
<Button
|
||||
className="rounded-4 text-sm p-xss"
|
||||
data-testid="saveAssociatedTag"
|
||||
type="primary"
|
||||
onMouseDown={onHeadingSave}>
|
||||
<CheckOutlined />
|
||||
</Button>
|
||||
</Space>
|
||||
</Space>
|
||||
) : (
|
||||
<Space align="baseline">
|
||||
<Typography.Title
|
||||
className="m-b-0 w-max-200"
|
||||
data-testid="team-heading"
|
||||
ellipsis={{ tooltip: true }}
|
||||
level={5}>
|
||||
{heading}
|
||||
</Typography.Title>
|
||||
{(hasAccess || isCurrentTeamOwner) && (
|
||||
<Tooltip
|
||||
placement="right"
|
||||
title={
|
||||
hasEditDisplayNamePermission
|
||||
? t('label.edit-entity', {
|
||||
entity: t('label.display-name'),
|
||||
})
|
||||
: t('message.no-permission-for-action')
|
||||
}>
|
||||
<Icon
|
||||
className="align-middle"
|
||||
component={EditIcon}
|
||||
data-testid="edit-team-name"
|
||||
disabled={!hasEditDisplayNamePermission}
|
||||
style={{ fontSize: '16px' }}
|
||||
onClick={() => setIsHeadingEditing(true)}
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Space>
|
||||
),
|
||||
[heading, isHeadingEditing, hasEditDisplayNamePermission]
|
||||
);
|
||||
const updateTeamSubscription = async (data?: SubscriptionWebhook) => {
|
||||
if (currentTeam) {
|
||||
const updatedData: Team = {
|
||||
...currentTeam,
|
||||
profile: {
|
||||
subscription: isEmpty(data)
|
||||
? undefined
|
||||
: {
|
||||
[data?.webhook ?? '']: { endpoint: data?.endpoint },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
await updateTeamHandler(updatedData);
|
||||
}
|
||||
};
|
||||
|
||||
const emailRender = useMemo(
|
||||
() => (
|
||||
@ -329,15 +266,15 @@ const TeamsInfo = ({
|
||||
setShowTypeSelector,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (currentTeam) {
|
||||
setHeading(currentTeam.displayName ?? currentTeam.name);
|
||||
}
|
||||
}, [currentTeam]);
|
||||
|
||||
return (
|
||||
<Space size={4}>
|
||||
{teamHeadingRender}
|
||||
<Space size={0}>
|
||||
<DomainLabel
|
||||
domain={currentTeam.domain}
|
||||
entityFqn={fullyQualifiedName ?? ''}
|
||||
entityId={id ?? ''}
|
||||
entityType={EntityType.TEAM}
|
||||
hasPermission={hasEditPermission}
|
||||
/>
|
||||
<Divider type="vertical" />
|
||||
<OwnerLabel
|
||||
className="text-sm"
|
||||
@ -347,6 +284,13 @@ const TeamsInfo = ({
|
||||
/>
|
||||
<Divider type="vertical" />
|
||||
{emailRender}
|
||||
|
||||
<Divider type="vertical" />
|
||||
<TeamsSubscription
|
||||
hasEditPermission={hasEditSubscriptionPermission}
|
||||
subscription={currentTeam.profile?.subscription}
|
||||
updateTeamSubscription={updateTeamSubscription}
|
||||
/>
|
||||
{teamTypeElement}
|
||||
</Space>
|
||||
);
|
||||
|
||||
@ -21,17 +21,12 @@ import {
|
||||
ICON_DIMENSION,
|
||||
NO_DATA_PLACEHOLDER,
|
||||
} from '../../../../constants/constants';
|
||||
import {
|
||||
TAG_CONSTANT,
|
||||
TAG_START_WITH,
|
||||
} from '../../../../constants/Tag.constants';
|
||||
import {
|
||||
SUBSCRIPTION_WEBHOOK,
|
||||
SUBSCRIPTION_WEBHOOK_OPTIONS,
|
||||
} from '../../../../constants/Teams.constants';
|
||||
import { Webhook } from '../../../../generated/type/profile';
|
||||
import { getWebhookIcon } from '../../../../utils/TeamUtils';
|
||||
import TagsV1 from '../../../Tag/TagsV1/TagsV1.component';
|
||||
import { SubscriptionWebhook, TeamsSubscriptionProps } from '../team.interface';
|
||||
|
||||
const TeamsSubscription = ({
|
||||
@ -47,7 +42,14 @@ const TeamsSubscription = ({
|
||||
const getWebhookIconByKey = useCallback((item: SUBSCRIPTION_WEBHOOK) => {
|
||||
const Icon = getWebhookIcon(item);
|
||||
|
||||
return <Icon data-testid={`${item}-icon`} height={20} width={20} />;
|
||||
return (
|
||||
<Icon
|
||||
className="align-middle"
|
||||
data-testid={`${item}-icon`}
|
||||
height={20}
|
||||
width={20}
|
||||
/>
|
||||
);
|
||||
}, []);
|
||||
|
||||
// Watchers
|
||||
@ -55,12 +57,9 @@ const TeamsSubscription = ({
|
||||
|
||||
const cellItem = useCallback(
|
||||
(key: string, value: Webhook) => (
|
||||
<Space align="start">
|
||||
<Typography.Link href={value.endpoint} target="_blank">
|
||||
{getWebhookIconByKey(key as SUBSCRIPTION_WEBHOOK)}
|
||||
<Typography.Text className="text-xs text-grey-muted">
|
||||
{value.endpoint}
|
||||
</Typography.Text>
|
||||
</Space>
|
||||
</Typography.Link>
|
||||
),
|
||||
[]
|
||||
);
|
||||
@ -71,8 +70,18 @@ const TeamsSubscription = ({
|
||||
if (isEmpty(subscription)) {
|
||||
if (hasEditPermission) {
|
||||
return (
|
||||
<div onClick={() => setEditSubscription(true)}>
|
||||
<TagsV1 startWith={TAG_START_WITH.PLUS} tag={TAG_CONSTANT} />
|
||||
<div className="flex-center gap-2">
|
||||
<Typography.Text
|
||||
className="font-medium"
|
||||
data-testid="subscription-no-data">
|
||||
{t('label.none')}
|
||||
</Typography.Text>
|
||||
<EditIcon
|
||||
className="cursor-pointer"
|
||||
color={DE_ACTIVE_COLOR}
|
||||
width={14}
|
||||
onClick={() => setEditSubscription(true)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -119,7 +128,7 @@ const TeamsSubscription = ({
|
||||
}, [subscription, editSubscription]);
|
||||
|
||||
return (
|
||||
<Space align="start" data-testid="teams-subscription">
|
||||
<Space align="center" data-testid="teams-subscription">
|
||||
<Typography.Text className="right-panel-label font-normal">
|
||||
{`${t('label.subscription')} :`}
|
||||
</Typography.Text>
|
||||
|
||||
@ -64,3 +64,9 @@ export interface SubscriptionWebhook {
|
||||
webhook: string;
|
||||
endpoint: string;
|
||||
}
|
||||
|
||||
export interface TeamsHeadingLabelProps {
|
||||
currentTeam: Team;
|
||||
entityPermissions: OperationPermission;
|
||||
updateTeamHandler: (data: Team) => Promise<void>;
|
||||
}
|
||||
|
||||
@ -95,6 +95,14 @@
|
||||
.ant-card {
|
||||
background: none;
|
||||
}
|
||||
|
||||
.ant-collapse-arrow {
|
||||
top: 35px !important; // overriding from antd
|
||||
}
|
||||
|
||||
.domain-link {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.teams-tabs-content-container {
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
*/
|
||||
import { Space, Typography } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import classNames from 'classnames';
|
||||
import { compare } from 'fast-json-patch';
|
||||
import { isUndefined } from 'lodash';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
@ -28,6 +29,7 @@ import {
|
||||
import { getEntityName } from '../../../utils/EntityUtils';
|
||||
import { getDomainPath } from '../../../utils/RouterUtils';
|
||||
import { showErrorToast } from '../../../utils/ToastUtils';
|
||||
import { DataAssetWithDomains } from '../../DataAssets/DataAssetsHeader/DataAssetsHeader.interface';
|
||||
import DomainSelectableList from '../DomainSelectableList/DomainSelectableList.component';
|
||||
import { DomainLabelProps } from './DomainLabel.interface';
|
||||
|
||||
@ -39,6 +41,7 @@ export const DomainLabel = ({
|
||||
entityType,
|
||||
entityFqn,
|
||||
entityId,
|
||||
showDomainHeading = false,
|
||||
}: DomainLabelProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [activeDomain, setActiveDomain] = useState<EntityReference>();
|
||||
@ -63,7 +66,8 @@ export const DomainLabel = ({
|
||||
|
||||
// update the domain details here
|
||||
setActiveDomain(res.domain);
|
||||
!isUndefined(afterDomainUpdateAction) && afterDomainUpdateAction(res);
|
||||
!isUndefined(afterDomainUpdateAction) &&
|
||||
afterDomainUpdateAction(res as DataAssetWithDomains);
|
||||
}
|
||||
} catch (err) {
|
||||
// Handle errors as needed
|
||||
@ -77,7 +81,72 @@ export const DomainLabel = ({
|
||||
setActiveDomain(domain);
|
||||
}, [domain]);
|
||||
|
||||
const domainLink = useMemo(() => {
|
||||
if (activeDomain || domainDisplayName) {
|
||||
return (
|
||||
<Link
|
||||
className={classNames(
|
||||
'text-primary no-underline domain-link',
|
||||
!showDomainHeading ? 'font-medium text-xs' : ''
|
||||
)}
|
||||
data-testid="domain-link"
|
||||
to={getDomainPath(activeDomain?.fullyQualifiedName)}>
|
||||
{isUndefined(domainDisplayName)
|
||||
? getEntityName(activeDomain)
|
||||
: domainDisplayName}
|
||||
</Link>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Typography.Text
|
||||
className={classNames(
|
||||
'domain-link',
|
||||
!showDomainHeading ? 'font-medium text-xs' : ''
|
||||
)}
|
||||
data-testid="no-domain-text">
|
||||
{t('label.no-entity', { entity: t('label.domain') })}
|
||||
</Typography.Text>
|
||||
);
|
||||
}
|
||||
}, [activeDomain, domainDisplayName]);
|
||||
|
||||
const selectableList = useMemo(() => {
|
||||
return (
|
||||
hasPermission && (
|
||||
<DomainSelectableList
|
||||
hasPermission={Boolean(hasPermission)}
|
||||
selectedDomain={activeDomain}
|
||||
onUpdate={handleDomainSave}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}, [hasPermission, activeDomain]);
|
||||
|
||||
const label = useMemo(() => {
|
||||
if (showDomainHeading) {
|
||||
return (
|
||||
<>
|
||||
<div className="d-flex items-center m-b-xs">
|
||||
<Typography.Text className="right-panel-label m-r-xss">
|
||||
{t('label.domain')}
|
||||
</Typography.Text>
|
||||
{selectableList}
|
||||
</div>
|
||||
|
||||
<Space>
|
||||
<DomainIcon
|
||||
className="d-flex"
|
||||
color={DE_ACTIVE_COLOR}
|
||||
height={16}
|
||||
name="folder"
|
||||
width={16}
|
||||
/>
|
||||
{domainLink}
|
||||
</Space>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Space>
|
||||
<Typography.Text className="self-center text-xs whitespace-nowrap">
|
||||
@ -89,33 +158,12 @@ export const DomainLabel = ({
|
||||
width={16}
|
||||
/>
|
||||
</Typography.Text>
|
||||
{activeDomain || domainDisplayName ? (
|
||||
<Link
|
||||
className="text-primary font-medium text-xs no-underline"
|
||||
data-testid="domain-link"
|
||||
to={getDomainPath(activeDomain?.fullyQualifiedName)}>
|
||||
{isUndefined(domainDisplayName)
|
||||
? getEntityName(activeDomain)
|
||||
: domainDisplayName}
|
||||
</Link>
|
||||
) : (
|
||||
<Typography.Text
|
||||
className="font-medium text-xs"
|
||||
data-testid="no-domain-text">
|
||||
{t('label.no-entity', { entity: t('label.domain') })}
|
||||
</Typography.Text>
|
||||
)}
|
||||
{domainLink}
|
||||
|
||||
{hasPermission && (
|
||||
<DomainSelectableList
|
||||
hasPermission={Boolean(hasPermission)}
|
||||
selectedDomain={activeDomain}
|
||||
onUpdate={handleDomainSave}
|
||||
/>
|
||||
)}
|
||||
{selectableList}
|
||||
</Space>
|
||||
);
|
||||
}, [activeDomain, hasPermission]);
|
||||
}, [activeDomain, hasPermission, selectableList]);
|
||||
|
||||
return label;
|
||||
};
|
||||
|
||||
@ -23,4 +23,5 @@ export type DomainLabelProps = {
|
||||
entityType: EntityType;
|
||||
entityFqn: string;
|
||||
entityId: string;
|
||||
showDomainHeading?: boolean;
|
||||
};
|
||||
|
||||
@ -26,10 +26,12 @@ import { EntityReference } from '../../../generated/entity/type';
|
||||
import { getDomainList } from '../../../rest/domainAPI';
|
||||
import { searchData } from '../../../rest/miscAPI';
|
||||
import { formatDomainsResponse } from '../../../utils/APIUtils';
|
||||
import { Transi18next } from '../../../utils/CommonUtils';
|
||||
import {
|
||||
getEntityName,
|
||||
getEntityReferenceListFromEntities,
|
||||
} from '../../../utils/EntityUtils';
|
||||
import { getDomainPath } from '../../../utils/RouterUtils';
|
||||
import { SelectableList } from '../SelectableList/SelectableList.component';
|
||||
import './domain-select-dropdown.less';
|
||||
import { DomainSelectableListProps } from './DomainSelectableList.interface';
|
||||
@ -111,6 +113,22 @@ const DomainSelectableList = ({
|
||||
content={
|
||||
<SelectableList
|
||||
customTagRenderer={DomainListItemRenderer}
|
||||
emptyPlaceholderText={
|
||||
<Transi18next
|
||||
i18nKey="message.no-domain-available"
|
||||
renderElement={
|
||||
<a
|
||||
href={getDomainPath()}
|
||||
rel="noreferrer"
|
||||
style={{ color: '#1890ff' }}
|
||||
target="_blank"
|
||||
/>
|
||||
}
|
||||
values={{
|
||||
link: t('label.domain-plural'),
|
||||
}}
|
||||
/>
|
||||
}
|
||||
fetchOptions={fetchOptions}
|
||||
multiSelect={false}
|
||||
removeIconTooltipLabel={t('label.remove-entity', {
|
||||
|
||||
@ -10,6 +10,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@import (reference) url('../../../styles/variables.less');
|
||||
|
||||
.domain-select-popover {
|
||||
min-width: 275px;
|
||||
padding-top: 0;
|
||||
@ -29,4 +32,8 @@
|
||||
.ant-list-footer {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.ant-list-empty-text {
|
||||
color: @text-color;
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,6 +39,7 @@ export const SelectableList = ({
|
||||
customTagRenderer,
|
||||
searchBarDataTestId,
|
||||
removeIconTooltipLabel,
|
||||
emptyPlaceholderText,
|
||||
}: SelectableListProps) => {
|
||||
const [uniqueOptions, setUniqueOptions] = useState<EntityReference[]>([]);
|
||||
const [searchText, setSearchText] = useState('');
|
||||
@ -175,6 +176,7 @@ export const SelectableList = ({
|
||||
return (
|
||||
<List
|
||||
data-testid="selectable-list"
|
||||
dataSource={uniqueOptions}
|
||||
footer={
|
||||
multiSelect && (
|
||||
<div className="d-flex justify-between">
|
||||
@ -217,38 +219,43 @@ export const SelectableList = ({
|
||||
}
|
||||
itemLayout="vertical"
|
||||
loading={{ spinning: fetching, indicator: <Loader /> }}
|
||||
locale={{
|
||||
emptyText: emptyPlaceholderText ?? t('message.no-data-available'),
|
||||
}}
|
||||
size="small">
|
||||
<VirtualList
|
||||
data={uniqueOptions}
|
||||
height={ADD_USER_CONTAINER_HEIGHT}
|
||||
itemKey="id"
|
||||
onScroll={onScroll}>
|
||||
{(item) => (
|
||||
<List.Item
|
||||
className="selectable-list-item cursor-pointer"
|
||||
extra={
|
||||
multiSelect ? (
|
||||
<Checkbox checked={selectedItemsInternal.has(item.id)} />
|
||||
) : (
|
||||
selectedItemsInternal.has(item.id) && (
|
||||
<RemoveIcon
|
||||
removeIconTooltipLabel={removeIconTooltipLabel}
|
||||
removeOwner={handleRemoveClick}
|
||||
/>
|
||||
{uniqueOptions.length > 0 && (
|
||||
<VirtualList
|
||||
data={uniqueOptions}
|
||||
height={ADD_USER_CONTAINER_HEIGHT}
|
||||
itemKey="id"
|
||||
onScroll={onScroll}>
|
||||
{(item) => (
|
||||
<List.Item
|
||||
className="selectable-list-item cursor-pointer"
|
||||
extra={
|
||||
multiSelect ? (
|
||||
<Checkbox checked={selectedItemsInternal.has(item.id)} />
|
||||
) : (
|
||||
selectedItemsInternal.has(item.id) && (
|
||||
<RemoveIcon
|
||||
removeIconTooltipLabel={removeIconTooltipLabel}
|
||||
removeOwner={handleRemoveClick}
|
||||
/>
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
key={item.id}
|
||||
title={getEntityName(item)}
|
||||
onClick={() => selectionHandler(item)}>
|
||||
{customTagRenderer ? (
|
||||
customTagRenderer(item)
|
||||
) : (
|
||||
<UserTag id={item.id} name={getEntityName(item)} />
|
||||
)}
|
||||
</List.Item>
|
||||
)}
|
||||
</VirtualList>
|
||||
}
|
||||
key={item.id}
|
||||
title={getEntityName(item)}
|
||||
onClick={() => selectionHandler(item)}>
|
||||
{customTagRenderer ? (
|
||||
customTagRenderer(item)
|
||||
) : (
|
||||
<UserTag id={item.id} name={getEntityName(item)} />
|
||||
)}
|
||||
</List.Item>
|
||||
)}
|
||||
</VirtualList>
|
||||
)}
|
||||
</List>
|
||||
);
|
||||
};
|
||||
|
||||
@ -27,4 +27,5 @@ export interface SelectableListProps {
|
||||
customTagRenderer?: (props: EntityReference) => ReactNode;
|
||||
searchBarDataTestId?: string;
|
||||
removeIconTooltipLabel?: string;
|
||||
emptyPlaceholderText?: ReactNode;
|
||||
}
|
||||
|
||||
@ -1238,6 +1238,8 @@
|
||||
"disable-classification-description": "Durch Deaktivieren der Klassifizierung können Sie nicht mehr nach dieser suchen oder sie mit zugeordneten Tags einer Entität zuweisen.",
|
||||
"disabled-classification-actions-message": "Sie können diese Aktion auf deaktivierten Klassifikationen nicht ausführen.",
|
||||
"discover-your-data-and-unlock-the-value-of-data-assets": "Die Dinge werden einfacher mit Data Quality ohne Code. Einfache Schritte zum Testen, Bereitstellen und Sammeln von Ergebnissen mit sofortigen Benachrichtigungen bei Testfehlern. Bleiben Sie auf dem Laufenden mit zuverlässigen Daten, denen Sie vertrauen können.",
|
||||
"domain-does-not-have-assets": "Domain {{name}} doesn't have any assets to add to the Data Product",
|
||||
"domains-not-configured": "Domains are not configured",
|
||||
"downstream-depth-message": "Bitte wählen Sie einen Wert für die nachgelagerte Tiefe aus.",
|
||||
"downstream-depth-tooltip": "Zeigen Sie bis zu 3 Knoten der nachgelagerten Verbindungslinie an, um das Ziel (Kinderebenen) zu identifizieren.",
|
||||
"drag-and-drop-files-here": "Dateien hierher ziehen und ablegen",
|
||||
@ -1307,6 +1309,7 @@
|
||||
"filter-pattern-include-exclude-info": "Schließen Sie explizit {{filterPattern}} durch Hinzufügen einer Liste von durch Kommas getrennten regulären Ausdrücken {{activity}} ein oder aus.",
|
||||
"filter-pattern-info": "Wählen Sie aus, ob {{filterPattern}} als Teil der Metadaten-Erfassung ein- oder ausgeschlossen werden soll.",
|
||||
"filter-pattern-placeholder": "Um einen Filtermuster hinzuzufügen, geben Sie es einfach ein und drücken Sie Enter.",
|
||||
"find-apps-to-improve-data": "Find applications to improve your data",
|
||||
"find-in-table": "In Tabelle suchen",
|
||||
"fosters-collaboration-among-producers-and-consumers": "Setzen Sie Unternehmensziele und KPIs, um die Datenkultur Ihres Unternehmens proaktiv voranzutreiben. Fördern Sie eine Kultur kontinuierlicher Verbesserung mit rechtzeitigen Berichten zur Überwachung der Datenqualität.",
|
||||
"get-started-with-open-metadata": "Erste Schritte mit OpenMetadata",
|
||||
@ -1371,6 +1374,7 @@
|
||||
"no-data-available": "Keine Daten verfügbar.",
|
||||
"no-data-available-for-selected-filter": "Keine Daten gefunden. Versuchen Sie, die Filter zu ändern.",
|
||||
"no-domain-assigned-to-entity": "No Domains are Assigned to {{entity}}",
|
||||
"no-domain-available": "No Domains are available to configure. Click on <0>{{link}}</0> to add Domains",
|
||||
"no-entity-activity-message": "Es gibt noch keine Aktivität auf {{entity}}. Starten Sie ein Gespräch, indem Sie auf das",
|
||||
"no-entity-available-with-name": "Keine {{entity}} mit dem Namen verfügbar",
|
||||
"no-entity-data-available": "Keine {{entity}}-Daten verfügbar.",
|
||||
|
||||
@ -1238,6 +1238,8 @@
|
||||
"disable-classification-description": "By disabling classification, you will not be able to search by, or assign associated tags to any entity.",
|
||||
"disabled-classification-actions-message": "You can not perform this action on disabled classifications.",
|
||||
"discover-your-data-and-unlock-the-value-of-data-assets": "Things got easier with no-code data quality. Simple steps to test, deploy, and gather results, with instant test failure notifications. Stay up-to-date with reliable data that you can trust.",
|
||||
"domain-does-not-have-assets": "Domain {{name}} doesn't have any assets to add to the Data Product",
|
||||
"domains-not-configured": "Domains are not configured",
|
||||
"downstream-depth-message": "Please select a value for downstream depth",
|
||||
"downstream-depth-tooltip": "Display up to 3 nodes of downstream lineage to identify the target (child levels).",
|
||||
"drag-and-drop-files-here": "Drag & drop files here",
|
||||
@ -1307,6 +1309,7 @@
|
||||
"filter-pattern-include-exclude-info": "Explicitly {{activity}} {{filterPattern}} by adding a list of comma-separated regex.",
|
||||
"filter-pattern-info": "Choose to include or exclude {{filterPattern}} as part of the metadata ingestion.",
|
||||
"filter-pattern-placeholder": "To add a filter pattern, simply type it in and press Enter",
|
||||
"find-apps-to-improve-data": "Find applications to improve your data",
|
||||
"find-in-table": "Find in table",
|
||||
"fosters-collaboration-among-producers-and-consumers": "Set organizational goals and KPIs to proactively drive the data culture of your company. Foster a culture of continuous improvement with timely reports to monitor data health.",
|
||||
"get-started-with-open-metadata": "Get started with OpenMetadata",
|
||||
@ -1371,6 +1374,7 @@
|
||||
"no-data-available": "No data available.",
|
||||
"no-data-available-for-selected-filter": "No data found. Try changing the filters.",
|
||||
"no-domain-assigned-to-entity": "No Domains are Assigned to {{entity}}",
|
||||
"no-domain-available": "No Domains are available to configure. Click on <0>{{link}}</0> to add Domains",
|
||||
"no-entity-activity-message": "There is no activity on the {{entity}} yet. Start a conversation by clicking on the",
|
||||
"no-entity-available-with-name": "No {{entity}} available with name",
|
||||
"no-entity-data-available": "No {{entity}} data available.",
|
||||
|
||||
@ -1238,6 +1238,8 @@
|
||||
"disable-classification-description": "Option to disable classifications, You won't be able to see associated tags within application",
|
||||
"disabled-classification-actions-message": "You can not perform this action on disabled classifications.",
|
||||
"discover-your-data-and-unlock-the-value-of-data-assets": "Descubra sus datos y desbloquee el valor de los activos de datos.",
|
||||
"domain-does-not-have-assets": "Domain {{name}} doesn't have any assets to add to the Data Product",
|
||||
"domains-not-configured": "Domains are not configured",
|
||||
"downstream-depth-message": "Por favor seleccione un valor para la profundidad del lineaje",
|
||||
"downstream-depth-tooltip": "Muestre hasta 3 nodos de linaje para identificar el objetivo (niveles descendientes).",
|
||||
"drag-and-drop-files-here": "Arrastre y suelte archivos aquí",
|
||||
@ -1307,6 +1309,7 @@
|
||||
"filter-pattern-include-exclude-info": "Excluya o incluya explícitamente {{filterPattern}} mediante la adición de una lista de expresiones regulares separadas por comas.",
|
||||
"filter-pattern-info": "Elija incluir o excluir {{filterPattern}} como parte de la ingestión de metadatos.",
|
||||
"filter-pattern-placeholder": "To add a filter pattern, simply type it in and press Enter",
|
||||
"find-apps-to-improve-data": "Find applications to improve your data",
|
||||
"find-in-table": "Buscar en la tabla",
|
||||
"fosters-collaboration-among-producers-and-consumers": "Fomenta la colaboración entre los productores y consumidores de datos.",
|
||||
"get-started-with-open-metadata": "Empezar con OpenMetadata",
|
||||
@ -1371,6 +1374,7 @@
|
||||
"no-data-available": "No hay datos disponibles.",
|
||||
"no-data-available-for-selected-filter": "No se encontraron datos. Intenta cambiar los filtros.",
|
||||
"no-domain-assigned-to-entity": "No Domains are Assigned to {{entity}}",
|
||||
"no-domain-available": "No Domains are available to configure. Click on <0>{{link}}</0> to add Domains",
|
||||
"no-entity-activity-message": "No hay actividad en {{entity}} todavía. Comienza una conversación haciendo clic en",
|
||||
"no-entity-available-with-name": "No hay {{entity}} disponible con el nombre",
|
||||
"no-entity-data-available": "No hay datos disponibles de {{entity}}.",
|
||||
|
||||
@ -1238,6 +1238,8 @@
|
||||
"disable-classification-description": "Option to disable classifications, You won't be able to see associated tags within the application",
|
||||
"disabled-classification-actions-message": "You cannot perform this action on disabled classifications.",
|
||||
"discover-your-data-and-unlock-the-value-of-data-assets": "Découvrez vos données et libérez la valeur de vos ressources de données",
|
||||
"domain-does-not-have-assets": "Domain {{name}} doesn't have any assets to add to the Data Product",
|
||||
"domains-not-configured": "Domains are not configured",
|
||||
"downstream-depth-message": "Merci de sélectionner une valeur pour la profondeur aval",
|
||||
"downstream-depth-tooltip": "Afficher jusqu'à 3 nœuds de lignée descendante pour identifier la cible (niveaux enfants).",
|
||||
"drag-and-drop-files-here": "Glisser et déposer les fichiers ici",
|
||||
@ -1307,6 +1309,7 @@
|
||||
"filter-pattern-include-exclude-info": "Explicitly {{activity}} {{filterPattern}} by adding a list of comma-separated regex.",
|
||||
"filter-pattern-info": "Choisir d'inclure ou d'exclure {{filterPattern}} en tant que partie de l'ingestion de métadonnées.",
|
||||
"filter-pattern-placeholder": "To add a filter pattern, simply type it in and press Enter",
|
||||
"find-apps-to-improve-data": "Find applications to improve your data",
|
||||
"find-in-table": "Trouver dans la table",
|
||||
"fosters-collaboration-among-producers-and-consumers": "Encouragez la collaborations entre les consommateurs et producteurs de données",
|
||||
"get-started-with-open-metadata": "Commencez votre Journée avec OpenMetadata",
|
||||
@ -1371,6 +1374,7 @@
|
||||
"no-data-available": "Aucune donnée disponible",
|
||||
"no-data-available-for-selected-filter": "Aucune donnée trouvée. Essayez de modifier les filtres.",
|
||||
"no-domain-assigned-to-entity": "No Domains are Assigned to {{entity}}",
|
||||
"no-domain-available": "No Domains are available to configure. Click on <0>{{link}}</0> to add Domains",
|
||||
"no-entity-activity-message": "Il n'y a aucune activité sur {{entity}} pour le moment. Démarrez une conversation en cliquant sur le bouton",
|
||||
"no-entity-available-with-name": "Aucun {{entity}} disponible avec le nom",
|
||||
"no-entity-data-available": "Aucun {{entity}} disponible.",
|
||||
|
||||
@ -1238,6 +1238,8 @@
|
||||
"disable-classification-description": "Option to disable classifications, You won't be able to see associated tags within application",
|
||||
"disabled-classification-actions-message": "You can not perform this action on disabled classifications.",
|
||||
"discover-your-data-and-unlock-the-value-of-data-assets": "Discover your data and unlock the value of data assets.",
|
||||
"domain-does-not-have-assets": "Domain {{name}} doesn't have any assets to add to the Data Product",
|
||||
"domains-not-configured": "Domains are not configured",
|
||||
"downstream-depth-message": "Please select a value for downstream depth",
|
||||
"downstream-depth-tooltip": "Display up to 3 nodes of downstream lineage to identify the target (child levels).",
|
||||
"drag-and-drop-files-here": "ここにファイルをドラッグ&ドロップ",
|
||||
@ -1307,6 +1309,7 @@
|
||||
"filter-pattern-include-exclude-info": "Explicitly {{activity}} {{filterPattern}} by adding a list of comma-separated regex.",
|
||||
"filter-pattern-info": "メタデータ取り込み時に{{filterPattern}}を含めるか除外するか選択する。",
|
||||
"filter-pattern-placeholder": "To add a filter pattern, simply type it in and press Enter",
|
||||
"find-apps-to-improve-data": "Find applications to improve your data",
|
||||
"find-in-table": "テーブルで探す",
|
||||
"fosters-collaboration-among-producers-and-consumers": "Fosters collaboration among the producers and consumers of data.",
|
||||
"get-started-with-open-metadata": "Get started with OpenMetadata",
|
||||
@ -1371,6 +1374,7 @@
|
||||
"no-data-available": "利用できるデータがありません",
|
||||
"no-data-available-for-selected-filter": "No data found. Try changing the filters.",
|
||||
"no-domain-assigned-to-entity": "No Domains are Assigned to {{entity}}",
|
||||
"no-domain-available": "No Domains are available to configure. Click on <0>{{link}}</0> to add Domains",
|
||||
"no-entity-activity-message": "There is no activity on the {{entity}} yet. Start a conversation by clicking on the",
|
||||
"no-entity-available-with-name": "No {{entity}} available with name",
|
||||
"no-entity-data-available": "No {{entity}} data available.",
|
||||
|
||||
@ -1238,6 +1238,8 @@
|
||||
"disable-classification-description": "Option to disable classifications, You won't be able to see associated tags within application",
|
||||
"disabled-classification-actions-message": "You can not perform this action on disabled classifications.",
|
||||
"discover-your-data-and-unlock-the-value-of-data-assets": "Descubra seus dados e desbloqueie o valor dos ativos de dados.",
|
||||
"domain-does-not-have-assets": "Domain {{name}} doesn't have any assets to add to the Data Product",
|
||||
"domains-not-configured": "Domains are not configured",
|
||||
"downstream-depth-message": "Por favor, selecione um valor para a profundidade downstream.",
|
||||
"downstream-depth-tooltip": "Exibir até 3 nós de linhagem downstream para identificar o alvo (níveis filhos).",
|
||||
"drag-and-drop-files-here": "Arraste e solte arquivos aqui",
|
||||
@ -1307,6 +1309,7 @@
|
||||
"filter-pattern-include-exclude-info": "{{activity}} explicitamente {{filterPattern}} adicionando uma lista de regex separadas por vírgula.",
|
||||
"filter-pattern-info": "Escolha incluir ou excluir {{filterPattern}} como parte da ingestão de metadados.",
|
||||
"filter-pattern-placeholder": "To add a filter pattern, simply type it in and press Enter",
|
||||
"find-apps-to-improve-data": "Find applications to improve your data",
|
||||
"find-in-table": "Encontrar na tabela",
|
||||
"fosters-collaboration-among-producers-and-consumers": "Promove a colaboração entre produtores e consumidores de dados.",
|
||||
"get-started-with-open-metadata": "Comece com o OpenMetadata",
|
||||
@ -1371,6 +1374,7 @@
|
||||
"no-data-available": "Nenhum dado disponível.",
|
||||
"no-data-available-for-selected-filter": "Nenhum dado encontrado. Tente alterar os filtros.",
|
||||
"no-domain-assigned-to-entity": "No Domains are Assigned to {{entity}}",
|
||||
"no-domain-available": "No Domains are available to configure. Click on <0>{{link}}</0> to add Domains",
|
||||
"no-entity-activity-message": "Não há atividade em {{entity}} ainda. Inicie uma conversa clicando em",
|
||||
"no-entity-available-with-name": "Não há {{entity}} disponível com o nome",
|
||||
"no-entity-data-available": "Nenhum dado disponível para {{entity}}.",
|
||||
|
||||
@ -1238,6 +1238,8 @@
|
||||
"disable-classification-description": "Отключив классификацию, вы не сможете выполнять поиск или назначать связанные теги любому объекту.",
|
||||
"disabled-classification-actions-message": "Вы не можете выполнить это действие с отключенными классификациями.",
|
||||
"discover-your-data-and-unlock-the-value-of-data-assets": "Откройте для себя ваши данные и раскройте ценность информационных ресурсов.",
|
||||
"domain-does-not-have-assets": "Domain {{name}} doesn't have any assets to add to the Data Product",
|
||||
"domains-not-configured": "Domains are not configured",
|
||||
"downstream-depth-message": "Пожалуйста, выберите значение для нисходящей линии",
|
||||
"downstream-depth-tooltip": "Отобразите до 3 узлов нисходящей линии для идентификации цели (дочерние уровни).",
|
||||
"drag-and-drop-files-here": "Перетащите файлы сюда",
|
||||
@ -1307,6 +1309,7 @@
|
||||
"filter-pattern-include-exclude-info": "{{activity}} {{filterPattern}} путем добавления списка регулярных выражений, разделенных запятыми.",
|
||||
"filter-pattern-info": "Выберите, следует ли включить или исключить {{filterPattern}} при приеме метаданных.",
|
||||
"filter-pattern-placeholder": "Чтобы добавить шаблон фильтра, просто введите его и нажмите Enter.",
|
||||
"find-apps-to-improve-data": "Find applications to improve your data",
|
||||
"find-in-table": "Найти в таблице",
|
||||
"fosters-collaboration-among-producers-and-consumers": "Способствует сотрудничеству между производителями и потребителями данных.",
|
||||
"get-started-with-open-metadata": "Начните работу с OpenMetadata",
|
||||
@ -1371,6 +1374,7 @@
|
||||
"no-data-available": "Данные недоступны.",
|
||||
"no-data-available-for-selected-filter": "Данные не найдены. Попробуйте поменять фильтры.",
|
||||
"no-domain-assigned-to-entity": "No Domains are Assigned to {{entity}}",
|
||||
"no-domain-available": "No Domains are available to configure. Click on <0>{{link}}</0> to add Domains",
|
||||
"no-entity-activity-message": "В {{entity}} пока нет активности. Начните обсуждение, нажав на кнопку",
|
||||
"no-entity-available-with-name": "Нет доступного {{entity}} с именем",
|
||||
"no-entity-data-available": "Данные {{entity}} недоступны.",
|
||||
|
||||
@ -1238,6 +1238,8 @@
|
||||
"disable-classification-description": "禁用分类选项,您将无法查看到关联的标签",
|
||||
"disabled-classification-actions-message": "您无法在已禁用的分类上执行此操作",
|
||||
"discover-your-data-and-unlock-the-value-of-data-assets": "深入探索数据,释放数据资产的价值",
|
||||
"domain-does-not-have-assets": "Domain {{name}} doesn't have any assets to add to the Data Product",
|
||||
"domains-not-configured": "Domains are not configured",
|
||||
"downstream-depth-message": "请选择下游深度的值",
|
||||
"downstream-depth-tooltip": "显示最多三个下游谱系节点以确定目标(子级)",
|
||||
"drag-and-drop-files-here": "拖放文件到此处",
|
||||
@ -1307,6 +1309,7 @@
|
||||
"filter-pattern-include-exclude-info": "通过添加逗号分隔的正则表达式列表明确{{activity}} {{filterPattern}}",
|
||||
"filter-pattern-info": "选择包含或排除{{filterPattern}}作为元数据提取的一部分",
|
||||
"filter-pattern-placeholder": "输入并按回车键,即可新建一个过滤器",
|
||||
"find-apps-to-improve-data": "Find applications to improve your data",
|
||||
"find-in-table": "在数据表中查找",
|
||||
"fosters-collaboration-among-producers-and-consumers": "促进数据生产者和使用者之间的合作",
|
||||
"get-started-with-open-metadata": "开始使用 OpenMetadata",
|
||||
@ -1371,6 +1374,7 @@
|
||||
"no-data-available": "没有可用的数据",
|
||||
"no-data-available-for-selected-filter": "未找到数据,请尝试更改筛选条件",
|
||||
"no-domain-assigned-to-entity": "No Domains are Assigned to {{entity}}",
|
||||
"no-domain-available": "No Domains are available to configure. Click on <0>{{link}}</0> to add Domains",
|
||||
"no-entity-activity-message": "{{entity}}上还没有任何活动,单击开始对话",
|
||||
"no-entity-available-with-name": "名称为{{entity}}不可用",
|
||||
"no-entity-data-available": "没有可用的{{entity}}数据。",
|
||||
|
||||
@ -32,6 +32,10 @@
|
||||
border: 0px;
|
||||
margin-top: 16px;
|
||||
|
||||
.side-panel-icons {
|
||||
width: 14px;
|
||||
}
|
||||
|
||||
.ant-menu-item::after {
|
||||
left: 0;
|
||||
right: unset;
|
||||
|
||||
@ -123,7 +123,7 @@ const GlossaryPage = () => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const { data } = await getGlossariesList({
|
||||
fields: 'owner,tags,reviewers,votes',
|
||||
fields: 'owner,tags,reviewers,votes,domain',
|
||||
limit: PAGE_SIZE_LARGE,
|
||||
});
|
||||
setGlossaries(data);
|
||||
|
||||
@ -305,7 +305,7 @@ const TeamsPage = () => {
|
||||
try {
|
||||
const data = await getTeamByName(
|
||||
name,
|
||||
['users', 'defaultRoles', 'policies', 'childrenCount'],
|
||||
['users', 'defaultRoles', 'policies', 'childrenCount', 'domain'],
|
||||
'all'
|
||||
);
|
||||
|
||||
|
||||
@ -11,10 +11,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Operation } from 'fast-json-patch';
|
||||
import {
|
||||
AssetsUnion,
|
||||
MapPatchAPIResponse,
|
||||
} from '../../components/Assets/AssetsSelectionModal/AssetSelectionModal.interface';
|
||||
import { MapPatchAPIResponse } from '../../components/Assets/AssetsSelectionModal/AssetSelectionModal.interface';
|
||||
import { AssetsOfEntity } from '../../components/Glossary/GlossaryTerms/tabs/AssetsTabs.interface';
|
||||
import { EntityType } from '../../enums/entity.enum';
|
||||
import { SearchIndex } from '../../enums/search.enum';
|
||||
@ -33,7 +30,9 @@ import {
|
||||
patchDataModelDetails,
|
||||
} from '../../rest/dataModelsAPI';
|
||||
import {
|
||||
getGlossariesByName,
|
||||
getGlossaryTermByFQN,
|
||||
patchGlossaries,
|
||||
patchGlossaryTerm,
|
||||
} from '../../rest/glossaryAPI';
|
||||
import { getMlModelByFQN, patchMlModelDetails } from '../../rest/mlModelAPI';
|
||||
@ -55,11 +54,12 @@ import {
|
||||
patchStoredProceduresDetails,
|
||||
} from '../../rest/storedProceduresAPI';
|
||||
import { getTableDetailsByFQN, patchTableDetails } from '../../rest/tableAPI';
|
||||
import { getTeamByName, patchTeamDetail } from '../../rest/teamsAPI';
|
||||
import { getTopicByFqn, patchTopicDetails } from '../../rest/topicsAPI';
|
||||
import { getServiceCategoryFromEntityType } from '../../utils/ServiceUtils';
|
||||
|
||||
export const getAPIfromSource = (
|
||||
source: AssetsUnion
|
||||
source: keyof MapPatchAPIResponse
|
||||
): ((
|
||||
id: string,
|
||||
jsonPatch: Operation[]
|
||||
@ -85,10 +85,14 @@ export const getAPIfromSource = (
|
||||
return patchDataModelDetails;
|
||||
case EntityType.GLOSSARY_TERM:
|
||||
return patchGlossaryTerm;
|
||||
case EntityType.GLOSSARY:
|
||||
return patchGlossaries;
|
||||
case EntityType.DATABASE_SCHEMA:
|
||||
return patchDatabaseSchemaDetails;
|
||||
case EntityType.DATABASE:
|
||||
return patchDatabaseDetails;
|
||||
case EntityType.TEAM:
|
||||
return patchTeamDetail;
|
||||
case EntityType.MESSAGING_SERVICE:
|
||||
case EntityType.DASHBOARD_SERVICE:
|
||||
case EntityType.PIPELINE_SERVICE:
|
||||
@ -105,7 +109,7 @@ export const getAPIfromSource = (
|
||||
};
|
||||
|
||||
export const getEntityAPIfromSource = (
|
||||
source: AssetsUnion
|
||||
source: keyof MapPatchAPIResponse
|
||||
): ((
|
||||
id: string,
|
||||
queryFields: string | string[]
|
||||
@ -129,12 +133,16 @@ export const getEntityAPIfromSource = (
|
||||
return getDataModelsByName;
|
||||
case EntityType.GLOSSARY_TERM:
|
||||
return getGlossaryTermByFQN;
|
||||
case EntityType.GLOSSARY:
|
||||
return getGlossariesByName;
|
||||
case EntityType.DATABASE_SCHEMA:
|
||||
return getDatabaseSchemaDetailsByFQN;
|
||||
case EntityType.DATABASE:
|
||||
return getDatabaseDetailsByFQN;
|
||||
case EntityType.SEARCH_INDEX:
|
||||
return getSearchIndexDetailsByFQN;
|
||||
case EntityType.TEAM:
|
||||
return getTeamByName;
|
||||
case EntityType.MESSAGING_SERVICE:
|
||||
case EntityType.DASHBOARD_SERVICE:
|
||||
case EntityType.PIPELINE_SERVICE:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user