mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-11-08 23:14:00 +00:00
MINOR: fix the knowledge, Glossary/Term page redirect notification link (#21341)
* fix the knowledge page redirect notification link * fix the feed redirection for glossary * use entityRef data for displayName if present (cherry picked from commit 8d4b7c78947678e151ff448a77f63bf2eb00a23d)
This commit is contained in:
parent
ca8610314d
commit
66dfc9d375
@ -21,7 +21,7 @@ import {
|
|||||||
formatDateTime,
|
formatDateTime,
|
||||||
getRelativeTime,
|
getRelativeTime,
|
||||||
} from '../../utils/date-time/DateTimeUtils';
|
} from '../../utils/date-time/DateTimeUtils';
|
||||||
import { getEntityLinkFromType } from '../../utils/EntityUtils';
|
import { getEntityLinkFromType, getEntityName } from '../../utils/EntityUtils';
|
||||||
import { entityDisplayName, prepareFeedLink } from '../../utils/FeedUtils';
|
import { entityDisplayName, prepareFeedLink } from '../../utils/FeedUtils';
|
||||||
import Fqn from '../../utils/Fqn';
|
import Fqn from '../../utils/Fqn';
|
||||||
import { getTaskDetailPath } from '../../utils/TasksUtils';
|
import { getTaskDetailPath } from '../../utils/TasksUtils';
|
||||||
@ -84,6 +84,12 @@ const NotificationFeedCard: FC<NotificationFeedProp> = ({
|
|||||||
);
|
);
|
||||||
}, [entityType, task, taskDetails]);
|
}, [entityType, task, taskDetails]);
|
||||||
|
|
||||||
|
const entityName = useMemo(() => {
|
||||||
|
return task?.entityRef
|
||||||
|
? getEntityName(task?.entityRef)
|
||||||
|
: entityDisplayName(entityType, entityFQN);
|
||||||
|
}, [task, entityType, entityFQN]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
className="no-underline"
|
className="no-underline"
|
||||||
@ -96,7 +102,10 @@ const NotificationFeedCard: FC<NotificationFeedProp> = ({
|
|||||||
avatar={<ProfilePicture name={createdBy} width="32" />}
|
avatar={<ProfilePicture name={createdBy} width="32" />}
|
||||||
className="m-0"
|
className="m-0"
|
||||||
description={
|
description={
|
||||||
<Space direction="vertical" size={0}>
|
<Space
|
||||||
|
data-testid={`notification-item-${entityName}`}
|
||||||
|
direction="vertical"
|
||||||
|
size={0}>
|
||||||
<Typography.Paragraph
|
<Typography.Paragraph
|
||||||
className="m-0"
|
className="m-0"
|
||||||
style={{ color: '#37352F', marginBottom: 0 }}>
|
style={{ color: '#37352F', marginBottom: 0 }}>
|
||||||
@ -107,8 +116,9 @@ const NotificationFeedCard: FC<NotificationFeedProp> = ({
|
|||||||
<span>{entityType} </span>
|
<span>{entityType} </span>
|
||||||
<Link
|
<Link
|
||||||
className="truncate"
|
className="truncate"
|
||||||
|
data-testid={`notification-link-${entityName}`}
|
||||||
to={prepareFeedLink(entityType, entityFQN)}>
|
to={prepareFeedLink(entityType, entityFQN)}>
|
||||||
{entityDisplayName(entityType, entityFQN)}
|
{entityName}
|
||||||
</Link>
|
</Link>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
import { act, render, screen } from '@testing-library/react';
|
import { act, render, screen } from '@testing-library/react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ThreadType } from '../../generated/api/feed/createThread';
|
import { ThreadType } from '../../generated/api/feed/createThread';
|
||||||
|
import { Thread } from '../../generated/entity/feed/thread';
|
||||||
import NotificationFeedCard from './NotificationFeedCard.component';
|
import NotificationFeedCard from './NotificationFeedCard.component';
|
||||||
|
|
||||||
jest.mock('../../utils/date-time/DateTimeUtils', () => ({
|
jest.mock('../../utils/date-time/DateTimeUtils', () => ({
|
||||||
@ -40,21 +41,63 @@ jest.mock('react-router-dom', () => ({
|
|||||||
}));
|
}));
|
||||||
jest.mock('../../utils/EntityUtils', () => ({
|
jest.mock('../../utils/EntityUtils', () => ({
|
||||||
getEntityLinkFromType: jest.fn().mockReturnValue('/mock-entity-link'),
|
getEntityLinkFromType: jest.fn().mockReturnValue('/mock-entity-link'),
|
||||||
|
getEntityName: jest
|
||||||
|
.fn()
|
||||||
|
.mockImplementation(({ displayName, name }) => displayName || name || ''),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../../utils/Fqn', () => ({
|
jest.mock('../../utils/Fqn', () => ({
|
||||||
split: jest.fn().mockReturnValue(['mockGlossary']),
|
split: jest.fn().mockReturnValue(['mockGlossary']),
|
||||||
}));
|
}));
|
||||||
const mockThread = {
|
const mockThread = {
|
||||||
about: 'test',
|
|
||||||
id: '33873393-bd68-46e9-bccc-7701c1c41ad6',
|
id: '33873393-bd68-46e9-bccc-7701c1c41ad6',
|
||||||
message: 'f93d08e9-2d38-4d01-a294-f8b44fbb0f4a',
|
type: 'Conversation',
|
||||||
|
href: 'http://host.docker.internal:8585/v1/feed/b41ef8d2-e369-4fce-b106-8f000258e361',
|
||||||
|
threadTs: 1755772414483,
|
||||||
|
about: '<#E::page::Article_sQDEeTK6::description>',
|
||||||
|
entityRef: {
|
||||||
|
id: 'eda48fe4-515f-44ee-8afc-f7e4ef01277a',
|
||||||
|
type: 'page',
|
||||||
|
name: 'Article_sQDEeTK6',
|
||||||
|
fullyQualifiedName: 'Article_sQDEeTK6',
|
||||||
|
description: '',
|
||||||
|
displayName: 'SACHIN',
|
||||||
|
},
|
||||||
|
generatedBy: 'user',
|
||||||
|
cardStyle: 'default',
|
||||||
|
fieldOperation: 'updated',
|
||||||
|
createdBy: 'admin',
|
||||||
|
updatedAt: 1755772414483,
|
||||||
|
updatedBy: 'admin',
|
||||||
|
resolved: false,
|
||||||
|
task: {
|
||||||
|
id: 16,
|
||||||
|
type: 'RequestTestCaseFailureResolution',
|
||||||
|
assignees: [
|
||||||
|
{
|
||||||
|
id: '9311f065-e150-4948-96a4-e98906443b37',
|
||||||
|
type: 'user',
|
||||||
|
name: 'admin',
|
||||||
|
fullyQualifiedName: 'admin',
|
||||||
|
displayName: 'admin',
|
||||||
|
deleted: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
status: 'Open',
|
||||||
|
testCaseResolutionStatusId: '29c0871d-bd96-431b-8823-e968316915af',
|
||||||
|
},
|
||||||
|
message:
|
||||||
|
'<#E::user::admin|[@admin](http://localhost:3000/users/admin)> Hii!',
|
||||||
|
postsCount: 0,
|
||||||
|
posts: [],
|
||||||
|
reactions: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const mockProps = {
|
const mockProps = {
|
||||||
createdBy: 'admin',
|
createdBy: 'admin',
|
||||||
entityType: 'task',
|
entityType: 'task',
|
||||||
entityFQN: 'test',
|
entityFQN: 'test',
|
||||||
task: mockThread,
|
task: mockThread as Thread,
|
||||||
feedType: ThreadType.Task,
|
feedType: ThreadType.Task,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -66,4 +109,76 @@ describe('Test NotificationFeedCard Component', () => {
|
|||||||
|
|
||||||
expect(await screen.findByText('ProfilePicture')).toBeInTheDocument();
|
expect(await screen.findByText('ProfilePicture')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('renders assigned task message and link for ThreadType.Task', async () => {
|
||||||
|
await act(async () => {
|
||||||
|
render(<NotificationFeedCard {...mockProps} />);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(
|
||||||
|
screen.getByText(/assigned-you-a-new-task-lowercase/i)
|
||||||
|
).toBeInTheDocument();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
screen.getByText(`#${mockThread.task.id} ${mockThread.task.type}`)
|
||||||
|
).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders mentioned message and entity link for ThreadType.Conversation', async () => {
|
||||||
|
const conversationProps = {
|
||||||
|
...mockProps,
|
||||||
|
feedType: ThreadType.Conversation,
|
||||||
|
};
|
||||||
|
await act(async () => {
|
||||||
|
render(<NotificationFeedCard {...conversationProps} />);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(
|
||||||
|
screen.getByText(/mentioned-you-on-the-lowercase/i)
|
||||||
|
).toBeInTheDocument();
|
||||||
|
|
||||||
|
expect(screen.getByText(conversationProps.entityType)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should renders entityRef data is available', async () => {
|
||||||
|
const conversationProps = {
|
||||||
|
...mockProps,
|
||||||
|
feedType: ThreadType.Conversation,
|
||||||
|
};
|
||||||
|
await act(async () => {
|
||||||
|
render(<NotificationFeedCard {...conversationProps} />);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(
|
||||||
|
screen.getByText(mockThread.entityRef.displayName)
|
||||||
|
).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should renders default entityName by entityDisplayName if entityRef not present', async () => {
|
||||||
|
const conversationProps = {
|
||||||
|
...mockProps,
|
||||||
|
task: {
|
||||||
|
...mockProps.task,
|
||||||
|
entityRef: undefined,
|
||||||
|
},
|
||||||
|
feedType: ThreadType.Conversation,
|
||||||
|
};
|
||||||
|
await act(async () => {
|
||||||
|
render(<NotificationFeedCard {...conversationProps} />);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(screen.getByText('database.schema.table')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders timestamp', async () => {
|
||||||
|
const timestampProps = {
|
||||||
|
...mockProps,
|
||||||
|
timestamp: 1692612000000, // Example: 2023-08-21T10:00:00Z in ms
|
||||||
|
};
|
||||||
|
await act(async () => {
|
||||||
|
render(<NotificationFeedCard {...timestampProps} />);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(screen.getByText('1692612000000')).toBeInTheDocument();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -501,9 +501,8 @@ export const updateThreadData = async (
|
|||||||
export const prepareFeedLink = (entityType: string, entityFQN: string) => {
|
export const prepareFeedLink = (entityType: string, entityFQN: string) => {
|
||||||
const withoutFeedEntities = [
|
const withoutFeedEntities = [
|
||||||
EntityType.WEBHOOK,
|
EntityType.WEBHOOK,
|
||||||
EntityType.GLOSSARY,
|
|
||||||
EntityType.GLOSSARY_TERM,
|
|
||||||
EntityType.TYPE,
|
EntityType.TYPE,
|
||||||
|
EntityType.KNOWLEDGE_PAGE,
|
||||||
];
|
];
|
||||||
|
|
||||||
const entityLink = entityUtilClassBase.getEntityLink(entityType, entityFQN);
|
const entityLink = entityUtilClassBase.getEntityLink(entityType, entityFQN);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user