Skip to content

Commit 88a1423

Browse files
committed
Merge branch 'release-v1.9.1' into release-v1.9.2
2 parents fd254a6 + 5d5b020 commit 88a1423

File tree

13 files changed

+169
-91
lines changed

13 files changed

+169
-91
lines changed

development-environment/reindex.sh

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,31 @@ get_reindexing_token() {
1818
}
1919

2020
trigger_reindex() {
21-
local token
21+
local token raw status body
2222
token=$(get_reindexing_token)
23-
curl -s -f -X POST \
23+
24+
raw=$(curl -X POST \
2425
-H "Authorization: Bearer ${token}" \
2526
-H "Content-Type: application/json" \
26-
"${EVENTS_URL%/}/events/reindex"
27+
-w "\n%{http_code}" \
28+
"${EVENTS_URL%/}/events/reindex" 2>&1)
29+
30+
status=$(echo "$raw" | tail -n1)
31+
body=$(echo "$raw" | sed '$d')
32+
33+
if [[ "$status" == "000" ]]; then
34+
echo "curl failed (connection or TLS error)"
35+
echo "$body"
36+
return 1
37+
fi
38+
39+
if (( status >= 200 && status < 300 )); then
40+
return 0
41+
fi
42+
43+
echo "curl failed with status $status"
44+
echo "$body"
45+
return 1
2746
}
2847

2948
reindexing_attempts=0

packages/client/.storybook/preview.tsx

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import { useApolloClient } from '@client/utils/apolloClient'
2222
import { ApolloProvider } from '@client/utils/ApolloProvider'
2323
import { queryClient, TRPCProvider } from '@client/v2-events/trpc'
2424
import { Provider, useSelector } from 'react-redux'
25-
import { clear } from 'idb-keyval'
2625
import {
2726
createMemoryRouter,
2827
Outlet,
@@ -53,6 +52,7 @@ import {
5352
} from '@client/v2-events/features/events/fixtures'
5453
import { EventConfig } from '@opencrvs/commons/client'
5554
import { getUserDetails } from '@client/profile/profileSelectors'
55+
import { storage } from '@client/storage'
5656

5757
WebFont.load({
5858
google: {
@@ -165,15 +165,6 @@ export const parameters = {
165165

166166
const generator = testDataGenerator()
167167

168-
/*
169-
* Clear all indexedDB databases before each story
170-
*/
171-
export async function clearStorage() {
172-
clear()
173-
}
174-
175-
clearStorage()
176-
177168
const preview: Preview = {
178169
loaders: [
179170
mswLoader,
@@ -197,7 +188,7 @@ const preview: Preview = {
197188
}
198189
},
199190
async (options) => {
200-
await clearStorage()
191+
await storage.clearStorage()
201192
queryClient.clear()
202193
const primaryOfficeId = '028d2c85-ca31-426d-b5d1-2cef545a4902' as UUID
203194

packages/client/src/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ WebFont.load({
2929
}
3030
})
3131

32-
storage.configStorage('OpenCRVS')
32+
storage.configStorage()
3333

3434
const { store } = createStore()
3535

packages/client/src/storage.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,37 @@
88
*
99
* Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS.
1010
*/
11-
import { createStore, get, set, del, UseStore } from 'idb-keyval'
11+
import { createStore, get, set, del, entries, clear } from 'idb-keyval'
1212
import { validateApplicationVersion } from '@client/utils'
1313

14-
let store: UseStore | undefined
15-
function configStorage(dbName: string) {
16-
store = createStore(dbName, 'keyvaluepairs')
14+
const DATABASE_NAME = 'OpenCRVS'
15+
const STORE_NAME = 'keyvaluepairs'
16+
17+
/**
18+
* Create store when module is first loaded.
19+
*
20+
* Previously store was created on-demand, initiated at application root. (index.tsx).
21+
* However, files are executed during import. React renders after everything is imported.
22+
*
23+
* There is no guarantee that application root is executed before other files that might use storage (e.g. useDrafts).
24+
*/
25+
let store = createStore(DATABASE_NAME, STORE_NAME)
26+
27+
function configStorage() {
28+
if (!store) {
29+
store = createStore(DATABASE_NAME, STORE_NAME)
30+
}
1731

1832
validateApplicationVersion()
1933
}
2034

2135
async function getItem<T = string>(key: string): Promise<T | null> {
36+
if (!store) {
37+
// eslint-disable-next-line no-console
38+
console.error('IDB store not initialized before getItem:', key)
39+
return null
40+
}
41+
2242
return (await get<T>(key, store)) || null
2343
}
2444

@@ -30,8 +50,13 @@ async function removeItem(key: string) {
3050
return await del(key, store)
3151
}
3252

53+
async function clearStorage() {
54+
return clear(store)
55+
}
56+
3357
export const storage = {
3458
configStorage,
59+
clearStorage,
3560
getItem,
3661
setItem,
3762
removeItem

packages/client/src/v2-events/features/drafts/useDrafts.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ export function useDrafts() {
231231

232232
createDraft.mutate({
233233
eventId: localDraft.eventId,
234-
declaration: deepDropNulls(localDraft.action.declaration),
234+
declaration: localDraft.action.declaration,
235235
annotation: deepDropNulls(localDraft.action.annotation),
236236
transactionId: localDraft.transactionId,
237237
type: localDraft.action.type,

packages/client/src/v2-events/features/events/ReadOnlyView.stories.tsx

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ import {
2121
generateEventDraftDocument,
2222
generateWorkqueues,
2323
getCurrentEventState,
24-
tennisClubMembershipEvent
24+
tennisClubMembershipEvent,
25+
TestUserRole
2526
} from '@opencrvs/commons/client'
2627
import { AppRouter } from '@client/v2-events/trpc'
2728
import { ROUTES, routesConfig } from '@client/v2-events/routes'
@@ -72,17 +73,6 @@ const modifiedDraft = generateEventDraftDocument({
7273
})
7374

7475
export const ViewRecordMenuItemInsideActionMenus: Story = {
75-
loaders: [
76-
async () => {
77-
window.localStorage.setItem(
78-
'opencrvs',
79-
generator.user.token.localRegistrar
80-
)
81-
// Intermittent failures starts to happen when global state gets out of whack.
82-
// // This is a workaround to ensure that the state is reset when similar tests are run in parallel.
83-
await new Promise((resolve) => setTimeout(resolve, 50))
84-
}
85-
],
8676
play: async ({ canvasElement, step }) => {
8777
const canvas = within(canvasElement)
8878
await step('Finds view record menu item in action menu', async () => {
@@ -108,6 +98,7 @@ export const ViewRecordMenuItemInsideActionMenus: Story = {
10898
})
10999
},
110100
parameters: {
101+
userRole: TestUserRole.enum.LOCAL_REGISTRAR,
111102
reactRouter: {
112103
router: routesConfig,
113104
initialPath: ROUTES.V2.EVENTS.OVERVIEW.buildPath({

packages/client/src/v2-events/features/events/components/Action/DeclarationAction.tsx

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import {
1616
Draft,
1717
createEmptyDraft,
1818
findActiveDraftForEvent,
19-
dangerouslyGetCurrentEventStateWithDrafts,
2019
getActionAnnotation,
2120
ActionType,
2221
deepMerge,
@@ -26,7 +25,8 @@ import {
2625
EventDocument,
2726
EventConfig,
2827
getAvailableActionsForEvent,
29-
getCurrentEventState
28+
getCurrentEventState,
29+
applyDraftToEventIndex
3030
} from '@opencrvs/commons/client'
3131
import { withSuspense } from '@client/v2-events/components/withSuspense'
3232
import { useEventFormData } from '@client/v2-events/features/events/useEventFormData'
@@ -190,14 +190,10 @@ function DeclarationActionComponent({
190190
? mergeDrafts(activeRemoteDraft, localDraftWithAdjustedTimestamp)
191191
: localDraftWithAdjustedTimestamp
192192

193-
const eventStateWithDrafts = useMemo(
194-
() =>
195-
dangerouslyGetCurrentEventStateWithDrafts({
196-
event,
197-
draft: mergedDraft,
198-
configuration
199-
}),
200-
[mergedDraft, event, configuration]
193+
const eventStateWithDraftApplied = applyDraftToEventIndex(
194+
getCurrentEventState(event, configuration),
195+
mergedDraft,
196+
configuration
201197
)
202198

203199
const actionAnnotation = useMemo(() => {
@@ -249,7 +245,7 @@ function DeclarationActionComponent({
249245
// Then use form values from drafts.
250246
const initialFormValues = deepMerge(
251247
currentDeclaration || {},
252-
eventStateWithDrafts.declaration
248+
eventStateWithDraftApplied.declaration
253249
)
254250

255251
setFormValues(initialFormValues)

packages/client/src/v2-events/features/events/components/Output.stories.tsx

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,3 +324,63 @@ export const DataOutput: Story = {
324324
} satisfies FieldValue
325325
}
326326
}
327+
328+
export const VerificationStatusOutputWhenStatusIsVerified: Story = {
329+
args: {
330+
value: 'verified',
331+
field: {
332+
type: FieldType.VERIFICATION_STATUS,
333+
id: 'applicant.verificationStatus',
334+
label: {
335+
id: 'applicant.verificationStatus',
336+
defaultMessage: 'Verification Status',
337+
description: 'The verification status of the applicant'
338+
},
339+
configuration: {
340+
status: {
341+
id: 'verified.status.text',
342+
defaultMessage:
343+
'{value, select, authenticated {ID Authenticated} verified {ID Verified} failed {Unverified ID} pending {Pending verification} other {Invalid value}}',
344+
description:
345+
'Status text shown on the pill on both form declaration and review page'
346+
},
347+
description: {
348+
id: 'verified.status.description',
349+
defaultMessage:
350+
"{value, select, authenticated {This identity has been successfully authenticated with the Farajaland’s National ID System. To make edits, please remove the authentication first.} verified {This identity data has been successfully verified with the Farajaland’s National ID System. Please note that their identity has not been authenticated using the individual's biometrics. To make edits, please remove the verification first.} pending {Identity pending verification with Farajaland’s National ID system} failed {The identity data does not match an entry in Farajaland’s National ID System} other {Invalid value}}",
351+
description: 'Description text of the status'
352+
}
353+
}
354+
}
355+
}
356+
}
357+
358+
export const VerificationStatusOutputWhenStatusIsNull: Story = {
359+
args: {
360+
value: null,
361+
field: {
362+
type: FieldType.VERIFICATION_STATUS,
363+
id: 'applicant.verificationStatus',
364+
label: {
365+
id: 'applicant.verificationStatus',
366+
defaultMessage: 'Verification Status',
367+
description: 'The verification status of the applicant'
368+
},
369+
configuration: {
370+
status: {
371+
id: 'verified.status.text',
372+
defaultMessage:
373+
'{value, select, authenticated {ID Authenticated} verified {ID Verified} failed {Unverified ID} pending {Pending verification} other {Invalid value}}',
374+
description:
375+
'Status text shown on the pill on both form declaration and review page'
376+
},
377+
description: {
378+
id: 'verified.status.description',
379+
defaultMessage:
380+
"{value, select, authenticated {This identity has been successfully authenticated with the Farajaland’s National ID System. To make edits, please remove the authentication first.} verified {This identity data has been successfully verified with the Farajaland’s National ID System. Please note that their identity has not been authenticated using the individual's biometrics. To make edits, please remove the verification first.} pending {Identity pending verification with Farajaland’s National ID system} failed {The identity data does not match an entry in Farajaland’s National ID System} other {Invalid value}}",
381+
description: 'Description text of the status'
382+
}
383+
}
384+
}
385+
}
386+
}

packages/client/src/v2-events/features/events/registered-fields/LinkButton.tsx

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,23 +35,7 @@ function LinkButtonInput({
3535
}) {
3636
const intl = useIntl()
3737
const url = setRedirectURI(configuration.url)
38-
const { submitLocalDraft, isLocalDraftSubmitted } = useDrafts()
3938

40-
useEffect(() => {
41-
if (isLocalDraftSubmitted) {
42-
window.location.href = url
43-
}
44-
}, [isLocalDraftSubmitted, url])
45-
46-
const handleClick = (e: React.MouseEvent) => {
47-
e.preventDefault()
48-
try {
49-
submitLocalDraft()
50-
} catch (err) {
51-
// eslint-disable-next-line no-console
52-
console.error('Error submitting local draft:', err)
53-
}
54-
}
5539
return (
5640
<Button
5741
fullWidth
@@ -61,7 +45,6 @@ function LinkButtonInput({
6145
id={id}
6246
size="large"
6347
type="secondary"
64-
onClick={handleClick}
6548
>
6649
{configuration.icon && (
6750
<Icon

packages/client/src/v2-events/features/events/registered-fields/TimeField.interaction.stories.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,9 @@ export const TimeInput12HourDisplay: StoryObj<typeof FormFieldGenerator> = {
199199
})
200200

201201
await step('Verify output is in 24-hour format', async () => {
202-
const outputDisplay = await canvas.findByTestId('time-output-12h')
202+
const outputDisplay = await canvas.findByTestId('time-output-24h')
203203
await expect(outputDisplay).toBeInTheDocument()
204-
await expect(outputDisplay).toHaveTextContent('14:30')
204+
await expect(outputDisplay).toHaveTextContent('2:30')
205205
})
206206
},
207207
render: function Component(args) {
@@ -231,7 +231,7 @@ export const TimeInput12HourDisplay: StoryObj<typeof FormFieldGenerator> = {
231231
setFormData(data)
232232
}}
233233
/>
234-
<OutputDisplay data-testid="time-output-12h">
234+
<OutputDisplay data-testid="time-output-24h">
235235
{'Output (always 24-hour): '}
236236
{formData['storybook.time'] || 'No value'}
237237
</OutputDisplay>

0 commit comments

Comments
 (0)