Skip to content

Commit 2a4b652

Browse files
authored
Merge branch 'develop' into ocrvs-10132
2 parents 2b3495d + ec8c36d commit 2a4b652

File tree

17 files changed

+215
-47
lines changed

17 files changed

+215
-47
lines changed

packages/client/src/v2-events/components/forms/FormFieldGenerator/GeneratedInputField.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,9 @@ import { File } from '@client/v2-events/components/forms/inputs/FileInput/FileIn
9191
import { FileWithOption } from '@client/v2-events/components/forms/inputs/FileInput/DocumentUploaderWithOption'
9292
import { DateRangeField } from '@client/v2-events/features/events/registered-fields/DateRangeField'
9393
import { Name } from '@client/v2-events/features/events/registered-fields/Name'
94+
import { QueryParamReader } from '@client/v2-events/features/events/registered-fields/QueryParamReader'
9495
import { makeFormikFieldIdOpenCRVSCompatible } from '../utils'
9596
import { SignatureField } from '../inputs/SignatureField'
96-
import { QueryParamReader } from '../inputs/QueryParamReader'
9797
import {
9898
makeFormikFieldIdsOpenCRVSCompatible,
9999
parseFieldReferencesInConfiguration

packages/client/src/v2-events/features/events/actions/print-certificate/Review.tsx

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS.
1010
*/
1111

12-
import React from 'react'
12+
import React, { useState } from 'react'
1313
import { defineMessages, useIntl } from 'react-intl'
1414
import { Navigate, useNavigate } from 'react-router-dom'
1515
import { v4 as uuid } from 'uuid'
@@ -75,6 +75,7 @@ const TooltipMessage = styled.p`
7575
${({ theme }) => theme.fonts.reg19};
7676
max-width: 200px;
7777
`
78+
7879
const messages = defineMessages({
7980
printTitle: {
8081
id: 'printAction.title',
@@ -87,22 +88,11 @@ const messages = defineMessages({
8788
'Please confirm that the informant has reviewed that the information on the certificate is correct and that it is ready to print.',
8889
description: 'The description for print action'
8990
},
90-
printModalTitle: {
91-
id: 'print.certificate.review.printModalTitle',
92-
defaultMessage: 'Print certificate?',
93-
description: 'Print certificate modal title text'
94-
},
9591
printAndIssueModalTitle: {
9692
id: 'print.certificate.review.printAndIssueModalTitle',
9793
defaultMessage: 'Print and issue certificate?',
9894
description: 'Print and issue certificate modal title text'
9995
},
100-
printModalBody: {
101-
id: 'print.certificate.review.modal.body.print',
102-
defaultMessage:
103-
'A Pdf of the certificate will open in a new tab for printing. The record will move to the ready-to-issue queue.',
104-
description: 'Print certificate modal body text'
105-
},
10696
printAndIssueModalBody: {
10797
id: 'print.certificate.review.modal.body.printAndIssue',
10898
defaultMessage:
@@ -192,6 +182,7 @@ export function Review() {
192182
const formConfig = getPrintForm(eventConfiguration)
193183
const { isActionAllowed } = useUserAllowedActions(fullEvent.type)
194184
const userDetails = useSelector(getUserDetails)
185+
const { isPending } = onlineActions.printCertificate
195186

196187
if (!userDetails) {
197188
throw new Error('User details are not available')
@@ -281,6 +272,7 @@ export function Review() {
281272
</Button>,
282273
<Button
283274
key="print-certificate"
275+
disabled={!isOnline || isPending}
284276
id="print-certificate"
285277
type="primary"
286278
onClick={() => close(true)}
@@ -388,7 +380,7 @@ export function Review() {
388380
>
389381
<Button
390382
fullWidth
391-
disabled={!isOnline}
383+
disabled={!isOnline || isPending}
392384
id="confirm-print"
393385
size="large"
394386
type="positive"

packages/client/src/v2-events/components/forms/inputs/QueryParamReader.stories.tsx renamed to packages/client/src/v2-events/features/events/registered-fields/QueryParamReader.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020
never
2121
} from '@opencrvs/commons/client'
2222
import { TRPCProvider } from '@client/v2-events/trpc'
23-
import { FormFieldGenerator } from '../FormFieldGenerator'
23+
import { FormFieldGenerator } from '../../../components/forms/FormFieldGenerator'
2424
import { getTestValidatorContext } from '../../../../../.storybook/decorators'
2525

2626
interface Args {

packages/client/src/v2-events/components/forms/inputs/QueryParamReader.tsx renamed to packages/client/src/v2-events/features/events/registered-fields/QueryParamReader.tsx

File renamed without changes.

packages/client/src/v2-events/features/events/registered-fields/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import { TimeField } from './TimeField'
3333
import { AlphaPrintButton } from './AlphaPrintButton'
3434
import { LinkButton } from './LinkButton'
3535
import { VerificationStatus } from './VerificationStatus'
36+
import { QueryParamReader } from './QueryParamReader'
3637

3738
export * from './Address'
3839
export * from './AdministrativeArea'
@@ -109,6 +110,8 @@ export function getRegisteredFieldByFieldConfig<T extends FieldConfig>(
109110
return LinkButton
110111
case FieldType.VERIFICATION_STATUS:
111112
return VerificationStatus
113+
case FieldType.QUERY_PARAM_READER:
114+
return QueryParamReader
112115
default:
113116
return undefined
114117
}

packages/client/src/v2-events/features/events/useEventFormNavigation.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,10 @@ export function useEventFormNavigation() {
150150
closeActionView()
151151
}
152152

153-
async function deleteDeclaration(eventId: string) {
153+
async function deleteDeclaration(
154+
eventId: string,
155+
workqueueToGoBackTo?: string
156+
) {
154157
const deleteConfirm = await openModal<boolean | null>((close) => (
155158
<ResponsiveModal
156159
autoHeight
@@ -191,7 +194,7 @@ export function useEventFormNavigation() {
191194

192195
if (deleteConfirm) {
193196
deleteEvent.mutate({ eventId })
194-
closeActionView()
197+
closeActionView(workqueueToGoBackTo)
195198
}
196199
}
197200

packages/client/src/v2-events/features/events/useEvents/procedures/actions/action.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,8 @@ export function useEventAction<P extends DecorateMutationProcedure<any>>(
465465
mutate: (params: ActionMutationInput) =>
466466
mutation.mutate(getMutationPayload(params)),
467467
mutateAsync: async (params: ActionMutationInput) =>
468-
mutation.mutateAsync(getMutationPayload(params))
468+
mutation.mutateAsync(getMutationPayload(params)),
469+
isPending: mutation.isPending
469470
}
470471
}
471472

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/*
2+
* This Source Code Form is subject to the terms of the Mozilla Public
3+
* License, v. 2.0. If a copy of the MPL was not distributed with this
4+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
5+
*
6+
* OpenCRVS is also distributed under the terms of the Civil Registration
7+
* & Healthcare Disclaimer located at http://opencrvs.org/license.
8+
*
9+
* Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS.
10+
*/
11+
import { Meta, StoryObj } from '@storybook/react'
12+
import { userEvent, waitFor, within, expect } from '@storybook/test'
13+
import superjson from 'superjson'
14+
import { createTRPCMsw, httpLink } from '@vafanassieff/msw-trpc'
15+
import {
16+
ActionType,
17+
generateEventDocument,
18+
getCurrentEventState,
19+
tennisClubMembershipEvent
20+
} from '@opencrvs/commons/client'
21+
import { ROUTES, routesConfig } from '@client/v2-events/routes'
22+
import { AppRouter } from '@client/v2-events/trpc'
23+
import {
24+
addLocalEventConfig,
25+
setEventData
26+
} from '@client/v2-events/features/events/useEvents/api'
27+
import { ActionMenu } from '../ActionMenu'
28+
29+
export default {
30+
title: 'ActionMenu/RegistrationAgent/Deleted'
31+
} as Meta<typeof ActionMenu>
32+
33+
const createdEventDocument = generateEventDocument({
34+
configuration: tennisClubMembershipEvent,
35+
actions: [ActionType.CREATE, ActionType.ASSIGN],
36+
user: {
37+
assignedTo: '6821c175dce4d7886d4e8210'
38+
}
39+
})
40+
41+
const eventState = getCurrentEventState(
42+
createdEventDocument,
43+
tennisClubMembershipEvent
44+
)
45+
46+
const tRPCMsw = createTRPCMsw<AppRouter>({
47+
links: [
48+
httpLink({
49+
url: '/api/events'
50+
})
51+
],
52+
transformer: { input: superjson, output: superjson }
53+
})
54+
55+
export const deletedScenariosForRegistrationAgent: StoryObj<typeof ActionMenu> =
56+
{
57+
parameters: {
58+
layout: 'centered',
59+
reactRouter: {
60+
router: routesConfig,
61+
initialPath: ROUTES.V2.EVENTS.OVERVIEW.buildPath({
62+
eventId: createdEventDocument.id
63+
})
64+
},
65+
msw: {
66+
events: [
67+
tRPCMsw.event.search.query(() => {
68+
return {
69+
results: [eventState],
70+
total: 1
71+
}
72+
})
73+
]
74+
}
75+
},
76+
beforeEach: () => {
77+
/*
78+
* Ensure record is "downloaded offline" in the user's browser
79+
*/
80+
addLocalEventConfig(tennisClubMembershipEvent)
81+
setEventData(createdEventDocument.id, createdEventDocument)
82+
},
83+
play: async ({ canvasElement, step }) => {
84+
const canvas = within(canvasElement)
85+
86+
await step(
87+
'Renders modal when delete declaration is clicked',
88+
async () => {
89+
await new Promise((resolve) => setTimeout(resolve, 5000))
90+
void canvas.getByTestId('action-dropdownMenu').click()
91+
92+
// wait for the list to appear
93+
const list = await waitFor(() =>
94+
document.querySelector('#action-Dropdown-Content')
95+
)
96+
97+
// click the 3rd <li>
98+
const items = list?.querySelectorAll('li')
99+
if (!items || items.length < 3) {
100+
throw new Error('Menu items not found')
101+
}
102+
103+
await userEvent.click(items[2])
104+
105+
await expect(canvas.getByText('Delete draft?')).toBeInTheDocument()
106+
await expect(
107+
canvas.getByText(
108+
"Are you certain you want to delete this draft declaration form? Please note, this action can't be undone."
109+
)
110+
).toBeInTheDocument()
111+
112+
const cancelDelete = await waitFor(() =>
113+
document.querySelector('#cancel_delete')
114+
)
115+
116+
if (!cancelDelete) {
117+
throw new Error('Cancel delete button not found')
118+
}
119+
120+
await userEvent.click(cancelDelete)
121+
}
122+
)
123+
}
124+
}

packages/client/src/v2-events/features/workqueues/EventOverview/components/useAllowedActionConfigurations.tsx

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*/
1111
import { useNavigate } from 'react-router-dom'
1212
import { useSelector } from 'react-redux'
13-
import React from 'react'
13+
import React, { useCallback } from 'react'
1414
import { useIntl } from 'react-intl'
1515
import {
1616
ActionType,
@@ -207,13 +207,20 @@ function useViewableActionConfigurations(
207207
locations.find((l) => l.id === assignedOffice)?.name || ''
208208
const { archiveModal, onArchive } = useArchiveModal()
209209

210+
const { modal: deleteModal, deleteDeclaration } = useEventFormNavigation()
211+
const onDelete = useCallback(
212+
async (workqueue?: string) => {
213+
await deleteDeclaration(event.id, workqueue)
214+
},
215+
[event, deleteDeclaration]
216+
)
217+
210218
/**
211219
* Refer to https://tanstack.com/query/latest/docs/framework/react/guides/dependent-queries
212220
* This does not immediately execute the query but instead prepares it to be fetched conditionally when needed.
213221
*/
214222
const { refetch: refetchEvent } = events.getEvent.findFromCache(event.id)
215223

216-
const { mutate: deleteEvent } = events.deleteEvent.useMutation()
217224
const { eventConfiguration } = useEventConfiguration(event.type)
218225

219226
const assignmentStatus = getAssignmentStatus(event, authentication.sub)
@@ -269,7 +276,7 @@ function useViewableActionConfigurations(
269276
* If you need to extend the functionality, consider whether it can be done elsewhere.
270277
*/
271278
return {
272-
modals: [assignModal, archiveModal],
279+
modals: [assignModal, archiveModal, deleteModal],
273280
config: {
274281
[ActionType.READ]: {
275282
label: actionLabels[ActionType.READ],
@@ -406,14 +413,8 @@ function useViewableActionConfigurations(
406413
[ActionType.DELETE]: {
407414
label: actionLabels[ActionType.DELETE],
408415
icon: 'Trash' as const,
409-
onClick: (workqueue?: string) => {
410-
deleteEvent({
411-
eventId: event.id
412-
})
413-
// What if there is a workqueue?
414-
if (!workqueue) {
415-
navigate(ROUTES.V2.buildPath({}))
416-
}
416+
onClick: async (workqueue?: string) => {
417+
await onDelete(workqueue)
417418
},
418419
disabled: !isDownloadedAndAssignedToUser
419420
},

packages/commons/src/events/FieldConfig.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ const BaseField = z.object({
9191
'Reference to a parent field. If a field has a parent, it will be reset when the parent field is changed.'
9292
),
9393
required: requiredSchema,
94-
disabled: z.boolean().default(false).optional(),
9594
conditionals: z.array(FieldConditional).default([]).optional(),
9695
secured: z.boolean().default(false).optional(),
9796
placeholder: TranslationConfig.optional(),
@@ -824,7 +823,8 @@ export const FieldConfig: z.ZodType<
824823
AlphaPrintButton,
825824
HttpField,
826825
LinkButtonField,
827-
VerificationStatus
826+
VerificationStatus,
827+
QueryParamReaderField
828828
])
829829
.openapi({
830830
description: 'Form field configuration',

0 commit comments

Comments
 (0)