Skip to content

Commit

Permalink
🚚 [#4608] Move objects API specific configuration to own file
Browse files Browse the repository at this point in the history
  • Loading branch information
sergei-maertens committed Oct 8, 2024
1 parent 9ff3049 commit 9f11639
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 197 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {get} from 'utils/fetch';
import AttributeField from './AttributeField';
import IdentifierRoleField from './IdentifierRoleField';
import PluginField from './PluginField';
import {ErrorsType} from './types';

// Load the possible prefill attributes
// XXX: this would benefit from client-side caching
Expand Down Expand Up @@ -96,11 +97,6 @@ const DefaultFields = ({errors}) => {
);
};

const ErrorsType = PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.array])),
PropTypes.string,
]);

DefaultFields.propTypes = {
errors: PropTypes.shape({
plugin: ErrorsType,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
/**
* Prefill configuration form specific to the Objects API prefill plugin.
*
* Most other plugins can be configured with the generic form in `./DefaultFields`.
*/
import {useFormikContext} from 'formik';
import PropTypes from 'prop-types';
import {useContext} from 'react';
import {FormattedMessage, useIntl} from 'react-intl';
import useAsync from 'react-use/esm/useAsync';

import {FormContext} from 'components/admin/form_design/Context';
import Field from 'components/admin/forms/Field';
import Fieldset from 'components/admin/forms/Fieldset';
import FormRow from 'components/admin/forms/FormRow';
import {LOADING_OPTION} from 'components/admin/forms/Select';
import VariableMapping from 'components/admin/forms/VariableMapping';
import {
ObjectTypeSelect,
ObjectTypeVersionSelect,
ObjectsAPIGroup,
} from 'components/admin/forms/objects_api';
import {FAIcon} from 'components/admin/icons';
import ErrorBoundary from 'components/errors/ErrorBoundary';
import {get} from 'utils/fetch';

import PluginField from './PluginField';
import {ErrorsType} from './types';

const PLUGIN_ID = 'objects_api';

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

// Load the possible prefill properties
// XXX: this would benefit from client-side caching
const getProperties = async (objectsApiGroup, objecttype, objecttypeVersion) => {
const endpoint = `/api/v2/prefill/plugins/objects-api/objecttypes/${objecttype}/versions/${objecttypeVersion}/properties`;
// XXX: clean up error handling here at some point...
const response = await get(endpoint, {objects_api_group: objectsApiGroup});
if (!response.ok) throw response.data;

return response.data.map(property => [property.targetPath, property.targetPath.join(' > ')]);
};

const ObjectsAPIFields = ({errors}) => {
const {
values: {
plugin,
options: {objecttype, objecttypeVersion, objectsApiGroup},
},
setFieldValue,
} = useFormikContext();
const intl = useIntl();

const {
plugins: {availablePrefillPlugins},
} = useContext(FormContext);
const objectsPlugin = availablePrefillPlugins.find(elem => elem.id === PLUGIN_ID);

const {apiGroups} = objectsPlugin.configurationContext;

const {
loading,
value = [],
error,
} = useAsync(async () => {
if (!plugin || !objecttype || !objecttypeVersion || !objectsApiGroup) return [];
try {
return await getProperties(objectsApiGroup, objecttype, objecttypeVersion);
} catch (e) {
throw e;
}
}, [plugin, objecttype, objecttypeVersion, objectsApiGroup]);

// throw errors to the nearest error boundary
if (error) throw error;
const prefillProperties = loading ? LOADING_OPTION : value;

return (
<>
<Fieldset>
<FormRow>
<Field
name="plugin"
label={
<FormattedMessage
description="Variable prefill plugin label"
defaultMessage="Plugin"
/>
}
errors={errors.plugin}
>
<PluginField />
</Field>
</FormRow>

<ObjectsAPIGroup
apiGroupChoices={apiGroups}
onChangeCheck={() => {
if (values.options.variablesMapping.length === 0) return true;
const confirmSwitch = window.confirm(
intl.formatMessage({
description:
'Objects API registration options: warning message when changing the api group',
defaultMessage: `Changing the api group will remove the existing variables mapping.
Are you sure you want to continue?`,
})
);
if (!confirmSwitch) return false;
setFieldValue('options.variablesMapping', []);
return true;
}}
name="options.objectsApiGroup"
onApiGroupChange={onApiGroupChange}
/>

<ErrorBoundary
errorMessage={
<FormattedMessage
description="Objects API registrations options: object type select error"
defaultMessage="Something went wrong while retrieving the available object types."
/>
}
>
<ObjectTypeSelect
name="options.objecttype"
apiGroupFieldName="options.objectsApiGroup"
versionFieldName="options.objecttypeVersion"
onChangeCheck={() => {
if (values.options.variablesMapping.length === 0) return true;
const confirmSwitch = window.confirm(
intl.formatMessage({
description:
'Objects API registration options: warning message when changing the object type',
defaultMessage: `Changing the objecttype will remove the existing variables mapping.
Are you sure you want to continue?`,
})
);
if (!confirmSwitch) return false;
setFieldValue('options.variablesMapping', []);
return true;
}}
/>
</ErrorBoundary>

<ErrorBoundary
errorMessage={
<FormattedMessage
description="Objects API registrations options: object type version select error"
defaultMessage="Something went wrong while retrieving the available object type versions."
/>
}
>
<ObjectTypeVersionSelect
name="options.objecttypeVersion"
apiGroupFieldName="options.objectsApiGroup"
objectTypeFieldName="options.objecttype"
/>
</ErrorBoundary>
</Fieldset>

<Fieldset
title={
<FormattedMessage
description="Objects API prefill mappings fieldset title"
defaultMessage="Mappings"
/>
}
>
<FormRow>
<VariableMapping
name="options.variablesMapping"
loading={loading}
directionIcon={<FAIcon icon="arrow-left-long" aria-hidden="true" />}
propertyName="prefillProperty"
propertyChoices={prefillProperties}
propertyHeading={
<FormattedMessage
description="Prefill / Objects API: column header for object type property selection"
defaultMessage="Source path"
/>
}
propertySelectLabel={intl.formatMessage({
description:
'Prefill / Objects API: accessible label for object type property selection',
defaultMessage: 'Select a property from the object type',
})}
/>
</FormRow>
</Fieldset>
</>
);
};

ObjectsAPIFields.propTypes = {
errors: PropTypes.shape({
plugin: ErrorsType,
}).isRequired,
};

export default ObjectsAPIFields;
Loading

0 comments on commit 9f11639

Please sign in to comment.