Skip to content

Commit

Permalink
Merge pull request #3912 from open-formulieren/feature/3855-error-in-…
Browse files Browse the repository at this point in the history
…admin-no-camunda

[#3855] Catch errors when DMN plugin is not working
  • Loading branch information
sergei-maertens authored Feb 23, 2024
2 parents b759366 + 6215a3c commit 4def8b8
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 44 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Form, Formik, useField, useFormikContext} from 'formik';
import PropTypes from 'prop-types';
import React, {useContext, useState} from 'react';
import React, {useContext, useEffect} from 'react';
import {FormattedMessage, defineMessage} from 'react-intl';
import {useAsync} from 'react-use';

Expand All @@ -11,6 +11,7 @@ import {
} from 'components/admin/form_design/constants';
import Field from 'components/admin/forms/Field';
import Select from 'components/admin/forms/Select';
import ErrorBoundary from 'components/errors/ErrorBoundary';
import {get} from 'utils/fetch';

import DMNParametersForm from './DMNParametersForm';
Expand All @@ -24,32 +25,40 @@ const ERRORS = {
};

const DecisionDefinitionIdField = () => {
const {values, setFieldValue, getFieldProps, errors, touched} = useFormikContext();
const {
values: {pluginId},
setFieldValue,
getFieldProps,
errors,
touched,
setFieldTouched,
handleChange,
} = useFormikContext();
const [field] = useField('decisionDefinitionId');
const [decisionDefinitions, setDecisionDefinitions] = useState([]);

useAsync(async () => {
if (!values.pluginId) {
setFieldValue('decisionDefinitionId', '');
setDecisionDefinitions([]);
return;
}
const {error, value: decisionDefinitions = []} = useAsync(async () => {
if (!pluginId) return [];

const response = await get(DMN_DECISION_DEFINITIONS_LIST, {
engine: values.pluginId,
engine: pluginId,
});

const definitionChoices = response.data.map(item => [item.id, item.label]);
setDecisionDefinitions(definitionChoices);
return response.data.map(item => [item.id, item.label]);
}, [pluginId]);

// If pluginId has changed, reset the value of the definition
if (
values.decisionDefinitionId !== '' &&
!definitionChoices.find(item => item[0] === values.decisionDefinitionId)
) {
useEffect(() => {
if (!touched.pluginId) return;

if (!pluginId) {
setFieldValue('decisionDefinitionId', '');
return;
}
}, [values.pluginId, setFieldValue]);

// If pluginId has changed, reset the value of the definition
setFieldValue('decisionDefinitionId', '');
}, [pluginId, setFieldValue]);

if (error) throw error;

return (
<Field
Expand All @@ -68,10 +77,15 @@ const DecisionDefinitionIdField = () => {
}
>
<Select
allowBlank={true}
allowBlank
choices={decisionDefinitions}
{...field}
{...getFieldProps('decisionDefinitionId')}
onChange={(...args) => {
// Otherwise the field is set as 'touched' only on the blur event
setFieldTouched('decisionDefinitionId');
handleChange(...args);
}}
/>
</Field>
);
Expand All @@ -82,35 +96,37 @@ const DecisionDefinitionVersionField = () => {
values: {pluginId, decisionDefinitionId},
setFieldValue,
getFieldProps,
touched,
setFieldTouched,
handleChange,
} = useFormikContext();
const [field] = useField('decisionDefinitionVersion');
const [decisionDefinitionVersions, setDecisionDefinitionVersions] = useState([]);

useAsync(async () => {
if (!pluginId || !decisionDefinitionId) {
setFieldValue('decisionDefinitionVersion', '');
setDecisionDefinitionVersions([]);
return;
}
const {error, value: decisionDefinitionVersions = []} = useAsync(async () => {
if (!pluginId || !decisionDefinitionId) return [];

const response = await get(DMN_DECISION_DEFINITIONS_VERSIONS_LIST, {
engine: pluginId,
definition: decisionDefinitionId,
});

const versionChoices = response.data.map(item => [item.id, item.label]);
setDecisionDefinitionVersions(versionChoices);
return response.data.map(item => [item.id, item.label]);
}, [pluginId, decisionDefinitionId]);

useEffect(() => {
if (!touched.pluginId && !touched.decisionDefinitionId) return;

// If decisionDefinitionId has changed, reset the value of the definition version if the new decision definition
// does not have that version
if (
values.decisionDefinitionVersion !== '' &&
!versionChoices.find(item => item[0] === values.decisionDefinitionVersion)
) {
if (!pluginId || !decisionDefinitionId) {
setFieldValue('decisionDefinitionVersion', '');
return;
}

// If decisionDefinitionId has changed, reset the value of the definition version
setFieldValue('decisionDefinitionVersion', '');
}, [pluginId, decisionDefinitionId, setFieldValue]);

if (error) throw error;

return (
<Field
name="decisionDefinitionVersion"
Expand All @@ -123,10 +139,15 @@ const DecisionDefinitionVersionField = () => {
}
>
<Select
allowBlank={true}
allowBlank
choices={decisionDefinitionVersions}
{...field}
{...getFieldProps('decisionDefinitionVersion')}
onChange={(...args) => {
// Otherwise the field is set as 'touched' only on the blur event
setFieldTouched('decisionDefinitionVersion');
handleChange(...args);
}}
/>
</Field>
);
Expand Down Expand Up @@ -165,7 +186,7 @@ const DMNActionConfig = ({initialValues, onSave}) => {
{formik => (
<Form>
<fieldset className="aligned">
<div className="form-row">
<div className="form-row form-row--no-bottom-line">
<Field
name="pluginId"
htmlFor="pluginId"
Expand All @@ -184,19 +205,35 @@ const DMNActionConfig = ({initialValues, onSave}) => {
allowBlank={true}
choices={plugins.availableDMNPlugins.map(choice => [choice.id, choice.label])}
{...formik.getFieldProps('pluginId')}
onChange={(...args) => {
// Otherwise the field is set as 'touched' only on the blur event
formik.setFieldTouched('pluginId');
formik.handleChange(...args);
}}
/>
</Field>
</div>
<div className="form-row">
<DecisionDefinitionIdField />
</div>
<div className="form-row">
<DecisionDefinitionVersionField />
</div>
</fieldset>

<DMNParametersForm />

<ErrorBoundary
errorMessage={
<FormattedMessage
description="Admin error for API error when configuring Camunda actions"
defaultMessage="Could not retrieve the decision definitions IDs/versions. Is the selected DMN plugin running and properly configured?"
/>
}
>
<fieldset className="aligned">
<div className="form-row">
<DecisionDefinitionIdField />
</div>
<div className="form-row">
<DecisionDefinitionVersionField />
</div>
</fieldset>

<DMNParametersForm />
</ErrorBoundary>
<div className="submit-row">
<input type="submit" name="_save" value="Save" />
</div>
Expand Down
6 changes: 6 additions & 0 deletions src/openforms/scss/components/builder/_builder.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@use 'microscope-sass/lib/bem';

@import '@fortawesome/fontawesome-free/scss/fontawesome';
@import '@fortawesome/fontawesome-free/scss/v4-shims.scss';
@import '@fortawesome/fontawesome-free/scss/brands';
Expand Down Expand Up @@ -225,4 +227,8 @@ div.flatpickr-calendar.open {
.form-builder__container {
color: var(--body-fg);
}

@include bem.modifier('no-bottom-line') {
border-bottom: 0;
}
}

0 comments on commit 4def8b8

Please sign in to comment.