mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-17 19:57:56 +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);
|
||||
cy.get('[data-testid="incident"]').click();
|
||||
verifyResponseStatusCode('@getTaskFeed', 200);
|
||||
cy.get('[data-testid="task-cta-buttons"]')
|
||||
.contains('Reassign')
|
||||
cy.get('[data-testid="task-cta-buttons"] [role="img"]')
|
||||
.scrollIntoView()
|
||||
.click();
|
||||
cy.get('[role="menu"').find('[data-menu-id*="re-assign"]').click();
|
||||
interceptURL(
|
||||
'GET',
|
||||
'/api/v1/search/suggest?q=admin&index=*user_search_index*',
|
||||
@ -309,10 +309,10 @@ describe('Incident Manager', () => {
|
||||
verifyResponseStatusCode('@getTestCase', 200);
|
||||
cy.get('[data-testid="incident"]').click();
|
||||
verifyResponseStatusCode('@getTaskFeed', 200);
|
||||
cy.get('[data-testid="task-cta-buttons"] [role="img"]')
|
||||
cy.get('[data-testid="task-cta-buttons"]')
|
||||
.contains('Resolve')
|
||||
.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')
|
||||
|
@ -12,7 +12,15 @@
|
||||
*/
|
||||
|
||||
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 { isUndefined } from 'lodash';
|
||||
import React from 'react';
|
||||
@ -32,6 +40,7 @@ const ParameterForm: React.FC<ParameterFormProps> = ({ definition, table }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const prepareForm = (data: TestCaseParameterDefinition) => {
|
||||
let internalFormItemProps: FormItemProps = {};
|
||||
let Field = (
|
||||
<Input
|
||||
placeholder={`${t('message.enter-a-field', {
|
||||
@ -122,6 +131,10 @@ const ParameterForm: React.FC<ParameterFormProps> = ({ definition, table }) => {
|
||||
break;
|
||||
case TestDataType.Boolean:
|
||||
Field = <Switch />;
|
||||
internalFormItemProps = {
|
||||
...internalFormItemProps,
|
||||
valuePropName: 'checked',
|
||||
};
|
||||
|
||||
break;
|
||||
case TestDataType.Array:
|
||||
@ -204,7 +217,8 @@ const ParameterForm: React.FC<ParameterFormProps> = ({ definition, table }) => {
|
||||
})}`,
|
||||
},
|
||||
]}
|
||||
tooltip={data.description}>
|
||||
tooltip={data.description}
|
||||
{...internalFormItemProps}>
|
||||
{Field}
|
||||
</Form.Item>
|
||||
);
|
||||
|
@ -103,6 +103,7 @@ export const TestCaseStatusModal = ({
|
||||
...data.testCaseResolutionStatusDetails,
|
||||
assignee: {
|
||||
name: updatedAssignees[0].name,
|
||||
displayName: updatedAssignees[0].displayName,
|
||||
id: updatedAssignees[0].value,
|
||||
type: EntityType.USER,
|
||||
},
|
||||
|
@ -10,7 +10,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Divider, Skeleton, Space, Typography } from 'antd';
|
||||
import { Divider, Skeleton, Space, Tooltip, Typography } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import { compare } from 'fast-json-patch';
|
||||
import { first, isUndefined, last } from 'lodash';
|
||||
@ -274,9 +274,13 @@ const IncidentManagerPageHeader = ({
|
||||
<Divider className="self-center m-x-sm" type="vertical" />
|
||||
<Typography.Text className="self-center text-xs whitespace-nowrap">
|
||||
<span className="text-grey-muted">{`${t('label.test-type')}: `}</span>
|
||||
<span className="font-medium" data-testid="test-definition-name">
|
||||
{getEntityName(testCaseData?.testDefinition)}
|
||||
</span>
|
||||
<Tooltip
|
||||
placement="bottom"
|
||||
title={testCaseData?.testDefinition.description}>
|
||||
<span className="font-medium" data-testid="test-definition-name">
|
||||
{getEntityName(testCaseData?.testDefinition)}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</Typography.Text>
|
||||
</Space>
|
||||
);
|
||||
|
@ -60,6 +60,7 @@ const SeverityModal = ({
|
||||
onFinish={handleFormSubmit}>
|
||||
<Form.Item label={t('label.severity')} name="severity">
|
||||
<Select
|
||||
allowClear
|
||||
data-testid="severity-select"
|
||||
placeholder={t('label.please-select-entity', {
|
||||
entity: t('label.severity'),
|
||||
|
@ -134,7 +134,7 @@ const TestCaseResultTab = ({
|
||||
<Typography.Text className="right-panel-label">
|
||||
{t('label.parameter-plural')}
|
||||
</Typography.Text>
|
||||
{hasEditPermission && (
|
||||
{hasEditPermission && Boolean(withoutSqlParams.length) && (
|
||||
<Icon
|
||||
component={EditIcon}
|
||||
data-testid="edit-parameter-icon"
|
||||
|
@ -152,10 +152,10 @@ const TestSummary: React.FC<TestSummaryProps> = ({
|
||||
failedRows: result.failedRows,
|
||||
passedRowsPercentage: isUndefined(result.passedRowsPercentage)
|
||||
? undefined
|
||||
: `${result.passedRowsPercentage}%`,
|
||||
: `${round(result.passedRowsPercentage, 2)}%`,
|
||||
failedRowsPercentage: isUndefined(result.failedRowsPercentage)
|
||||
? undefined
|
||||
: `${result.failedRowsPercentage}%`,
|
||||
: `${round(result.failedRowsPercentage, 2)}%`,
|
||||
};
|
||||
|
||||
chartData.push({
|
||||
@ -270,7 +270,7 @@ const TestSummary: React.FC<TestSummaryProps> = ({
|
||||
const referenceArea = () => {
|
||||
const params = data.parameterValues ?? [];
|
||||
|
||||
if (params.length < 2) {
|
||||
if (params.length && params.length < 2) {
|
||||
return (
|
||||
<ReferenceLine
|
||||
label={params[0].name}
|
||||
|
@ -171,15 +171,18 @@ const CustomMetricGraphs = ({
|
||||
|
||||
return (
|
||||
<Row data-testid="custom-metric-graph-container" gutter={[16, 16]}>
|
||||
{!isEmpty(customMetricsGraphData) && (
|
||||
{!isEmpty(customMetrics) && (
|
||||
<Col span={24}>
|
||||
<PageHeader data={PAGE_HEADERS.CUSTOM_METRICS} />
|
||||
</Col>
|
||||
)}
|
||||
{toPairs(customMetricsGraphData).map(([key, metric], i) => {
|
||||
const metricDetails = customMetrics?.find(
|
||||
(metric) => metric.name === key
|
||||
);
|
||||
const color = TOTAL_ENTITY_CHART_COLOR[i] ?? getRandomHexColor();
|
||||
|
||||
return (
|
||||
return isUndefined(metricDetails) ? null : (
|
||||
<Col key={key} span={24}>
|
||||
<Card
|
||||
className="shadow-none global-border-radius custom-metric-card"
|
||||
|
@ -161,4 +161,20 @@ describe('CustomMetricGraphs', () => {
|
||||
|
||||
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 classNames from 'classnames';
|
||||
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 React, {
|
||||
useCallback,
|
||||
@ -136,9 +143,25 @@ export const TaskTab = ({
|
||||
} = useActivityFeedProvider();
|
||||
const isTaskTestCaseResult =
|
||||
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 [showEditTaskModel, setShowEditTaskModel] = useState(false);
|
||||
const [comment, setComment] = useState('');
|
||||
@ -353,6 +376,7 @@ export const TaskTab = ({
|
||||
};
|
||||
|
||||
const onTestCaseIncidentAssigneeUpdate = async () => {
|
||||
setIsActionLoading(true);
|
||||
const testCaseIncident: CreateTestCaseResolutionStatus = {
|
||||
testCaseResolutionStatusType: TestCaseResolutionStatusTypes.Assigned,
|
||||
testCaseReference: entityFQN,
|
||||
@ -360,6 +384,7 @@ export const TaskTab = ({
|
||||
assignee: {
|
||||
id: updatedAssignees[0].value,
|
||||
name: updatedAssignees[0].name,
|
||||
displayName: updatedAssignees[0].displayName,
|
||||
type: updatedAssignees[0].type,
|
||||
},
|
||||
},
|
||||
@ -372,6 +397,8 @@ export const TaskTab = ({
|
||||
});
|
||||
} catch (error) {
|
||||
showErrorToast(error as AxiosError);
|
||||
} finally {
|
||||
setIsActionLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
@ -382,6 +409,7 @@ export const TaskTab = ({
|
||||
testCaseFailureReason: TestCaseFailureReasonType;
|
||||
testCaseFailureComment: string;
|
||||
}) => {
|
||||
setIsActionLoading(true);
|
||||
const testCaseIncident: CreateTestCaseResolutionStatus = {
|
||||
testCaseResolutionStatusType: TestCaseResolutionStatusTypes.Resolved,
|
||||
testCaseReference: entityFQN,
|
||||
@ -402,6 +430,8 @@ export const TaskTab = ({
|
||||
setShowEditTaskModel(false);
|
||||
} catch (error) {
|
||||
showErrorToast(error as AxiosError);
|
||||
} finally {
|
||||
setIsActionLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
@ -484,6 +514,7 @@ export const TaskTab = ({
|
||||
className="m-t-sm"
|
||||
data-testid="task-cta-buttons"
|
||||
icon={<DownOutlined />}
|
||||
loading={isActionLoading}
|
||||
menu={{
|
||||
items: INCIDENT_TASK_ACTION_LIST,
|
||||
selectable: true,
|
||||
@ -618,6 +649,10 @@ export const TaskTab = ({
|
||||
setOptions(assigneeOptions);
|
||||
}, [initialAssignees, assigneeOptions]);
|
||||
|
||||
useEffect(() => {
|
||||
setTaskAction(latestAction);
|
||||
}, [latestAction]);
|
||||
|
||||
const taskHeader = isTaskTestCaseResult ? (
|
||||
<TaskTabIncidentManagerHeader thread={taskThread} />
|
||||
) : (
|
||||
@ -763,6 +798,9 @@ export const TaskTab = ({
|
||||
maskClosable
|
||||
closable={false}
|
||||
closeIcon={null}
|
||||
okButtonProps={{
|
||||
loading: isActionLoading,
|
||||
}}
|
||||
okText={t('label.submit')}
|
||||
open={showEditTaskModel}
|
||||
title={`${t('label.resolve')} ${t('label.task')} #${taskDetails?.id}`}
|
||||
@ -885,6 +923,9 @@ export const TaskTab = ({
|
||||
maskClosable
|
||||
closable={false}
|
||||
closeIcon={null}
|
||||
okButtonProps={{
|
||||
loading: isActionLoading,
|
||||
}}
|
||||
okText={t('label.submit')}
|
||||
open={isEditAssignee}
|
||||
title={`${t('label.re-assign')} ${t('label.task')} #${
|
||||
|
@ -12,13 +12,14 @@
|
||||
*/
|
||||
import { Col, Row, Tabs, TabsProps } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import { compare } from 'fast-json-patch';
|
||||
import { compare, Operation as PatchOperation } from 'fast-json-patch';
|
||||
import { isUndefined } from 'lodash';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useHistory, useLocation, useParams } from 'react-router-dom';
|
||||
import { ReactComponent as TestCaseIcon } from '../../../assets/svg/ic-checklist.svg';
|
||||
import ActivityFeedProvider from '../../../components/ActivityFeed/ActivityFeedProvider/ActivityFeedProvider';
|
||||
import ManageButton from '../../../components/common/EntityPageInfos/ManageButton/ManageButton';
|
||||
import ErrorPlaceHolder from '../../../components/common/ErrorWithPlaceholder/ErrorPlaceHolder';
|
||||
import TitleBreadcrumb from '../../../components/common/TitleBreadcrumb/TitleBreadcrumb.component';
|
||||
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 TestCaseResultTab from '../../../components/IncidentManager/TestCaseResultTab/TestCaseResultTab.component';
|
||||
import Loader from '../../../components/Loader/Loader';
|
||||
import { EntityName } from '../../../components/Modals/EntityNameModal/EntityNameModal.interface';
|
||||
import PageLayoutV1 from '../../../components/PageLayoutV1/PageLayoutV1';
|
||||
import { usePermissionProvider } from '../../../components/PermissionProvider/PermissionProvider';
|
||||
import { ResourceEntity } from '../../../components/PermissionProvider/PermissionProvider.interface';
|
||||
@ -73,13 +75,26 @@ const IncidentManagerDetailPage = () => {
|
||||
);
|
||||
|
||||
const { permissions } = usePermissionProvider();
|
||||
const hasViewPermission = useMemo(() => {
|
||||
return checkPermission(
|
||||
Operation.ViewAll,
|
||||
ResourceEntity.TEST_CASE,
|
||||
permissions
|
||||
);
|
||||
}, [permissions]);
|
||||
const { hasViewPermission, editDisplayNamePermission, hasDeletePermission } =
|
||||
useMemo(() => {
|
||||
return {
|
||||
hasViewPermission: checkPermission(
|
||||
Operation.ViewAll,
|
||||
ResourceEntity.TEST_CASE,
|
||||
permissions
|
||||
),
|
||||
editDisplayNamePermission: checkPermission(
|
||||
Operation.EditDisplayName,
|
||||
ResourceEntity.TEST_CASE,
|
||||
permissions
|
||||
),
|
||||
hasDeletePermission: checkPermission(
|
||||
Operation.Delete,
|
||||
ResourceEntity.TEST_CASE,
|
||||
permissions
|
||||
),
|
||||
};
|
||||
}, [permissions]);
|
||||
|
||||
const onTestCaseUpdate = (data: TestCase) => {
|
||||
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 data = testCaseData.data;
|
||||
if (data) {
|
||||
@ -178,13 +200,23 @@ const IncidentManagerDetailPage = () => {
|
||||
};
|
||||
const jsonPatch = compare(data, updatedTestCase);
|
||||
|
||||
if (jsonPatch.length) {
|
||||
try {
|
||||
const res = await updateTestCaseById(data.id ?? '', jsonPatch);
|
||||
onTestCaseUpdate(res);
|
||||
} catch (error) {
|
||||
showErrorToast(error as AxiosError);
|
||||
}
|
||||
if (jsonPatch.length && data.id) {
|
||||
updateTestCase(data.id, jsonPatch);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
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} />
|
||||
</Col>
|
||||
<Col className="p-x-lg" data-testid="entity-page-header" span={24}>
|
||||
<EntityHeaderTitle
|
||||
className="w-max-full-45"
|
||||
displayName={testCaseData.data?.displayName}
|
||||
icon={<TestCaseIcon className="h-9" />}
|
||||
name={testCaseData.data?.name ?? ''}
|
||||
serviceName="testCase"
|
||||
/>
|
||||
<Row gutter={16}>
|
||||
<Col span={23}>
|
||||
<EntityHeaderTitle
|
||||
className="w-max-full-45"
|
||||
displayName={testCaseData.data?.displayName}
|
||||
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 className="p-x-lg">
|
||||
<IncidentManagerPageHeader
|
||||
|
@ -45,6 +45,7 @@ export interface Option {
|
||||
value: string;
|
||||
type: string;
|
||||
name?: string;
|
||||
displayName?: string;
|
||||
children?: string;
|
||||
'data-label'?: string;
|
||||
'data-testid'?: string;
|
||||
|
@ -56,6 +56,7 @@ const Assignees: FC<Props> = ({
|
||||
value: option.value,
|
||||
type: option.type,
|
||||
name: option.name,
|
||||
displayName: option.displayName,
|
||||
}));
|
||||
|
||||
onChange(newValues as Option[]);
|
||||
|
@ -30,7 +30,7 @@ export const deleteCustomMetric = async ({
|
||||
: customMetricName;
|
||||
|
||||
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([
|
||||
{
|
||||
label: 'Ashish Gupta',
|
||||
displayName: 'Ashish Gupta',
|
||||
name: 'ashish',
|
||||
type: 'user',
|
||||
value: '18ca6cd1-d696-4a22-813f-c7a42fc09dc4',
|
||||
},
|
||||
{
|
||||
displayName: 'Ashley King',
|
||||
label: 'Ashley King',
|
||||
name: 'ashley_king5',
|
||||
type: 'user',
|
||||
@ -212,6 +214,7 @@ describe('Tests for fetchOptions', () => {
|
||||
|
||||
expect(mockSetOptions).toHaveBeenCalledWith([
|
||||
{
|
||||
displayName: 'Ashley King',
|
||||
label: 'Ashley King',
|
||||
name: 'ashley_king5',
|
||||
type: 'user',
|
||||
|
@ -213,6 +213,7 @@ export const fetchOptions = ({
|
||||
value: hit._id,
|
||||
type: hit._source.entityType,
|
||||
name: hit._source.name,
|
||||
displayName: hit._source.displayName,
|
||||
}));
|
||||
|
||||
setOptions(suggestOptions.filter((item) => item.value !== currentUserId));
|
||||
@ -226,6 +227,7 @@ export const generateOptions = (assignees: EntityReference[]) => {
|
||||
value: assignee.id || '',
|
||||
type: assignee.type,
|
||||
name: assignee.name,
|
||||
displayName: assignee.displayName,
|
||||
}));
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user