Skip to content

Commit

Permalink
feat: Validate field config and fix multiple form in page (#83)
Browse files Browse the repository at this point in the history
* feat: custom validators for config form fields and fix multiple form in same page

* chore: updated README

* chore: removed console log
  • Loading branch information
giuliaghisini committed Mar 14, 2024
1 parent 14223c7 commit ca373b6
Show file tree
Hide file tree
Showing 21 changed files with 208 additions and 35 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,24 @@ i.e.: aggregated data from user federated authentication:

![Static fields](./docs/form-static-fields.png)

## Schema validators

If you want to validate configuration field (for example, testing if 'From email' is an address of a specific domain), you could add your validation functions to block config:

```js
config.blocks.blocksConfig.form = {
...config.blocks.blocksConfig.form,
schemaValidators: {
fieldname: yourValidationFN(data),
},
};
```

`yourValidationFN` have to return:

- null if field is valid
- a string with the error message if field is invalid.

## Upgrade guide

To upgrade to version 2.4.0 you need to:
Expand Down
5 changes: 5 additions & 0 deletions locales/de/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,11 @@ msgstr "Daten exportieren"
msgid "form_edit_fill_required_configuration_fields"
msgstr ""

#: components/ValidateConfigForm
# defaultMessage: Please, verify this configuration errors in sidebar. The form will be not displayed in view mode until this errors fields are not fixed.
msgid "form_edit_other_errors"
msgstr ""

#: components/Edit
# defaultMessage: Attenzione!
msgid "form_edit_warning"
Expand Down
5 changes: 5 additions & 0 deletions locales/en/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,11 @@ msgstr "Export in CSV"
msgid "form_edit_fill_required_configuration_fields"
msgstr ""

#: components/ValidateConfigForm
# defaultMessage: Please, verify this configuration errors in sidebar. The form will be not displayed in view mode until this errors fields are not fixed.
msgid "form_edit_other_errors"
msgstr ""

#: components/Edit
# defaultMessage: Attenzione!
msgid "form_edit_warning"
Expand Down
5 changes: 5 additions & 0 deletions locales/es/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,11 @@ msgstr "Exportar datos"
msgid "form_edit_fill_required_configuration_fields"
msgstr ""

#: components/ValidateConfigForm
# defaultMessage: Please, verify this configuration errors in sidebar. The form will be not displayed in view mode until this errors fields are not fixed.
msgid "form_edit_other_errors"
msgstr ""

#: components/Edit
# defaultMessage: Attenzione!
msgid "form_edit_warning"
Expand Down
5 changes: 5 additions & 0 deletions locales/eu/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,11 @@ msgstr "Esportatu datuak"
msgid "form_edit_fill_required_configuration_fields"
msgstr ""

#: components/ValidateConfigForm
# defaultMessage: Please, verify this configuration errors in sidebar. The form will be not displayed in view mode until this errors fields are not fixed.
msgid "form_edit_other_errors"
msgstr ""

#: components/Edit
# defaultMessage: Attenzione!
msgid "form_edit_warning"
Expand Down
5 changes: 5 additions & 0 deletions locales/fr/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,11 @@ msgstr "Exporter au format CSV"
msgid "form_edit_fill_required_configuration_fields"
msgstr ""

#: components/ValidateConfigForm
# defaultMessage: Please, verify this configuration errors in sidebar. The form will be not displayed in view mode until this errors fields are not fixed.
msgid "form_edit_other_errors"
msgstr ""

#: components/Edit
# defaultMessage: Attenzione!
msgid "form_edit_warning"
Expand Down
7 changes: 6 additions & 1 deletion locales/it/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,12 @@ msgstr "Esporta in CSV"
#: components/ValidateConfigForm
# defaultMessage: Please, fill-in required configuration fields in sidebar. The form will be not displayed in view mode until required fields are filled-in.
msgid "form_edit_fill_required_configuration_fields"
msgstr "Inserire i campi obbligatori per la configurazione del form nella sidebar di destra. Il form non verrà mostrata sul sito finché i campi obbligatori non saranno configurati."
msgstr "Inserire i campi obbligatori per la configurazione del form nella sidebar di destra. Il form non verrà mostrato sul sito finché i campi obbligatori non saranno configurati."

#: components/ValidateConfigForm
# defaultMessage: Please, verify this configuration errors in sidebar. The form will be not displayed in view mode until this errors fields are not fixed.
msgid "form_edit_other_errors"
msgstr "Verifica i seguenti errori di configurazione nella sidebar di destra. Il form non verrà mostrato sul sito finchè questi errori non sono stati sistemati."

#: components/Edit
# defaultMessage: Attenzione!
Expand Down
5 changes: 5 additions & 0 deletions locales/ja/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,11 @@ msgstr ""
msgid "form_edit_fill_required_configuration_fields"
msgstr ""

#: components/ValidateConfigForm
# defaultMessage: Please, verify this configuration errors in sidebar. The form will be not displayed in view mode until this errors fields are not fixed.
msgid "form_edit_other_errors"
msgstr ""

#: components/Edit
# defaultMessage: Attenzione!
msgid "form_edit_warning"
Expand Down
5 changes: 5 additions & 0 deletions locales/nl/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,11 @@ msgstr ""
msgid "form_edit_fill_required_configuration_fields"
msgstr ""

#: components/ValidateConfigForm
# defaultMessage: Please, verify this configuration errors in sidebar. The form will be not displayed in view mode until this errors fields are not fixed.
msgid "form_edit_other_errors"
msgstr ""

#: components/Edit
# defaultMessage: Attenzione!
msgid "form_edit_warning"
Expand Down
5 changes: 5 additions & 0 deletions locales/pt/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,11 @@ msgstr ""
msgid "form_edit_fill_required_configuration_fields"
msgstr ""

#: components/ValidateConfigForm
# defaultMessage: Please, verify this configuration errors in sidebar. The form will be not displayed in view mode until this errors fields are not fixed.
msgid "form_edit_other_errors"
msgstr ""

#: components/Edit
# defaultMessage: Attenzione!
msgid "form_edit_warning"
Expand Down
5 changes: 5 additions & 0 deletions locales/pt_BR/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,11 @@ msgstr "Exportar dados"
msgid "form_edit_fill_required_configuration_fields"
msgstr ""

#: components/ValidateConfigForm
# defaultMessage: Please, verify this configuration errors in sidebar. The form will be not displayed in view mode until this errors fields are not fixed.
msgid "form_edit_other_errors"
msgstr ""

#: components/Edit
# defaultMessage: Attenzione!
msgid "form_edit_warning"
Expand Down
5 changes: 5 additions & 0 deletions locales/ro/LC_MESSAGES/volto.po
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,11 @@ msgstr ""
msgid "form_edit_fill_required_configuration_fields"
msgstr ""

#: components/ValidateConfigForm
# defaultMessage: Please, verify this configuration errors in sidebar. The form will be not displayed in view mode until this errors fields are not fixed.
msgid "form_edit_other_errors"
msgstr ""

#: components/Edit
# defaultMessage: Attenzione!
msgid "form_edit_warning"
Expand Down
7 changes: 6 additions & 1 deletion locales/volto.pot
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: Plone\n"
"POT-Creation-Date: 2024-03-11T13:38:04.642Z\n"
"POT-Creation-Date: 2024-03-14T13:21:14.614Z\n"
"Last-Translator: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
"Language-Team: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
"MIME-Version: 1.0\n"
Expand Down Expand Up @@ -300,6 +300,11 @@ msgstr ""
msgid "form_edit_fill_required_configuration_fields"
msgstr ""

#: components/ValidateConfigForm
# defaultMessage: Please, verify this configuration errors in sidebar. The form will be not displayed in view mode until this errors fields are not fixed.
msgid "form_edit_other_errors"
msgstr ""

#: components/Edit
# defaultMessage: Attenzione!
msgid "form_edit_warning"
Expand Down
8 changes: 6 additions & 2 deletions src/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const SUBMIT_FORM_ACTION = 'SUBMIT_FORM_ACTION';
export function submitForm(path = '', block_id, data, attachments, captcha) {
return {
type: SUBMIT_FORM_ACTION,
subrequest: block_id,
request: {
op: 'post',
path: path + '/@submit-form',
Expand All @@ -35,12 +36,15 @@ export function submitForm(path = '', block_id, data, attachments, captcha) {
*/
export const EXPORT_CSV_FORMDATA = 'EXPORT_CSV_FORMDATA';

export function exportCsvFormData(path = '') {
export function exportCsvFormData(path = '', filename, block_id) {
return {
type: EXPORT_CSV_FORMDATA,
filename: filename,
request: {
op: 'get',
path: path + '/@form-data-export',
path: `${path}/@form-data-export${
block_id ? '?block_id=' + block_id : ''
}`,
},
};
}
Expand Down
10 changes: 9 additions & 1 deletion src/components/FormView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,15 @@ const FormView = ({
<Grid.Row centered className="row-padded-top">
<Grid.Column textAlign="center">
{data?.show_cancel && (
<Button secondary type="button" onClick={resetFormState}>
<Button
secondary
type="button"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
resetFormState();
}}
>
{data.cancel_label ||
intl.formatMessage(messages.default_cancel_label)}
</Button>
Expand Down
1 change: 1 addition & 0 deletions src/components/Sidebar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ const Sidebar = ({
exportCsvFormData(
flattenToAppURL(properties['@id']),
`export-${properties.id ?? 'form'}.csv`,
block,
),
)
}
Expand Down
40 changes: 37 additions & 3 deletions src/components/ValidateConfigForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,20 @@ const messages = defineMessages({
defaultMessage:
'Please, fill-in required configuration fields in sidebar. The form will be not displayed in view mode until required fields are filled-in.',
},
other_errors: {
id: 'form_edit_other_errors',
defaultMessage:
'Please, verify this configuration errors in sidebar. The form will be not displayed in view mode until this errors fields are not fixed.',
},
});

const ValidateConfigForm = ({ data = {}, children, onEdit }) => {
const intl = useIntl();
var Schema = config.blocks.blocksConfig.form.formSchema;
var SchemaValidators = config.blocks.blocksConfig.form.schemaValidators;
var blockSchema = Schema(data);
const required_fields = blockSchema.required;
const valid =
const noRequired =
required_fields.filter(
(r) =>
data[r] === null ||
Expand All @@ -24,19 +30,47 @@ const ValidateConfigForm = ({ data = {}, children, onEdit }) => {
(blockSchema.properties[r].type === 'boolean' && !data[r]),
).length === 0;

let schema_validation = [];
if (SchemaValidators) {
Object.keys(SchemaValidators).forEach((fieldName) => {
const validateFieldFN = SchemaValidators[fieldName];
const validation = validateFieldFN(data);

if (validation) {
schema_validation.push({ field: fieldName, message: validation });
}
});
}

let noInvalidFields = schema_validation.length === 0;

const valid = noRequired && noInvalidFields;

return (
<>
{!valid && onEdit && (
<div
style={{
padding: '1rem',
textAlign: 'center',

backgroundColor: '#fff0f0',
border: '1px solid #c40e00',
borderRadius: '3px',
}}
>
{intl.formatMessage(messages.fill_required_config_fields)}
{!noRequired && (
<>{intl.formatMessage(messages.fill_required_config_fields)}</>
)}
{schema_validation?.length > 0 && (
<div>
{intl.formatMessage(messages.other_errors)}
<ul>
{schema_validation.map((v) => (
<li>{v.message}</li>
))}
</ul>
</div>
)}
</div>
)}
{(valid || onEdit) && <>{children}</>}
Expand Down
5 changes: 4 additions & 1 deletion src/components/View.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,10 @@ const View = ({ data, id, path }) => {

const [formState, setFormState] = useReducer(formStateReducer, initialState);
const [formErrors, setFormErrors] = useState([]);
const submitResults = useSelector((state) => state.submitForm);

const submitResults = useSelector(
(state) => state.submitForm?.subrequests?.[id],
);
const captchaToken = useRef();

const onChangeFormData = (field_id, field, value, extras) => {
Expand Down
1 change: 1 addition & 0 deletions src/formSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ const Schema = (data) => {
'default_to',
'default_from',
'default_subject',
'captcha',
...conditional_required,
],
};
Expand Down
11 changes: 7 additions & 4 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ const applyConfig = (config) => {
from: FromSchemaExtender,
hidden: HiddenSchemaExtender,
},
schemaValidators: {
/*fieldname: validationFN(data)*/
},
attachment_fields: ['attachment'],
restricted: false,
mostUsed: true,
Expand All @@ -65,11 +68,11 @@ const applyConfig = (config) => {
clearFormData,
};

config.settings.loadables['HCaptcha'] = loadable(() =>
import('@hcaptcha/react-hcaptcha'),
config.settings.loadables['HCaptcha'] = loadable(
() => import('@hcaptcha/react-hcaptcha'),
);
config.settings.loadables['GoogleReCaptcha'] = loadable.lib(() =>
import('react-google-recaptcha-v3'),
config.settings.loadables['GoogleReCaptcha'] = loadable.lib(
() => import('react-google-recaptcha-v3'),
);

return config;
Expand Down
Loading

0 comments on commit ca373b6

Please sign in to comment.