mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-11-01 19:18:05 +00:00
chore: feed and task improvements (#12567)
* chore: feed and task improvements * fix: unit test * fix: flaky test
This commit is contained in:
parent
91b8df6261
commit
31296f066e
@ -52,6 +52,7 @@ describe('Task flow should work', () => {
|
||||
verifyResponseStatusCode('@suggestApi', 200);
|
||||
|
||||
cy.get(`[data-testid="assignee-option-${secondAssignee}"]`)
|
||||
.should('be.visible')
|
||||
.trigger('mouseover')
|
||||
.trigger('click');
|
||||
|
||||
@ -94,6 +95,7 @@ describe('Task flow should work', () => {
|
||||
verifyResponseStatusCode('@suggestApi', 200);
|
||||
|
||||
cy.get(`[data-testid="assignee-option-${assignee}"]`)
|
||||
.should('be.visible')
|
||||
.trigger('mouseover')
|
||||
.trigger('click');
|
||||
|
||||
@ -136,6 +138,7 @@ describe('Task flow should work', () => {
|
||||
verifyResponseStatusCode('@suggestApi', 200);
|
||||
|
||||
cy.get(`[data-testid="assignee-option-${assignee}"]`)
|
||||
.should('be.visible')
|
||||
.trigger('mouseover')
|
||||
.trigger('click');
|
||||
|
||||
|
||||
@ -18,7 +18,6 @@ import { ThreadType } from 'generated/api/feed/createThread';
|
||||
import React, { FC } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Thread } from '../../../generated/entity/feed/thread';
|
||||
import { getEntityField, getEntityFQN } from '../../../utils/FeedUtils';
|
||||
import ActivityFeedEditor from '../ActivityFeedEditor/ActivityFeedEditor';
|
||||
import FeedPanelBodyV1 from '../ActivityFeedPanel/FeedPanelBodyV1';
|
||||
import FeedPanelHeader from '../ActivityFeedPanel/FeedPanelHeader';
|
||||
@ -41,10 +40,6 @@ const ActivityFeedDrawer: FC<ActivityFeedDrawerProps> = ({
|
||||
postFeed,
|
||||
selectedThread,
|
||||
} = useActivityFeedProvider();
|
||||
const entityField = selectedThread
|
||||
? getEntityField(selectedThread.about)
|
||||
: '';
|
||||
const entityFQN = selectedThread ? getEntityFQN(selectedThread.about) : '';
|
||||
|
||||
const onSave = (message: string) => {
|
||||
postFeed(message, selectedThread?.id ?? '').catch(() => {
|
||||
@ -64,8 +59,7 @@ const ActivityFeedDrawer: FC<ActivityFeedDrawerProps> = ({
|
||||
) : (
|
||||
<FeedPanelHeader
|
||||
className="p-x-md"
|
||||
entityFQN={entityFQN}
|
||||
entityField={entityField as string}
|
||||
entityLink={selectedThread?.about ?? ''}
|
||||
threadType={selectedThread?.type ?? ThreadType.Conversation}
|
||||
onCancel={hideDrawer}
|
||||
/>
|
||||
|
||||
@ -33,8 +33,7 @@ export interface ActivityFeedPanelProp extends HTMLAttributes<HTMLDivElement> {
|
||||
export interface FeedPanelHeaderProp
|
||||
extends HTMLAttributes<HTMLHeadingElement>,
|
||||
Pick<ActivityFeedPanelProp, 'onCancel'> {
|
||||
entityField: string;
|
||||
entityFQN?: string;
|
||||
entityLink: string;
|
||||
noun?: string;
|
||||
threadType?: ThreadType;
|
||||
onShowNewConversation?: (v: boolean) => void;
|
||||
|
||||
@ -19,9 +19,10 @@ import FeedPanelHeader from './FeedPanelHeader';
|
||||
|
||||
const mockFeedPanelHeaderProp = {
|
||||
onCancel: jest.fn(),
|
||||
entityField: 'description',
|
||||
noun: 'Conversations',
|
||||
onShowNewConversation: jest.fn(),
|
||||
entityLink:
|
||||
'<#E::table::sample_data.ecommerce_db.shopify.dim_address::description>',
|
||||
};
|
||||
|
||||
describe('Test FeedPanelHeader Component', () => {
|
||||
@ -85,8 +86,7 @@ describe('Test FeedPanelHeader Component', () => {
|
||||
const { container } = render(
|
||||
<FeedPanelHeader
|
||||
{...mockFeedPanelHeaderProp}
|
||||
entityFQN="x.y.z"
|
||||
entityField=""
|
||||
entityLink="<#E::testCase::sample_data.ecommerce_db.shopify.dim_address.address_id.unique_column_test>"
|
||||
/>,
|
||||
{
|
||||
wrapper: MemoryRouter,
|
||||
@ -95,15 +95,15 @@ describe('Test FeedPanelHeader Component', () => {
|
||||
|
||||
const entityAttribute = await findByTestId(container, 'entity-attribute');
|
||||
|
||||
expect(entityAttribute).toHaveTextContent(/x.y.z/i);
|
||||
expect(entityAttribute).toHaveTextContent(
|
||||
'ecommerce_db.shopify.dim_address'
|
||||
);
|
||||
});
|
||||
|
||||
it('Should render noun according to the threadtype', async () => {
|
||||
it('Should render noun according to the thread type', async () => {
|
||||
const { container } = render(
|
||||
<FeedPanelHeader
|
||||
{...mockFeedPanelHeaderProp}
|
||||
entityFQN="x.y.z"
|
||||
entityField=""
|
||||
noun={undefined}
|
||||
threadType={ThreadType.Announcement}
|
||||
/>,
|
||||
|
||||
@ -15,23 +15,31 @@ import { PlusOutlined } from '@ant-design/icons';
|
||||
import { Button, Tooltip } from 'antd';
|
||||
import React, { FC } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { getEntityLink } from 'utils/TableUtils';
|
||||
import {
|
||||
entityDisplayName,
|
||||
getEntityField,
|
||||
getEntityFieldDisplay,
|
||||
getEntityFQN,
|
||||
getEntityType,
|
||||
getFeedPanelHeaderText,
|
||||
} from '../../../utils/FeedUtils';
|
||||
import { FeedPanelHeaderProp } from './ActivityFeedPanel.interface';
|
||||
|
||||
const FeedPanelHeader: FC<FeedPanelHeaderProp> = ({
|
||||
onCancel,
|
||||
entityField,
|
||||
className,
|
||||
entityLink,
|
||||
noun,
|
||||
onShowNewConversation,
|
||||
threadType,
|
||||
entityFQN = '',
|
||||
onCancel,
|
||||
hideCloseIcon = false,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const entityType = getEntityType(entityLink);
|
||||
const entityFQN = getEntityFQN(entityLink);
|
||||
const entityField = getEntityField(entityLink);
|
||||
|
||||
return (
|
||||
<header className={className}>
|
||||
@ -42,7 +50,16 @@ const FeedPanelHeader: FC<FeedPanelHeaderProp> = ({
|
||||
{t('label.on-lowercase')}{' '}
|
||||
</span>
|
||||
<span className="tw-heading" data-testid="entity-attribute">
|
||||
{entityField ? getEntityFieldDisplay(entityField) : entityFQN}
|
||||
{entityField ? (
|
||||
getEntityFieldDisplay(entityField)
|
||||
) : (
|
||||
<Link
|
||||
className="break-all"
|
||||
data-testid="entitylink"
|
||||
to={getEntityLink(entityType, entityFQN)}>
|
||||
<span>{entityDisplayName(entityType, entityFQN)}</span>
|
||||
</Link>
|
||||
)}
|
||||
</span>
|
||||
</p>
|
||||
<div className="d-flex">
|
||||
|
||||
@ -38,7 +38,6 @@ import { useHistory, useParams } from 'react-router-dom';
|
||||
import { getAllFeeds, getFeedCount } from 'rest/feedsAPI';
|
||||
import { getCountBadge, getEntityDetailLink } from 'utils/CommonUtils';
|
||||
import { ENTITY_LINK_SEPARATOR, getEntityFeedLink } from 'utils/EntityUtils';
|
||||
import { getEntityField } from 'utils/FeedUtils';
|
||||
import '../../Widgets/FeedsWidget/feeds-widget.less';
|
||||
import ActivityFeedEditor from '../ActivityFeedEditor/ActivityFeedEditor';
|
||||
import ActivityFeedListV1 from '../ActivityFeedList/ActivityFeedListV1.component';
|
||||
@ -241,10 +240,6 @@ export const ActivityFeedTab = ({
|
||||
});
|
||||
};
|
||||
|
||||
const entityField = selectedThread
|
||||
? getEntityField(selectedThread.about)
|
||||
: '';
|
||||
|
||||
const threads = useMemo(() => {
|
||||
if (activeTab === ActivityFeedTabs.TASKS) {
|
||||
return entityThread.filter(
|
||||
@ -407,8 +402,7 @@ export const ActivityFeedTab = ({
|
||||
<FeedPanelHeader
|
||||
hideCloseIcon
|
||||
className="p-x-md"
|
||||
entityFQN={fqn}
|
||||
entityField={entityField as string}
|
||||
entityLink={selectedThread.about}
|
||||
threadType={selectedThread?.type ?? ThreadType.Conversation}
|
||||
onCancel={noop}
|
||||
/>
|
||||
|
||||
@ -31,7 +31,6 @@ import {
|
||||
} from '../../../generated/entity/feed/thread';
|
||||
import { Paging } from '../../../generated/type/paging';
|
||||
import { useElementInView } from '../../../hooks/useElementInView';
|
||||
import { getEntityField } from '../../../utils/FeedUtils';
|
||||
import { showErrorToast } from '../../../utils/ToastUtils';
|
||||
import ErrorPlaceHolder from '../../common/error-with-placeholder/ErrorPlaceHolder';
|
||||
import Loader from '../../Loader/Loader';
|
||||
@ -139,8 +138,6 @@ const ActivityThreadPanelBody: FC<ActivityThreadPanelBodyProp> = ({
|
||||
setConfirmationState(data);
|
||||
};
|
||||
|
||||
const entityField = getEntityField(threadLink);
|
||||
|
||||
const onShowNewConversation = (value: boolean) => {
|
||||
setShowNewConversation(value);
|
||||
};
|
||||
@ -239,7 +236,7 @@ const ActivityThreadPanelBody: FC<ActivityThreadPanelBodyProp> = ({
|
||||
{showHeader && isConversationType && (
|
||||
<FeedPanelHeader
|
||||
className="tw-px-4 tw-shadow-sm"
|
||||
entityField={entityField as string}
|
||||
entityLink={selectedThread?.about ?? ''}
|
||||
noun={
|
||||
isConversationType
|
||||
? t('label.conversation-plural')
|
||||
|
||||
@ -211,9 +211,8 @@ export const TaskTab = ({
|
||||
*
|
||||
* @returns True if has access otherwise false
|
||||
*/
|
||||
const hasEditAccess = () => isAdminUser || isAssignee || isOwner;
|
||||
|
||||
const hasTaskUpdateAccess = () => hasEditAccess() || isPartOfAssigneeTeam;
|
||||
const hasEditAccess =
|
||||
isAdminUser || isAssignee || isOwner || Boolean(isPartOfAssigneeTeam);
|
||||
|
||||
const onSave = (message: string) => {
|
||||
postFeed(message, taskThread?.id ?? '').catch(() => {
|
||||
@ -266,10 +265,10 @@ export const TaskTab = ({
|
||||
className="m-t-sm items-end w-full"
|
||||
data-testid="task-cta-buttons"
|
||||
size="small">
|
||||
{(isCreator || hasTaskUpdateAccess()) && (
|
||||
{(isCreator || hasEditAccess) && (
|
||||
<Button onClick={onTaskReject}>{t('label.close')}</Button>
|
||||
)}
|
||||
{hasTaskUpdateAccess() ? (
|
||||
{hasEditAccess ? (
|
||||
<>
|
||||
{['RequestDescription', 'RequestTag'].includes(
|
||||
taskDetails?.type ?? ''
|
||||
@ -428,7 +427,7 @@ export const TaskTab = ({
|
||||
profileWidth="24"
|
||||
showUserName={false}
|
||||
/>
|
||||
{(isCreator || hasTaskUpdateAccess()) && !isTaskClosed ? (
|
||||
{(isCreator || hasEditAccess) && !isTaskClosed ? (
|
||||
<Button
|
||||
className="flex-center p-0"
|
||||
data-testid="edit-assignees"
|
||||
@ -457,7 +456,7 @@ export const TaskTab = ({
|
||||
<Col span={24}>
|
||||
{isTaskDescription && (
|
||||
<DescriptionTask
|
||||
hasEditAccess={hasEditAccess()}
|
||||
hasEditAccess={hasEditAccess}
|
||||
isTaskActionEdit={false}
|
||||
taskThread={taskThread}
|
||||
onChange={(value) => form.setFieldValue('description', value)}
|
||||
@ -466,7 +465,7 @@ export const TaskTab = ({
|
||||
|
||||
{isTaskTags && (
|
||||
<TagsTask
|
||||
hasEditAccess={hasEditAccess()}
|
||||
hasEditAccess={hasEditAccess}
|
||||
isTaskActionEdit={false}
|
||||
task={taskDetails}
|
||||
onChange={(value) => form.setFieldValue('updatedTags', value)}
|
||||
@ -522,7 +521,7 @@ export const TaskTab = ({
|
||||
trigger="onChange">
|
||||
<TagsTask
|
||||
isTaskActionEdit
|
||||
hasEditAccess={hasEditAccess()}
|
||||
hasEditAccess={hasEditAccess}
|
||||
task={taskDetails}
|
||||
onChange={(value) => form.setFieldValue('updatedTags', value)}
|
||||
/>
|
||||
@ -543,7 +542,7 @@ export const TaskTab = ({
|
||||
trigger="onTextChange">
|
||||
<DescriptionTask
|
||||
isTaskActionEdit
|
||||
hasEditAccess={hasEditAccess()}
|
||||
hasEditAccess={hasEditAccess}
|
||||
taskThread={taskThread}
|
||||
onChange={(value) => form.setFieldValue('description', value)}
|
||||
/>
|
||||
|
||||
@ -483,7 +483,7 @@ export const prepareFeedLink = (entityType: string, entityFQN: string) => {
|
||||
|
||||
export const entityDisplayName = (entityType: string, entityFQN: string) => {
|
||||
let displayName;
|
||||
if (entityType === EntityType.TABLE) {
|
||||
if (entityType === EntityType.TABLE || entityType === EntityType.TEST_CASE) {
|
||||
displayName = getPartialNameFromTableFQN(
|
||||
entityFQN,
|
||||
[FqnPart.Database, FqnPart.Schema, FqnPart.Table],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user