Skip to content

Commit 65b9156

Browse files
committed
NCL-8075 NCL-8075 Implement Remove Deliverable Analysis label feature
1 parent 09dab03 commit 65b9156

File tree

6 files changed

+172
-8
lines changed

6 files changed

+172
-8
lines changed

src/common/constants.ts

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export const ButtonTitles = {
4747
create: 'Create',
4848
edit: 'Edit',
4949
add: 'Add',
50+
remove: 'Remove',
5051
view: 'View',
5152
};
5253

src/common/deliverableAnalysisLabelEntryEntityAttributes.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ import { DeliverableAnalyzerLabelEntry, DeliverableAnalyzerReport } from 'pnc-ap
22

33
import { TEntityAttributes } from 'common/entityAttributes';
44

5-
export type AssignableDeliverableAnalysisLabel = Exclude<NonNullable<DeliverableAnalyzerReport['labels']>[number], 'SCRATCH'>;
5+
export type DeliverableAnalysisLabel = NonNullable<DeliverableAnalyzerReport['labels']>[number];
66

7-
const labelValues: AssignableDeliverableAnalysisLabel[] = ['RELEASED', 'DELETED'];
7+
export type EditableDeliverableAnalysisLabel = Exclude<DeliverableAnalysisLabel, 'SCRATCH'>;
8+
9+
const labelValues: EditableDeliverableAnalysisLabel[] = ['RELEASED', 'DELETED'];
810

911
export const deliverableAnalysisLabelEntryEntityAttributes = {
1012
label: {

src/components/DeliverableAnalysisDetailPage/DeliverableAnalysisDetailPage.tsx

+31-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { Text, TextContent, TextVariants } from '@patternfly/react-core';
22
import { useCallback, useEffect, useMemo, useState } from 'react';
33

4-
import { DeliverableAnalyzerOperation } from 'pnc-api-types-ts';
4+
import { DeliverableAnalyzerOperation, DeliverableAnalyzerReport } from 'pnc-api-types-ts';
55

66
import { breadcrumbData } from 'common/breadcrumbData';
77
import { EntityTitles } from 'common/constants';
8+
import { DeliverableAnalysisLabel } from 'common/deliverableAnalysisLabelEntryEntityAttributes';
89
import { deliverableAnalysisOperationEntityAttributes } from 'common/deliverableAnalysisOperationEntityAttributes';
910
import { deliverableAnalysisReportEntityAttributes } from 'common/deliverableAnalysisReportEntityAttributes';
1011

@@ -25,6 +26,7 @@ import { ContentBox } from 'components/ContentBox/ContentBox';
2526
import { DateTime } from 'components/DateTime/DateTime';
2627
import { DeliverableAnalysisAddLabelModal } from 'components/DeliverableAnalysisAddLabelModal/DeliverableAnalysisAddLabelModal';
2728
import { DeliverableAnalysisAddLabelModalButton } from 'components/DeliverableAnalysisAddLabelModal/DeliverableAnalysisAddLabelModalButton';
29+
import { DeliverableAnalysisRemoveLabelModal } from 'components/DeliverableAnalysisRemoveLabelModal/DeliverableAnalysisRemoveLabelModal';
2830
import { DeliverableAnalysisLabelLabelMapper } from 'components/LabelMapper/DeliverableAnalysisLabelLabelMapper';
2931
import { DeliverableAnalysisProgressStatusLabelMapper } from 'components/LabelMapper/DeliverableAnalysisProgressStatusLabelMapper';
3032
import { DeliverableAnalysisResultLabelMapper } from 'components/LabelMapper/DeliverableAnalysisResultLabelMapper';
@@ -209,7 +211,7 @@ export const DeliverableAnalysisDetailPage = () => {
209211
>
210212
<div className="display-flex gap-5">
211213
{serviceContainerDeliverableAnalysisReport.data?.labels?.map((label) => (
212-
<DeliverableAnalysisLabelLabelMapper key={label} label={label} />
214+
<DeliverableAnalysisLabelLabel key={label} label={label} deliverableAnalysisReport={deliverableAnalysis!} />
213215
))}
214216
</div>
215217
</ServiceContainerLoading>
@@ -273,3 +275,30 @@ const LogViewerSection = ({ deliverableAnalysis }: ILogViewerSectionProps) => {
273275
</>
274276
);
275277
};
278+
279+
interface IDeliverableAnalysisLabelLabelProps {
280+
label: DeliverableAnalysisLabel;
281+
deliverableAnalysisReport: DeliverableAnalyzerReport;
282+
}
283+
284+
const DeliverableAnalysisLabelLabel = ({ label, deliverableAnalysisReport }: IDeliverableAnalysisLabelLabelProps) => {
285+
const [isRemoveLabelModalOpen, setIsRemoveLabelModalOpen] = useState<boolean>(false);
286+
287+
const toggleRemoveLabelModal = () => setIsRemoveLabelModalOpen((isRemoveLabelModalOpen) => !isRemoveLabelModalOpen);
288+
289+
const canLabelBeChanged = label !== 'SCRATCH';
290+
291+
return (
292+
<>
293+
<DeliverableAnalysisLabelLabelMapper label={label} onClose={canLabelBeChanged ? toggleRemoveLabelModal : undefined} />
294+
{canLabelBeChanged && (
295+
<DeliverableAnalysisRemoveLabelModal
296+
isModalOpen={isRemoveLabelModalOpen}
297+
toggleModal={toggleRemoveLabelModal}
298+
deliverableAnalysisReport={deliverableAnalysisReport}
299+
label={label}
300+
/>
301+
)}
302+
</>
303+
);
304+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import { Form, FormGroup, TextArea } from '@patternfly/react-core';
2+
3+
import { DeliverableAnalyzerReport } from 'pnc-api-types-ts';
4+
5+
import { ButtonTitles } from 'common/constants';
6+
import {
7+
EditableDeliverableAnalysisLabel,
8+
deliverableAnalysisLabelEntryEntityAttributes,
9+
} from 'common/deliverableAnalysisLabelEntryEntityAttributes';
10+
11+
import { IFieldConfigs, IFieldValues, useForm } from 'hooks/useForm';
12+
import { useServiceContainer } from 'hooks/useServiceContainer';
13+
14+
import { ActionModal } from 'components/ActionModal/ActionModal';
15+
import { FormInputHelperText } from 'components/FormInputHelperText/FormInputHelperText';
16+
import { DeliverableAnalysisLabelLabelMapper } from 'components/LabelMapper/DeliverableAnalysisLabelLabelMapper';
17+
18+
import * as deliverableAnalysisApi from 'services/deliverableAnalysisApi';
19+
20+
import { maxLengthValidator } from 'utils/formValidationHelpers';
21+
22+
const fieldConfigs = {
23+
reason: {
24+
isRequired: true,
25+
validators: [maxLengthValidator(200)],
26+
},
27+
} satisfies IFieldConfigs;
28+
29+
interface IDeliverableAnalysisRemoveLabelModalProps {
30+
isModalOpen: boolean;
31+
toggleModal: () => void;
32+
deliverableAnalysisReport: DeliverableAnalyzerReport;
33+
label: EditableDeliverableAnalysisLabel;
34+
}
35+
36+
export const DeliverableAnalysisRemoveLabelModal = ({
37+
isModalOpen,
38+
toggleModal,
39+
deliverableAnalysisReport,
40+
label,
41+
}: IDeliverableAnalysisRemoveLabelModalProps) => {
42+
const serviceContainerDeliverableAnalysisRemoveLabel = useServiceContainer(
43+
deliverableAnalysisApi.removeDeliverableAnalysisLabel,
44+
0
45+
);
46+
47+
const { register, getFieldErrors, handleSubmit, isSubmitDisabled, hasFormChanged } = useForm();
48+
49+
const confirmModal = (data: IFieldValues) => {
50+
return serviceContainerDeliverableAnalysisRemoveLabel.run({
51+
serviceData: {
52+
id: deliverableAnalysisReport.id!,
53+
data: { label: label, reason: data.reason },
54+
},
55+
onError: () => console.error('Failed to remove Deliverable Analysis Label.'),
56+
});
57+
};
58+
59+
return (
60+
<ActionModal
61+
modalTitle={`${ButtonTitles.remove} Deliverable Analysis Label: ${deliverableAnalysisReport.id}`}
62+
actionTitle={ButtonTitles.remove}
63+
isOpen={isModalOpen}
64+
isSubmitDisabled={isSubmitDisabled}
65+
wereSubmitDataChanged={hasFormChanged}
66+
onToggle={toggleModal}
67+
onSubmit={handleSubmit(confirmModal)}
68+
serviceContainer={serviceContainerDeliverableAnalysisRemoveLabel}
69+
modalVariant="large"
70+
>
71+
<Form
72+
onSubmit={(e) => {
73+
e.preventDefault();
74+
}}
75+
>
76+
<FormGroup
77+
label={deliverableAnalysisLabelEntryEntityAttributes.label.title}
78+
fieldId={deliverableAnalysisLabelEntryEntityAttributes.label.id}
79+
>
80+
<DeliverableAnalysisLabelLabelMapper label={label} />
81+
</FormGroup>
82+
<FormGroup
83+
isRequired
84+
label={deliverableAnalysisLabelEntryEntityAttributes.reason.title}
85+
fieldId={deliverableAnalysisLabelEntryEntityAttributes.reason.id}
86+
>
87+
<TextArea
88+
isRequired
89+
type="text"
90+
id={deliverableAnalysisLabelEntryEntityAttributes.reason.id}
91+
name={deliverableAnalysisLabelEntryEntityAttributes.reason.id}
92+
resizeOrientation="vertical"
93+
autoComplete="off"
94+
{...register<string>(deliverableAnalysisLabelEntryEntityAttributes.reason.id, fieldConfigs.reason)}
95+
/>
96+
<FormInputHelperText variant="error">
97+
{getFieldErrors(deliverableAnalysisLabelEntryEntityAttributes.reason.id)}
98+
</FormInputHelperText>
99+
</FormGroup>
100+
</Form>
101+
</ActionModal>
102+
);
103+
};

src/components/LabelMapper/DeliverableAnalysisLabelLabelMapper.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ const DELIVERABLE_ANALYSIS_LABELS: ILabelMapper<deliverableAnalysisLabel> = {
2121

2222
interface IDeliverableAnalysisLabelLabelMapperProps {
2323
label: deliverableAnalysisLabel;
24+
onClose?: () => void;
2425
}
2526

26-
export const DeliverableAnalysisLabelLabelMapper = ({ label }: IDeliverableAnalysisLabelLabelMapperProps) => (
27-
<LabelMapper mapperItem={DELIVERABLE_ANALYSIS_LABELS[label]} />
27+
export const DeliverableAnalysisLabelLabelMapper = ({ label, onClose }: IDeliverableAnalysisLabelLabelMapperProps) => (
28+
<LabelMapper mapperItem={DELIVERABLE_ANALYSIS_LABELS[label]} onClose={onClose} />
2829
);

src/services/deliverableAnalysisApi.ts

+30-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { AxiosRequestConfig } from 'axios';
22

33
import { DeliverableAnalyzerReport } from 'pnc-api-types-ts';
44

5-
import { AssignableDeliverableAnalysisLabel } from 'common/deliverableAnalysisLabelEntryEntityAttributes';
5+
import { EditableDeliverableAnalysisLabel } from 'common/deliverableAnalysisLabelEntryEntityAttributes';
66

77
import { pncClient } from 'services/pncClient';
88

@@ -24,9 +24,37 @@ export const getDeliverableAnalysisReport = (
2424
return pncClient.getHttpClient().get<DeliverableAnalyzerReport>(`/deliverable-analyses/${id}`, requestConfig);
2525
};
2626

27+
interface IDeliverableAnalysisReportEditLabelApiData {
28+
id: string;
29+
data: { label: EditableDeliverableAnalysisLabel; reason: string };
30+
}
31+
32+
/**
33+
* Adds a label to the Deliverable Analysis report.
34+
*
35+
* @param serviceData - object containing:
36+
* - id - Deliverable Analysis ID
37+
* - data - label and the reason for the change
38+
* @param requestConfig - Axios based request config
39+
*/
2740
export const addDeliverableAnalysisLabel = (
28-
{ id, data }: { id: string; data: { label: AssignableDeliverableAnalysisLabel; reason: string } },
41+
{ id, data }: IDeliverableAnalysisReportEditLabelApiData,
2942
requestConfig: AxiosRequestConfig = {}
3043
) => {
3144
return pncClient.getHttpClient().post<undefined>(`/deliverable-analyses/${id}/add-label`, data, requestConfig);
3245
};
46+
47+
/**
48+
* Removes a label from the Deliverable Analysis report.
49+
*
50+
* @param serviceData - object containing:
51+
* - id - Deliverable Analysis ID
52+
* - data - label and the reason for the change
53+
* @param requestConfig - Axios based request config
54+
*/
55+
export const removeDeliverableAnalysisLabel = (
56+
{ id, data }: IDeliverableAnalysisReportEditLabelApiData,
57+
requestConfig: AxiosRequestConfig = {}
58+
) => {
59+
return pncClient.getHttpClient().post<undefined>(`/deliverable-analyses/${id}/remove-label`, data, requestConfig);
60+
};

0 commit comments

Comments
 (0)