Minor: address feedback for incident manager feature (#14955)

This commit is contained in:
Shailesh Parmar 2024-01-30 23:25:50 +05:30 committed by GitHub
parent 686dbed964
commit 728a71ee5d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 74 additions and 55 deletions

View File

@ -269,7 +269,10 @@ describe('Incident Manager', () => {
verifyResponseStatusCode('@getTestCase', 200);
cy.get('[data-testid="incident"]').click();
verifyResponseStatusCode('@getTaskFeed', 200);
cy.get('[data-testid="reject-task"]').scrollIntoView().click();
cy.get('[data-testid="task-cta-buttons"]')
.contains('Reassign')
.scrollIntoView()
.click();
interceptURL(
'GET',
'/api/v1/search/suggest?q=admin&index=*user_search_index*',
@ -286,12 +289,12 @@ describe('Incident Manager', () => {
cy.get('.ant-modal-footer').contains('Submit').click();
verifyResponseStatusCode('@updateTestCaseIncidentStatus', 200);
// Todo: skipping this for now as its not working from backend
// cy.clickOnLogo();
// cy.get('[id*="tab-tasks"]').click();
// cy.get('[data-testid="task-feed-card"]')
// .contains(NEW_TABLE_TEST_CASE.name)
// .scrollIntoView()
// .should('be.visible');
cy.clickOnLogo();
cy.get('[id*="tab-tasks"]').click();
cy.get('[data-testid="task-feed-card"]')
.contains(testCaseName)
.scrollIntoView()
.should('be.visible');
});
it('Resolve incident', () => {
@ -306,7 +309,10 @@ describe('Incident Manager', () => {
verifyResponseStatusCode('@getTestCase', 200);
cy.get('[data-testid="incident"]').click();
verifyResponseStatusCode('@getTaskFeed', 200);
cy.get('[data-testid="approve-task"]').scrollIntoView().click();
cy.get('[data-testid="task-cta-buttons"] [role="img"]')
.scrollIntoView()
.click();
cy.get('[role="menu"').find('[data-menu-id*="resolve"]').click();
cy.get('#testCaseFailureReason').click();
cy.get('[title="Missing Data"]').click();
cy.get('.toastui-editor-md-container > .toastui-editor > .ProseMirror')

View File

@ -89,11 +89,11 @@ jest.mock('../../../utils/FeedUtils', () => ({
}));
jest.mock('../../../utils/TasksUtils', () => ({
...jest.requireActual('../../../utils/TasksUtils'),
fetchOptions: jest.fn().mockReturnValue('getEntityLink'),
getTaskDetailPath: jest.fn().mockReturnValue('/'),
isDescriptionTask: jest.fn().mockReturnValue(false),
isTagsTask: jest.fn().mockReturnValue(true),
TASK_ACTION_LIST: jest.fn().mockReturnValue([]),
generateOptions: jest.fn().mockReturnValue([]),
}));

View File

@ -83,6 +83,7 @@ import {
fetchOptions,
generateOptions,
getTaskDetailPath,
INCIDENT_TASK_ACTION_LIST,
isDescriptionTask,
isTagsTask,
TASK_ACTION_LIST,
@ -133,7 +134,11 @@ export const TaskTab = ({
testCaseResolutionStatus,
initialAssignees: usersList,
} = useActivityFeedProvider();
const [taskAction, setTaskAction] = useState<TaskAction>(TASK_ACTION_LIST[0]);
const isTaskTestCaseResult =
taskDetails?.type === TaskType.RequestTestCaseFailureResolution;
const [taskAction, setTaskAction] = useState<TaskAction>(
isTaskTestCaseResult ? INCIDENT_TASK_ACTION_LIST[0] : TASK_ACTION_LIST[0]
);
const isTaskClosed = isEqual(taskDetails?.status, ThreadTaskStatus.Closed);
const [showEditTaskModel, setShowEditTaskModel] = useState(false);
const [comment, setComment] = useState('');
@ -185,8 +190,6 @@ export const TaskTab = ({
const isTaskDescription = isDescriptionTask(taskDetails?.type as TaskType);
const isTaskTags = isTagsTask(taskDetails?.type as TaskType);
const isTaskTestCaseResult =
taskDetails?.type === TaskType.RequestTestCaseFailureResolution;
const isTaskGlossaryApproval = taskDetails?.type === TaskType.RequestApproval;
@ -408,6 +411,31 @@ export const TaskTab = ({
}
};
const handleTaskMenuClick = (info: MenuInfo) => {
setTaskAction(
INCIDENT_TASK_ACTION_LIST.find((action) => action.key === info.key) ??
INCIDENT_TASK_ACTION_LIST[0]
);
switch (info.key) {
case TaskActionMode.RE_ASSIGN:
setIsEditAssignee(true);
break;
case TaskActionMode.RESOLVE:
setShowEditTaskModel(true);
break;
}
};
const onTaskDropdownClick = () => {
if (taskAction.key === TaskActionMode.RESOLVE) {
setShowEditTaskModel(true);
} else {
handleTaskMenuClick({ key: taskAction.key } as MenuInfo);
}
};
const approvalWorkflowActions = useMemo(() => {
const hasApprovalAccess =
isAssignee || (Boolean(isPartOfAssigneeTeam) && !isCreator);
@ -458,33 +486,23 @@ export const TaskTab = ({
const hasApprovalAccess = isAssignee || isCreator || editPermission;
return (
<Space
className="m-t-sm items-end w-full"
<Dropdown.Button
className="m-t-sm"
data-testid="task-cta-buttons"
size="small">
<Tooltip
title={!hasApprovalAccess && t('message.no-access-placeholder')}>
<Button
data-testid="reject-task"
disabled={!hasApprovalAccess}
onClick={() => setIsEditAssignee(true)}>
{t('label.re-assign')}
</Button>
</Tooltip>
<Tooltip
title={!hasApprovalAccess && t('message.no-access-placeholder')}>
<Button
data-testid="approve-task"
disabled={!hasApprovalAccess}
type="primary"
onClick={() => setShowEditTaskModel(true)}>
{t('label.resolve')}
</Button>
</Tooltip>
</Space>
icon={<DownOutlined />}
menu={{
items: INCIDENT_TASK_ACTION_LIST,
selectable: true,
selectedKeys: [taskAction.key],
onClick: handleTaskMenuClick,
disabled: !hasApprovalAccess,
}}
type="primary"
onClick={onTaskDropdownClick}>
{taskAction.label}
</Dropdown.Button>
);
}, [taskDetails, isAssignee, isPartOfAssigneeTeam]);
}, [taskDetails, isAssignee, isPartOfAssigneeTeam, taskAction]);
const actionButtons = useMemo(() => {
if (isTaskClosed) {

View File

@ -22,7 +22,6 @@ import {
useState,
} from 'react';
import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom';
import {
Area,
AreaChart,
@ -35,7 +34,6 @@ import {
import { ReactComponent as TotalDataAssetsEmptyIcon } from '../../assets/svg/data-insight-no-data-placeholder.svg';
import { CHART_WIDGET_DAYS_DURATION } from '../../constants/constants';
import { TOTAL_ENTITY_CHART_COLOR } from '../../constants/DataInsight.constants';
import { DATA_INSIGHT_GUIDE_DOCS } from '../../constants/docs.constants';
import { SIZE } from '../../enums/common.enum';
import { WidgetWidths } from '../../enums/CustomizablePage.enum';
import { DataReportIndex } from '../../generated/dataInsight/dataInsightChart';
@ -45,7 +43,6 @@ import {
} from '../../generated/dataInsight/dataInsightChartResult';
import { getAggregateChartData } from '../../rest/DataInsightAPI';
import { axisTickFormatter } from '../../utils/ChartUtils';
import { Transi18next } from '../../utils/CommonUtils';
import { getGraphDataByEntityType } from '../../utils/DataInsightUtils';
import {
getCurrentMillis,
@ -151,21 +148,6 @@ const TotalDataAssetsWidget = ({
width={SIZE.X_SMALL}
/>
}
message={
<Transi18next
i18nKey="message.no-total-data-assets"
renderElement={
<Link
rel="noreferrer"
target="_blank"
to={{ pathname: DATA_INSIGHT_GUIDE_DOCS }}
/>
}
values={{
setup: t('message.setup-data-insights'),
}}
/>
}
/>
</Col>
</Row>

View File

@ -59,6 +59,8 @@ export interface TaskAction {
export enum TaskActionMode {
VIEW = 'view',
EDIT = 'edit',
RE_ASSIGN = 're-assign',
RESOLVE = 'resolve',
}
export enum TaskTabs {

View File

@ -567,6 +567,17 @@ export const TASK_ACTION_LIST: TaskAction[] = [
},
];
export const INCIDENT_TASK_ACTION_LIST: TaskAction[] = [
{
label: i18Next.t('label.re-assign'),
key: TaskActionMode.RE_ASSIGN,
},
{
label: i18Next.t('label.resolve'),
key: TaskActionMode.RESOLVE,
},
];
export const isDescriptionTask = (taskType: TaskType) =>
[TaskType.RequestDescription, TaskType.UpdateDescription].includes(taskType);