Skip to content

Commit 7629847

Browse files
committed
feat(dref-translation): use finalize api in dref table and add view mode in all dref forms
1 parent eb36b71 commit 7629847

File tree

60 files changed

+936
-89
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+936
-89
lines changed

app/src/components/domain/ImageWithCaptionInput/index.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ interface Props<N> {
3030
name: N;
3131
url: SupportedPaths;
3232
value: Value | null | undefined;
33+
readOnly: boolean;
3334
onChange: (value: SetValueArg<Value> | undefined, name: N) => void;
3435
error: ObjectError<Value> | undefined;
3536
fileIdToUrlMap: Record<number, string>;
@@ -44,6 +45,7 @@ interface Props<N> {
4445
function ImageWithCaptionInput<const N extends string | number>(props: Props<N>) {
4546
const {
4647
className,
48+
readOnly,
4749
name,
4850
value,
4951
url,
@@ -92,6 +94,7 @@ function ImageWithCaptionInput<const N extends string | number>(props: Props<N>)
9294
name="id"
9395
accept="image/*"
9496
value={value?.id}
97+
readOnly={readOnly}
9598
onChange={handleFileInputChange}
9699
url={url}
97100
fileIdToUrlMap={fileIdToUrlMap}
@@ -116,6 +119,7 @@ function ImageWithCaptionInput<const N extends string | number>(props: Props<N>)
116119
className={styles.captionInput}
117120
name="caption"
118121
value={value?.caption}
122+
readOnly={readOnly}
119123
onChange={setFieldValue}
120124
error={error?.caption}
121125
placeholder={strings.imageWithCaptionEnterCaption}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"namespace": "languageMismatchMessage",
33
"strings": {
4-
"languageMismatchErrorTitle": "Edit not available in selected language!",
5-
"languageMismatchErrorMessage": "This form was originally created in {originalLanguage} and cannot be edited in a different language!",
6-
"languageMismatchHelpMessage": "Please change the language to {originalLanguage} to edit it!"
4+
"languageMismatchErrorTitle": "Edit not available in {selectedLanguage} language!",
5+
"languageMismatchErrorMessage": "This is because form was originally created in {originalLanguage} language and edits cannot be edited in the {selectedLanguage} language.",
6+
"languageMismatchHelpMessage": "To make changes, please switch to the original language of the form."
77
}
88
}

app/src/components/domain/LanguageMismatchMessage/index.tsx

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,16 @@ interface Props {
1414
// FIXME: typings should be fixed in the server
1515
// this should be of type Language
1616
originalLanguage: string | undefined;
17+
selectedLanguage: Language;
1718
}
1819

1920
function LanguageMismatchMessage(props: Props) {
2021
const strings = useTranslation(i18n);
2122

2223
const {
2324
title = strings.languageMismatchErrorTitle,
24-
originalLanguage = 'en',
25+
originalLanguage,
26+
selectedLanguage,
2527
} = props;
2628

2729
return (
@@ -32,16 +34,13 @@ function LanguageMismatchMessage(props: Props) {
3234
resolveToString(
3335
strings.languageMismatchErrorMessage,
3436
// FIXME: this should not require cast
35-
{ originalLanguage: languageNameMapEn[originalLanguage as Language] ?? '--' },
36-
)
37-
}
38-
actions={
39-
resolveToString(
40-
strings.languageMismatchHelpMessage,
41-
// FIXME: this should not require cast
42-
{ originalLanguage: languageNameMapEn[originalLanguage as Language] ?? '--' },
37+
{
38+
originalLanguage: languageNameMapEn[originalLanguage as Language] ?? '--',
39+
selectedLanguage: languageNameMapEn[selectedLanguage] ?? '--',
40+
},
4341
)
4442
}
43+
actions={strings.languageMismatchHelpMessage}
4544
/>
4645
);
4746
}

app/src/components/domain/MultiImageWithCaptionInput/index.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ interface Props<N> {
4545
label: React.ReactNode;
4646
icons?: React.ReactNode;
4747
actions?: React.ReactNode;
48+
readOnly?: boolean;
4849
disabled?: boolean;
4950
}
5051

@@ -62,6 +63,7 @@ function MultiImageWithCaptionInput<const N extends string | number>(props: Prop
6263
label,
6364
icons,
6465
actions,
66+
readOnly,
6567
disabled,
6668
} = props;
6769

@@ -139,6 +141,7 @@ function MultiImageWithCaptionInput<const N extends string | number>(props: Prop
139141
icons={icons}
140142
actions={actions}
141143
withoutPreview
144+
readOnly={readOnly}
142145
disabled={disabled}
143146
>
144147
{label}
@@ -168,7 +171,7 @@ function MultiImageWithCaptionInput<const N extends string | number>(props: Prop
168171
ariaLabel={strings.removeImagesButtonTitle}
169172
variant="secondary"
170173
spacing="none"
171-
disabled={disabled}
174+
disabled={disabled || readOnly}
172175
>
173176
<DeleteBinLineIcon />
174177
</IconButton>
@@ -187,6 +190,7 @@ function MultiImageWithCaptionInput<const N extends string | number>(props: Prop
187190
onChange={handleCaptionChange}
188191
error={imageError?.caption}
189192
placeholder={strings.enterCaptionPlaceholder}
193+
readOnly={readOnly}
190194
disabled={disabled}
191195
/>
192196
</div>

app/src/components/domain/SourceInformationInput/index.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ interface Props {
3131
onRemove: (index: number) => void;
3232
index: number;
3333
disabled?: boolean;
34+
readOnly: boolean;
3435
}
3536

3637
function SourceInformationInput(props: Props) {
@@ -41,6 +42,7 @@ function SourceInformationInput(props: Props) {
4142
index,
4243
onRemove,
4344
disabled,
45+
readOnly,
4446
} = props;
4547

4648
const strings = useTranslation(i18n);
@@ -92,6 +94,7 @@ function SourceInformationInput(props: Props) {
9294
value={value.source_name}
9395
error={error?.source_name}
9496
onChange={onFieldChange}
97+
readOnly={readOnly}
9598
disabled={disabled}
9699
/>
97100
<TextInput
@@ -101,14 +104,15 @@ function SourceInformationInput(props: Props) {
101104
value={value.source_link}
102105
error={error?.source_link}
103106
onChange={handleSourceFieldChange}
107+
readOnly={readOnly}
104108
disabled={disabled}
105109
/>
106110
<Button
107111
className={styles.removeButton}
108112
name={index}
109113
onClick={onRemove}
110114
variant="tertiary"
111-
disabled={disabled}
115+
disabled={disabled || readOnly}
112116
title={strings.sourceInformationDeleteButton}
113117
>
114118
<DeleteBinTwoLineIcon />

app/src/utils/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ export const FONT_FAMILY_HEADER = 'Montserrat';
8383
// FIXME: fix typing in server (medium priority)
8484
// This should not be the same as OperationType.
8585
export type DrefStatus = components<'read'>['schemas']['DrefDrefStatusEnumKey'];
86-
// const DREF_STATUS_COMPLETED = 1 satisfies DrefStatus;
8786
export const DREF_STATUS_DRAFT = 1 satisfies DrefStatus;
87+
export const DREF_STATUS_FINALIZED = 3 satisfies DrefStatus;
8888
export const DREF_STATUS_APPROVED = 4 satisfies DrefStatus;
8989

9090
export type TypeOfDrefEnum = components<'read'>['schemas']['DrefDrefDrefTypeEnumKey'];

app/src/views/AccountMyFormsDref/DrefTableActions/i18n.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"namespace": "accountMyFormsDref",
33
"strings": {
44
"dropdownActionApproveLabel": "Approved",
5+
"dropdownActionFinalizeLabel": "Finalize",
56
"dropdownActionAllocationFormLabel": "Allocation Form",
67
"dropdownActionAddOpsUpdateLabel": "Add Operational Update",
78
"dropdownActionCreateFinalReportLabel": "Create Final Report",
@@ -10,10 +11,13 @@
1011
"dropdownActionEditLabel": "Edit",
1112
"drefApprovalSuccessTitle": "Successfully approved the DREF!",
1213
"drefApprovalFailureTitle": "Failed to approve the DREF!",
14+
"drefFinalizeSuccessTitle": "Successfully finalize the DREF!",
15+
"drefFinalizeFailureTitle": "Failed to finalize the DREF!",
1316
"drefApprovalInProgressTitle": "Approval in progress...",
1417
"drefAccountCouldNotCreate": "Could not create new operational update",
1518
"drefAccountCouldNotCreateFinalReport": "Could not create final report",
1619
"drefAccountConfirmMessage": "You're about to Approve this DREF. Once approved, it can no longer be edited. Are you sure you want to Approve?",
20+
"drefAccountFinalizeConfirmMessage": "You're about to Finalize this DREF. Once finalize, it can no longer be edited. Are you sure you want to Finalize?",
1721
"dropdownActionImminentNewOpsUpdateConfirmationHeading": "Confirm addition of Operational Update",
1822
"dropdownActionImminentNewOpsUpdateConfirmationMessage": "The DREF type will be changed to Response (from Imminent) for the Operational Update. Once created, you'll be able to change it to other types except Imminent. Are you sure you want to add an Operational Update?"
1923
}

app/src/views/AccountMyFormsDref/DrefTableActions/index.tsx

Lines changed: 133 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import useAlert from '#hooks/useAlert';
2828
import useRouting from '#hooks/useRouting';
2929
import {
3030
DREF_STATUS_DRAFT,
31+
DREF_STATUS_FINALIZED,
3132
DREF_TYPE_IMMINENT,
3233
DREF_TYPE_LOAN,
3334
type DrefStatus,
@@ -255,6 +256,96 @@ function DrefTableActions(props: Props) {
255256
},
256257
});
257258

259+
const {
260+
trigger: finalizeDref,
261+
pending: finalizeDrefPending,
262+
} = useLazyRequest({
263+
method: 'POST',
264+
url: '/api/v2/dref/{id}/finalize/',
265+
pathVariables: { id: String(id) },
266+
body: () => ({} as never),
267+
onSuccess: () => {
268+
alert.show(
269+
strings.drefFinalizeSuccessTitle,
270+
{ variant: 'success' },
271+
);
272+
if (onPublishSuccess) {
273+
onPublishSuccess();
274+
}
275+
},
276+
onFailure: ({
277+
value: { messageForNotification },
278+
}) => {
279+
alert.show(
280+
strings.drefFinalizeFailureTitle,
281+
{
282+
description: messageForNotification,
283+
variant: 'danger',
284+
},
285+
);
286+
},
287+
});
288+
289+
const {
290+
trigger: finalizeOpsUpdate,
291+
pending: finalizeOpsUpdatePending,
292+
} = useLazyRequest({
293+
method: 'POST',
294+
url: '/api/v2/dref-op-update/{id}/finalize/',
295+
pathVariables: { id: String(id) },
296+
body: () => ({} as never),
297+
onSuccess: () => {
298+
alert.show(
299+
strings.drefFinalizeSuccessTitle,
300+
{ variant: 'success' },
301+
);
302+
if (onPublishSuccess) {
303+
onPublishSuccess();
304+
}
305+
},
306+
onFailure: ({
307+
value: { messageForNotification },
308+
}) => {
309+
alert.show(
310+
strings.drefFinalizeFailureTitle,
311+
{
312+
description: messageForNotification,
313+
variant: 'danger',
314+
},
315+
);
316+
},
317+
});
318+
319+
const {
320+
trigger: finalizeFinalReport,
321+
pending: finalizeFinalReportPending,
322+
} = useLazyRequest({
323+
method: 'POST',
324+
url: '/api/v2/dref-final-report/{id}/finalize/',
325+
pathVariables: { id: String(id) },
326+
body: () => ({} as never),
327+
onSuccess: () => {
328+
alert.show(
329+
strings.drefFinalizeSuccessTitle,
330+
{ variant: 'success' },
331+
);
332+
if (onPublishSuccess) {
333+
onPublishSuccess();
334+
}
335+
},
336+
onFailure: ({
337+
value: { messageForNotification },
338+
}) => {
339+
alert.show(
340+
strings.drefFinalizeFailureTitle,
341+
{
342+
description: messageForNotification,
343+
variant: 'danger',
344+
},
345+
);
346+
},
347+
});
348+
258349
// FIXME: the type should be fixed on the server
259350
type OpsUpdateRequestBody = GoApiBody<'/api/v2/dref-op-update/', 'POST'>;
260351

@@ -368,6 +459,26 @@ function DrefTableActions(props: Props) {
368459
],
369460
);
370461

462+
const handleFinalizeClick = useCallback(
463+
() => {
464+
if (applicationType === 'DREF') {
465+
finalizeDref(null);
466+
} else if (applicationType === 'OPS_UPDATE') {
467+
finalizeOpsUpdate(null);
468+
} else if (applicationType === 'FINAL_REPORT') {
469+
finalizeFinalReport(null);
470+
} else {
471+
applicationType satisfies never;
472+
}
473+
},
474+
[
475+
applicationType,
476+
finalizeDref,
477+
finalizeOpsUpdate,
478+
finalizeFinalReport,
479+
],
480+
);
481+
371482
const handleDrefAllocationExport = useCallback(
372483
() => {
373484
if (applicationType === 'DREF') {
@@ -385,13 +496,18 @@ function DrefTableActions(props: Props) {
385496

386497
const canDownloadAllocation = (applicationType === 'DREF' || applicationType === 'OPS_UPDATE');
387498

388-
const canApprove = status === DREF_STATUS_DRAFT && hasPermissionToApprove;
499+
const canApprove = status === DREF_STATUS_FINALIZED && hasPermissionToApprove;
500+
501+
const canFinalize = status === DREF_STATUS_DRAFT && hasPermissionToApprove;
389502

390503
const shouldConfirmImminentAddOpsUpdate = drefType === DREF_TYPE_IMMINENT && isDrefImminentV2;
391504

392505
const disabled = fetchingDref
393506
|| fetchingOpsUpdate
394507
|| publishDrefPending
508+
|| finalizeDrefPending
509+
|| finalizeOpsUpdatePending
510+
|| finalizeFinalReportPending
395511
|| publishOpsUpdatePending
396512
|| publishFinalReportPending
397513
|| createOpsUpdatePending
@@ -402,6 +518,19 @@ function DrefTableActions(props: Props) {
402518
persistent
403519
extraActions={(
404520
<>
521+
{canFinalize && (
522+
<DropdownMenuItem
523+
name={undefined}
524+
type="confirm-button"
525+
icons={<CheckLineIcon className={styles.icon} />}
526+
confirmMessage={strings.drefAccountFinalizeConfirmMessage}
527+
onConfirm={handleFinalizeClick}
528+
disabled={disabled}
529+
persist
530+
>
531+
{strings.dropdownActionFinalizeLabel}
532+
</DropdownMenuItem>
533+
)}
405534
{canApprove && (
406535
<DropdownMenuItem
407536
name={undefined}
@@ -494,7 +623,7 @@ function DrefTableActions(props: Props) {
494623
</>
495624
)}
496625
>
497-
{status === DREF_STATUS_DRAFT && applicationType === 'DREF' && (
626+
{(status === DREF_STATUS_DRAFT || status === DREF_STATUS_FINALIZED) && applicationType === 'DREF' && (
498627
<Link
499628
to="drefApplicationForm"
500629
urlParams={{ drefId: id }}
@@ -504,7 +633,7 @@ function DrefTableActions(props: Props) {
504633
{strings.dropdownActionEditLabel}
505634
</Link>
506635
)}
507-
{status === DREF_STATUS_DRAFT && applicationType === 'OPS_UPDATE' && (
636+
{(status === DREF_STATUS_DRAFT || status === DREF_STATUS_FINALIZED) && applicationType === 'OPS_UPDATE' && (
508637
<Link
509638
to="drefOperationalUpdateForm"
510639
urlParams={{ opsUpdateId: id }}
@@ -514,7 +643,7 @@ function DrefTableActions(props: Props) {
514643
{strings.dropdownActionEditLabel}
515644
</Link>
516645
)}
517-
{status === DREF_STATUS_DRAFT && applicationType === 'FINAL_REPORT' && (
646+
{(status === DREF_STATUS_DRAFT || status === DREF_STATUS_FINALIZED) && applicationType === 'FINAL_REPORT' && (
518647
<Link
519648
to={isDrefImminentV2 ? 'drefFinalReportForm' : 'oldDrefFinalReportForm'}
520649
urlParams={{ finalReportId: id }}

0 commit comments

Comments
 (0)