Fix #6635 UI : Announcement improvements (#6647)

* Fix #6635 UI : Announcement improvements

* Add unit test

* Fix unit test

* Fix announcement banner is not showing up!
This commit is contained in:
Sachin Chaurasiya 2022-08-09 11:29:04 +05:30 committed by GitHub
parent 77ad1b1c87
commit a9c010b03d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 82 additions and 14 deletions

View File

@ -172,13 +172,16 @@ export const updateTask: Function = (
};
export const getActiveAnnouncement = async (entityLink: string) => {
const response = await APIClient.get<Thread[]>('/feed', {
const response = await APIClient.get<{ data: Thread[]; paging: Paging }>(
'/feed',
{
params: {
entityLink,
type: ThreadType.Announcement,
activeAnnouncement: true,
},
});
}
);
return response.data;
};

View File

@ -12,6 +12,7 @@
*/
import { HTMLAttributes } from 'react';
import { ThreadType } from '../../../generated/api/feed/createThread';
import { Thread } from '../../../generated/entity/feed/thread';
import { ThreadUpdatedFunc } from '../../../interface/feed.interface';
import { ConfirmState } from '../ActivityFeedCard/ActivityFeedCard.interface';
@ -29,7 +30,9 @@ export interface FeedPanelHeaderProp
extends HTMLAttributes<HTMLHeadingElement>,
Pick<ActivityFeedPanelProp, 'onCancel'> {
entityField: string;
entityFQN?: string;
noun?: string;
threadType?: ThreadType;
onShowNewConversation?: (v: boolean) => void;
}
export interface FeedPanelOverlayProp

View File

@ -57,6 +57,7 @@ const mockFeedPanelProp = {
jest.mock('../../../utils/FeedUtils', () => ({
getEntityField: jest.fn(),
getEntityFQN: jest.fn(),
}));
jest.mock('../ActivityFeedEditor/ActivityFeedEditor', () => {

View File

@ -18,7 +18,7 @@ import { getFeedById } from '../../../axiosAPIs/feedsAPI';
import { confirmStateInitialValue } from '../../../constants/feed.constants';
import { Thread } from '../../../generated/entity/feed/thread';
import jsonData from '../../../jsons/en';
import { getEntityField } from '../../../utils/FeedUtils';
import { getEntityField, getEntityFQN } from '../../../utils/FeedUtils';
import { showErrorToast } from '../../../utils/ToastUtils';
import { ConfirmState } from '../ActivityFeedCard/ActivityFeedCard.interface';
import ActivityFeedEditor from '../ActivityFeedEditor/ActivityFeedEditor';
@ -40,6 +40,7 @@ const ActivityFeedPanel: FC<ActivityFeedPanelProp> = ({
const [threadData, setThreadData] = useState<Thread>(selectedThread);
const [isLoading, setIsLoading] = useState<boolean>(false);
const entityField = getEntityField(selectedThread.about);
const entityFQN = getEntityFQN(selectedThread.about);
const [confirmationState, setConfirmationState] = useState<ConfirmState>(
confirmStateInitialValue
@ -88,7 +89,9 @@ const ActivityFeedPanel: FC<ActivityFeedPanelProp> = ({
id="feed-panel">
<FeedPanelHeader
className="tw-px-4 tw-shadow-sm"
entityFQN={entityFQN}
entityField={entityField as string}
threadType={selectedThread.type}
onCancel={onCancel}
/>

View File

@ -14,6 +14,7 @@
import { findByTestId, queryByTestId, render } from '@testing-library/react';
import React from 'react';
import { MemoryRouter } from 'react-router-dom';
import { ThreadType } from '../../../generated/entity/feed/thread';
import FeedPanelHeader from './FeedPanelHeader';
const mockFeedPanelHeaderProp = {
@ -85,4 +86,40 @@ describe('Test FeedPanelHeader Component', () => {
// noun is undefined so default noun should be present in text content
expect(noun).toHaveTextContent('Conversation on');
});
it('Should render entityFQN if entityField is empty', async () => {
const { container } = render(
<FeedPanelHeader
{...mockFeedPanelHeaderProp}
entityFQN="x.y.z"
entityField=""
/>,
{
wrapper: MemoryRouter,
}
);
const entityAttribute = await findByTestId(container, 'entity-attribute');
expect(entityAttribute).toHaveTextContent(/x.y.z/i);
});
it('Should render noun according to the threadtype', async () => {
const { container } = render(
<FeedPanelHeader
{...mockFeedPanelHeaderProp}
entityFQN="x.y.z"
entityField=""
noun={undefined}
threadType={ThreadType.Announcement}
/>,
{
wrapper: MemoryRouter,
}
);
const noun = await findByTestId(container, 'header-noun');
expect(noun).toHaveTextContent(/Announcement on/i);
});
});

View File

@ -14,7 +14,10 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import classNames from 'classnames';
import React, { FC } from 'react';
import { getEntityFieldDisplay } from '../../../utils/FeedUtils';
import {
getEntityFieldDisplay,
getFeedPanelHeaderText,
} from '../../../utils/FeedUtils';
import { Button } from '../../buttons/Button/Button';
import PopOver from '../../common/popover/PopOver';
import { FeedPanelHeaderProp } from './ActivityFeedPanel.interface';
@ -24,16 +27,18 @@ const FeedPanelHeader: FC<FeedPanelHeaderProp> = ({
className,
noun,
onShowNewConversation,
threadType,
entityFQN = '',
}) => {
return (
<header className={className}>
<div className="tw-flex tw-justify-between tw-py-3">
<p data-testid="header-title">
<span data-testid="header-noun">
{noun ? noun : 'Conversation'} on{' '}
{noun ? noun : getFeedPanelHeaderText(threadType)} on{' '}
</span>
<span className="tw-heading">
{getEntityFieldDisplay(entityField)}
<span className="tw-heading" data-testid="entity-attribute">
{entityField ? getEntityFieldDisplay(entityField) : entityFQN}
</span>
</p>
<div className="tw-flex">

View File

@ -15,6 +15,7 @@ import { CloseOutlined } from '@ant-design/icons';
import { Button, Drawer, Space, Typography } from 'antd';
import { AxiosError } from 'axios';
import { Operation } from 'fast-json-patch';
import { uniqueId } from 'lodash';
import { observer } from 'mobx-react';
import React, { FC, useMemo, useState } from 'react';
import AppState from '../../../../AppState';
@ -123,6 +124,7 @@ const AnnouncementDrawer: FC<Props> = ({
className="tw-p-0"
createThread={createThread}
deletePostHandler={deletePostHandler}
key={uniqueId()}
postFeedHandler={postFeedHandler}
showHeader={false}
threadLink={getEntityFeedLink(entityType, entityFQN)}

View File

@ -377,8 +377,8 @@ const EntityPageInfo = ({
getEntityFeedLink(entityType, entityFqn)
);
if (!isEmpty(announcements)) {
setActiveAnnouncement(announcements[0]);
if (!isEmpty(announcements.data)) {
setActiveAnnouncement(announcements.data[0]);
}
} catch (error) {
showErrorToast(error as AxiosError);

View File

@ -506,3 +506,17 @@ export const entityDisplayName = (entityType: string, entityFQN: string) => {
export const MarkdownToHTMLConverter = new Showdown.Converter({
strikethrough: true,
});
export const getFeedPanelHeaderText = (
threadType: ThreadType = ThreadType.Conversation
) => {
switch (threadType) {
case ThreadType.Announcement:
return 'Announcement';
case ThreadType.Task:
return 'Task';
case ThreadType.Conversation:
default:
return 'Conversation';
}
};