diff --git a/openmetadata-ui/src/main/resources/ui/cypress/common/TaskUtils.ts b/openmetadata-ui/src/main/resources/ui/cypress/common/TaskUtils.ts
index 5b0afda91d7..4d49e0af723 100644
--- a/openmetadata-ui/src/main/resources/ui/cypress/common/TaskUtils.ts
+++ b/openmetadata-ui/src/main/resources/ui/cypress/common/TaskUtils.ts
@@ -19,7 +19,9 @@ import {
const owner = 'admin';
const assignee = 'adam.matthews2';
+const assigneeDisplayName = 'Adam Matthews';
const secondAssignee = 'aaron_johnson0';
+const secondAssigneeDisplayName = 'Aaron Johnson';
export type TaskDetails = {
assignee?: string;
@@ -44,9 +46,14 @@ export const verifyTaskDetails = (
expect(matches).to.not.be.null;
});
+ // creator of the task
cy.get('[data-testid="owner-link"]').should('contain', owner);
- cy.get(`[data-testid="${taskAssignee ?? assignee}"]`).should('be.visible');
+ // assignee of the task
+ cy.get('[data-testid="task-assignees"] [data-testid="owner-link"]').should(
+ 'contain',
+ taskAssignee ?? assigneeDisplayName
+ );
};
export const editAssignee = () => {
@@ -71,7 +78,14 @@ export const editAssignee = () => {
verifyResponseStatusCode('@editAssignee', 200);
- cy.get(`[data-testid="${assignee}"]`).should('be.visible');
+ cy.get('[data-testid="task-assignees"] [data-testid="owner-link"]').should(
+ 'contain',
+ assigneeDisplayName
+ );
+ cy.get('[data-testid="task-assignees"] [data-testid="owner-link"]').should(
+ 'contain',
+ secondAssigneeDisplayName
+ );
};
export const createDescriptionTask = (
diff --git a/openmetadata-ui/src/main/resources/ui/cypress/e2e/Flow/Task.spec.ts b/openmetadata-ui/src/main/resources/ui/cypress/e2e/Flow/Task.spec.ts
index 11e200e9386..da8b6f5655e 100644
--- a/openmetadata-ui/src/main/resources/ui/cypress/e2e/Flow/Task.spec.ts
+++ b/openmetadata-ui/src/main/resources/ui/cypress/e2e/Flow/Task.spec.ts
@@ -369,9 +369,10 @@ describe('Task flow should work', { tags: 'DataAssets' }, () => {
verifyResponseStatusCode('@taskFeed', 200);
// verify the task details
- verifyTaskDetails(/#(\d+) Request to update description for/, USER_NAME);
-
- cy.get(`[data-testid="${USER_NAME}"]`).should('be.visible');
+ verifyTaskDetails(
+ /#(\d+) Request to update description for/,
+ USER_DETAILS.firstName
+ );
// Accept the description suggestion which is created
cy.get('.ant-btn-compact-first-item').contains('Accept Suggestion').click();
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider.tsx b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider.tsx
index 81c5ae8a17d..bcf0667013e 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider.tsx
@@ -245,6 +245,21 @@ const ActivityFeedProvider = ({ children, user }: Props) => {
setEntityThread([...threads]);
}, []);
+ const updateEntityThread = useCallback(
+ (thread: Thread) => {
+ setEntityThread((prev) => {
+ return prev.map((threadItem) => {
+ if (threadItem.id === thread.id) {
+ return thread;
+ } else {
+ return threadItem;
+ }
+ });
+ });
+ },
+ [setEntityThread]
+ );
+
const deleteFeed = useCallback(
async (threadId: string, postId: string, isThread: boolean) => {
if (isThread) {
@@ -457,6 +472,7 @@ const ActivityFeedProvider = ({ children, user }: Props) => {
hideDrawer,
updateEditorFocus,
setActiveThread,
+ updateEntityThread,
entityPaging,
userId: user ?? currentUser?.id ?? '',
testCaseResolutionStatus,
@@ -481,6 +497,7 @@ const ActivityFeedProvider = ({ children, user }: Props) => {
hideDrawer,
updateEditorFocus,
setActiveThread,
+ updateEntityThread,
entityPaging,
user,
currentUser,
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProviderContext.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProviderContext.interface.ts
index 3e9ed8d57a3..ab0c7920584 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProviderContext.interface.ts
+++ b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityFeedProvider/ActivityFeedProviderContext.interface.ts
@@ -34,6 +34,7 @@ export interface ActivityFeedProviderContextType {
focusReplyEditor: boolean;
entityPaging: Paging;
setActiveThread: (thread?: Thread) => void;
+ updateEntityThread: (thread: Thread) => void;
userId: string;
deleteFeed: (
threadId: string,
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityThreadPanel/ActivityThread.mock.ts b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityThreadPanel/ActivityThread.mock.ts
index 73c3efb8efc..5423d7c0096 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityThreadPanel/ActivityThread.mock.ts
+++ b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityThreadPanel/ActivityThread.mock.ts
@@ -11,6 +11,11 @@
* limitations under the License.
*/
+import {
+ TaskType,
+ ThreadTaskStatus,
+} from '../../../generated/entity/feed/thread';
+
export const mockThreadData = [
{
id: '465b2dfb-300e-45f5-a1a6-e19c6225e9e7',
@@ -26,6 +31,32 @@ export const mockThreadData = [
postsCount: 0,
posts: [],
relativeDay: 'Today',
+ task: {
+ id: 153,
+ type: TaskType.RequestTag,
+ assignees: [
+ {
+ id: 'ef1b9e8a-75ba-4c12-9874-034c135be925',
+ type: 'team',
+ name: 'Sales',
+ fullyQualifiedName: 'Sales',
+ displayName: 'Sales',
+ deleted: false,
+ },
+ {
+ id: '83bd6004-9237-47a1-b917-ef006b3192d7',
+ type: 'user',
+ name: 'aaron_johnson0',
+ fullyQualifiedName: 'aaron_johnson0',
+ displayName: 'Aaron Johnson',
+ deleted: false,
+ },
+ ],
+ status: ThreadTaskStatus.Open,
+ oldValue: '[]',
+ suggestion:
+ '[{"tagFQN":"PII.None","source":"Classification","name":"None","description":"Non PII"}]',
+ },
},
{
id: '40c2faec-0159-4d86-9b15-c17f3e1c081b',
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityThreadPanel/ActivityThreadList.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityThreadPanel/ActivityThreadList.test.tsx
index bb277c31acd..cf9eaa434cf 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityThreadPanel/ActivityThreadList.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityThreadPanel/ActivityThreadList.test.tsx
@@ -11,7 +11,12 @@
* limitations under the License.
*/
-import { findByTestId, queryByTestId, render } from '@testing-library/react';
+import {
+ findByTestId,
+ getByText,
+ queryByTestId,
+ render,
+} from '@testing-library/react';
import React from 'react';
import { MemoryRouter } from 'react-router-dom';
import { mockThreadData } from './ActivityThread.mock';
@@ -50,6 +55,10 @@ jest.mock('../ActivityFeedCard/FeedCardFooter/FeedCardFooter', () => {
return jest.fn().mockReturnValue(
FeedCardFooter
);
});
+jest.mock('../../common/OwnerLabel/OwnerLabel.component', () => ({
+ OwnerLabel: jest.fn().mockReturnValue(OwnerLabel
),
+}));
+
describe('Test ActivityThreadList Component', () => {
it('Check if it has all child elements', async () => {
const { container } = render(
@@ -145,4 +154,16 @@ describe('Test ActivityThreadList Component', () => {
expect(thread2MainMessage).toBeInTheDocument();
expect(thread2QuickReplyEditor).toBeInTheDocument();
});
+
+ it('should render task assignee when there is task', async () => {
+ const { container } = render(
+ ,
+ {
+ wrapper: MemoryRouter,
+ }
+ );
+
+ expect(getByText(container, 'label.assignee-plural:')).toBeInTheDocument();
+ expect(getByText(container, 'OwnerLabel')).toBeInTheDocument();
+ });
});
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityThreadPanel/ActivityThreadList.tsx b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityThreadPanel/ActivityThreadList.tsx
index 34c2d9c02b3..d2229921f94 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityThreadPanel/ActivityThreadList.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/ActivityThreadPanel/ActivityThreadList.tsx
@@ -10,7 +10,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { Card, Space } from 'antd';
+import { Card, Typography } from 'antd';
import { isEqual } from 'lodash';
import React, { FC, Fragment } from 'react';
import { useTranslation } from 'react-i18next';
@@ -29,7 +29,7 @@ import {
} from '../../../generated/entity/feed/thread';
import { getFeedListWithRelativeDays } from '../../../utils/FeedUtils';
import { getTaskDetailPath } from '../../../utils/TasksUtils';
-import AssigneeList from '../../common/AssigneeList/AssigneeList';
+import { OwnerLabel } from '../../common/OwnerLabel/OwnerLabel.component';
import ActivityFeedCard from '../ActivityFeedCard/ActivityFeedCard';
import FeedCardFooter from '../ActivityFeedCard/FeedCardFooter/FeedCardFooter';
import ActivityFeedEditor from '../ActivityFeedEditor/ActivityFeedEditor';
@@ -166,14 +166,12 @@ const ActivityThreadList: FC = ({
) : null}
{thread.task && (
-
-
+
+
{t('label.assignee-plural')}:{' '}
-
-
-
+
+
+
)}
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/TaskFeedCard/TaskFeedCard.component.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/TaskFeedCard/TaskFeedCard.component.test.tsx
index 7ec199fcfb1..89982fa7d76 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/TaskFeedCard/TaskFeedCard.component.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/TaskFeedCard/TaskFeedCard.component.test.tsx
@@ -34,9 +34,9 @@ jest.mock('../ActivityFeedProvider/ActivityFeedProvider', () => ({
default: 'ActivityFeedProvider',
}));
-jest.mock('../../../components/common/AssigneeList/AssigneeList', () => {
- return jest.fn().mockImplementation(() => AssigneeList
);
-});
+jest.mock('../../common/OwnerLabel/OwnerLabel.component', () => ({
+ OwnerLabel: jest.fn().mockReturnValue(OwnerLabel
),
+}));
jest.mock('../../../components/common/PopOverCard/EntityPopOverCard', () => {
return jest.fn().mockImplementation(({ children }) => children);
@@ -102,4 +102,15 @@ describe('Test TaskFeedCard Component', () => {
expect(screen.getByTestId('task-status-icon-open')).toBeInTheDocument();
expect(screen.getByTestId('redirect-task-button-link')).toBeInTheDocument();
});
+
+ it('Should render OwnerLabel when show thread is true', async () => {
+ await act(async () => {
+ render(, {
+ wrapper: MemoryRouter,
+ });
+ });
+
+ expect(screen.getByText('label.assignee-plural:')).toBeInTheDocument();
+ expect(screen.getByText('OwnerLabel')).toBeInTheDocument();
+ });
});
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/TaskFeedCard/TaskFeedCard.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/TaskFeedCard/TaskFeedCard.component.tsx
index 0aae1946cef..9705471c75e 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/TaskFeedCard/TaskFeedCard.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/TaskFeedCard/TaskFeedCard.component.tsx
@@ -20,7 +20,6 @@ import { useHistory } from 'react-router-dom';
import { ReactComponent as TaskCloseIcon } from '../../../assets/svg/ic-close-task.svg';
import { ReactComponent as TaskOpenIcon } from '../../../assets/svg/ic-open-task.svg';
import { ReactComponent as ThreadIcon } from '../../../assets/svg/thread.svg';
-import AssigneeList from '../../../components/common/AssigneeList/AssigneeList';
import EntityPopOverCard from '../../../components/common/PopOverCard/EntityPopOverCard';
import UserPopOverCard from '../../../components/common/PopOverCard/UserPopOverCard';
import {
@@ -38,6 +37,7 @@ import { getEntityFQN, getEntityType } from '../../../utils/FeedUtils';
import { TASK_TYPES } from '../../../constants/Task.constant';
import { getTaskDetailPath } from '../../../utils/TasksUtils';
+import { OwnerLabel } from '../../common/OwnerLabel/OwnerLabel.component';
import ProfilePicture from '../../common/ProfilePicture/ProfilePicture';
import { useActivityFeedProvider } from '../ActivityFeedProvider/ActivityFeedProvider';
import ActivityFeedActions from '../Shared/ActivityFeedActions';
@@ -206,7 +206,7 @@ const TaskFeedCard = ({
{!showThread ? (
-
+
{postLength > 0 && (
<>
@@ -228,24 +228,23 @@ const TaskFeedCard = ({
className="d-flex items-center thread-count cursor-pointer m-l-xs"
onClick={!hidePopover ? showReplies : noop}>
{' '}
- {postLength}
+
+ {postLength}
+
>
)}
0
? 'm-l-sm text-sm text-grey-muted'
: 'text-sm text-grey-muted'
- }>
+ )}>
{`${t('label.assignee-plural')}: `}
-
+
) : null}
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Entity/Task/TaskTab/TaskTab.component.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Entity/Task/TaskTab/TaskTab.component.test.tsx
index 28f0d91464e..1c8269944f1 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/Entity/Task/TaskTab/TaskTab.component.test.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/Entity/Task/TaskTab/TaskTab.component.test.tsx
@@ -54,10 +54,6 @@ jest.mock('../../../ActivityFeed/ActivityFeedEditor/ActivityFeedEditor', () => {
));
});
-jest.mock('../../../common/AssigneeList/AssigneeList', () => {
- return jest.fn().mockImplementation(() =>
AssigneeList
);
-});
-
jest.mock('../../../common/OwnerLabel/OwnerLabel.component', () => ({
OwnerLabel: jest.fn().mockImplementation(() =>
OwnerLabel
),
}));
@@ -171,6 +167,16 @@ describe('Test TaskFeedCard component', () => {
expect(activityFeedCard).toBeInTheDocument();
});
+ it('Should render the assignee and creator of task', async () => {
+ render(
, {
+ wrapper: MemoryRouter,
+ });
+
+ expect(screen.getByText('label.assignee-plural:')).toBeInTheDocument();
+ expect(screen.getByText('label.created-by:')).toBeInTheDocument();
+ expect(screen.getAllByText('OwnerLabel')).toHaveLength(2);
+ });
+
it('should not render task action button to the task owner if task has reviewer', async () => {
render(
, {
wrapper: MemoryRouter,
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Entity/Task/TaskTab/TaskTab.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Entity/Task/TaskTab/TaskTab.component.tsx
index d0bc57da6fc..ec20f632ee9 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/Entity/Task/TaskTab/TaskTab.component.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/Entity/Task/TaskTab/TaskTab.component.tsx
@@ -103,7 +103,6 @@ import ActivityFeedEditor, {
EditorContentRef,
} from '../../../ActivityFeed/ActivityFeedEditor/ActivityFeedEditor';
import { useActivityFeedProvider } from '../../../ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
-import AssigneeList from '../../../common/AssigneeList/AssigneeList';
import InlineEdit from '../../../common/InlineEdit/InlineEdit.component';
import { OwnerLabel } from '../../../common/OwnerLabel/OwnerLabel.component';
import EntityPopOverCard from '../../../common/PopOverCard/EntityPopOverCard';
@@ -144,7 +143,7 @@ export const TaskTab = ({
const { isAdminUser } = useAuth();
const {
postFeed,
- setActiveThread,
+ updateEntityThread,
fetchUpdatedThread,
updateTestCaseIncidentStatus,
testCaseResolutionStatus,
@@ -233,7 +232,7 @@ export const TaskTab = ({
const [comment, setComment] = useState('');
const [isEditAssignee, setIsEditAssignee] = useState
(false);
const [options, setOptions] = useState