mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-09-06 07:32:46 +00:00
ui: revamp entity task component (#12419)
* revamp entity task component * added test related to tags and description --------- Co-authored-by: Chirag Madlani <12962843+chirag-madlani@users.noreply.github.com>
This commit is contained in:
parent
0a6e91d69a
commit
fc29eba285
@ -140,7 +140,7 @@ const ContainerDataModel: FC<ContainerDataModelProps> = ({
|
|||||||
<TableDescription
|
<TableDescription
|
||||||
columnData={{
|
columnData={{
|
||||||
fqn: record.fullyQualifiedName ?? '',
|
fqn: record.fullyQualifiedName ?? '',
|
||||||
description: record.description,
|
field: record.description,
|
||||||
}}
|
}}
|
||||||
entityFieldThreads={entityFieldThreads}
|
entityFieldThreads={entityFieldThreads}
|
||||||
entityFqn={entityFqn}
|
entityFqn={entityFqn}
|
||||||
|
@ -470,7 +470,7 @@ const DashboardDetails = ({
|
|||||||
<TableDescription
|
<TableDescription
|
||||||
columnData={{
|
columnData={{
|
||||||
fqn: record.fullyQualifiedName ?? '',
|
fqn: record.fullyQualifiedName ?? '',
|
||||||
description: record.description,
|
field: record.description,
|
||||||
}}
|
}}
|
||||||
entityFieldThreads={getEntityFieldThreadCounts(
|
entityFieldThreads={getEntityFieldThreadCounts(
|
||||||
EntityField.DESCRIPTION,
|
EntityField.DESCRIPTION,
|
||||||
|
@ -110,7 +110,7 @@ const ModelTab = ({
|
|||||||
<TableDescription
|
<TableDescription
|
||||||
columnData={{
|
columnData={{
|
||||||
fqn: record.fullyQualifiedName ?? '',
|
fqn: record.fullyQualifiedName ?? '',
|
||||||
description: record.description,
|
field: record.description,
|
||||||
}}
|
}}
|
||||||
entityFieldThreads={entityFieldThreads}
|
entityFieldThreads={entityFieldThreads}
|
||||||
entityFqn={entityFqn}
|
entityFqn={entityFqn}
|
||||||
|
@ -209,7 +209,7 @@ const MlModelFeaturesList = ({
|
|||||||
<TableDescription
|
<TableDescription
|
||||||
columnData={{
|
columnData={{
|
||||||
fqn: feature.fullyQualifiedName ?? '',
|
fqn: feature.fullyQualifiedName ?? '',
|
||||||
description: feature.description,
|
field: feature.description,
|
||||||
}}
|
}}
|
||||||
entityFieldThreads={entityFieldThreads}
|
entityFieldThreads={entityFieldThreads}
|
||||||
entityFqn={entityFqn}
|
entityFqn={entityFqn}
|
||||||
|
@ -394,7 +394,7 @@ const PipelineDetails = ({
|
|||||||
<TableDescription
|
<TableDescription
|
||||||
columnData={{
|
columnData={{
|
||||||
fqn: record.fullyQualifiedName ?? '',
|
fqn: record.fullyQualifiedName ?? '',
|
||||||
description: record.description,
|
field: record.description,
|
||||||
}}
|
}}
|
||||||
entityFieldThreads={getEntityFieldThreadCounts(
|
entityFieldThreads={getEntityFieldThreadCounts(
|
||||||
EntityField.TASKS,
|
EntityField.TASKS,
|
||||||
|
@ -258,7 +258,7 @@ const SchemaTable = ({
|
|||||||
<TableDescription
|
<TableDescription
|
||||||
columnData={{
|
columnData={{
|
||||||
fqn: record.fullyQualifiedName ?? '',
|
fqn: record.fullyQualifiedName ?? '',
|
||||||
description: record.description,
|
field: record.description,
|
||||||
}}
|
}}
|
||||||
entityFieldThreads={entityFieldThreads}
|
entityFieldThreads={entityFieldThreads}
|
||||||
entityFqn={entityFqn}
|
entityFqn={entityFqn}
|
||||||
|
@ -14,7 +14,8 @@
|
|||||||
import { Space } from 'antd';
|
import { Space } from 'antd';
|
||||||
import RichTextEditorPreviewer from 'components/common/rich-text-editor/RichTextEditorPreviewer';
|
import RichTextEditorPreviewer from 'components/common/rich-text-editor/RichTextEditorPreviewer';
|
||||||
import { DE_ACTIVE_COLOR } from 'constants/constants';
|
import { DE_ACTIVE_COLOR } from 'constants/constants';
|
||||||
import EntityTaskDescription from 'pages/TasksPage/EntityTaskDescription/EntityTaskDescription.component';
|
import { EntityField } from 'constants/Feeds.constants';
|
||||||
|
import EntityTasks from 'pages/TasksPage/EntityTasks/EntityTasks.component';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ReactComponent as EditIcon } from '../../assets/svg/edit-new.svg';
|
import { ReactComponent as EditIcon } from '../../assets/svg/edit-new.svg';
|
||||||
@ -39,8 +40,8 @@ const TableDescription = ({
|
|||||||
data-testid="description"
|
data-testid="description"
|
||||||
direction="vertical"
|
direction="vertical"
|
||||||
id={`field-description-${index}`}>
|
id={`field-description-${index}`}>
|
||||||
{columnData.description ? (
|
{columnData.field ? (
|
||||||
<RichTextEditorPreviewer markdown={columnData.description} />
|
<RichTextEditorPreviewer markdown={columnData.field} />
|
||||||
) : (
|
) : (
|
||||||
<span className="text-grey-muted">
|
<span className="text-grey-muted">
|
||||||
{t('label.no-entity', {
|
{t('label.no-entity', {
|
||||||
@ -62,10 +63,11 @@ const TableDescription = ({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<EntityTaskDescription
|
<EntityTasks
|
||||||
data={columnData}
|
data={columnData}
|
||||||
entityFieldThreads={entityFieldThreads}
|
entityFieldThreads={entityFieldThreads}
|
||||||
entityFqn={entityFqn}
|
entityFqn={entityFqn}
|
||||||
|
entityTaskType={EntityField.DESCRIPTION}
|
||||||
entityType={entityType}
|
entityType={entityType}
|
||||||
onThreadLinkSelect={onThreadLinkSelect}
|
onThreadLinkSelect={onThreadLinkSelect}
|
||||||
/>
|
/>
|
||||||
|
@ -19,7 +19,7 @@ export interface TableDescriptionProps {
|
|||||||
index: number;
|
index: number;
|
||||||
columnData: {
|
columnData: {
|
||||||
fqn: string;
|
fqn: string;
|
||||||
description?: string;
|
field?: string;
|
||||||
};
|
};
|
||||||
entityFqn: string;
|
entityFqn: string;
|
||||||
entityType: EntityType;
|
entityType: EntityType;
|
||||||
|
@ -13,7 +13,8 @@
|
|||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import TagsContainerV2 from 'components/Tag/TagsContainerV2/TagsContainerV2';
|
import TagsContainerV2 from 'components/Tag/TagsContainerV2/TagsContainerV2';
|
||||||
import EntityTaskTags from 'pages/TasksPage/EntityTaskTags/EntityTaskTags.component';
|
import { EntityField } from 'constants/Feeds.constants';
|
||||||
|
import EntityTasks from 'pages/TasksPage/EntityTasks/EntityTasks.component';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { TableTagsComponentProps, TableUnion } from './TableTags.interface';
|
import { TableTagsComponentProps, TableUnion } from './TableTags.interface';
|
||||||
|
|
||||||
@ -48,13 +49,14 @@ const TableTags = <T extends TableUnion>({
|
|||||||
}}>
|
}}>
|
||||||
<>
|
<>
|
||||||
{!isReadOnly && (
|
{!isReadOnly && (
|
||||||
<EntityTaskTags
|
<EntityTasks
|
||||||
data={{
|
data={{
|
||||||
fqn: record.fullyQualifiedName ?? '',
|
fqn: record.fullyQualifiedName ?? '',
|
||||||
tags: record.tags ?? [],
|
field: record.tags ?? [],
|
||||||
}}
|
}}
|
||||||
entityFieldThreads={entityFieldThreads}
|
entityFieldThreads={entityFieldThreads}
|
||||||
entityFqn={entityFqn}
|
entityFqn={entityFqn}
|
||||||
|
entityTaskType={EntityField.TAGS}
|
||||||
entityType={entityType}
|
entityType={entityType}
|
||||||
tagSource={type}
|
tagSource={type}
|
||||||
onThreadLinkSelect={onThreadLinkSelect}
|
onThreadLinkSelect={onThreadLinkSelect}
|
||||||
|
@ -27,8 +27,8 @@ jest.mock('utils/FeedElementUtils', () => ({
|
|||||||
),
|
),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('pages/TasksPage/EntityTaskTags/EntityTaskTags.component', () => {
|
jest.mock('pages/TasksPage/EntityTasks/EntityTasks.component', () => {
|
||||||
return jest.fn().mockImplementation(() => <div>EntityTaskTags</div>);
|
return jest.fn().mockImplementation(() => <div>EntityTasks</div>);
|
||||||
});
|
});
|
||||||
|
|
||||||
const glossaryTags = [
|
const glossaryTags = [
|
||||||
@ -171,10 +171,10 @@ describe('Test EntityTableTags Component', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const tagContainer = await screen.findByTestId('Classification-tags-0');
|
const tagContainer = await screen.findByTestId('Classification-tags-0');
|
||||||
const entityTaskTags = screen.queryByText('EntityTaskTags');
|
const entityTasks = screen.queryByText('EntityTasks');
|
||||||
|
|
||||||
expect(tagContainer).toBeInTheDocument();
|
expect(tagContainer).toBeInTheDocument();
|
||||||
expect(entityTaskTags).not.toBeInTheDocument();
|
expect(entityTasks).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should render update and request tags buttons', async () => {
|
it('Should render update and request tags buttons', async () => {
|
||||||
@ -194,9 +194,9 @@ describe('Test EntityTableTags Component', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const tagContainer = await screen.findByTestId('Classification-tags-0');
|
const tagContainer = await screen.findByTestId('Classification-tags-0');
|
||||||
const entityTaskTags = screen.queryByText('EntityTaskTags');
|
const entityTasks = screen.queryByText('EntityTasks');
|
||||||
|
|
||||||
expect(tagContainer).toBeInTheDocument();
|
expect(tagContainer).toBeInTheDocument();
|
||||||
expect(entityTaskTags).toBeInTheDocument();
|
expect(entityTasks).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -182,7 +182,7 @@ const TopicSchemaFields: FC<TopicSchemaFieldsProps> = ({
|
|||||||
<TableDescription
|
<TableDescription
|
||||||
columnData={{
|
columnData={{
|
||||||
fqn: record.fullyQualifiedName ?? '',
|
fqn: record.fullyQualifiedName ?? '',
|
||||||
description: record.description,
|
field: record.description,
|
||||||
}}
|
}}
|
||||||
entityFieldThreads={entityFieldThreads}
|
entityFieldThreads={entityFieldThreads}
|
||||||
entityFqn={entityFqn}
|
entityFqn={entityFqn}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
import { startCase } from 'lodash';
|
import { startCase } from 'lodash';
|
||||||
import i18n from 'utils/i18next/LocalUtil';
|
import i18n from 'utils/i18next/LocalUtil';
|
||||||
|
import { EntityField } from './Feeds.constants';
|
||||||
|
|
||||||
export const ENTITY_DELETE_STATE = {
|
export const ENTITY_DELETE_STATE = {
|
||||||
loading: 'initial',
|
loading: 'initial',
|
||||||
@ -32,3 +33,14 @@ export const STEPS_FOR_IMPORT_ENTITY = [
|
|||||||
step: 2,
|
step: 2,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const ENTITY_TASKS_TOOLTIP = {
|
||||||
|
[EntityField.DESCRIPTION]: {
|
||||||
|
request: i18n.t('message.request-description'),
|
||||||
|
update: i18n.t('message.request-update-description'),
|
||||||
|
},
|
||||||
|
[EntityField.TAGS]: {
|
||||||
|
request: i18n.t('label.request-tag-plural'),
|
||||||
|
update: i18n.t('label.update-request-tag-plural'),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
@ -1,106 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 { Space, Tooltip } from 'antd';
|
|
||||||
import { FQN_SEPARATOR_CHAR } from 'constants/char.constants';
|
|
||||||
import { DE_ACTIVE_COLOR } from 'constants/constants';
|
|
||||||
import { EntityField } from 'constants/Feeds.constants';
|
|
||||||
import React, { useMemo } from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { useHistory } from 'react-router-dom';
|
|
||||||
import { getPartialNameFromTableFQN } from 'utils/CommonUtils';
|
|
||||||
import { ENTITY_LINK_SEPARATOR } from 'utils/EntityUtils';
|
|
||||||
import { getFieldThreadElement } from 'utils/FeedElementUtils';
|
|
||||||
import {
|
|
||||||
getEntityTaskDetails,
|
|
||||||
getRequestDescriptionPath,
|
|
||||||
getUpdateDescriptionPath,
|
|
||||||
} from 'utils/TasksUtils';
|
|
||||||
import { ReactComponent as IconRequest } from '../../../assets/svg/request-icon.svg';
|
|
||||||
import { EntityTaskDescriptionProps } from './entityTaskDescription.interface';
|
|
||||||
|
|
||||||
const EntityTaskDescription = ({
|
|
||||||
entityFqn,
|
|
||||||
entityType,
|
|
||||||
data,
|
|
||||||
onThreadLinkSelect,
|
|
||||||
entityFieldThreads,
|
|
||||||
}: EntityTaskDescriptionProps) => {
|
|
||||||
const history = useHistory();
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
const { fqnPart, entityField } = useMemo(
|
|
||||||
() => getEntityTaskDetails(entityType),
|
|
||||||
[entityType]
|
|
||||||
);
|
|
||||||
|
|
||||||
const columnName = useMemo(() => {
|
|
||||||
const columnName = getPartialNameFromTableFQN(data.fqn ?? '', fqnPart);
|
|
||||||
|
|
||||||
return columnName.includes(FQN_SEPARATOR_CHAR)
|
|
||||||
? `"${columnName}"`
|
|
||||||
: columnName;
|
|
||||||
}, [data.fqn]);
|
|
||||||
|
|
||||||
const handleDescriptionTask = (hasDescription: boolean) => {
|
|
||||||
history.push(
|
|
||||||
(hasDescription ? getUpdateDescriptionPath : getRequestDescriptionPath)(
|
|
||||||
entityType,
|
|
||||||
entityFqn,
|
|
||||||
entityField,
|
|
||||||
columnName
|
|
||||||
)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const requestDescriptionElement = useMemo(() => {
|
|
||||||
const hasDescription = Boolean(data?.description);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Tooltip
|
|
||||||
destroyTooltipOnHide
|
|
||||||
title={
|
|
||||||
hasDescription
|
|
||||||
? t('message.request-update-description')
|
|
||||||
: t('message.request-description')
|
|
||||||
}>
|
|
||||||
<IconRequest
|
|
||||||
className="cursor-pointer hover-cell-icon"
|
|
||||||
data-testid="request-description"
|
|
||||||
height={14}
|
|
||||||
name={t('message.request-description')}
|
|
||||||
style={{ color: DE_ACTIVE_COLOR }}
|
|
||||||
width={14}
|
|
||||||
onClick={() => handleDescriptionTask(hasDescription)}
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
}, [data]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Space size="middle">
|
|
||||||
{requestDescriptionElement}
|
|
||||||
{getFieldThreadElement(
|
|
||||||
columnName,
|
|
||||||
EntityField.DESCRIPTION,
|
|
||||||
entityFieldThreads,
|
|
||||||
onThreadLinkSelect,
|
|
||||||
entityType,
|
|
||||||
entityFqn,
|
|
||||||
`${entityField}${ENTITY_LINK_SEPARATOR}${columnName}${ENTITY_LINK_SEPARATOR}${EntityField.DESCRIPTION}`
|
|
||||||
)}
|
|
||||||
</Space>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default EntityTaskDescription;
|
|
@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 { EntityType } from 'enums/entity.enum';
|
|
||||||
import { ThreadType } from 'generated/api/feed/createThread';
|
|
||||||
import { EntityFieldThreads } from 'interface/feed.interface';
|
|
||||||
|
|
||||||
export interface EntityTaskDescriptionProps {
|
|
||||||
data: {
|
|
||||||
fqn?: string;
|
|
||||||
description?: string;
|
|
||||||
};
|
|
||||||
entityFqn: string;
|
|
||||||
entityType: EntityType;
|
|
||||||
entityFieldThreads: EntityFieldThreads[];
|
|
||||||
onThreadLinkSelect: (value: string, threadType?: ThreadType) => void;
|
|
||||||
}
|
|
@ -14,6 +14,7 @@
|
|||||||
import { Space, Tooltip } from 'antd';
|
import { Space, Tooltip } from 'antd';
|
||||||
import { FQN_SEPARATOR_CHAR } from 'constants/char.constants';
|
import { FQN_SEPARATOR_CHAR } from 'constants/char.constants';
|
||||||
import { DE_ACTIVE_COLOR } from 'constants/constants';
|
import { DE_ACTIVE_COLOR } from 'constants/constants';
|
||||||
|
import { ENTITY_TASKS_TOOLTIP } from 'constants/entity.constants';
|
||||||
import { EntityField } from 'constants/Feeds.constants';
|
import { EntityField } from 'constants/Feeds.constants';
|
||||||
import { TagSource } from 'generated/type/tagLabel';
|
import { TagSource } from 'generated/type/tagLabel';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
@ -25,20 +26,23 @@ import { ENTITY_LINK_SEPARATOR } from 'utils/EntityUtils';
|
|||||||
import { getFieldThreadElement } from 'utils/FeedElementUtils';
|
import { getFieldThreadElement } from 'utils/FeedElementUtils';
|
||||||
import {
|
import {
|
||||||
getEntityTaskDetails,
|
getEntityTaskDetails,
|
||||||
|
getRequestDescriptionPath,
|
||||||
getRequestTagsPath,
|
getRequestTagsPath,
|
||||||
|
getUpdateDescriptionPath,
|
||||||
getUpdateTagsPath,
|
getUpdateTagsPath,
|
||||||
} from 'utils/TasksUtils';
|
} from 'utils/TasksUtils';
|
||||||
import { ReactComponent as IconRequest } from '../../../assets/svg/request-icon.svg';
|
import { ReactComponent as IconRequest } from '../../../assets/svg/request-icon.svg';
|
||||||
import { EntityTaskTagsProps } from './EntityTaskTags.interface';
|
import { EntityTasksProps } from './EntityTasks.interface';
|
||||||
|
|
||||||
const EntityTaskTags = ({
|
const EntityTasks = ({
|
||||||
data,
|
data,
|
||||||
tagSource,
|
tagSource,
|
||||||
entityFqn,
|
entityFqn,
|
||||||
entityType,
|
entityType,
|
||||||
|
entityTaskType,
|
||||||
entityFieldThreads,
|
entityFieldThreads,
|
||||||
onThreadLinkSelect,
|
onThreadLinkSelect,
|
||||||
}: EntityTaskTagsProps) => {
|
}: EntityTasksProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
|
||||||
@ -55,59 +59,70 @@ const EntityTaskTags = ({
|
|||||||
: columnName;
|
: columnName;
|
||||||
}, [data.fqn]);
|
}, [data.fqn]);
|
||||||
|
|
||||||
const handleTagTask = (hasTags: boolean) => {
|
const handleTask = (hasData: boolean) => {
|
||||||
|
if (entityTaskType === EntityField.DESCRIPTION) {
|
||||||
history.push(
|
history.push(
|
||||||
(hasTags ? getUpdateTagsPath : getRequestTagsPath)(
|
(hasData ? getUpdateDescriptionPath : getRequestDescriptionPath)(
|
||||||
entityType,
|
entityType,
|
||||||
entityFqn,
|
entityFqn,
|
||||||
entityField,
|
entityField,
|
||||||
columnName
|
columnName
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
history.push(
|
||||||
|
(hasData ? getUpdateTagsPath : getRequestTagsPath)(
|
||||||
|
entityType,
|
||||||
|
entityFqn,
|
||||||
|
entityField,
|
||||||
|
columnName
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getRequestTagsElement = useMemo(() => {
|
const taskElement = useMemo(() => {
|
||||||
const hasTags = !isEmpty(data.tags);
|
const hasData = !isEmpty(data.field);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
destroyTooltipOnHide
|
destroyTooltipOnHide
|
||||||
overlayClassName="ant-popover-request-description"
|
overlayClassName="ant-popover-request-description"
|
||||||
title={
|
title={
|
||||||
hasTags
|
hasData
|
||||||
? t('label.update-request-tag-plural')
|
? ENTITY_TASKS_TOOLTIP[entityTaskType].update
|
||||||
: t('label.request-tag-plural')
|
: ENTITY_TASKS_TOOLTIP[entityTaskType].request
|
||||||
}>
|
}>
|
||||||
<IconRequest
|
<IconRequest
|
||||||
className="hover-cell-icon cursor-pointer"
|
className="hover-cell-icon cursor-pointer"
|
||||||
data-testid="request-tags"
|
data-testid="task-element"
|
||||||
height={14}
|
height={14}
|
||||||
name={t('label.request-tag-plural')}
|
name={t('label.request-tag-plural')}
|
||||||
style={{ color: DE_ACTIVE_COLOR }}
|
style={{ color: DE_ACTIVE_COLOR }}
|
||||||
width={14}
|
width={14}
|
||||||
onClick={() => handleTagTask(hasTags)}
|
onClick={() => handleTask(hasData)}
|
||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
);
|
||||||
}, [data]);
|
}, [data.field]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Space size="middle">
|
<Space data-testid="entity-task" size="middle">
|
||||||
{/* Request and Update tags */}
|
{/* Request and Update Tasks */}
|
||||||
{tagSource === TagSource.Classification && getRequestTagsElement}
|
{tagSource !== TagSource.Glossary && taskElement}
|
||||||
|
|
||||||
{/* List Conversation */}
|
{/* List Conversation */}
|
||||||
{getFieldThreadElement(
|
{getFieldThreadElement(
|
||||||
columnName,
|
columnName,
|
||||||
EntityField.TAGS,
|
entityTaskType,
|
||||||
entityFieldThreads,
|
entityFieldThreads,
|
||||||
onThreadLinkSelect,
|
onThreadLinkSelect,
|
||||||
entityType,
|
entityType,
|
||||||
entityFqn,
|
entityFqn,
|
||||||
`${entityField}${ENTITY_LINK_SEPARATOR}${columnName}${ENTITY_LINK_SEPARATOR}${EntityField.TAGS}`
|
`${entityField}${ENTITY_LINK_SEPARATOR}${columnName}${ENTITY_LINK_SEPARATOR}${entityTaskType}`
|
||||||
)}
|
)}
|
||||||
</Space>
|
</Space>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default EntityTaskTags;
|
export default EntityTasks;
|
@ -11,19 +11,21 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { EntityField } from 'constants/Feeds.constants';
|
||||||
import { EntityType } from 'enums/entity.enum';
|
import { EntityType } from 'enums/entity.enum';
|
||||||
import { ThreadType } from 'generated/api/feed/createThread';
|
import { ThreadType } from 'generated/api/feed/createThread';
|
||||||
import { TagLabel, TagSource } from 'generated/type/tagLabel';
|
import { TagLabel, TagSource } from 'generated/type/tagLabel';
|
||||||
import { EntityFieldThreads } from 'interface/feed.interface';
|
import { EntityFieldThreads } from 'interface/feed.interface';
|
||||||
|
|
||||||
export interface EntityTaskTagsProps {
|
export interface EntityTasksProps {
|
||||||
data: {
|
data: {
|
||||||
fqn: string;
|
fqn: string;
|
||||||
tags: TagLabel[];
|
field?: string | TagLabel[];
|
||||||
};
|
};
|
||||||
tagSource: TagSource;
|
tagSource?: TagSource;
|
||||||
entityFqn: string;
|
entityFqn: string;
|
||||||
entityType: EntityType;
|
entityType: EntityType;
|
||||||
|
entityTaskType: EntityField.TAGS | EntityField.DESCRIPTION;
|
||||||
entityFieldThreads: EntityFieldThreads[];
|
entityFieldThreads: EntityFieldThreads[];
|
||||||
onThreadLinkSelect: (value: string, threadType?: ThreadType) => void;
|
onThreadLinkSelect: (value: string, threadType?: ThreadType) => void;
|
||||||
}
|
}
|
@ -0,0 +1,225 @@
|
|||||||
|
/*
|
||||||
|
* 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, fireEvent, render, screen } from '@testing-library/react';
|
||||||
|
import { EntityField } from 'constants/Feeds.constants';
|
||||||
|
import { EntityType, FqnPart } from 'enums/entity.enum';
|
||||||
|
import { TagSource } from 'generated/type/tagLabel';
|
||||||
|
import React from 'react';
|
||||||
|
import EntityTasks from './EntityTasks.component';
|
||||||
|
import { EntityTasksProps } from './EntityTasks.interface';
|
||||||
|
|
||||||
|
const mockRequestTags = {
|
||||||
|
pathname: '/request-tags/table/sample_data.ecommerce_db.shopify.fact_sale',
|
||||||
|
search: 'field=columns&value=sale_id',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockUpdateTags = {
|
||||||
|
pathname: '/update-tags/table/sample_data.ecommerce_db.shopify.fact_sale',
|
||||||
|
search: 'field=columns&value=sale_id',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockRequestDescription = {
|
||||||
|
pathname:
|
||||||
|
'/request-description/table/sample_data.ecommerce_db.shopify.fact_sale',
|
||||||
|
search: 'field=columns&value=sale_id',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockUpdateDescription = {
|
||||||
|
pathname:
|
||||||
|
'/update-description/table/sample_data.ecommerce_db.shopify.fact_sale',
|
||||||
|
search: 'field=columns&value=sale_id',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockProps: EntityTasksProps = {
|
||||||
|
data: {
|
||||||
|
fqn: 'sample_data.ecommerce_db.shopify.fact_session',
|
||||||
|
field: 'this is test',
|
||||||
|
},
|
||||||
|
tagSource: TagSource.Classification,
|
||||||
|
entityFqn: '',
|
||||||
|
entityType: EntityType.TABLE,
|
||||||
|
entityTaskType: EntityField.TAGS,
|
||||||
|
entityFieldThreads: [],
|
||||||
|
onThreadLinkSelect: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
jest.mock('../../../utils/TasksUtils', () => ({
|
||||||
|
getEntityTaskDetails: jest.fn().mockReturnValue({
|
||||||
|
fqnPart: FqnPart.NestedColumn,
|
||||||
|
entityField: EntityField.COLUMNS,
|
||||||
|
}),
|
||||||
|
getRequestDescriptionPath: jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(() => mockRequestDescription),
|
||||||
|
getRequestTagsPath: jest.fn().mockImplementation(() => mockRequestTags),
|
||||||
|
getUpdateDescriptionPath: jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(() => mockUpdateDescription),
|
||||||
|
getUpdateTagsPath: jest.fn().mockImplementation(() => mockUpdateTags),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('../../../utils/FeedElementUtils', () => ({
|
||||||
|
getFieldThreadElement: jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(() => (
|
||||||
|
<p data-testid="list-conversation">List Conversation</p>
|
||||||
|
)),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('../../../utils/CommonUtils', () => ({
|
||||||
|
getPartialNameFromTableFQN: jest.fn().mockReturnValue('test'),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const mockHistory = {
|
||||||
|
push: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
jest.mock('react-router-dom', () => ({
|
||||||
|
useHistory: jest.fn().mockImplementation(() => mockHistory),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('Entity Task component', () => {
|
||||||
|
it('Should render the component', async () => {
|
||||||
|
render(<EntityTasks {...mockProps} />);
|
||||||
|
|
||||||
|
const container = await screen.findByTestId('entity-task');
|
||||||
|
|
||||||
|
expect(container).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Task Element should be visible when tagSource is not glossary', async () => {
|
||||||
|
render(<EntityTasks {...mockProps} />);
|
||||||
|
|
||||||
|
const container = await screen.findByTestId('entity-task');
|
||||||
|
|
||||||
|
expect(container).toBeInTheDocument();
|
||||||
|
|
||||||
|
const taskElement = screen.queryByTestId('task-element');
|
||||||
|
|
||||||
|
expect(taskElement).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Task Element should not visible when tagSource is glossary', async () => {
|
||||||
|
render(<EntityTasks {...mockProps} tagSource={TagSource.Glossary} />);
|
||||||
|
|
||||||
|
const container = await screen.findByTestId('entity-task');
|
||||||
|
|
||||||
|
expect(container).toBeInTheDocument();
|
||||||
|
|
||||||
|
const taskElement = screen.queryByTestId('task-element');
|
||||||
|
|
||||||
|
expect(taskElement).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('List conversation should be there in component', async () => {
|
||||||
|
render(<EntityTasks {...mockProps} tagSource={TagSource.Glossary} />);
|
||||||
|
|
||||||
|
const container = await screen.findByTestId('entity-task');
|
||||||
|
|
||||||
|
expect(container).toBeInTheDocument();
|
||||||
|
|
||||||
|
const conversation = await screen.findByTestId('list-conversation');
|
||||||
|
|
||||||
|
expect(conversation).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Handle update tags click', async () => {
|
||||||
|
render(<EntityTasks {...mockProps} />);
|
||||||
|
|
||||||
|
const container = await screen.findByTestId('entity-task');
|
||||||
|
|
||||||
|
expect(container).toBeInTheDocument();
|
||||||
|
|
||||||
|
const taskElement = await screen.findByTestId('task-element');
|
||||||
|
|
||||||
|
expect(taskElement).toBeInTheDocument();
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
fireEvent.click(taskElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockHistory.push).toHaveBeenCalledWith(mockUpdateTags);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Handle request tags click', async () => {
|
||||||
|
render(
|
||||||
|
<EntityTasks
|
||||||
|
{...mockProps}
|
||||||
|
data={{
|
||||||
|
fqn: 'sample_data.ecommerce_db.shopify.fact_session',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
const container = await screen.findByTestId('entity-task');
|
||||||
|
|
||||||
|
expect(container).toBeInTheDocument();
|
||||||
|
|
||||||
|
const taskElement = await screen.findByTestId('task-element');
|
||||||
|
|
||||||
|
expect(taskElement).toBeInTheDocument();
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
fireEvent.click(taskElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockHistory.push).toHaveBeenCalledWith(mockRequestTags);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Handle update description click', async () => {
|
||||||
|
render(
|
||||||
|
<EntityTasks {...mockProps} entityTaskType={EntityField.DESCRIPTION} />
|
||||||
|
);
|
||||||
|
|
||||||
|
const container = await screen.findByTestId('entity-task');
|
||||||
|
|
||||||
|
expect(container).toBeInTheDocument();
|
||||||
|
|
||||||
|
const taskElement = await screen.findByTestId('task-element');
|
||||||
|
|
||||||
|
expect(taskElement).toBeInTheDocument();
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
fireEvent.click(taskElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockHistory.push).toHaveBeenCalledWith(mockUpdateDescription);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Handle request description click', async () => {
|
||||||
|
render(
|
||||||
|
<EntityTasks
|
||||||
|
{...mockProps}
|
||||||
|
data={{
|
||||||
|
fqn: 'sample_data.ecommerce_db.shopify.fact_session',
|
||||||
|
}}
|
||||||
|
entityTaskType={EntityField.DESCRIPTION}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
const container = await screen.findByTestId('entity-task');
|
||||||
|
|
||||||
|
expect(container).toBeInTheDocument();
|
||||||
|
|
||||||
|
const taskElement = await screen.findByTestId('task-element');
|
||||||
|
|
||||||
|
expect(taskElement).toBeInTheDocument();
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
fireEvent.click(taskElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockHistory.push).toHaveBeenCalledWith(mockRequestDescription);
|
||||||
|
});
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user