Skip to content

Commit

Permalink
Merge pull request #4869 from open-formulieren/feature/4606-zgw-ux-me…
Browse files Browse the repository at this point in the history
…dewerker-roltype

Refactor ZGW options components structure
  • Loading branch information
sergei-maertens authored Nov 29, 2024
2 parents 65133e1 + dfb2ca9 commit d69aca5
Show file tree
Hide file tree
Showing 14 changed files with 320 additions and 203 deletions.
12 changes: 6 additions & 6 deletions src/openforms/js/compiled-lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2517,6 +2517,12 @@
"value": "Add variable"
}
],
"LbiXCA": [
{
"type": 0,
"value": "Something went wrong while retrieving the available products defined in the selected case. Please check that the services in the selected API group are configured correctly."
}
],
"LeVpdf": [
{
"type": 0,
Expand Down Expand Up @@ -5337,12 +5343,6 @@
"value": "Add item"
}
],
"ln2iyc": [
{
"type": 0,
"value": "Something went wrong while retrieving the available catalogues or products defined in the selected case. Please check that the services in the selected API group are configured correctly."
}
],
"ln72CJ": [
{
"type": 0,
Expand Down
18 changes: 6 additions & 12 deletions src/openforms/js/compiled-lang/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -2538,6 +2538,12 @@
"value": "Variabele toevoegen"
}
],
"LbiXCA": [
{
"type": 0,
"value": "Er ging iets fout bij het ophalen van de beschikbare producten binnen het geselecteerde zaaktype. Controleer of de services in de geselecteerde API-groep goed ingesteld zijn."
}
],
"LeVpdf": [
{
"type": 0,
Expand Down Expand Up @@ -5109,12 +5115,6 @@
"value": "optie 2: € 15,99"
}
],
"jtWzSW": [
{
"type": 0,
"value": "optie 2: € 15,99"
}
],
"jy1jTd": [
{
"offset": 0,
Expand Down Expand Up @@ -5365,12 +5365,6 @@
"value": "Item toevoegen"
}
],
"ln2iyc": [
{
"type": 0,
"value": "Er ging iets fout bij het ophalen van de beschikbare catalogi of geselecteerde zaak producten. Controleer of de services in de geselecteerde API-groep goed ingesteld zijn."
}
],
"ln72CJ": [
{
"type": 0,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import {useFormikContext} from 'formik';
import PropTypes from 'prop-types';
import {FormattedMessage, useIntl} from 'react-intl';
import {useAsync, usePrevious, useUpdateEffect} from 'react-use';
import {FormattedMessage} from 'react-intl';

import useConfirm from 'components/admin/form_design/useConfirm';
import Fieldset from 'components/admin/forms/Fieldset';
import {getCatalogueOption} from 'components/admin/forms/zgw';
import {CatalogueSelectOptions} from 'components/admin/forms/zgw';
import ErrorBoundary from 'components/errors/ErrorBoundary';

import {CaseTypeSelect, CatalogueSelect, DocumentTypeSelect, ZGWAPIGroup} from './fields';
import {getCatalogues} from './utils';

// Components

const BasicOptionsFieldset = ({apiGroupChoices}) => {
const BasicOptionsFieldset = ({
apiGroupChoices,
loadingCatalogues,
catalogueOptionGroups = [],
cataloguesError = undefined,
catalogueUrl = '',
}) => {
const {
values: {
caseTypeIdentification,
Expand Down Expand Up @@ -61,7 +65,10 @@ const BasicOptionsFieldset = ({apiGroupChoices}) => {
/>
}
>
<CatalogiApiFields />
<MaybeThrowError error={cataloguesError} />
<CatalogueSelect loading={loadingCatalogues} optionGroups={catalogueOptionGroups} />
<CaseTypeSelect catalogueUrl={catalogueUrl} />
<DocumentTypeSelect catalogueUrl={catalogueUrl} />
</ErrorBoundary>
<ConfirmationModal
{...confirmationModalProps}
Expand All @@ -86,74 +93,23 @@ BasicOptionsFieldset.propTypes = {
])
)
).isRequired,
loadingCatalogues: PropTypes.bool.isRequired,
catalogueOptionGroups: CatalogueSelectOptions.isRequired,
cataloguesError: PropTypes.any,
catalogueUrl: PropTypes.string,
};

const CatalogiApiFields = () => {
const {
values: {
zgwApiGroup = null,
catalogue = undefined,
caseTypeIdentification = '',
documentTypeDescription = '',
productUrl = '',
},
setFieldValue,
} = useFormikContext();

const previousCatalogue = usePrevious(catalogue);
const previousCaseTypeIdentification = usePrevious(caseTypeIdentification);

// fetch available catalogues and re-use the result
const {
loading: loadingCatalogues,
value: catalogueOptionGroups = [],
error: cataloguesError,
} = useAsync(async () => {
if (!zgwApiGroup) return [];
return await getCatalogues(zgwApiGroup);
}, [zgwApiGroup]);
if (cataloguesError) throw cataloguesError;

const catalogueValue = getCatalogueOption(catalogueOptionGroups, catalogue || {});
const catalogueUrl = catalogueValue?.url;

// Synchronize dependent fields when dependencies change.
// 1. Clear case type when catalogue changes.
useUpdateEffect(() => {
const catalogueChanged = catalogue !== previousCatalogue;
if (previousCatalogue && catalogueChanged && caseTypeIdentification) {
setFieldValue('caseTypeIdentification', '');
}
}, [setFieldValue, previousCatalogue, catalogue, caseTypeIdentification]);

// 2. Clear document type when case type changes
useUpdateEffect(() => {
const caseTypeChanged = caseTypeIdentification !== previousCaseTypeIdentification;
if (previousCaseTypeIdentification && caseTypeChanged && documentTypeDescription) {
setFieldValue('documentTypeDescription', '');
}
}, [
setFieldValue,
previousCaseTypeIdentification,
caseTypeIdentification,
documentTypeDescription,
]);

// 3. Clear selected product when case type changes
useUpdateEffect(() => {
const caseTypeChanged = caseTypeIdentification !== previousCaseTypeIdentification;
if (previousCaseTypeIdentification && caseTypeChanged && productUrl) {
setFieldValue('productUrl', '');
}
}, [setFieldValue, previousCaseTypeIdentification, caseTypeIdentification, productUrl]);
/**
* Component that only throws an error if it's not undefined, intended to trigger a
* parent error boundary.
*/
const MaybeThrowError = ({error = undefined}) => {
if (error) throw error;
return null;
};

return (
<>
<CatalogueSelect loading={loadingCatalogues} optionGroups={catalogueOptionGroups} />
<CaseTypeSelect catalogueUrl={catalogueUrl} />
<DocumentTypeSelect catalogueUrl={catalogueUrl} />
</>
);
MaybeThrowError.propTypes = {
error: PropTypes.any,
};

export default BasicOptionsFieldset;
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {FormattedMessage} from 'react-intl';

import Fieldset from 'components/admin/forms/Fieldset';

import {LegacyCaseType, LegacyDocumentType} from './fields';

/**
* @deprecated
*/
const LegacyOptionsFieldset = () => (
<Fieldset
title={
<FormattedMessage
description="ZGw APIs registration: legacy configuration options fieldset title"
defaultMessage="Legacy configuration"
/>
}
fieldNames={['zaaktype', 'informatieobjecttype']}
collapsible
>
<div className="description">
<FormattedMessage
description="ZGW APIs legacy config options informative message"
defaultMessage={`The configuration options here are legacy options. They
will continue working, but you should upgrade to the new configuration
options above. If a new configuration option is specified, the matching
legacy option will be ignored.`}
/>
</div>
<LegacyCaseType />
<LegacyDocumentType />
</Fieldset>
);

export default LegacyOptionsFieldset;
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {useFormikContext} from 'formik';
import PropTypes from 'prop-types';
import {FormattedMessage} from 'react-intl';

import {ContentJSON} from 'components/admin/form_design/registrations/objectsapi/LegacyConfigFields';
import Fieldset from 'components/admin/forms/Fieldset';
import {ObjectsAPIGroup} from 'components/admin/forms/objects_api';

import {ObjectType, ObjectTypeVersion} from './fields';

/**
* Callback to invoke when the API group changes - used to reset the dependent fields.
*/
const onApiGroupChange = prevValues => ({
...prevValues,
objecttype: '',
objecttypeVersion: undefined,
});

/**
* Configuration fields related to the Objects API (template based) integration.
*/
const ObjectsAPIOptionsFieldset = ({objectsApiGroupChoices}) => {
const {
values: {objecttype = ''},
} = useFormikContext();
return (
<Fieldset
title={
<FormattedMessage
description="ZGW APIs registration: Objects API fieldset title"
defaultMessage="Objects API integration"
/>
}
collapsible
fieldNames={['objecttype', 'objecttypeVersion', 'contentJson']}
>
<ObjectsAPIGroup
apiGroupChoices={objectsApiGroupChoices}
onApiGroupChange={onApiGroupChange}
required={!!objecttype}
isClearable
/>
<ObjectType />
<ObjectTypeVersion />
<ContentJSON />
</Fieldset>
);
};

ObjectsAPIOptionsFieldset.propTypes = {
objectsApiGroupChoices: PropTypes.arrayOf(
PropTypes.arrayOf(
PropTypes.oneOfType([
PropTypes.number, // value
PropTypes.string, // label
])
)
),
};

export default ObjectsAPIOptionsFieldset;
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
import {useFormikContext} from 'formik';
import PropTypes from 'prop-types';
import {FormattedMessage} from 'react-intl';
import {useAsync} from 'react-use';

import Fieldset from 'components/admin/forms/Fieldset';
import {getCatalogueOption} from 'components/admin/forms/zgw';
import ErrorBoundary from 'components/errors/ErrorBoundary';

import {ConfidentialityLevel, MedewerkerRoltype, OrganisationRSIN, ProductSelect} from './fields';
import {getCatalogues} from './utils';

const OptionalOptionsFieldset = ({confidentialityLevelChoices}) => {
const OptionalOptionsFieldset = ({confidentialityLevelChoices, catalogueUrl}) => {
return (
<Fieldset
title={
Expand Down Expand Up @@ -42,38 +38,22 @@ const OptionalOptionsFieldset = ({confidentialityLevelChoices}) => {
<FormattedMessage
description="ZGW APIs registrations options: case product error"
defaultMessage={`Something went wrong while retrieving the available
catalogues or products defined in the selected case. Please
check that the services in the selected API group are configured correctly.`}
products defined in the selected case. Please check that the services in
the selected API group are configured correctly.`}
/>
}
>
<CatalogiApiField />
<ProductSelect catalogueUrl={catalogueUrl} />
</ErrorBoundary>
</Fieldset>
);
};

const CatalogiApiField = () => {
const {
values: {zgwApiGroup = null, catalogue = undefined},
} = useFormikContext();

// fetch available catalogues and re-use the result
const {value: catalogueOptionGroups = [], error: cataloguesError} = useAsync(async () => {
if (!zgwApiGroup) return [];
return await getCatalogues(zgwApiGroup);
}, [zgwApiGroup]);
if (cataloguesError) throw cataloguesError;

const catalogueValue = getCatalogueOption(catalogueOptionGroups, catalogue || {});
const catalogueUrl = catalogueValue?.url;
return <ProductSelect catalogueUrl={catalogueUrl} />;
};

OptionalOptionsFieldset.propTypes = {
confidentialityLevelChoices: PropTypes.arrayOf(
PropTypes.arrayOf(PropTypes.string) // value & label are both string
).isRequired,
catalogueUrl: PropTypes.string,
};

export default OptionalOptionsFieldset;
Loading

0 comments on commit d69aca5

Please sign in to comment.