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

Implement Objects API sets #4343

Merged
merged 25 commits into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
385ae36
[#4267] Remove unused cassettes
Viicos May 28, 2024
86af64b
[#4267] Add `ObjectsAPIGroupConfig`
Viicos May 31, 2024
d071062
[#4267] Add migration to migrate existing `ObjectsAPIConfig`
Viicos May 31, 2024
b04570e
[#4267] Remove unused fields from the `ObjectsAPIConfig`
Viicos May 31, 2024
d1e1553
[#4267] Update admin index fixture
Viicos May 27, 2024
9ea6348
[#4267] Register ObjectsAPIGroupConfig in admin
Viicos May 31, 2024
9c28999
[#4267] Update config checks
Viicos May 31, 2024
b68a6b0
[#4267] Update Objecttypes client tests
Viicos May 28, 2024
b4d5653
[#4267] Update API endpoints related to Objecttypes and objecttypes v…
Viicos May 31, 2024
2c92099
[#4267] Add option to select Objects API group in the frontend
Viicos May 31, 2024
5b28902
[#4267] Update Objects API plugin implementation to use Objects API g…
Viicos May 31, 2024
acbc6bb
[#4267] Update Objects API registration tests
Viicos Jun 3, 2024
cbc7749
[#4267] Update misc. tests related to config refactor
Viicos Jun 3, 2024
84f76a3
[#4267] Update informatieobjecttypes endpoint
Viicos Jun 3, 2024
5862ae7
[#4267] Make JS messages
Viicos Jun 3, 2024
2e81f62
[#4267] Add business validation in the Objects API registration seria…
Viicos Jun 3, 2024
03cbb3e
[#4267] Add tests related to business validation
Viicos Jun 17, 2024
d9929d0
[#4267] Add admin webtest
Viicos Jun 18, 2024
7b68214
[#4267] Update Storybook stories
Viicos Jun 18, 2024
a417238
[#4267] Auto select Objects API group if only one available
Viicos Jun 18, 2024
3f3feae
[#4267] PR feedback
Viicos Jun 19, 2024
37c2372
[#4267] Add migration to set a default objects API group to backends …
Viicos Jun 19, 2024
4e2374e
[#4267] Regenerate OAS
Viicos Jun 19, 2024
c540a7b
:art: [#4267] Parametrize story render function with args
sergei-maertens Jun 20, 2024
ee57bb7
:green_heart: [#4267] Handle async behaviour in interaction test
sergei-maertens Jun 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3802,6 +3802,12 @@ paths:
registration backend and ZGW APIs services.
summary: List available InformatieObjectTypen
parameters:
- in: query
name: objects_api_group
schema:
type: integer
description: The primary key of the Objects API group to use. The informatieobjecttypen
from the Catalogi API in this group will be returned.
- in: query
name: registration_backend
schema:
Expand All @@ -3824,6 +3830,7 @@ paths:
* `objects_api` - Objects API registration
* `microsoft-graph` - Microsoft Graph (OneDrive/SharePoint)
* `camunda` - Camunda
required: true
- in: query
name: zgw_api_group
schema:
Expand Down Expand Up @@ -3919,6 +3926,12 @@ paths:
List the available Objecttypes.
Note that the response data is essentially proxied from the configured Objecttypes API.
parameters:
- in: query
name: objects_api_group
schema:
type: string
description: Which Objects API group to use.
tags:
- registration
security:
Expand Down Expand Up @@ -3949,6 +3962,11 @@ paths:
Note that the response data is essentially proxied from the configured Objecttypes API.
parameters:
- in: query
name: objects_api_group
schema:
type: string
description: Which Objects API group to use.
- in: path
name: submission_uuid
schema:
Expand Down Expand Up @@ -9919,6 +9937,9 @@ components:
TargetPathsInput:
type: object
properties:
objectsApiGroup:
type: integer
description: Which Objects API group to use.
objecttypeUrl:
type: string
format: uri
Expand All @@ -9931,6 +9952,7 @@ components:
additionalProperties: {}
description: The JSON Schema of the form variable.
required:
- objectsApiGroup
- objecttypeUrl
- objecttypeVersion
- variableJsonSchema
Expand Down
1 change: 1 addition & 0 deletions src/openforms/fixtures/admin_index_unlisted.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"qmatic.QmaticConfig",
"registrations_email.EmailConfig",
"registrations_microsoft_graph.MSGraphRegistrationConfig",
"registrations_objects_api.ObjectsAPIGroupConfig",
"registrations_objects_api.ObjectsAPIConfig",
"stuf.StufService",
"stuf_bg.StufBGConfig",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Generated by Django 4.2.11 on 2024-06-19 13:09

from django.db import migrations

from django.db.migrations.state import StateApps
from django.db.backends.base.schema import BaseDatabaseSchemaEditor


def add_default_objects_api_group(
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
) -> None:
FormRegistrationBackend = apps.get_model("forms", "FormRegistrationBackend")
ObjectsAPIGroupConfig = apps.get_model(
"registrations_objects_api", "ObjectsAPIGroupConfig"
)

objects_api_group_config = ObjectsAPIGroupConfig.objects.order_by("pk").first()
if objects_api_group_config is None:
# Because this migration runs after registrations_objects_api/0017_move_singleton_data,
# Having no Objects API Group means we had no solo config in the first place, thus
# it is safe to assume no Objects API registration backend was set up.
return

for registration_backend in FormRegistrationBackend.objects.filter(
backend="objects_api"
):
registration_backend.options.setdefault(
"objects_api_group", objects_api_group_config.pk
)
registration_backend.save()


class Migration(migrations.Migration):

dependencies = [
("forms", "0099_auto_20240613_0654"),
("registrations_objects_api", "0017_move_singleton_data"),
]

operations = [
migrations.RunPython(
add_default_objects_api_group,
migrations.RunPython.noop,
),
]
38 changes: 38 additions & 0 deletions src/openforms/forms/tests/test_migrations.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from django.db.migrations.state import StateApps

from zgw_consumers.constants import APITypes, AuthTypes

from openforms.utils.tests.test_migrations import TestMigrations
Expand Down Expand Up @@ -447,3 +449,39 @@ def test_conditionals_are_fixed(self):
isinstance(fixed_components[6]["components"][0]["conditional"]["eq"], bool)
)
self.assertTrue(fixed_components[6]["components"][0]["conditional"]["eq"])


class AddDefaultObjectsAPIGroupMigrationTests(TestMigrations):
app = "forms"
migrate_from = "0099_auto_20240613_0654"
migrate_to = "0100_add_default_objects_api_group"

def setUpBeforeMigration(self, apps: StateApps) -> None:
Form = apps.get_model("forms", "Form")
FormRegistrationBackend = apps.get_model("forms", "FormRegistrationBackend")
ObjectsAPIGroupConfig = apps.get_model(
"registrations_objects_api", "ObjectsAPIGroupConfig"
)

form = Form.objects.create(name="test form")
ObjectsAPIGroupConfig.objects.create(name="Objects API Group")

FormRegistrationBackend.objects.create(
form=form,
name="Objects API backend",
key="backend",
backend="objects_api",
)

def test_sets_default_objects_api_group(self) -> None:
FormRegistrationBackend = self.apps.get_model(
"forms", "FormRegistrationBackend"
)
ObjectsAPIGroupConfig = self.apps.get_model(
"registrations_objects_api", "ObjectsAPIGroupConfig"
)

backend = FormRegistrationBackend.objects.get()
self.assertEqual(
backend.options["objects_api_group"], ObjectsAPIGroupConfig.objects.get().pk
)
12 changes: 12 additions & 0 deletions src/openforms/js/compiled-lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2539,6 +2539,12 @@
"value": "Form variable"
}
],
"RELMCa": [
{
"type": 0,
"value": "Which Objects API group to use."
}
],
"RN628y": [
{
"type": 0,
Expand Down Expand Up @@ -4545,6 +4551,12 @@
"value": "House number"
}
],
"mgs/Xe": [
{
"type": 0,
"value": "Objects API group"
}
],
"mpzdoT": [
{
"type": 0,
Expand Down
12 changes: 12 additions & 0 deletions src/openforms/js/compiled-lang/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -2539,6 +2539,12 @@
"value": "Form variable"
}
],
"RELMCa": [
{
"type": 0,
"value": "Which Objects API group to use."
}
],
"RN628y": [
{
"type": 0,
Expand Down Expand Up @@ -4550,6 +4556,12 @@
"value": "Huisnummer"
}
],
"mgs/Xe": [
{
"type": 0,
"value": "Objects API group"
}
],
"mpzdoT": [
{
"type": 0,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import PropTypes from 'prop-types';
import React, {useContext} from 'react';
import React, {useContext, useEffect} from 'react';
import {useIntl} from 'react-intl';

import {CustomFieldTemplate} from 'components/admin/RJSFWrapper';
import {Checkbox, NumberInput, TextArea, TextInput} from 'components/admin/forms/Inputs';
import Select from 'components/admin/forms/Select';
import {ValidationErrorContext} from 'components/admin/forms/ValidationErrors';

import {getErrorMarkup, getFieldErrors} from './utils';
import {getChoicesFromSchema, getErrorMarkup, getFieldErrors} from './utils';

const LegacyConfigFields = ({index, name, formData, onChange}) => {
const LegacyConfigFields = ({index, name, schema, formData, onChange}) => {
const intl = useIntl();
const validationErrors = useContext(ValidationErrorContext);

const {
objectsApiGroup = '',
objecttype = '',
objecttypeVersion = '',
productaanvraagType = '',
Expand All @@ -30,8 +32,43 @@ const LegacyConfigFields = ({index, name, formData, onChange}) => {
return rawErrors ? getErrorMarkup(rawErrors) : null;
};

useEffect(() => {
if (schema.properties.objectsApiGroup.enum.length === 1 && objectsApiGroup === '') {
onChange({
target: {name: 'objectsApiGroup', value: schema.properties.objectsApiGroup.enum[0]},
});
}
}, []);

return (
<>
<CustomFieldTemplate
id="root_objectsApiGroup"
label={intl.formatMessage({
defaultMessage: 'Objects API group',
description: 'Objects API group',
})}
rawDescription={intl.formatMessage({
description: 'Objects API group selection',
defaultMessage: 'Which Objects API group to use.',
})}
rawErrors={getFieldErrors(name, index, validationErrors, 'objectsApiGroup')}
errors={buildErrorsComponent('objectsApiGroup')}
displayLabel
required
>
<Select
id="root_objectsApiGroup"
name="objectsApiGroup"
choices={getChoicesFromSchema(
schema.properties.objectsApiGroup.enum,
schema.properties.objectsApiGroup.enumNames
)}
value={objectsApiGroup}
onChange={onChange}
allowBlank
/>
</CustomFieldTemplate>
<CustomFieldTemplate
id="root_objecttype"
label={intl.formatMessage({
Expand Down Expand Up @@ -269,7 +306,9 @@ const LegacyConfigFields = ({index, name, formData, onChange}) => {
LegacyConfigFields.propTypes = {
index: PropTypes.number,
name: PropTypes.string,
schema: PropTypes.any,
formData: PropTypes.shape({
objectsApiGroup: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
version: PropTypes.number,
objecttype: PropTypes.string,
objecttypeVersion: PropTypes.string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const ObjectTypeSelect = ({availableObjectTypesState, objecttype, onChange}) =>
// synchronize the UI state back to the form state)
useEffect(() => {
// do nothing if no options have been loaded
if (loading) return;
if (loading || !availableObjecttypes.length) return;

// check if a valid option is selected, if this is the case -> do nothing
const isOptionPresent = availableObjecttypes.find(ot => ot.url === objecttype);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const getObjecttypeVersionsEndpoint = objecttype => {
};

const ObjectTypeVersionSelect = ({
objectsApiGroup,
availableObjecttypes = [],
selectedObjecttype,
selectedVersion,
Expand All @@ -27,17 +28,19 @@ const ObjectTypeVersionSelect = ({
value: availableVersions = [],
error,
} = useAsync(async () => {
if (!objectsApiGroup) return [];
const objecttype = availableObjecttypes.find(ot => ot.url === selectedObjecttype);
// no match -> no versions to retrieve;
if (!objecttype) return [];

const response = await get(getObjecttypeVersionsEndpoint(objecttype));
const params = {objects_api_group: objectsApiGroup};
const response = await get(getObjecttypeVersionsEndpoint(objecttype), params);
if (!response.ok) {
throw new Error('Loading available object types failed');
}
const versions = response.data;
return versions.sort((v1, v2) => v2.version - v1.version);
}, [selectedObjecttype, objecttypeUrls]);
}, [selectedObjecttype, objecttypeUrls, objectsApiGroup]);

const choices =
loading || error
Expand Down Expand Up @@ -76,6 +79,7 @@ const ObjectTypeVersionSelect = ({
};

ObjectTypeVersionSelect.propTypes = {
objectsApiGroup: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
availableObjecttypes: PropTypes.array,
selectedObjecttype: PropTypes.string.isRequired,
selectedVersion: PropTypes.string.isRequired,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ const ObjectsApiOptionsFormFields = ({index, name, schema, formData, onChange})
<LegacyConfigFields
index={index}
name={name}
schema={schema}
formData={formData}
onChange={onFieldChange}
/>
Expand All @@ -111,6 +112,7 @@ const ObjectsApiOptionsFormFields = ({index, name, schema, formData, onChange})
<V2ConfigFields
index={index}
name={name}
schema={schema}
formData={formData}
onChange={onFieldChange}
/>
Expand All @@ -126,6 +128,7 @@ ObjectsApiOptionsFormFields.propTypes = {
name: PropTypes.string,
schema: PropTypes.any,
formData: PropTypes.shape({
objectsApiGroup: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
version: PropTypes.number,
objecttype: PropTypes.string,
objecttypeVersion: PropTypes.string,
Expand Down
Loading
Loading