Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

👽 [#4693] Integrate Objects API prefill modal with backend #4799

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
12 changes: 5 additions & 7 deletions src/openforms/forms/api/serializers/form_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,15 +205,13 @@ def validate(self, attrs):
}
)

if (prefill_plugin and not prefill_attribute) or (
not prefill_plugin and prefill_attribute
if (prefill_plugin and not (prefill_attribute or prefill_options)) or (
not prefill_plugin and (prefill_attribute or prefill_options)
):
raise ValidationError(
{
"prefill_attribute": _(
"Prefill plugin and attribute must both be specified."
),
}
_(
"Prefill plugin must be specified with either prefill attribute or prefill options."
)
)

# check the specific validation options of the prefill plugin
Expand Down
32 changes: 31 additions & 1 deletion src/openforms/forms/tests/variables/test_viewset.py
Original file line number Diff line number Diff line change
Expand Up @@ -977,7 +977,9 @@ def test_bulk_create_and_update_with_prefill_constraints(self):
self.assertEqual(response.json()["invalidParams"][0]["code"], "invalid")
self.assertEqual(
response.json()["invalidParams"][0]["reason"],
_("Prefill plugin and attribute must both be specified."),
_(
"Prefill plugin must be specified with either prefill attribute or prefill options."
),
)

with self.subTest(
Expand Down Expand Up @@ -1018,3 +1020,31 @@ def test_bulk_create_and_update_with_prefill_constraints(self):
"Prefill plugin, attribute and options can not be specified at the same time."
),
)

with self.subTest(
"user_defined with prefill plugin and prefill options is allowed"
):
data = [
{
"form": form_url,
"form_definition": form_definition_url,
"key": "userdefined",
"name": "Test",
"service_fetch_configuration": None,
"data_type": FormVariableDataTypes.string,
"source": FormVariableSources.user_defined,
"prefill_plugin": "objects_api",
"prefill_attribute": "",
"prefill_options": {"foo": "bar"},
}
]

response = self.client.put(
reverse(
"api:form-variables",
kwargs={"uuid_or_slug": form.uuid},
),
data=data,
)

self.assertEqual(status.HTTP_200_OK, response.status_code)
24 changes: 24 additions & 0 deletions src/openforms/js/compiled-lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1583,6 +1583,12 @@
"value": "Move down"
}
],
"DJ8XX2": [
{
"type": 0,
"value": "Select a registration backend and click the button to copy the configuration."
}
],
"DJWATl": [
{
"type": 0,
Expand Down Expand Up @@ -3083,6 +3089,12 @@
"value": "change a property of a component."
}
],
"ScGRie": [
{
"type": 0,
"value": "Copying the configuration from the registration backend will clear the existing configuration. Are you sure you want to continue?"
}
],
"ScbJK7": [
{
"type": 0,
Expand Down Expand Up @@ -4479,6 +4491,12 @@
"value": "Pricing logic"
}
],
"fQuLvm": [
{
"type": 0,
"value": "Copy configuration from registration backend"
}
],
"fRMCJI": [
{
"type": 0,
Expand Down Expand Up @@ -4931,6 +4949,12 @@
"value": "Edit complex variable"
}
],
"jU6W0l": [
{
"type": 0,
"value": "Copy"
}
],
"jUPlH5": [
{
"type": 0,
Expand Down
24 changes: 24 additions & 0 deletions src/openforms/js/compiled-lang/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -1604,6 +1604,12 @@
"value": "Verplaats omlaag"
}
],
"DJ8XX2": [
{
"type": 0,
"value": "Select a registration backend and click the button to copy the configuration."
}
],
"DJWATl": [
{
"type": 0,
Expand Down Expand Up @@ -3100,6 +3106,12 @@
"value": "wijzig een attribuut van een veld/component."
}
],
"ScGRie": [
{
"type": 0,
"value": "Copying the configuration from the registration backend will clear the existing configuration. Are you sure you want to continue?"
}
],
"ScbJK7": [
{
"type": 0,
Expand Down Expand Up @@ -4501,6 +4513,12 @@
"value": "Prijslogica"
}
],
"fQuLvm": [
{
"type": 0,
"value": "Copy configuration from registration backend"
}
],
"fRMCJI": [
{
"type": 0,
Expand Down Expand Up @@ -4953,6 +4971,12 @@
"value": "Wijzig complexe waarde"
}
],
"jU6W0l": [
{
"type": 0,
"value": "Copy"
}
],
"jUPlH5": [
{
"type": 0,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {expect, fn, screen, userEvent, waitFor, within} from '@storybook/test';
import selectEvent from 'react-select-event';

import {
mockObjectsAPIPrefillPropertiesGet,
Expand Down Expand Up @@ -80,9 +81,9 @@ const VARIABLES = [
initialValue: [],
prefillOptions: {
objectsApiGroup: 1,
objecttype: '2c77babf-a967-4057-9969-0200320d23f2',
objecttypeUuid: '2c77babf-a967-4057-9969-0200320d23f2',
objecttypeVersion: 1,
variablesMapping: [{formVariable: 'formioComponent', prefillProperty: ['firstName']}],
variablesMapping: [{variableKey: 'formioComponent', targetPath: ['firstName']}],
},
},
];
Expand Down Expand Up @@ -626,6 +627,102 @@ export const ConfigurePrefillObjectsAPI = {
},
};

export const ConfigurePrefillObjectsAPIWithCopyButton = {
args: {
registrationBackends: [
{
backend: 'objects_api',
key: 'objects_api_1',
name: 'Example Objects API reg.',
options: {
version: 2,
objectsApiGroup: 1,
objecttype: '2c77babf-a967-4057-9969-0200320d23f1',
objecttypeVersion: 2,
variablesMapping: [
{
variableKey: 'formioComponent',
targetPath: ['height'],
},
{
variableKey: 'userDefined',
targetPath: ['species'],
},
],
},
},
{
backend: 'objects_api',
key: 'objects_api_2',
name: 'Other Objects API registration with a long name',
options: {
version: 2,
objectsApiGroup: 1,
objecttype: '209e0341-834d-4060-bd19-a3419d19ed74',
objecttypeVersion: 2,
variablesMapping: [
{
variableKey: 'formioComponent',
targetPath: ['path', 'to.the', 'target'],
},
],
},
},
],
},
play: async ({canvasElement, step}) => {
const canvas = within(canvasElement);

await step('Open configuration modal', async () => {
const userDefinedVarsTab = await canvas.findByRole('tab', {name: 'Gebruikersvariabelen'});
expect(userDefinedVarsTab).toBeVisible();
await userEvent.click(userDefinedVarsTab);

// open modal for configuration
const editIcon = canvas.getByTitle('Prefill instellen');
await userEvent.click(editIcon);
expect(await screen.findByRole('dialog')).toBeVisible();
});

await step('Configure Objects API prefill with copy button', async () => {
window.confirm = () => true;
const modal = within(await screen.findByRole('dialog'));
const pluginDropdown = await screen.findByLabelText('Plugin');
expect(pluginDropdown).toBeVisible();
await userEvent.selectOptions(pluginDropdown, 'Objects API');

const copyDropdown = await modal.findByLabelText(
'Copy configuration from registration backend'
);
expect(copyDropdown).toBeVisible();
await selectEvent.select(copyDropdown, 'Example Objects API reg.');

const copyButton = await modal.findByRole('button', {
name: 'Copy',
});
expect(copyButton).toBeVisible();
await userEvent.click(copyButton);

const modalForm = await screen.findByTestId('modal-form');
expect(modalForm).toBeVisible();
// Wait until the API call to retrieve the prefillAttributes is done
await waitFor(async () => {
expect(modalForm).toHaveFormValues({
'options.objectsApiGroup': '1',
'options.objecttypeUuid': '2c77babf-a967-4057-9969-0200320d23f1',
'options.objecttypeVersion': '2',
});

const propertyDropdowns = await modal.findAllByLabelText(
'Selecteer een attribuut uit het objecttype'
);
expect(propertyDropdowns[0]).toHaveValue(serializeValue(['height']));
expect(propertyDropdowns[1]).toHaveValue(serializeValue(['species']));
});
});
},
};

export const WithValidationErrors = {
args: {
variables: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,12 @@ const EditableVariableRow = ({index, variable, onDelete, onChange, onFieldChange
identifierRole={variable.prefillIdentifierRole}
errors={variable.errors}
options={variable.prefillOptions}
onChange={({plugin, attribute, identifierRole}) =>
onChange={({plugin, attribute, identifierRole, options}) =>
onChange(variable.key, '', {
prefillPlugin: plugin,
prefillAttribute: attribute,
prefillIdentifierRole: identifierRole,
prefillOptions: options,
})
}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {useField, useFormikContext} from 'formik';
import PropTypes from 'prop-types';

import Select from 'components/admin/forms/Select';
import Select, {SelectChoicesType} from 'components/admin/forms/Select';

const AttributeField = ({prefillAttributes}) => {
const [fieldProps] = useField('attribute');
Expand All @@ -21,7 +21,7 @@ const AttributeField = ({prefillAttributes}) => {
};

AttributeField.propTypes = {
prefillAttributes: PropTypes.arrayOf(PropTypes.string).isRequired,
prefillAttributes: SelectChoicesType.isRequired,
};

export default AttributeField;
Loading
Loading