Skip to content

Commit ed55597

Browse files
committed
[#5074] Started with transforming the data for the Objects API in the variables tab
1 parent 069f6d5 commit ed55597

File tree

8 files changed

+98
-42
lines changed

8 files changed

+98
-42
lines changed

src/openforms/js/components/admin/form_design/registrations/objectsapi/AddressNlObjectsApiVariableConfigurationEditor.js

+1-22
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ import FormRow from 'components/admin/forms/FormRow';
1212
import {Checkbox} from 'components/admin/forms/Inputs';
1313
import {TargetPathSelect} from 'components/admin/forms/objects_api';
1414
import ErrorMessage from 'components/errors/ErrorMessage';
15-
import {post} from 'utils/fetch';
1615

1716
import {MappedVariableTargetPathSelect} from './GenericObjectsApiVariableConfigurationEditor';
17+
import {fetchTargetPaths} from './utils';
1818

1919
const ADDRESSNL_NESTED_PROPERTIES = {
2020
postcode: {type: 'string'},
@@ -25,27 +25,6 @@ const ADDRESSNL_NESTED_PROPERTIES = {
2525
streetName: {type: 'string'},
2626
};
2727

28-
const fetchTargetPaths = async (
29-
csrftoken,
30-
objectsApiGroup,
31-
objecttype,
32-
objecttypeVersion,
33-
schemaType
34-
) => {
35-
const response = await post(REGISTRATION_OBJECTS_TARGET_PATHS, csrftoken, {
36-
objectsApiGroup,
37-
objecttype,
38-
objecttypeVersion,
39-
variableJsonSchema: schemaType,
40-
});
41-
42-
if (!response.ok) {
43-
throw new Error(`Error when loading target paths for type: ${schemaType}`);
44-
}
45-
46-
return response.data;
47-
};
48-
4928
export const AddressNlEditor = ({
5029
variable,
5130
components,

src/openforms/js/components/admin/form_design/registrations/objectsapi/GenericObjectsApiVariableConfigurationEditor.js

+48-18
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {FormattedMessage} from 'react-intl';
66
import {useAsync, useToggle} from 'react-use';
77

88
import {APIContext} from 'components/admin/form_design/Context';
9-
import {REGISTRATION_OBJECTS_TARGET_PATHS} from 'components/admin/form_design/constants';
109
import Field from 'components/admin/forms/Field';
1110
import FormRow from 'components/admin/forms/FormRow';
1211
import {Checkbox} from 'components/admin/forms/Inputs';
@@ -15,6 +14,7 @@ import ErrorMessage from 'components/errors/ErrorMessage';
1514
import {post} from 'utils/fetch';
1615

1716
import {asJsonSchema} from './utils';
17+
import {SCHEMA_TYPES_WITH_TRANSFORMATION, fetchTargetPaths} from './utils';
1818

1919
/**
2020
* Hack-ish way to manage the variablesMapping state for one particular entry.
@@ -83,6 +83,7 @@ export const GenericEditor = ({
8383
components,
8484
namePrefix,
8585
isGeometry,
86+
transformData,
8687
index,
8788
mappedVariable,
8889
objecttype,
@@ -93,27 +94,31 @@ export const GenericEditor = ({
9394
const [jsonSchemaVisible, toggleJsonSchemaVisible] = useToggle(false);
9495
const {setFieldValue} = useFormikContext();
9596

97+
const componentType = components[variable?.key]?.type;
98+
99+
// Load all the possible target paths in parallel
96100
const {
97101
loading,
98-
value: targetPaths,
102+
value: targetPaths = [],
99103
error,
100-
} = useAsync(
101-
async () => {
102-
const response = await post(REGISTRATION_OBJECTS_TARGET_PATHS, csrftoken, {
103-
objectsApiGroup,
104-
objecttype,
105-
objecttypeVersion,
106-
variableJsonSchema: asJsonSchema(variable, components),
107-
});
108-
if (!response.ok) {
109-
throw new Error('Error when loading target paths');
110-
}
104+
} = useAsync(async () => {
105+
const promises = transformData
106+
? SCHEMA_TYPES_WITH_TRANSFORMATION[componentType].map(type =>
107+
fetchTargetPaths(csrftoken, objectsApiGroup, objecttype, objecttypeVersion, type)
108+
)
109+
: [
110+
fetchTargetPaths(
111+
csrftoken,
112+
objectsApiGroup,
113+
objecttype,
114+
objecttypeVersion,
115+
asJsonSchema(variable, components)
116+
),
117+
];
111118

112-
return response.data;
113-
},
114-
// Load only once:
115-
[]
116-
);
119+
const results = await Promise.all(promises);
120+
return results.flat(1);
121+
}, [transformData]);
117122

118123
const getTargetPath = pathSegment => targetPaths.find(t => isEqual(t.targetPath, pathSegment));
119124

@@ -153,6 +158,31 @@ export const GenericEditor = ({
153158
/>
154159
</Field>
155160
</FormRow>
161+
{componentType in SCHEMA_TYPES_WITH_TRANSFORMATION && (
162+
<FormRow>
163+
<Field name="transformData">
164+
<Checkbox
165+
name="transformDataCheckbox"
166+
label={
167+
<FormattedMessage
168+
defaultMessage="Transform data"
169+
description="'Transform data' checkbox label"
170+
/>
171+
}
172+
helpText={
173+
<FormattedMessage
174+
description="'Transform data' checkbox help text"
175+
defaultMessage="Whether to transform the data of the component to another data type or not (depends on the component)"
176+
/>
177+
}
178+
checked={transformData}
179+
onChange={event => {
180+
setFieldValue('transformData', event.target.checked);
181+
}}
182+
/>
183+
</Field>
184+
</FormRow>
185+
)}
156186
<FormRow>
157187
<Field
158188
name={`${namePrefix}.targetPath`}

src/openforms/js/components/admin/form_design/registrations/objectsapi/ObjectsApiVariableConfigurationEditor.js

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ const ObjectsApiVariableConfigurationEditor = ({variable}) => {
4545
objecttype,
4646
objecttypeVersion,
4747
geometryVariableKey,
48+
transformData,
4849
variablesMapping,
4950
version,
5051
} = backendOptions;
@@ -99,6 +100,7 @@ const ObjectsApiVariableConfigurationEditor = ({variable}) => {
99100
components={components}
100101
namePrefix={namePrefix}
101102
isGeometry={isGeometry}
103+
transformData={transformData}
102104
index={index}
103105
mappedVariable={mappedVariable}
104106
objecttype={objecttype}

src/openforms/js/components/admin/form_design/registrations/objectsapi/utils.js

+27-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import {REGISTRATION_OBJECTS_TARGET_PATHS} from 'components/admin/form_design/constants';
2+
import {post} from 'utils/fetch';
3+
14
const VARIABLE_TYPE_MAP = {
25
boolean: 'boolean',
36
int: 'integer',
@@ -13,6 +16,8 @@ const FORMAT_TYPE_MAP = {
1316
date: 'date',
1417
};
1518

19+
const SCHEMA_TYPES_WITH_TRANSFORMATION = {selectboxes: [{type: 'object'}, {type: 'array'}]};
20+
1621
/**
1722
* Return a JSON Schema definition matching the provided variable.
1823
* @param {Object} variable - The current variable
@@ -57,4 +62,25 @@ const asJsonSchema = (variable, components) => {
5762
};
5863
};
5964

60-
export {asJsonSchema};
65+
const fetchTargetPaths = async (
66+
csrftoken,
67+
objectsApiGroup,
68+
objecttype,
69+
objecttypeVersion,
70+
schemaType
71+
) => {
72+
const response = await post(REGISTRATION_OBJECTS_TARGET_PATHS, csrftoken, {
73+
objectsApiGroup,
74+
objecttype,
75+
objecttypeVersion,
76+
variableJsonSchema: schemaType,
77+
});
78+
79+
if (!response.ok) {
80+
throw new Error(`Error when loading target paths for type: ${schemaType}`);
81+
}
82+
83+
return response.data;
84+
};
85+
86+
export {asJsonSchema, fetchTargetPaths, SCHEMA_TYPES_WITH_TRANSFORMATION};

src/openforms/registrations/contrib/objects_api/config.py

+8
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,14 @@ class ObjectsAPIOptionsSerializer(JsonSchemaSerializerMixin, serializers.Seriali
256256
required=False,
257257
allow_blank=True,
258258
)
259+
transform_data = serializers.BooleanField(
260+
label=_("transform data"),
261+
help_text=_(
262+
"Indicates whether or not the data of the component will be transformed "
263+
"to another data type."
264+
),
265+
default=False,
266+
)
259267

260268
def validate(self, attrs: RegistrationOptions) -> RegistrationOptions:
261269
v1_only_fields = {

src/openforms/registrations/contrib/objects_api/handlers/v2.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from openforms.formio.typing.vanilla import FileComponent
1616
from openforms.typing import JSONObject, JSONValue
1717

18-
from ..typing import ObjecttypeVariableMapping
18+
from ..typing import ObjecttypeVariableMapping, RegistrationOptionsV2
1919

2020

2121
@dataclass
@@ -58,6 +58,7 @@ def process_mapped_variable(
5858
value: (
5959
JSONValue | date | datetime
6060
), # can't narrow it down yet, as the type depends on the component type
61+
options: RegistrationOptionsV2 | None = None,
6162
component: Component | None = None,
6263
attachment_urls: dict[str, list[str]] | None = None,
6364
) -> AssignmentSpec | Sequence[AssignmentSpec]:
@@ -73,6 +74,8 @@ def process_mapped_variable(
7374
:arg value: The raw value of the form variable for the submission being processed.
7475
The type/shape of the value depends on the variable/component data type being
7576
processed and even the component configuration (such as multiple True/False).
77+
:arg options: The registration options. They are needed when additional information
78+
is needed for processing the variable.
7679
:arg component: If the variable corresponds to a Formio component, the component
7780
definition is provided, otherwise ``None``.
7881
:arg attachment_urls: The registration plugin uploads attachments to a Documents API
@@ -139,6 +142,12 @@ def process_mapped_variable(
139142
attachment_urls=attachment_urls,
140143
key_prefix=variable_key,
141144
)
145+
case {"type": "selectboxes"}:
146+
assert options
147+
assert isinstance(value, dict)
148+
if options["transform_data"]:
149+
value = [option for option, is_selected in value.items() if is_selected]
150+
142151
# not a component or standard behaviour where no transformation is necessary
143152
case None | _:
144153
pass

src/openforms/registrations/contrib/objects_api/submission_registration.py

+1
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,7 @@ def get_record_data(
571571
value=value,
572572
component=component,
573573
attachment_urls=urls_map,
574+
options=options,
574575
)
575576
if isinstance(assignment_spec, AssignmentSpec):
576577
assignment_specs.append(assignment_spec)

src/openforms/registrations/contrib/objects_api/typing.py

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class RegistrationOptionsV2(_BaseRegistrationOptions, total=False):
7070
version: Required[Literal[2]]
7171
variables_mapping: Required[list[ObjecttypeVariableMapping]]
7272
geometry_variable_key: str
73+
transform_data: Required[bool]
7374

7475

7576
type RegistrationOptions = RegistrationOptionsV1 | RegistrationOptionsV2

0 commit comments

Comments
 (0)