From 092fe5874c20fdd3b8d5f52cbf3c033f400cdf5c Mon Sep 17 00:00:00 2001 From: Sergei Maertens Date: Mon, 19 Aug 2024 17:15:14 +0200 Subject: [PATCH 1/4] :sparkles: [open-formulieren/open-forms#4542] Implement preview of email component with verification The preview displays an inert button for verification to get *some* impression of the effect of enabling this option. --- src/components/ComponentPreview.stories.tsx | 20 ++++++++++ src/components/ComponentPreview.tsx | 6 ++- src/components/formio/textfield.tsx | 33 +++++++++------- src/registry/email/edit.tsx | 6 ++- src/registry/email/preview.tsx | 43 +++++++++++++++------ src/registry/email/previews.scss | 13 +++++++ 6 files changed, 94 insertions(+), 27 deletions(-) create mode 100644 src/registry/email/previews.scss diff --git a/src/components/ComponentPreview.stories.tsx b/src/components/ComponentPreview.stories.tsx index 3663e9dc..14562c98 100644 --- a/src/components/ComponentPreview.stories.tsx +++ b/src/components/ComponentPreview.stories.tsx @@ -1,3 +1,4 @@ +import {EmailComponentSchema} from '@open-formulieren/types'; import {Meta, StoryFn, StoryObj} from '@storybook/react'; import {expect, fireEvent, fn, userEvent, waitFor, within} from '@storybook/test'; @@ -131,6 +132,25 @@ export const Email: Story = { }, }; +export const EmailWithVerification: Story = { + render: Template, + args: { + component: { + type: 'email', + id: 'email', + key: 'emailPreview', + label: 'Email preview', + description: 'A preview of the email Formio component', + hidden: true, // must be ignored + validateOn: 'blur', + openForms: { + translations: {}, + requireVerification: true, + }, + }, + }, +}; + export const EmailMultiple: Story = { render: Template, diff --git a/src/components/ComponentPreview.tsx b/src/components/ComponentPreview.tsx index 5d55e08e..fa2a1b5e 100644 --- a/src/components/ComponentPreview.tsx +++ b/src/components/ComponentPreview.tsx @@ -1,4 +1,5 @@ import {JSONEditor} from '@open-formulieren/monaco-json-editor'; +import clsx from 'clsx'; import {Formik} from 'formik'; import React, {useContext, useState} from 'react'; import {FormattedMessage} from 'react-intl'; @@ -55,7 +56,10 @@ const ComponentPreviewWrapper: React.FC = ({ throw new Error("Can't submit preview form"); }} > -
+
{children}
diff --git a/src/components/formio/textfield.tsx b/src/components/formio/textfield.tsx index 3fc85cf7..082a2103 100644 --- a/src/components/formio/textfield.tsx +++ b/src/components/formio/textfield.tsx @@ -20,6 +20,7 @@ export interface TextFieldProps { showCharCount?: boolean; inputMask?: string; onChange?: (event: React.ChangeEvent) => void; + childrenAfterField?: React.ReactNode; } export const TextField: React.FC = ({ @@ -31,6 +32,7 @@ export const TextField: React.FC { const {getFieldProps, getFieldMeta} = useFormikContext(); @@ -57,20 +59,23 @@ export const TextField: React.FC) => { - formikOnChange(event); - onChange?.(event); - }} - {...props} - /> + <> + ) => { + formikOnChange(event); + onChange?.(event); + }} + {...props} + /> + {childrenAfterField} + ); const hasFocus = inputRef.current === document.activeElement; diff --git a/src/registry/email/edit.tsx b/src/registry/email/edit.tsx index 0dd40358..286a405b 100644 --- a/src/registry/email/edit.tsx +++ b/src/registry/email/edit.tsx @@ -140,9 +140,13 @@ EditForm.defaultValues = { registration: { attribute: '', }, + // openForms extensions + openForms: { + translations: {}, + requireVerification: false, + }, // fixed but not editable validateOn: 'blur', - // inputType: 'email', }; interface DefaultValueProps { diff --git a/src/registry/email/preview.tsx b/src/registry/email/preview.tsx index 310a4e19..796a8f99 100644 --- a/src/registry/email/preview.tsx +++ b/src/registry/email/preview.tsx @@ -1,8 +1,10 @@ import {EmailComponentSchema} from '@open-formulieren/types'; +import {FormattedMessage} from 'react-intl'; import {TextField} from '@/components/formio'; import {ComponentPreviewProps} from '../types'; +import './previews.scss'; /** * Show a formio email component preview. @@ -12,19 +14,38 @@ import {ComponentPreviewProps} from '../types'; * @open-formulieren/formio-renderer instead for a more accurate preview. */ const Preview: React.FC> = ({component}) => { - const {key, label, description, tooltip, validate = {}, autocomplete, multiple} = component; + const { + key, + label, + description, + tooltip, + validate = {}, + autocomplete, + multiple, + openForms, + } = component; const {required = false} = validate; + const requireVerification = openForms?.requireVerification ?? false; + + const verificationButton = requireVerification ? ( + + ) : null; return ( - + <> + + ); }; diff --git a/src/registry/email/previews.scss b/src/registry/email/previews.scss new file mode 100644 index 00000000..154453f5 --- /dev/null +++ b/src/registry/email/previews.scss @@ -0,0 +1,13 @@ +.component-preview.component-preview--email { + // single value preview + .form-group > div:has(input + button) { + display: flex; + gap: 15px; + } + + // multiple value preview + td:has(input + button) { + display: flex; + gap: 15px; + } +} From 4d58c25f94aa1a62652dce1d18b91b65a95b6d6d Mon Sep 17 00:00:00 2001 From: Sergei Maertens Date: Mon, 19 Aug 2024 17:47:09 +0200 Subject: [PATCH 2/4] :sparkles: [open-formulieren/open-forms#4542] Add email address verification option to builder form --- src/registry/email/edit.tsx | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/registry/email/edit.tsx b/src/registry/email/edit.tsx index 286a405b..1277591c 100644 --- a/src/registry/email/edit.tsx +++ b/src/registry/email/edit.tsx @@ -87,6 +87,7 @@ const EditForm: EditFormDefinition = () => { {/* Validation tab */} + @@ -190,4 +191,26 @@ const IsConfirmationRecipient: React.FC = () => { ); }; +const RequireVerification = () => { + const intl = useIntl(); + const tooltip = intl.formatMessage({ + description: "Tooltip for email 'openForms.requireVerification' builder field", + defaultMessage: `When email address verification is enabled, the user must verify + their email address before they can submit the form. This proves the email address + exists and that they have access to the account.`, + }); + return ( + + } + tooltip={tooltip} + /> + ); +}; + export default EditForm; From 539a0e07aa2214231b2d23da84603654b8b98fcf Mon Sep 17 00:00:00 2001 From: Sergei Maertens Date: Mon, 19 Aug 2024 17:50:07 +0200 Subject: [PATCH 3/4] :globe_with_meridians: Updated translations --- i18n/messages/en.json | 20 ++++++++++++++++++++ i18n/messages/nl.json | 20 ++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/i18n/messages/en.json b/i18n/messages/en.json index 7a644ba8..2802a651 100644 --- a/i18n/messages/en.json +++ b/i18n/messages/en.json @@ -84,6 +84,11 @@ "description": "Tooltip for 'validate.min' builder field", "originalDefault": "The minimum value this field can have before the form can be submitted." }, + "205QX5": { + "defaultMessage": "When email address verification is enabled, the user must verify their email address before they can submit the form. This proves the email address exists and that they have access to the account.", + "description": "Tooltip for email 'openForms.requireVerification' builder field", + "originalDefault": "When email address verification is enabled, the user must verify their email address before they can submit the form. This proves the email address exists and that they have access to the account." + }, "2Lg8Vc": { "defaultMessage": "Hide fieldset header", "description": "Label for 'hideHeader' builder field", @@ -344,6 +349,11 @@ "description": "Character count remaining", "originalDefault": "{length} {length, plural, one {character remaining} other {characters remaining}}" }, + "Cf5zSF": { + "defaultMessage": "Verify", + "description": "Email verification button text", + "originalDefault": "Verify" + }, "D0hDzV": { "defaultMessage": "{componentType} component", "description": "Formio builder: component configuration form title", @@ -754,6 +764,11 @@ "description": "Date constraint mode 'past' label", "originalDefault": "In the past" }, + "Wb+QGm": { + "defaultMessage": "Require verification", + "description": "Label for email 'openForms.requireVerification' builder field", + "originalDefault": "Require verification" + }, "WkBjB5": { "defaultMessage": "In case that multiple identifiers are returned (in the case of eHerkenning bewindvoering and DigiD Machtigen), should the prefill data related to the main identifier be used, or that related to the authorised person?", "description": "Tooltip for 'prefill.identifierRole' builder field", @@ -1404,6 +1419,11 @@ "description": "Label for 'validate.maxLength' builder field", "originalDefault": "Maximum length" }, + "yGAl1a": { + "defaultMessage": "Close", + "description": "Modal close button label", + "originalDefault": "Close" + }, "yL9Ql7": { "defaultMessage": "Translations", "description": "Translations: translation column header", diff --git a/i18n/messages/nl.json b/i18n/messages/nl.json index 8367cd31..6e6bbaa1 100644 --- a/i18n/messages/nl.json +++ b/i18n/messages/nl.json @@ -85,6 +85,11 @@ "description": "Tooltip for 'validate.min' builder field", "originalDefault": "The minimum value this field can have before the form can be submitted." }, + "205QX5": { + "defaultMessage": "When email address verification is enabled, the user must verify their email address before they can submit the form. This proves the email address exists and that they have access to the account.", + "description": "Tooltip for email 'openForms.requireVerification' builder field", + "originalDefault": "When email address verification is enabled, the user must verify their email address before they can submit the form. This proves the email address exists and that they have access to the account." + }, "2Lg8Vc": { "defaultMessage": "Verberg veldengroepheader", "description": "Label for 'hideHeader' builder field", @@ -348,6 +353,11 @@ "description": "Character count remaining", "originalDefault": "{length} {length, plural, one {character remaining} other {characters remaining}}" }, + "Cf5zSF": { + "defaultMessage": "Verify", + "description": "Email verification button text", + "originalDefault": "Verify" + }, "D0hDzV": { "defaultMessage": "{componentType}-component", "description": "Formio builder: component configuration form title", @@ -764,6 +774,11 @@ "description": "Date constraint mode 'past' label", "originalDefault": "In the past" }, + "Wb+QGm": { + "defaultMessage": "Require verification", + "description": "Label for email 'openForms.requireVerification' builder field", + "originalDefault": "Require verification" + }, "WkBjB5": { "defaultMessage": "Indien meerdere unieke identificaties beschikbaar zijn (bijvoorbeeld bij eHerkenning Bewindvoering en DigiD Machtigen), welke prefill-gegevens moeten dan opgehaald worden? Deze voor de machtiger of de gemachtigde?", "description": "Tooltip for 'prefill.identifierRole' builder field", @@ -1423,6 +1438,11 @@ "description": "Label for 'validate.maxLength' builder field", "originalDefault": "Maximum length" }, + "yGAl1a": { + "defaultMessage": "Close", + "description": "Modal close button label", + "originalDefault": "Close" + }, "yL9Ql7": { "defaultMessage": "Vertalingen", "description": "Translations: translation column header", From c72a4966646583d646a62fd372b9feba35758546 Mon Sep 17 00:00:00 2001 From: Sergei Maertens Date: Tue, 20 Aug 2024 10:20:17 +0200 Subject: [PATCH 4/4] :arrow_up: [open-formulieren/open-forms#4542] Use types 0.29.0 --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 38a67938..a98c15d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,7 +39,7 @@ "@formatjs/cli": "^6.1.1", "@formatjs/ts-transformer": "^3.12.0", "@fortawesome/fontawesome-free": "^6.4.0", - "@open-formulieren/types": "^0.26.0", + "@open-formulieren/types": "^0.29.0", "@storybook/addon-actions": "^8.2.6", "@storybook/addon-essentials": "^8.2.6", "@storybook/addon-interactions": "^8.2.6", @@ -5262,9 +5262,9 @@ } }, "node_modules/@open-formulieren/types": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/@open-formulieren/types/-/types-0.26.0.tgz", - "integrity": "sha512-3FHn/HiEE5CIjQxpUXaf3CzDFKHX0Bs0eVYgBmfUvrOqC/IwmkNyWj31x54gRmwXDsaSewWyRzywnlNimO3o0A==", + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/@open-formulieren/types/-/types-0.29.0.tgz", + "integrity": "sha512-nsgXep2x1P6/QU7tGb8cWM5ukVgm/TL2AoDZtywAbKfPDiGtUZuBS78C8YCzTJQsd+JIgUe6pw4kdUIYphLdcQ==", "dev": true }, "node_modules/@pkgjs/parseargs": { @@ -26396,9 +26396,9 @@ } }, "@open-formulieren/types": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/@open-formulieren/types/-/types-0.26.0.tgz", - "integrity": "sha512-3FHn/HiEE5CIjQxpUXaf3CzDFKHX0Bs0eVYgBmfUvrOqC/IwmkNyWj31x54gRmwXDsaSewWyRzywnlNimO3o0A==", + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/@open-formulieren/types/-/types-0.29.0.tgz", + "integrity": "sha512-nsgXep2x1P6/QU7tGb8cWM5ukVgm/TL2AoDZtywAbKfPDiGtUZuBS78C8YCzTJQsd+JIgUe6pw4kdUIYphLdcQ==", "dev": true }, "@pkgjs/parseargs": { diff --git a/package.json b/package.json index b7da06f5..3e09a155 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "@formatjs/cli": "^6.1.1", "@formatjs/ts-transformer": "^3.12.0", "@fortawesome/fontawesome-free": "^6.4.0", - "@open-formulieren/types": "^0.26.0", + "@open-formulieren/types": "^0.29.0", "@storybook/addon-actions": "^8.2.6", "@storybook/addon-essentials": "^8.2.6", "@storybook/addon-interactions": "^8.2.6",