Skip to content

Commit

Permalink
Merge pull request #8347 from opencrvs/feat/summary-field-config
Browse files Browse the repository at this point in the history
Feat/summary field config
  • Loading branch information
makelicious authored Jan 22, 2025
2 parents 1e0cd50 + 2db1e0a commit 168936a
Show file tree
Hide file tree
Showing 12 changed files with 94 additions and 52 deletions.
7 changes: 5 additions & 2 deletions packages/client/src/v2-events/components/forms/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,11 @@ const initialValueMapping: Record<FieldType, FieldValue | null> = {
}

export function getInitialValues(fields: FieldConfig[]) {
return fields.reduce((initialValues, field) => {
return { ...initialValues, [field.id]: initialValueMapping[field.type] }
return fields.reduce((initialValues: Record<string, FieldValue>, field) => {
return {
...initialValues,
[field.id]: initialValueMapping[field.type]
}
}, {})
}

Expand Down
16 changes: 12 additions & 4 deletions packages/client/src/v2-events/features/events/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,16 +132,24 @@ export const tennisClubMembershipEvent = {
},
summary: {
title: {
defaultMessage: '{applicant.firstname} {applicant.surname}',
description: 'This is the title of the summary',
id: 'event.tennis-club-membership.summary.title'
id: 'event.tennis-club-membership.summary.title',
label: {
defaultMessage: '{applicant.firstname} {applicant.surname}',
description: 'This is the title of the summary',
id: 'event.tennis-club-membership.summary.title.label'
}
},
fields: [
{
id: 'applicant.firstname',
value: {
defaultMessage: '{applicant.firstname}',
description: 'Value for the matching field on form.',
id: 'event.tennis-club-membership.summary.field.firstname.value'
},
label: {
defaultMessage: 'First name',
description: 'Label for the gien field from form.',
description: 'Label for the given field on form.',
id: 'event.tennis-club-membership.summary.field.firstname.label'
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,18 +88,28 @@ function EventOverview({
const { eventConfiguration } = useEventConfiguration(event.type)
const intl = useIntlFormatMessageWithFlattenedParams()
const initialValues = getInitialValues(getAllFields(eventConfiguration))

const title = intl.formatMessage(summary.title.label, {
...initialValues,
...event.data
})

const fallbackTitle = summary.title.emptyValueMessage
? intl.formatMessage(summary.title.emptyValueMessage)
: ''
return (
<Content
icon={() => <IconWithName name={''} status={'orange'} />}
size={ContentSize.LARGE}
title={intl.formatMessage(summary.title, {
...initialValues,
...event.data
})}
title={title || fallbackTitle}
titleColor={event.id ? 'copy' : 'grey600'}
topActionButtons={[<ActionMenu key={event.id} eventId={event.id} />]}
>
<EventSummary event={event} summary={summary} />
<EventSummary
defaultValues={initialValues}
event={event}
summary={summary}
/>
<EventHistory history={history} />
</Content>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,29 @@
*/

import React from 'react'
import { useIntl } from 'react-intl'
import { Summary } from '@opencrvs/components/lib/Summary'
import { SummaryConfig } from '@opencrvs/commons/events'
import { EventIndex } from '@opencrvs/commons/client'
import { EventIndex, FieldValue } from '@opencrvs/commons/client'
import { useTransformer } from '@client/v2-events/hooks/useTransformer'
import { useIntlFormatMessageWithFlattenedParams } from '@client/v2-events/features/workqueues/utils'

/**
* Based on packages/client/src/views/RecordAudit/DeclarationInfo.tsx
*/

export function EventSummary({
event,
summary
summary,
defaultValues
}: {
event: EventIndex
summary: SummaryConfig
defaultValues: Record<string, FieldValue>
}) {
const intl = useIntl()
const intl = useIntlFormatMessageWithFlattenedParams()
const { toString } = useTransformer(event.type)
const data = toString(event.data)

return (
<>
<Summary id="summary">
Expand All @@ -43,7 +46,10 @@ export function EventSummary({
field.emptyValueMessage &&
intl.formatMessage(field.emptyValueMessage)
}
value={data[field.id]}
value={intl.formatMessage(field.value, {
...defaultValues,
...data
})}
/>
)
})}
Expand Down
22 changes: 14 additions & 8 deletions packages/client/src/v2-events/features/workqueues/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,21 @@ export function useIntlFormatMessageWithFlattenedParams() {
function formatMessage<T extends {}>(message: MessageDescriptor, params?: T) {
const variables = convertDotToTripleUnderscore(params ?? {})

return intl.formatMessage(
{
id: message.id,
description: message.description,
defaultMessage: convertDotInCurlyBraces(
message.defaultMessage as string
return (
intl
.formatMessage(
{
id: message.id,
description: message.description,
defaultMessage: convertDotInCurlyBraces(
message.defaultMessage as string
)
},
variables
)
},
variables
// When multiple variables are provided, we trim to ensure empty content in case both are missing.
// We might need to adjust this and allow more freedom for configuration (e.g. provide values and join pattern)
.trim()
)
}

Expand Down
8 changes: 2 additions & 6 deletions packages/commons/src/events/EventConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import { z } from 'zod'
import { ActionConfig } from './ActionConfig'
import { TranslationConfig } from './TranslationConfig'
import { SummaryConfig, SummaryConfigInput } from './SummaryConfig'
import { SummaryConfig } from './SummaryConfig'
import { WorkqueueConfig } from './WorkqueueConfig'
import { FormConfig, FormConfigInput, FormPage } from './FormConfig'
import { DeduplicationConfig } from './DeduplicationConfig'
Expand All @@ -34,12 +34,8 @@ export const EventConfig = z.object({
deduplication: z.array(DeduplicationConfig).optional().default([])
})

export const EventConfigInput = EventConfig.extend({
summary: SummaryConfigInput
})

export type EventConfig = z.infer<typeof EventConfig>
export type EventConfigInput = z.input<typeof EventConfigInput>
export type EventConfigInput = z.input<typeof EventConfig>

export const defineForm = (form: FormConfigInput): FormConfig =>
FormConfig.parse(form)
Expand Down
19 changes: 9 additions & 10 deletions packages/commons/src/events/SummaryConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,25 @@ import { z } from 'zod'
import { TranslationConfig } from './TranslationConfig'

const Field = z.object({
id: z.string().describe('Id of a field defined under form.'),
id: z.string().describe('Id of summary field'),
value: TranslationConfig.describe(
'Summary field value. Can utilise values defined in configuration and EventMetadata'
),
label: TranslationConfig,
emptyValueMessage: TranslationConfig.optional()
})

const FieldInput = Field.extend({
// label is enforced during runtime.
label: TranslationConfig.optional()
const Title = z.object({
id: z.string(),
label: TranslationConfig.describe('Title content'),
emptyValueMessage: TranslationConfig.optional()
})

export const SummaryConfig = z
.object({
title: TranslationConfig.describe('Header title of summary'),
title: Title.describe('Title of summary view.'),
fields: z.array(Field).describe('Fields rendered in summary view.')
})
.describe('Configuration for summary in event.')

export const SummaryConfigInput = SummaryConfig.extend({
fields: z.array(FieldInput)
})

export type SummaryConfig = z.infer<typeof SummaryConfig>
export type SummaryConfigInput = z.input<typeof SummaryConfigInput>
6 changes: 1 addition & 5 deletions packages/commons/src/events/defineConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,12 @@ import { findInputPageFields, resolveFieldLabels } from './utils'
* @param config - Event specific configuration
*/
export const defineConfig = (config: EventConfigInput) => {
const input = EventConfigInput.parse(config)
const input = EventConfig.parse(config)

const pageFields = findInputPageFields(input)

return EventConfig.parse({
...input,
summary: resolveFieldLabels({
config: input.summary,
pageFields
}),
workqueues: input.workqueues.map((workqueue) =>
resolveFieldLabels({
config: workqueue,
Expand Down
3 changes: 1 addition & 2 deletions packages/commons/src/events/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { TranslationConfig } from './TranslationConfig'
import { EventMetadataKeys, eventMetadataLabelMap } from './EventMetadata'
import { flattenDeep } from 'lodash'
import { EventConfig, EventConfigInput } from './EventConfig'
import { SummaryConfigInput } from './SummaryConfig'
import { WorkqueueConfigInput } from './WorkqueueConfig'
import { FieldConfig } from './FieldConfig'

Expand Down Expand Up @@ -96,7 +95,7 @@ export const resolveFieldLabels = ({
config,
pageFields
}: {
config: SummaryConfigInput | WorkqueueConfigInput
config: WorkqueueConfigInput
pageFields: { id: string; label: TranslationConfig }[]
}) => {
return {
Expand Down
25 changes: 22 additions & 3 deletions packages/commons/src/fixtures/tennis-club-membership-event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,32 @@ export const tennisClubMembershipEvent = defineConfig({
},
summary: {
title: {
defaultMessage: 'Summary',
description: 'This is the title of the summary',
id: 'event.tennis-club-membership.summary.title'
id: 'event.tennis-club-membership.summary.title',
label: {
defaultMessage: 'Summary',
description: 'This is the title of the summary',
id: 'event.tennis-club-membership.summary.title'
},
emptyValueMessage: {
defaultMessage: 'Membership application',
description:
'This is the message shown when the applicant name is missing',
id: 'event.tennis-club-membership.summary.title.empty'
}
},
fields: [
{
id: 'applicant.firstname',
label: {
defaultMessage: "Applicant's first name",
description: 'This is the label for the field',
id: 'event.tennis-club-membership.summary.field.firstname.label'
},
value: {
defaultMessage: '{applicant.firstname}',
description: 'This is the value to show in the summary',
id: 'event.tennis-club-membership.summary.field.firstname'
},
emptyValueMessage: {
defaultMessage: 'First name is not provided',
description: 'This is the message to show when the field is empty',
Expand Down
2 changes: 1 addition & 1 deletion packages/toolkit/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ else
sed -i 's|@opencrvs/events/build/types|.|g' dist/api/index.d.ts
fi

echo "Build completed successfully."
echo "Build completed successfully."
2 changes: 1 addition & 1 deletion packages/toolkit/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@opencrvs/toolkit",
"version": "0.0.18-events",
"version": "0.0.19-events-ml",
"description": "OpenCRVS toolkit for building country configurations",
"license": "MPL-2.0",
"exports": {
Expand Down

0 comments on commit 168936a

Please sign in to comment.