diff --git a/.storybook/decorators.tsx b/.storybook/decorators.tsx index dbadbcd..9609d02 100644 --- a/.storybook/decorators.tsx +++ b/.storybook/decorators.tsx @@ -13,6 +13,7 @@ import { DEFAULT_MAP_TILE_LAYERS, DEFAULT_PREFILL_ATTRIBUTES, DEFAULT_PREFILL_PLUGINS, + DEFAULT_REFERENTIELIJSTEN_TABELLEN, DEFAULT_REGISTRATION_ATTRIBUTES, DEFAULT_SERVICES, DEFAULT_VALIDATOR_PLUGINS, @@ -63,6 +64,9 @@ export const BuilderContextDecorator: Decorator = (Story, context) => { const defaultRegistrationAttributes = context.parameters.builder?.defaultRegistrationAttributes || DEFAULT_REGISTRATION_ATTRIBUTES; const defaultServices = context.parameters.builder?.defaultServices || DEFAULT_SERVICES; + const defaultReferentielijstenTabellen = + context.parameters.builder?.defaultReferentielijstenTabellen || + DEFAULT_REFERENTIELIJSTEN_TABELLEN; const defaultPrefillPlugins = context.parameters.builder?.defaultPrefillPlugins || DEFAULT_PREFILL_PLUGINS; const defaultPrefillAttributes = @@ -92,6 +96,10 @@ export const BuilderContextDecorator: Decorator = (Story, context) => { await sleep(context.parameters?.builder?.servicesDelay || 0); return context?.args?.services || defaultServices; }, + getReferentielijstenTabellen: async () => { + await sleep(context.parameters?.builder?.referentielijstenTabellenDelay || 0); + return context?.args?.referentielijstenTabellen || defaultReferentielijstenTabellen; + }, getPrefillPlugins: async () => { await sleep(context.parameters?.builder?.prefillPluginsDelay || 0); return context?.args?.prefillPlugins || defaultPrefillPlugins; diff --git a/src/components/ComponentConfiguration.tsx b/src/components/ComponentConfiguration.tsx index 67fe9cb..48910ef 100644 --- a/src/components/ComponentConfiguration.tsx +++ b/src/components/ComponentConfiguration.tsx @@ -39,6 +39,7 @@ const ComponentConfiguration: React.FC = ({ getValidatorPlugins, getRegistrationAttributes, getServices, + getReferentielijstenTabellen, getPrefillPlugins, getPrefillAttributes, getFileTypes, @@ -68,6 +69,7 @@ const ComponentConfiguration: React.FC = ({ getValidatorPlugins, getRegistrationAttributes, getServices, + getReferentielijstenTabellen, getPrefillPlugins, getPrefillAttributes, getFileTypes, diff --git a/src/components/builder/values/referentielijsten/code.tsx b/src/components/builder/values/referentielijsten/code.tsx index 511e7b5..9dc626a 100644 --- a/src/components/builder/values/referentielijsten/code.tsx +++ b/src/components/builder/values/referentielijsten/code.tsx @@ -1,6 +1,40 @@ +import {useFormikContext} from 'formik'; +import {useContext} from 'react'; import {FormattedMessage, useIntl} from 'react-intl'; +import useAsync from 'react-use/esm/useAsync'; -import {TextField} from '@/components/formio'; +import Select from '@/components/formio/select'; +import {BuilderContext} from '@/context'; + +export interface ReferentielijstenTabelOption { + code: string; + naam: string; + einddatumGeldigheid: string | null; +} + +function isTabelOptions( + options: ReferentielijstenTabelOption[] | undefined +): options is ReferentielijstenTabelOption[] { + return options !== undefined; +} + +function transformItems(items: ReferentielijstenTabelOption[]) { + return items.map(item => { + const {code, naam, einddatumGeldigheid} = item; + return { + value: code, + label: einddatumGeldigheid ? `${naam} (${einddatumGeldigheid})` : naam, + }; + }); +} + +interface ComponentWithReferentielijsten { + openForms?: { + dataSrc: 'referentielijsten' + service?: string; + code?: string; + }; +} /** * The `ReferentielijstenTabelCode` component is used to specify the code of the tabel @@ -8,8 +42,27 @@ import {TextField} from '@/components/formio'; */ export const ReferentielijstenTabelCode: React.FC = () => { const intl = useIntl(); + const {values} = useFormikContext(); + const service = values?.openForms?.service; + const {getReferentielijstenTabellen} = useContext(BuilderContext); + const { + value: options, + loading, + error, + } = useAsync(async () => { + if (service) { + return await getReferentielijstenTabellen(service); + } + return []; + }, [service]); + + if (error) { + throw error; + } + const _options = isTabelOptions(options) ? transformItems(options) : []; + return ( - { description: "Description for the 'openForms.code' builder field", defaultMessage: `The code of the table from which the options will be retrieved.`, })} + isLoading={loading} + options={_options} + valueProperty="value" required /> ); diff --git a/src/context.ts b/src/context.ts index 21607f2..c0b064f 100644 --- a/src/context.ts +++ b/src/context.ts @@ -5,6 +5,7 @@ import {PrefillAttributeOption, PrefillPluginOption} from '@/components/builder/ import {RegistrationAttributeOption} from '@/components/builder/registration/registration-attribute'; import type {ColorOption} from '@/components/builder/rich-text'; import {ValidatorOption} from '@/components/builder/validate/validator-select'; +import {ReferentielijstenTabelOption} from '@/components/builder/values/referentielijsten/code'; import {ReferentielijstenServiceOption} from '@/components/builder/values/referentielijsten/service'; import {AuthPluginOption} from '@/registry/cosignV1/edit'; import {AnyComponentSchema} from '@/types'; @@ -54,6 +55,7 @@ export interface BuilderContextType { getValidatorPlugins: (componentType: string) => Promise; getRegistrationAttributes: (componentType: string) => Promise; getServices: (type: string) => Promise; + getReferentielijstenTabellen: (service: string) => Promise; getPrefillPlugins: (componentType: string) => Promise; getPrefillAttributes: (plugin: string) => Promise; getFileTypes: () => Promise; @@ -73,6 +75,7 @@ const BuilderContext = React.createContext({ getValidatorPlugins: async () => [], getRegistrationAttributes: async () => [], getServices: async () => [], + getReferentielijstenTabellen: async () => [], getPrefillPlugins: async () => [], getPrefillAttributes: async () => [], getFileTypes: async () => [], diff --git a/src/registry/radio/radio-referentielijsten.stories.ts b/src/registry/radio/radio-referentielijsten.stories.ts index 096202f..bbfb79f 100644 --- a/src/registry/radio/radio-referentielijsten.stories.ts +++ b/src/registry/radio/radio-referentielijsten.stories.ts @@ -57,14 +57,14 @@ export const StoreValuesInComponent: Story = { await rsSelect(serviceInput, 'Referentielijsten'); const codeInput = canvas.getByLabelText('Referentielijsten table code'); - await userEvent.type(codeInput, 'tabel1'); + await rsSelect(codeInput, 'Tabel 2 (2025-04-11T13:02:25Z)'); await userEvent.click(canvas.getByRole('button', {name: 'Save'})); expect(args.onSubmit).toHaveBeenCalledWith( expect.objectContaining({ openForms: { - code: 'tabel1', + code: 'tabel2', dataSrc: 'referentielijsten', service: 'referentielijsten', translations: {}, @@ -89,7 +89,7 @@ export const SwitchToVariableResetOptions: Story = { await rsSelect(serviceInput, 'Referentielijsten'); const codeInput = canvas.getByLabelText('Referentielijsten table code'); - await userEvent.type(codeInput, 'tabel1'); + await rsSelect(codeInput, 'Tabel 2 (2025-04-11T13:02:25Z)'); await rsSelect(dataSourceInput, 'From variable'); @@ -126,7 +126,7 @@ export const SwitchToManualResetOptions: Story = { await rsSelect(serviceInput, 'Referentielijsten'); const codeInput = canvas.getByLabelText('Referentielijsten table code'); - await userEvent.type(codeInput, 'tabel1'); + await rsSelect(codeInput, 'Tabel 2 (2025-04-11T13:02:25Z)'); await rsSelect(dataSourceInput, 'Manually fill in'); diff --git a/src/registry/select/select-referentielijsten.stories.ts b/src/registry/select/select-referentielijsten.stories.ts index bb3b3ce..6909219 100644 --- a/src/registry/select/select-referentielijsten.stories.ts +++ b/src/registry/select/select-referentielijsten.stories.ts @@ -57,14 +57,14 @@ export const StoreValuesInComponent: Story = { await rsSelect(serviceInput, 'Referentielijsten'); const codeInput = canvas.getByLabelText('Referentielijsten table code'); - await userEvent.type(codeInput, 'tabel1'); + await rsSelect(codeInput, 'Tabel 2 (2025-04-11T13:02:25Z)'); await userEvent.click(canvas.getByRole('button', {name: 'Save'})); expect(args.onSubmit).toHaveBeenCalledWith( expect.objectContaining({ openForms: { - code: 'tabel1', + code: 'tabel2', dataSrc: 'referentielijsten', service: 'referentielijsten', translations: {}, @@ -89,7 +89,7 @@ export const SwitchToVariableResetOptions: Story = { await rsSelect(serviceInput, 'Referentielijsten'); const codeInput = canvas.getByLabelText('Referentielijsten table code'); - await userEvent.type(codeInput, 'tabel1'); + await rsSelect(codeInput, 'Tabel 2 (2025-04-11T13:02:25Z)'); await rsSelect(dataSourceInput, 'From variable'); @@ -126,7 +126,7 @@ export const SwitchToManualResetOptions: Story = { await rsSelect(serviceInput, 'Referentielijsten'); const codeInput = canvas.getByLabelText('Referentielijsten table code'); - await userEvent.type(codeInput, 'tabel1'); + await rsSelect(codeInput, 'Tabel 2 (2025-04-11T13:02:25Z)'); await rsSelect(dataSourceInput, 'Manually fill in'); diff --git a/src/registry/selectboxes/selectboxes-referentielijsten.stories.ts b/src/registry/selectboxes/selectboxes-referentielijsten.stories.ts index f59f8d5..66b1ca5 100644 --- a/src/registry/selectboxes/selectboxes-referentielijsten.stories.ts +++ b/src/registry/selectboxes/selectboxes-referentielijsten.stories.ts @@ -54,14 +54,14 @@ export const StoreValuesInComponent: Story = { await rsSelect(serviceInput, 'Referentielijsten'); const codeInput = canvas.getByLabelText('Referentielijsten table code'); - await userEvent.type(codeInput, 'tabel1'); + await rsSelect(codeInput, 'Tabel 2 (2025-04-11T13:02:25Z)'); await userEvent.click(canvas.getByRole('button', {name: 'Save'})); expect(args.onSubmit).toHaveBeenCalledWith( expect.objectContaining({ openForms: { - code: 'tabel1', + code: 'tabel2', dataSrc: 'referentielijsten', service: 'referentielijsten', translations: {}, @@ -86,7 +86,7 @@ export const SwitchToVariableResetOptions: Story = { await rsSelect(serviceInput, 'Referentielijsten'); const codeInput = canvas.getByLabelText('Referentielijsten table code'); - await userEvent.type(codeInput, 'tabel1'); + await rsSelect(codeInput, 'Tabel 2 (2025-04-11T13:02:25Z)'); await rsSelect(dataSourceInput, 'From variable'); @@ -123,7 +123,7 @@ export const SwitchToManualResetOptions: Story = { await rsSelect(serviceInput, 'Referentielijsten'); const codeInput = canvas.getByLabelText('Referentielijsten table code'); - await userEvent.type(codeInput, 'tabel1'); + await rsSelect(codeInput, 'Tabel 2 (2025-04-11T13:02:25Z)'); await rsSelect(dataSourceInput, 'Manually fill in'); diff --git a/src/tests/sharedUtils.tsx b/src/tests/sharedUtils.tsx index 97f0df2..9f0b627 100644 --- a/src/tests/sharedUtils.tsx +++ b/src/tests/sharedUtils.tsx @@ -1,4 +1,5 @@ // This module contains shared utilities and constants between Jest and Storybook. +import {ReferentielijstenTabelOption} from '@/components/builder/values/referentielijsten/code'; import {ReferentielijstenServiceOption} from '@/components/builder/values/referentielijsten/service'; import type {DocumentTypeOption, MapTileLayer, SelectOption} from '@/context'; import {ColorOption} from '@/registry/content/rich-text'; @@ -51,6 +52,19 @@ export const DEFAULT_SERVICES: ReferentielijstenServiceOption[] = [ }, ]; +export const DEFAULT_REFERENTIELIJSTEN_TABELLEN: ReferentielijstenTabelOption[] = [ + { + code: 'tabel1', + naam: 'Tabel 1', + einddatumGeldigheid: null, + }, + { + code: 'tabel2', + naam: 'Tabel 2', + einddatumGeldigheid: '2025-04-11T13:02:25Z', + }, +]; + export const DEFAULT_PREFILL_PLUGINS: PrefillPluginOption[] = [ {id: 'plugin-1', label: 'Plugin 1'}, {id: 'plugin-2', label: 'Plugin 2'},