mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-19 04:41:02 +00:00
Minor: Address feedback of Incident manager (#14997)
* Minor: Address feedback of Incident manager * added provision to delete and update display name from test case detail page * address the feedback * added option to clear severity
This commit is contained in:
parent
5839efcbf1
commit
4b43fa2079
@ -269,10 +269,10 @@ describe('Incident Manager', () => {
|
|||||||
verifyResponseStatusCode('@getTestCase', 200);
|
verifyResponseStatusCode('@getTestCase', 200);
|
||||||
cy.get('[data-testid="incident"]').click();
|
cy.get('[data-testid="incident"]').click();
|
||||||
verifyResponseStatusCode('@getTaskFeed', 200);
|
verifyResponseStatusCode('@getTaskFeed', 200);
|
||||||
cy.get('[data-testid="task-cta-buttons"]')
|
cy.get('[data-testid="task-cta-buttons"] [role="img"]')
|
||||||
.contains('Reassign')
|
|
||||||
.scrollIntoView()
|
.scrollIntoView()
|
||||||
.click();
|
.click();
|
||||||
|
cy.get('[role="menu"').find('[data-menu-id*="re-assign"]').click();
|
||||||
interceptURL(
|
interceptURL(
|
||||||
'GET',
|
'GET',
|
||||||
'/api/v1/search/suggest?q=admin&index=*user_search_index*',
|
'/api/v1/search/suggest?q=admin&index=*user_search_index*',
|
||||||
@ -309,10 +309,10 @@ describe('Incident Manager', () => {
|
|||||||
verifyResponseStatusCode('@getTestCase', 200);
|
verifyResponseStatusCode('@getTestCase', 200);
|
||||||
cy.get('[data-testid="incident"]').click();
|
cy.get('[data-testid="incident"]').click();
|
||||||
verifyResponseStatusCode('@getTaskFeed', 200);
|
verifyResponseStatusCode('@getTaskFeed', 200);
|
||||||
cy.get('[data-testid="task-cta-buttons"] [role="img"]')
|
cy.get('[data-testid="task-cta-buttons"]')
|
||||||
|
.contains('Resolve')
|
||||||
.scrollIntoView()
|
.scrollIntoView()
|
||||||
.click();
|
.click();
|
||||||
cy.get('[role="menu"').find('[data-menu-id*="resolve"]').click();
|
|
||||||
cy.get('#testCaseFailureReason').click();
|
cy.get('#testCaseFailureReason').click();
|
||||||
cy.get('[title="Missing Data"]').click();
|
cy.get('[title="Missing Data"]').click();
|
||||||
cy.get('.toastui-editor-md-container > .toastui-editor > .ProseMirror')
|
cy.get('.toastui-editor-md-container > .toastui-editor > .ProseMirror')
|
||||||
|
@ -12,7 +12,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { PlusOutlined } from '@ant-design/icons';
|
import { PlusOutlined } from '@ant-design/icons';
|
||||||
import { Button, Form, Input, InputNumber, Select, Switch } from 'antd';
|
import {
|
||||||
|
Button,
|
||||||
|
Form,
|
||||||
|
FormItemProps,
|
||||||
|
Input,
|
||||||
|
InputNumber,
|
||||||
|
Select,
|
||||||
|
Switch,
|
||||||
|
} from 'antd';
|
||||||
import 'codemirror/addon/fold/foldgutter.css';
|
import 'codemirror/addon/fold/foldgutter.css';
|
||||||
import { isUndefined } from 'lodash';
|
import { isUndefined } from 'lodash';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
@ -32,6 +40,7 @@ const ParameterForm: React.FC<ParameterFormProps> = ({ definition, table }) => {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const prepareForm = (data: TestCaseParameterDefinition) => {
|
const prepareForm = (data: TestCaseParameterDefinition) => {
|
||||||
|
let internalFormItemProps: FormItemProps = {};
|
||||||
let Field = (
|
let Field = (
|
||||||
<Input
|
<Input
|
||||||
placeholder={`${t('message.enter-a-field', {
|
placeholder={`${t('message.enter-a-field', {
|
||||||
@ -122,6 +131,10 @@ const ParameterForm: React.FC<ParameterFormProps> = ({ definition, table }) => {
|
|||||||
break;
|
break;
|
||||||
case TestDataType.Boolean:
|
case TestDataType.Boolean:
|
||||||
Field = <Switch />;
|
Field = <Switch />;
|
||||||
|
internalFormItemProps = {
|
||||||
|
...internalFormItemProps,
|
||||||
|
valuePropName: 'checked',
|
||||||
|
};
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case TestDataType.Array:
|
case TestDataType.Array:
|
||||||
@ -204,7 +217,8 @@ const ParameterForm: React.FC<ParameterFormProps> = ({ definition, table }) => {
|
|||||||
})}`,
|
})}`,
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
tooltip={data.description}>
|
tooltip={data.description}
|
||||||
|
{...internalFormItemProps}>
|
||||||
{Field}
|
{Field}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
);
|
);
|
||||||
|
@ -103,6 +103,7 @@ export const TestCaseStatusModal = ({
|
|||||||
...data.testCaseResolutionStatusDetails,
|
...data.testCaseResolutionStatusDetails,
|
||||||
assignee: {
|
assignee: {
|
||||||
name: updatedAssignees[0].name,
|
name: updatedAssignees[0].name,
|
||||||
|
displayName: updatedAssignees[0].displayName,
|
||||||
id: updatedAssignees[0].value,
|
id: updatedAssignees[0].value,
|
||||||
type: EntityType.USER,
|
type: EntityType.USER,
|
||||||
},
|
},
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { Divider, Skeleton, Space, Typography } from 'antd';
|
import { Divider, Skeleton, Space, Tooltip, Typography } from 'antd';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
import { compare } from 'fast-json-patch';
|
import { compare } from 'fast-json-patch';
|
||||||
import { first, isUndefined, last } from 'lodash';
|
import { first, isUndefined, last } from 'lodash';
|
||||||
@ -274,9 +274,13 @@ const IncidentManagerPageHeader = ({
|
|||||||
<Divider className="self-center m-x-sm" type="vertical" />
|
<Divider className="self-center m-x-sm" type="vertical" />
|
||||||
<Typography.Text className="self-center text-xs whitespace-nowrap">
|
<Typography.Text className="self-center text-xs whitespace-nowrap">
|
||||||
<span className="text-grey-muted">{`${t('label.test-type')}: `}</span>
|
<span className="text-grey-muted">{`${t('label.test-type')}: `}</span>
|
||||||
<span className="font-medium" data-testid="test-definition-name">
|
<Tooltip
|
||||||
{getEntityName(testCaseData?.testDefinition)}
|
placement="bottom"
|
||||||
</span>
|
title={testCaseData?.testDefinition.description}>
|
||||||
|
<span className="font-medium" data-testid="test-definition-name">
|
||||||
|
{getEntityName(testCaseData?.testDefinition)}
|
||||||
|
</span>
|
||||||
|
</Tooltip>
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
</Space>
|
</Space>
|
||||||
);
|
);
|
||||||
|
@ -60,6 +60,7 @@ const SeverityModal = ({
|
|||||||
onFinish={handleFormSubmit}>
|
onFinish={handleFormSubmit}>
|
||||||
<Form.Item label={t('label.severity')} name="severity">
|
<Form.Item label={t('label.severity')} name="severity">
|
||||||
<Select
|
<Select
|
||||||
|
allowClear
|
||||||
data-testid="severity-select"
|
data-testid="severity-select"
|
||||||
placeholder={t('label.please-select-entity', {
|
placeholder={t('label.please-select-entity', {
|
||||||
entity: t('label.severity'),
|
entity: t('label.severity'),
|
||||||
|
@ -134,7 +134,7 @@ const TestCaseResultTab = ({
|
|||||||
<Typography.Text className="right-panel-label">
|
<Typography.Text className="right-panel-label">
|
||||||
{t('label.parameter-plural')}
|
{t('label.parameter-plural')}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
{hasEditPermission && (
|
{hasEditPermission && Boolean(withoutSqlParams.length) && (
|
||||||
<Icon
|
<Icon
|
||||||
component={EditIcon}
|
component={EditIcon}
|
||||||
data-testid="edit-parameter-icon"
|
data-testid="edit-parameter-icon"
|
||||||
|
@ -152,10 +152,10 @@ const TestSummary: React.FC<TestSummaryProps> = ({
|
|||||||
failedRows: result.failedRows,
|
failedRows: result.failedRows,
|
||||||
passedRowsPercentage: isUndefined(result.passedRowsPercentage)
|
passedRowsPercentage: isUndefined(result.passedRowsPercentage)
|
||||||
? undefined
|
? undefined
|
||||||
: `${result.passedRowsPercentage}%`,
|
: `${round(result.passedRowsPercentage, 2)}%`,
|
||||||
failedRowsPercentage: isUndefined(result.failedRowsPercentage)
|
failedRowsPercentage: isUndefined(result.failedRowsPercentage)
|
||||||
? undefined
|
? undefined
|
||||||
: `${result.failedRowsPercentage}%`,
|
: `${round(result.failedRowsPercentage, 2)}%`,
|
||||||
};
|
};
|
||||||
|
|
||||||
chartData.push({
|
chartData.push({
|
||||||
@ -270,7 +270,7 @@ const TestSummary: React.FC<TestSummaryProps> = ({
|
|||||||
const referenceArea = () => {
|
const referenceArea = () => {
|
||||||
const params = data.parameterValues ?? [];
|
const params = data.parameterValues ?? [];
|
||||||
|
|
||||||
if (params.length < 2) {
|
if (params.length && params.length < 2) {
|
||||||
return (
|
return (
|
||||||
<ReferenceLine
|
<ReferenceLine
|
||||||
label={params[0].name}
|
label={params[0].name}
|
||||||
|
@ -171,15 +171,18 @@ const CustomMetricGraphs = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Row data-testid="custom-metric-graph-container" gutter={[16, 16]}>
|
<Row data-testid="custom-metric-graph-container" gutter={[16, 16]}>
|
||||||
{!isEmpty(customMetricsGraphData) && (
|
{!isEmpty(customMetrics) && (
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<PageHeader data={PAGE_HEADERS.CUSTOM_METRICS} />
|
<PageHeader data={PAGE_HEADERS.CUSTOM_METRICS} />
|
||||||
</Col>
|
</Col>
|
||||||
)}
|
)}
|
||||||
{toPairs(customMetricsGraphData).map(([key, metric], i) => {
|
{toPairs(customMetricsGraphData).map(([key, metric], i) => {
|
||||||
|
const metricDetails = customMetrics?.find(
|
||||||
|
(metric) => metric.name === key
|
||||||
|
);
|
||||||
const color = TOTAL_ENTITY_CHART_COLOR[i] ?? getRandomHexColor();
|
const color = TOTAL_ENTITY_CHART_COLOR[i] ?? getRandomHexColor();
|
||||||
|
|
||||||
return (
|
return isUndefined(metricDetails) ? null : (
|
||||||
<Col key={key} span={24}>
|
<Col key={key} span={24}>
|
||||||
<Card
|
<Card
|
||||||
className="shadow-none global-border-radius custom-metric-card"
|
className="shadow-none global-border-radius custom-metric-card"
|
||||||
|
@ -161,4 +161,20 @@ describe('CustomMetricGraphs', () => {
|
|||||||
|
|
||||||
expect(await screen.findByText('DeleteWidgetModal')).toBeInTheDocument();
|
expect(await screen.findByText('DeleteWidgetModal')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("CustomMetric should be visible based on 'customMetrics' prop", async () => {
|
||||||
|
render(
|
||||||
|
<CustomMetricGraphs
|
||||||
|
{...mockProps}
|
||||||
|
customMetrics={[mockProps.customMetrics[0]]}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
const name = mockProps.customMetrics[0].name;
|
||||||
|
const name2 = mockProps.customMetrics[1].name;
|
||||||
|
const metric = await screen.findByTestId(`${name}-custom-metrics`);
|
||||||
|
const metric2 = screen.queryByTestId(`${name2}-custom-metrics`);
|
||||||
|
|
||||||
|
expect(metric).toBeInTheDocument();
|
||||||
|
expect(metric2).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -28,7 +28,14 @@ import Modal from 'antd/lib/modal/Modal';
|
|||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { compare } from 'fast-json-patch';
|
import { compare } from 'fast-json-patch';
|
||||||
import { isEmpty, isEqual, isUndefined, startCase, unionBy } from 'lodash';
|
import {
|
||||||
|
isEmpty,
|
||||||
|
isEqual,
|
||||||
|
isUndefined,
|
||||||
|
last,
|
||||||
|
startCase,
|
||||||
|
unionBy,
|
||||||
|
} from 'lodash';
|
||||||
import { MenuInfo } from 'rc-menu/lib/interface';
|
import { MenuInfo } from 'rc-menu/lib/interface';
|
||||||
import React, {
|
import React, {
|
||||||
useCallback,
|
useCallback,
|
||||||
@ -136,9 +143,25 @@ export const TaskTab = ({
|
|||||||
} = useActivityFeedProvider();
|
} = useActivityFeedProvider();
|
||||||
const isTaskTestCaseResult =
|
const isTaskTestCaseResult =
|
||||||
taskDetails?.type === TaskType.RequestTestCaseFailureResolution;
|
taskDetails?.type === TaskType.RequestTestCaseFailureResolution;
|
||||||
const [taskAction, setTaskAction] = useState<TaskAction>(
|
|
||||||
isTaskTestCaseResult ? INCIDENT_TASK_ACTION_LIST[0] : TASK_ACTION_LIST[0]
|
const latestAction = useMemo(() => {
|
||||||
);
|
const resolutionStatus = last(testCaseResolutionStatus);
|
||||||
|
|
||||||
|
if (isTaskTestCaseResult) {
|
||||||
|
switch (resolutionStatus?.testCaseResolutionStatusType) {
|
||||||
|
case TestCaseResolutionStatusTypes.Assigned:
|
||||||
|
return INCIDENT_TASK_ACTION_LIST[1];
|
||||||
|
|
||||||
|
default:
|
||||||
|
return INCIDENT_TASK_ACTION_LIST[0];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return TASK_ACTION_LIST[0];
|
||||||
|
}
|
||||||
|
}, [testCaseResolutionStatus, isTaskTestCaseResult]);
|
||||||
|
|
||||||
|
const [taskAction, setTaskAction] = useState<TaskAction>(latestAction);
|
||||||
|
const [isActionLoading, setIsActionLoading] = useState(false);
|
||||||
const isTaskClosed = isEqual(taskDetails?.status, ThreadTaskStatus.Closed);
|
const isTaskClosed = isEqual(taskDetails?.status, ThreadTaskStatus.Closed);
|
||||||
const [showEditTaskModel, setShowEditTaskModel] = useState(false);
|
const [showEditTaskModel, setShowEditTaskModel] = useState(false);
|
||||||
const [comment, setComment] = useState('');
|
const [comment, setComment] = useState('');
|
||||||
@ -353,6 +376,7 @@ export const TaskTab = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onTestCaseIncidentAssigneeUpdate = async () => {
|
const onTestCaseIncidentAssigneeUpdate = async () => {
|
||||||
|
setIsActionLoading(true);
|
||||||
const testCaseIncident: CreateTestCaseResolutionStatus = {
|
const testCaseIncident: CreateTestCaseResolutionStatus = {
|
||||||
testCaseResolutionStatusType: TestCaseResolutionStatusTypes.Assigned,
|
testCaseResolutionStatusType: TestCaseResolutionStatusTypes.Assigned,
|
||||||
testCaseReference: entityFQN,
|
testCaseReference: entityFQN,
|
||||||
@ -360,6 +384,7 @@ export const TaskTab = ({
|
|||||||
assignee: {
|
assignee: {
|
||||||
id: updatedAssignees[0].value,
|
id: updatedAssignees[0].value,
|
||||||
name: updatedAssignees[0].name,
|
name: updatedAssignees[0].name,
|
||||||
|
displayName: updatedAssignees[0].displayName,
|
||||||
type: updatedAssignees[0].type,
|
type: updatedAssignees[0].type,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -372,6 +397,8 @@ export const TaskTab = ({
|
|||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showErrorToast(error as AxiosError);
|
showErrorToast(error as AxiosError);
|
||||||
|
} finally {
|
||||||
|
setIsActionLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -382,6 +409,7 @@ export const TaskTab = ({
|
|||||||
testCaseFailureReason: TestCaseFailureReasonType;
|
testCaseFailureReason: TestCaseFailureReasonType;
|
||||||
testCaseFailureComment: string;
|
testCaseFailureComment: string;
|
||||||
}) => {
|
}) => {
|
||||||
|
setIsActionLoading(true);
|
||||||
const testCaseIncident: CreateTestCaseResolutionStatus = {
|
const testCaseIncident: CreateTestCaseResolutionStatus = {
|
||||||
testCaseResolutionStatusType: TestCaseResolutionStatusTypes.Resolved,
|
testCaseResolutionStatusType: TestCaseResolutionStatusTypes.Resolved,
|
||||||
testCaseReference: entityFQN,
|
testCaseReference: entityFQN,
|
||||||
@ -402,6 +430,8 @@ export const TaskTab = ({
|
|||||||
setShowEditTaskModel(false);
|
setShowEditTaskModel(false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showErrorToast(error as AxiosError);
|
showErrorToast(error as AxiosError);
|
||||||
|
} finally {
|
||||||
|
setIsActionLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -484,6 +514,7 @@ export const TaskTab = ({
|
|||||||
className="m-t-sm"
|
className="m-t-sm"
|
||||||
data-testid="task-cta-buttons"
|
data-testid="task-cta-buttons"
|
||||||
icon={<DownOutlined />}
|
icon={<DownOutlined />}
|
||||||
|
loading={isActionLoading}
|
||||||
menu={{
|
menu={{
|
||||||
items: INCIDENT_TASK_ACTION_LIST,
|
items: INCIDENT_TASK_ACTION_LIST,
|
||||||
selectable: true,
|
selectable: true,
|
||||||
@ -618,6 +649,10 @@ export const TaskTab = ({
|
|||||||
setOptions(assigneeOptions);
|
setOptions(assigneeOptions);
|
||||||
}, [initialAssignees, assigneeOptions]);
|
}, [initialAssignees, assigneeOptions]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setTaskAction(latestAction);
|
||||||
|
}, [latestAction]);
|
||||||
|
|
||||||
const taskHeader = isTaskTestCaseResult ? (
|
const taskHeader = isTaskTestCaseResult ? (
|
||||||
<TaskTabIncidentManagerHeader thread={taskThread} />
|
<TaskTabIncidentManagerHeader thread={taskThread} />
|
||||||
) : (
|
) : (
|
||||||
@ -763,6 +798,9 @@ export const TaskTab = ({
|
|||||||
maskClosable
|
maskClosable
|
||||||
closable={false}
|
closable={false}
|
||||||
closeIcon={null}
|
closeIcon={null}
|
||||||
|
okButtonProps={{
|
||||||
|
loading: isActionLoading,
|
||||||
|
}}
|
||||||
okText={t('label.submit')}
|
okText={t('label.submit')}
|
||||||
open={showEditTaskModel}
|
open={showEditTaskModel}
|
||||||
title={`${t('label.resolve')} ${t('label.task')} #${taskDetails?.id}`}
|
title={`${t('label.resolve')} ${t('label.task')} #${taskDetails?.id}`}
|
||||||
@ -885,6 +923,9 @@ export const TaskTab = ({
|
|||||||
maskClosable
|
maskClosable
|
||||||
closable={false}
|
closable={false}
|
||||||
closeIcon={null}
|
closeIcon={null}
|
||||||
|
okButtonProps={{
|
||||||
|
loading: isActionLoading,
|
||||||
|
}}
|
||||||
okText={t('label.submit')}
|
okText={t('label.submit')}
|
||||||
open={isEditAssignee}
|
open={isEditAssignee}
|
||||||
title={`${t('label.re-assign')} ${t('label.task')} #${
|
title={`${t('label.re-assign')} ${t('label.task')} #${
|
||||||
|
@ -12,13 +12,14 @@
|
|||||||
*/
|
*/
|
||||||
import { Col, Row, Tabs, TabsProps } from 'antd';
|
import { Col, Row, Tabs, TabsProps } from 'antd';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
import { compare } from 'fast-json-patch';
|
import { compare, Operation as PatchOperation } from 'fast-json-patch';
|
||||||
import { isUndefined } from 'lodash';
|
import { isUndefined } from 'lodash';
|
||||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useHistory, useLocation, useParams } from 'react-router-dom';
|
import { useHistory, useLocation, useParams } from 'react-router-dom';
|
||||||
import { ReactComponent as TestCaseIcon } from '../../../assets/svg/ic-checklist.svg';
|
import { ReactComponent as TestCaseIcon } from '../../../assets/svg/ic-checklist.svg';
|
||||||
import ActivityFeedProvider from '../../../components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
|
import ActivityFeedProvider from '../../../components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
|
||||||
|
import ManageButton from '../../../components/common/EntityPageInfos/ManageButton/ManageButton';
|
||||||
import ErrorPlaceHolder from '../../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
|
import ErrorPlaceHolder from '../../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
|
||||||
import TitleBreadcrumb from '../../../components/common/TitleBreadcrumb/TitleBreadcrumb.component';
|
import TitleBreadcrumb from '../../../components/common/TitleBreadcrumb/TitleBreadcrumb.component';
|
||||||
import { TitleBreadcrumbProps } from '../../../components/common/TitleBreadcrumb/TitleBreadcrumb.interface';
|
import { TitleBreadcrumbProps } from '../../../components/common/TitleBreadcrumb/TitleBreadcrumb.interface';
|
||||||
@ -27,6 +28,7 @@ import IncidentManagerPageHeader from '../../../components/IncidentManager/Incid
|
|||||||
import TestCaseIncidentTab from '../../../components/IncidentManager/TestCaseIncidentTab/TestCaseIncidentTab.component';
|
import TestCaseIncidentTab from '../../../components/IncidentManager/TestCaseIncidentTab/TestCaseIncidentTab.component';
|
||||||
import TestCaseResultTab from '../../../components/IncidentManager/TestCaseResultTab/TestCaseResultTab.component';
|
import TestCaseResultTab from '../../../components/IncidentManager/TestCaseResultTab/TestCaseResultTab.component';
|
||||||
import Loader from '../../../components/Loader/Loader';
|
import Loader from '../../../components/Loader/Loader';
|
||||||
|
import { EntityName } from '../../../components/Modals/EntityNameModal/EntityNameModal.interface';
|
||||||
import PageLayoutV1 from '../../../components/PageLayoutV1/PageLayoutV1';
|
import PageLayoutV1 from '../../../components/PageLayoutV1/PageLayoutV1';
|
||||||
import { usePermissionProvider } from '../../../components/PermissionProvider/PermissionProvider';
|
import { usePermissionProvider } from '../../../components/PermissionProvider/PermissionProvider';
|
||||||
import { ResourceEntity } from '../../../components/PermissionProvider/PermissionProvider.interface';
|
import { ResourceEntity } from '../../../components/PermissionProvider/PermissionProvider.interface';
|
||||||
@ -73,13 +75,26 @@ const IncidentManagerDetailPage = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const { permissions } = usePermissionProvider();
|
const { permissions } = usePermissionProvider();
|
||||||
const hasViewPermission = useMemo(() => {
|
const { hasViewPermission, editDisplayNamePermission, hasDeletePermission } =
|
||||||
return checkPermission(
|
useMemo(() => {
|
||||||
Operation.ViewAll,
|
return {
|
||||||
ResourceEntity.TEST_CASE,
|
hasViewPermission: checkPermission(
|
||||||
permissions
|
Operation.ViewAll,
|
||||||
);
|
ResourceEntity.TEST_CASE,
|
||||||
}, [permissions]);
|
permissions
|
||||||
|
),
|
||||||
|
editDisplayNamePermission: checkPermission(
|
||||||
|
Operation.EditDisplayName,
|
||||||
|
ResourceEntity.TEST_CASE,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
hasDeletePermission: checkPermission(
|
||||||
|
Operation.Delete,
|
||||||
|
ResourceEntity.TEST_CASE,
|
||||||
|
permissions
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}, [permissions]);
|
||||||
|
|
||||||
const onTestCaseUpdate = (data: TestCase) => {
|
const onTestCaseUpdate = (data: TestCase) => {
|
||||||
setTestCaseData((prev) => ({ ...prev, data }));
|
setTestCaseData((prev) => ({ ...prev, data }));
|
||||||
@ -168,7 +183,14 @@ const IncidentManagerDetailPage = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const updateTestCase = async (id: string, patch: PatchOperation[]) => {
|
||||||
|
try {
|
||||||
|
const res = await updateTestCaseById(id, patch);
|
||||||
|
onTestCaseUpdate(res);
|
||||||
|
} catch (error) {
|
||||||
|
showErrorToast(error as AxiosError);
|
||||||
|
}
|
||||||
|
};
|
||||||
const handleOwnerChange = async (owner?: EntityReference) => {
|
const handleOwnerChange = async (owner?: EntityReference) => {
|
||||||
const data = testCaseData.data;
|
const data = testCaseData.data;
|
||||||
if (data) {
|
if (data) {
|
||||||
@ -178,13 +200,23 @@ const IncidentManagerDetailPage = () => {
|
|||||||
};
|
};
|
||||||
const jsonPatch = compare(data, updatedTestCase);
|
const jsonPatch = compare(data, updatedTestCase);
|
||||||
|
|
||||||
if (jsonPatch.length) {
|
if (jsonPatch.length && data.id) {
|
||||||
try {
|
updateTestCase(data.id, jsonPatch);
|
||||||
const res = await updateTestCaseById(data.id ?? '', jsonPatch);
|
}
|
||||||
onTestCaseUpdate(res);
|
}
|
||||||
} catch (error) {
|
};
|
||||||
showErrorToast(error as AxiosError);
|
|
||||||
}
|
const handleDisplayNameChange = async (entityName?: EntityName) => {
|
||||||
|
const data = testCaseData.data;
|
||||||
|
if (data) {
|
||||||
|
const updatedTestCase = {
|
||||||
|
...data,
|
||||||
|
...entityName,
|
||||||
|
};
|
||||||
|
const jsonPatch = compare(data, updatedTestCase);
|
||||||
|
|
||||||
|
if (jsonPatch.length && data.id) {
|
||||||
|
updateTestCase(data.id, jsonPatch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -228,13 +260,34 @@ const IncidentManagerDetailPage = () => {
|
|||||||
<TitleBreadcrumb className="m-b-sm" titleLinks={breadcrumb} />
|
<TitleBreadcrumb className="m-b-sm" titleLinks={breadcrumb} />
|
||||||
</Col>
|
</Col>
|
||||||
<Col className="p-x-lg" data-testid="entity-page-header" span={24}>
|
<Col className="p-x-lg" data-testid="entity-page-header" span={24}>
|
||||||
<EntityHeaderTitle
|
<Row gutter={16}>
|
||||||
className="w-max-full-45"
|
<Col span={23}>
|
||||||
displayName={testCaseData.data?.displayName}
|
<EntityHeaderTitle
|
||||||
icon={<TestCaseIcon className="h-9" />}
|
className="w-max-full-45"
|
||||||
name={testCaseData.data?.name ?? ''}
|
displayName={testCaseData.data?.displayName}
|
||||||
serviceName="testCase"
|
icon={<TestCaseIcon className="h-9" />}
|
||||||
/>
|
name={testCaseData.data?.name ?? ''}
|
||||||
|
serviceName="testCase"
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
<Col className="d-flex justify-end" span={1}>
|
||||||
|
<ManageButton
|
||||||
|
isRecursiveDelete
|
||||||
|
afterDeleteAction={() =>
|
||||||
|
history.push(ROUTES.INCIDENT_MANAGER)
|
||||||
|
}
|
||||||
|
allowSoftDelete={false}
|
||||||
|
canDelete={hasDeletePermission}
|
||||||
|
displayName={testCaseData.data.displayName}
|
||||||
|
editDisplayNamePermission={editDisplayNamePermission}
|
||||||
|
entityFQN={testCaseData.data.fullyQualifiedName}
|
||||||
|
entityId={testCaseData.data.id}
|
||||||
|
entityName={testCaseData.data.name}
|
||||||
|
entityType={EntityType.TEST_CASE}
|
||||||
|
onEditDisplayName={handleDisplayNameChange}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
</Col>
|
</Col>
|
||||||
<Col className="p-x-lg">
|
<Col className="p-x-lg">
|
||||||
<IncidentManagerPageHeader
|
<IncidentManagerPageHeader
|
||||||
|
@ -45,6 +45,7 @@ export interface Option {
|
|||||||
value: string;
|
value: string;
|
||||||
type: string;
|
type: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
|
displayName?: string;
|
||||||
children?: string;
|
children?: string;
|
||||||
'data-label'?: string;
|
'data-label'?: string;
|
||||||
'data-testid'?: string;
|
'data-testid'?: string;
|
||||||
|
@ -56,6 +56,7 @@ const Assignees: FC<Props> = ({
|
|||||||
value: option.value,
|
value: option.value,
|
||||||
type: option.type,
|
type: option.type,
|
||||||
name: option.name,
|
name: option.name,
|
||||||
|
displayName: option.displayName,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
onChange(newValues as Option[]);
|
onChange(newValues as Option[]);
|
||||||
|
@ -30,7 +30,7 @@ export const deleteCustomMetric = async ({
|
|||||||
: customMetricName;
|
: customMetricName;
|
||||||
|
|
||||||
return await APIClient.delete<Table>(
|
return await APIClient.delete<Table>(
|
||||||
`${BASE_URL}/${tableId}/customMetric/${url}`
|
`${BASE_URL}/${tableId}/customMetric/${url}?recursive=true&hardDelete=true`
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -182,11 +182,13 @@ describe('Tests for fetchOptions', () => {
|
|||||||
expect(mockSetOptions).toHaveBeenCalledWith([
|
expect(mockSetOptions).toHaveBeenCalledWith([
|
||||||
{
|
{
|
||||||
label: 'Ashish Gupta',
|
label: 'Ashish Gupta',
|
||||||
|
displayName: 'Ashish Gupta',
|
||||||
name: 'ashish',
|
name: 'ashish',
|
||||||
type: 'user',
|
type: 'user',
|
||||||
value: '18ca6cd1-d696-4a22-813f-c7a42fc09dc4',
|
value: '18ca6cd1-d696-4a22-813f-c7a42fc09dc4',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
displayName: 'Ashley King',
|
||||||
label: 'Ashley King',
|
label: 'Ashley King',
|
||||||
name: 'ashley_king5',
|
name: 'ashley_king5',
|
||||||
type: 'user',
|
type: 'user',
|
||||||
@ -212,6 +214,7 @@ describe('Tests for fetchOptions', () => {
|
|||||||
|
|
||||||
expect(mockSetOptions).toHaveBeenCalledWith([
|
expect(mockSetOptions).toHaveBeenCalledWith([
|
||||||
{
|
{
|
||||||
|
displayName: 'Ashley King',
|
||||||
label: 'Ashley King',
|
label: 'Ashley King',
|
||||||
name: 'ashley_king5',
|
name: 'ashley_king5',
|
||||||
type: 'user',
|
type: 'user',
|
||||||
|
@ -213,6 +213,7 @@ export const fetchOptions = ({
|
|||||||
value: hit._id,
|
value: hit._id,
|
||||||
type: hit._source.entityType,
|
type: hit._source.entityType,
|
||||||
name: hit._source.name,
|
name: hit._source.name,
|
||||||
|
displayName: hit._source.displayName,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
setOptions(suggestOptions.filter((item) => item.value !== currentUserId));
|
setOptions(suggestOptions.filter((item) => item.value !== currentUserId));
|
||||||
@ -226,6 +227,7 @@ export const generateOptions = (assignees: EntityReference[]) => {
|
|||||||
value: assignee.id || '',
|
value: assignee.id || '',
|
||||||
type: assignee.type,
|
type: assignee.type,
|
||||||
name: assignee.name,
|
name: assignee.name,
|
||||||
|
displayName: assignee.displayName,
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user