chore: feed and task improvements (#12567)

* chore: feed and task improvements

* fix: unit test

* fix: flaky test
This commit is contained in:
Sachin Chaurasiya 2023-07-25 00:15:57 +05:30 committed by GitHub
parent 91b8df6261
commit 31296f066e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 45 additions and 42 deletions

View File

@ -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');

View File

@ -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}
/>

View File

@ -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;

View File

@ -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}
/>,

View File

@ -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">

View File

@ -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}
/>

View File

@ -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')

View File

@ -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)}
/>

View File

@ -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],