Skip to content

Commit

Permalink
Merge pull request #3989 from open-formulieren/feature/3688-handle-va…
Browse files Browse the repository at this point in the history
…r-changes

[#3688] Handle mutations/deletions of variables
  • Loading branch information
sergei-maertens authored Mar 12, 2024
2 parents 0023a92 + 676c260 commit 84cd243
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {produce} from 'immer';
import cloneDeep from 'lodash/cloneDeep';
import getObjectValue from 'lodash/get';
import groupBy from 'lodash/groupBy';
import set from 'lodash/set';
Expand Down Expand Up @@ -746,12 +747,29 @@ function reducer(draft, action) {
}
case 'DELETE_USER_DEFINED_VARIABLE': {
const key = action.payload;
const deletedVariable = draft.formVariables.find(variable => variable.key === key);

// Update registration backends that might depend on the variable:
draft.form.registrationBackends = draft.form.registrationBackends.map(configuredBackend => {
const {backend: registrationBackend, options} = configuredBackend;

const handler = BACKEND_OPTIONS_FORMS[registrationBackend]?.onUserDefinedVariableEdit;
if (handler == null) return configuredBackend;
const updatedOptions = handler(options, deletedVariable, null);
if (!updatedOptions) return configuredBackend;

return {...configuredBackend, options: updatedOptions};
});

draft.formVariables = draft.formVariables.filter(variable => variable.key !== key);
break;
}
case 'CHANGE_USER_DEFINED_VARIABLE': {
const {key, propertyName, propertyValue} = action.payload;

const originalVariable = cloneDeep(
draft.formVariables.find(variable => variable.key === key)
);
const index = draft.formVariables.findIndex(variable => variable.key === key);

draft.formVariables[index][propertyName] = propertyValue;
Expand Down Expand Up @@ -781,6 +799,18 @@ function reducer(draft, action) {
draft.logicRules = updateKeyReferencesInLogic(draft.logicRules, key, propertyValue);
}
}

// Update registration backends that might depend on the variable:
draft.form.registrationBackends = draft.form.registrationBackends.map(configuredBackend => {
const {backend: registrationBackend, options} = configuredBackend;

const handler = BACKEND_OPTIONS_FORMS[registrationBackend]?.onUserDefinedVariableEdit;
if (handler == null) return configuredBackend;
const updatedOptions = handler(options, draft.formVariables[index], originalVariable);
if (!updatedOptions) return configuredBackend;

return {...configuredBackend, options: updatedOptions};
});
break;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import {WysiwygWidget} from 'components/admin/RJSFWrapper';

import CamundaOptionsForm from './camunda';
import {onCamundaStepEdit, onZGWStepEdit} from './handlers';
import ObjectsApiOptionsForm from './objectsapi/ObjectsApiOptionsForm';
import ObjectsApiSummaryHandler from './objectsapi/ObjectsApiSummaryHandler';
import ObjectsApiVariableConfigurationEditor from './objectsapi/ObjectsApiVariableConfigurationEditor';
import {onCamundaStepEdit, onObjectsAPIStepEdit, onZGWStepEdit} from './stepEditHandlers';
import {onObjectsAPIUserDefinedVariableEdit} from './userDefinedVariableEditHandlers';
import ZGWOptionsForm from './zgw';

/**
* @typedef {{
* form?: React.FC,
* uiSchema?: Object,
* onStepEdit?: (...args: any) => Object | null,
* onUserDefinedVariableEdit?: (...args: any) => Object | null,
* configurableFromVariables?: boolean | (options: Object) => boolean,
* summaryHandler?: React.FC
* variableConfigurationEditor?: React.FC
Expand All @@ -25,7 +28,8 @@ export const BACKEND_OPTIONS_FORMS = {
},
objects_api: {
form: ObjectsApiOptionsForm,
onStepEdit: null,
onStepEdit: onObjectsAPIStepEdit,
onUserDefinedVariableEdit: onObjectsAPIUserDefinedVariableEdit,
configurableFromVariables: options => options.version === 2,
summaryHandler: ObjectsApiSummaryHandler,
variableConfigurationEditor: ObjectsApiVariableConfigurationEditor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,36 @@ const onZGWStepEdit = (registrationBackendOptions, componentSchema, originalComp
return registrationBackendOptions;
};

export {onCamundaStepEdit, onZGWStepEdit};
/**
* Update the mapped properties after the form definitions change
* @param {Object} registrationBackendOptions The currently configured backend options,
* including the mapped properties. Note that this is
* an immer draft which can be mutated.
* @param {Object} componentSchema The Formio component (schema) that was mutated in some way
* @param {Object|null} originalComponent The component before it was mutated, null if the component is removed.
* @return {Object|null} The updated registrationBackendOptions draft. Return null to indicate
* no changes need to be made.
*/
const onObjectsAPIStepEdit = (registrationBackendOptions, componentSchema, originalComponent) => {
const removed = originalComponent == null;

if (removed) {
const matchingMappingIndex = registrationBackendOptions.variablesMapping.findIndex(
mapping => mapping.variableKey === componentSchema.key
);

if (matchingMappingIndex === -1) return;
registrationBackendOptions.variablesMapping.splice(matchingMappingIndex, 1);
} else {
const keyChanged = componentSchema.key !== originalComponent.key;
if (!keyChanged) return null;

for (const mapping of registrationBackendOptions.variablesMapping) {
if (mapping.variableKey === originalComponent.key) {
mapping.variableKey = componentSchema.key;
}
}
}
};

export {onCamundaStepEdit, onZGWStepEdit, onObjectsAPIStepEdit};
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Update the mapped properties after the user defined variable change
* @param {Object} registrationBackendOptions The currently configured backend options,
* including the mapped properties. Note that this is
* an immer draft which can be mutated.
* @param {Object} variable The user defined variable that was mutated in some way
* @param {Object|null} originalVariable The user defined variable before it was mutated, null if it is removed.
* @return {Object|null} The updated registrationBackendOptions draft. Return null to indicate
* no changes need to be made.
*/
const onObjectsAPIUserDefinedVariableEdit = (
registrationBackendOptions,
variable,
originalVariable
) => {
// If the data type has changed, the mapped target might not be compatible anymore:
const shouldRemove = originalVariable == null || variable.dataType !== originalVariable.dataType;

if (shouldRemove) {
const matchingMappingIndex = registrationBackendOptions.variablesMapping.findIndex(
mapping => mapping.variableKey === variable.key
);

if (matchingMappingIndex === -1) return;
registrationBackendOptions.variablesMapping.splice(matchingMappingIndex, 1);
} else {
const keyChanged = variable.key !== originalVariable.key;
if (!keyChanged) return null;

for (const mapping of registrationBackendOptions.variablesMapping) {
if (mapping.variableKey === originalVariable.key) {
mapping.variableKey = variable.key;
}
}
}
};

export {onObjectsAPIUserDefinedVariableEdit};

0 comments on commit 84cd243

Please sign in to comment.