diff --git a/backend/Makefile b/backend/Makefile
index 1e62119..e0b19f4 100644
--- a/backend/Makefile
+++ b/backend/Makefile
@@ -84,15 +84,15 @@ clean: ## Clean environment
.PHONY: start
start: ## Start a Plone instance on localhost:8080
- ALLOWED_DISTRIBUTIONS=portalbrasil-intranet PYTHONWARNINGS=ignore $(BIN_FOLDER)/runwsgi instance/etc/zope.ini
+ ENABLE_PRINTING_MAILHOST=True PYTHONWARNINGS=ignore $(BIN_FOLDER)/runwsgi instance/etc/zope.ini
.PHONY: console
console: instance/etc/zope.ini ## Start a console into a Plone instance
- ALLOWED_DISTRIBUTIONS=portalbrasil-intranet PYTHONWARNINGS=ignore $(BIN_FOLDER)/zconsole debug instance/etc/zope.conf
+ PYTHONWARNINGS=ignore $(BIN_FOLDER)/zconsole debug instance/etc/zope.conf
.PHONY: create-site
create-site: instance/etc/zope.ini ## Create a new site from scratch
- ALLOWED_DISTRIBUTIONS=portalbrasil-intranet PYTHONWARNINGS=ignore $(BIN_FOLDER)/zconsole run instance/etc/zope.conf ./scripts/create_site.py
+ PYTHONWARNINGS=ignore $(BIN_FOLDER)/zconsole run instance/etc/zope.conf ./scripts/create_site.py
# Example Content
.PHONY: update-example-content
diff --git a/backend/README.md b/backend/README.md
index 89f0426..3508593 100644
--- a/backend/README.md
+++ b/backend/README.md
@@ -8,7 +8,7 @@ Works with volto-form-block >= v3.8.0
## plone.restapi endpoints
-### `@submit-form`
+### `@schemaform-data`
Endpoint that the frontend should call as a submit action.
diff --git a/backend/pyproject.toml b/backend/pyproject.toml
index 0f4710a..4b08cb4 100644
--- a/backend/pyproject.toml
+++ b/backend/pyproject.toml
@@ -42,6 +42,7 @@ dependencies = [
"souper.plone",
"click",
"beautifulsoup4",
+ "jsonschema",
"pyotp",
]
@@ -101,6 +102,7 @@ dependencies = [
"plone.formwidget.recaptcha",
"plone.restapi[test]",
"Products.MailHost",
+ "Products.PrintingMailHost",
"pytest-cov==5.0.0",
"pytest-plone>=0.5.0",
"pytest",
diff --git a/backend/src/collective/volto/formsupport/captcha/honeypot.py b/backend/src/collective/volto/formsupport/captcha/honeypot.py
index 9b786f5..8f77dcf 100644
--- a/backend/src/collective/volto/formsupport/captcha/honeypot.py
+++ b/backend/src/collective/volto/formsupport/captcha/honeypot.py
@@ -6,6 +6,8 @@
from zExceptions import BadRequest
from zope.i18n import translate
+import json
+
class HoneypotSupport(CaptchaSupport):
name = _("Honeypot Support")
@@ -31,6 +33,8 @@ def verify(self, data):
# first check if volto-form-block send the compiled token
# (because by default it does not insert the honeypot field into the submitted
# form)
+ if isinstance(data, str):
+ data = json.loads(data)
if not data:
# @submit-form has been called not from volto-form-block so do the standard
# validation.
diff --git a/backend/src/collective/volto/formsupport/datamanager/catalog.py b/backend/src/collective/volto/formsupport/datamanager/catalog.py
index 808a7e3..032bce9 100644
--- a/backend/src/collective/volto/formsupport/datamanager/catalog.py
+++ b/backend/src/collective/volto/formsupport/datamanager/catalog.py
@@ -1,7 +1,6 @@
from collective.volto.formsupport import logger
from collective.volto.formsupport.interfaces import IFormDataStore
from collective.volto.formsupport.utils import get_blocks
-from copy import deepcopy
from datetime import datetime
from plone.dexterity.interfaces import IDexterityContent
from plone.restapi.deserializer import json_body
@@ -46,28 +45,24 @@ def block_id(self):
def get_form_fields(self):
blocks = get_blocks(self.context)
-
if not blocks:
return {}
- form_block = {}
- for id_, block in blocks.items():
- if id_ != self.block_id:
- continue
- block_type = block.get("@type", "")
- if block_type == "form":
- form_block = deepcopy(block)
- if not form_block:
- return {}
-
- subblocks = form_block.get("subblocks", [])
-
- # Add the 'custom_field_id' field back in as this isn't stored with each
- # subblock
- for index, field in enumerate(subblocks):
- if form_block.get(field["field_id"]):
- subblocks[index]["custom_field_id"] = form_block.get(field["field_id"])
-
- return subblocks
+ block = blocks.get(self.block_id, {})
+ block_type = block.get("@type", "")
+ if block_type == "schemaForm":
+ return [
+ {"field_id": name, "label": field.get("title", name)}
+ for name, field in block["schema"]["properties"].items()
+ ]
+ elif block_type == "form":
+ subblocks = block.get("subblocks", [])
+ # Add the 'custom_field_id' field back in as this isn't stored with each
+ # subblock
+ for index, field in enumerate(subblocks):
+ if block.get(field["field_id"]):
+ subblocks[index]["custom_field_id"] = block.get(field["field_id"])
+ return subblocks
+ return {}
def add(self, data):
form_fields = self.get_form_fields()
diff --git a/backend/src/collective/volto/formsupport/interfaces.py b/backend/src/collective/volto/formsupport/interfaces.py
index d2218a4..1c97f81 100644
--- a/backend/src/collective/volto/formsupport/interfaces.py
+++ b/backend/src/collective/volto/formsupport/interfaces.py
@@ -1,5 +1,9 @@
+from plone.dexterity.content import DexterityContent
+from zope.interface import Attribute
from zope.interface import Interface
from zope.publisher.interfaces.browser import IDefaultBrowserLayer
+from ZPublisher.BaseRequest import BaseRequest
+import dataclasses
class ICollectiveVoltoFormsupportLayer(IDefaultBrowserLayer):
@@ -44,3 +48,24 @@ def verify(data):
"""Verify the captcha
@return: True if verified, Raise exception otherwise
"""
+
+
+@dataclasses.dataclass
+class FormSubmissionContext:
+ context: DexterityContent
+ block: dict
+ form_data: dict
+ attachments: dict
+ request: BaseRequest
+
+
+class IFormSubmissionProcessor(Interface):
+ """Subscriber which processes form data when it is submitted"""
+
+ order: int = Attribute("Processors with the lowest order are processed first")
+
+ def __init__(context: FormSubmissionContext):
+ pass
+
+ def __call__():
+ """Process the data."""
diff --git a/backend/src/collective/volto/formsupport/processors/__init__.py b/backend/src/collective/volto/formsupport/processors/__init__.py
new file mode 100644
index 0000000..e9537f9
--- /dev/null
+++ b/backend/src/collective/volto/formsupport/processors/__init__.py
@@ -0,0 +1,9 @@
+def filter_parameters(data, block):
+ """
+ TODO do not send attachments fields.
+ """
+ return [{
+ "field_id": k,
+ "value": v,
+ "label": block["schema"]["properties"].get(k, {}).get("title", k),
+ } for k, v in data.items()]
diff --git a/backend/src/collective/volto/formsupport/processors/configure.zcml b/backend/src/collective/volto/formsupport/processors/configure.zcml
new file mode 100644
index 0000000..f96d5a9
--- /dev/null
+++ b/backend/src/collective/volto/formsupport/processors/configure.zcml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/backend/src/collective/volto/formsupport/processors/email.py b/backend/src/collective/volto/formsupport/processors/email.py
new file mode 100644
index 0000000..1e67ae6
--- /dev/null
+++ b/backend/src/collective/volto/formsupport/processors/email.py
@@ -0,0 +1,268 @@
+from bs4 import BeautifulSoup
+from collective.volto.formsupport import _
+from collective.volto.formsupport.processors import filter_parameters
+from collective.volto.formsupport.interfaces import FormSubmissionContext
+from collective.volto.formsupport.interfaces import IFormSubmissionProcessor
+from email import policy
+from email.message import EmailMessage
+from plone import api
+from plone.registry.interfaces import IRegistry
+from zExceptions import BadRequest
+from zope.component import adapter
+from zope.component import getMultiAdapter
+from zope.component import getUtility
+from zope.i18n import translate
+from zope.interface import implementer
+import codecs
+import os
+import re
+
+try:
+ from plone.base.interfaces.controlpanel import IMailSchema
+except ImportError:
+ from Products.CMFPlone.interfaces.controlpanel import IMailSchema
+
+CTE = os.environ.get("MAIL_CONTENT_TRANSFER_ENCODING", None)
+
+
+@implementer(IFormSubmissionProcessor)
+@adapter(FormSubmissionContext)
+class EmailFormProcessor:
+ """Sends an email with submitted form data"""
+
+ order = 1
+
+ def __init__(self, context: FormSubmissionContext):
+ self.context = context.context
+ self.request = context.request
+ self.block = context.block
+ self.form_data = context.form_data
+ self.attachments = context.attachments
+
+ def __call__(self):
+ if not self.block.get("send"):
+ return
+
+ portal = api.portal.get()
+ overview_controlpanel = getMultiAdapter(
+ (portal, self.request), name="overview-controlpanel"
+ )
+ if overview_controlpanel.mailhost_warning():
+ raise BadRequest("MailHost is not configured.")
+ registry = getUtility(IRegistry)
+ mail_settings = registry.forInterface(IMailSchema, prefix="plone")
+ charset = registry.get("plone.email_charset", "utf-8")
+
+ subject = self.get_subject()
+
+ # TODO
+ mfrom = self.form_data.get("from", "") or self.block.get("default_from", "") or mail_settings.email_from_address
+ mreply_to = self.get_reply_to()
+
+ if not subject or not mfrom:
+ raise BadRequest(
+ translate(
+ _(
+ "send_required_field_missing",
+ default="Missing required field: subject or from.",
+ ),
+ context=self.request,
+ )
+ )
+
+ # TODO sort out admin email vs acknowledgment
+ send_to = self.block.get("send", ["recipient"])
+ if not isinstance(send_to, list):
+ send_to = ["recipient"] if send_to else []
+
+ portal_transforms = api.portal.get_tool(name="portal_transforms")
+ mto = self.block.get("recipients", mail_settings.email_from_address)
+ message = self.prepare_message()
+ text_message = (
+ portal_transforms.convertTo("text/plain", message, mimetype="text/html")
+ .getData()
+ .strip()
+ )
+ msg = EmailMessage(policy=policy.SMTP)
+ msg.set_content(text_message, cte=CTE)
+ msg.add_alternative(message, subtype="html", cte=CTE)
+ msg["Subject"] = subject
+ msg["From"] = mfrom
+ msg["To"] = mto
+ msg["Reply-To"] = mreply_to
+
+ headers_to_forward = self.block.get("httpHeaders", [])
+ for header in headers_to_forward:
+ header_value = self.request.get(header)
+ if header_value:
+ msg[header] = header_value
+
+ self.manage_attachments(msg=msg)
+
+ if "recipient" in send_to:
+ self.send_mail(msg=msg, charset=charset)
+
+ # send a copy also to the fields with bcc flag
+ for bcc in self.get_bcc():
+ msg.replace_header("To", bcc)
+ self.send_mail(msg=msg, charset=charset)
+
+ acknowledgement_message = self.block.get("acknowledgementMessage")
+ if acknowledgement_message and "acknowledgement" in send_to:
+ acknowledgement_address = self.get_acknowledgement_field_value()
+ if acknowledgement_address:
+ acknowledgement_mail = EmailMessage(policy=policy.SMTP)
+ acknowledgement_mail["Subject"] = subject
+ acknowledgement_mail["From"] = mfrom
+ acknowledgement_mail["To"] = acknowledgement_address
+ ack_msg = acknowledgement_message.get("data")
+ ack_msg_text = (
+ portal_transforms.convertTo(
+ "text/plain", ack_msg, mimetype="text/html"
+ )
+ .getData()
+ .strip()
+ )
+ acknowledgement_mail.set_content(ack_msg_text, cte=CTE)
+ acknowledgement_mail.add_alternative(ack_msg, subtype="html", cte=CTE)
+ self.send_mail(msg=acknowledgement_mail, charset=charset)
+
+ def get_reply_to(self):
+ """This method retrieves the 'reply to' email address.
+
+ Three "levels" of logic:
+ 1. If there is a field marked with 'use_as_reply_to' set to True, that
+ field wins and we use that.
+ If not:
+ 2. We search for the "from" field.
+ If not present:
+ 3. We use the fallback field: "default_from"
+ """
+
+ subblocks = self.block.get("subblocks", "")
+ if subblocks:
+ for field in subblocks:
+ if field.get("use_as_reply_to", False):
+ field_id = field.get("field_id", "")
+ if field_id:
+ for data in data.get("data", ""):
+ if data.get("field_id", "") == field_id:
+ return data.get("value", "")
+
+ return self.form_data.get("from", "") or self.block.get("default_from", "")
+
+ def get_subject(self):
+ subject = self.block.get("subject") or "${subject}"
+ subject = self.substitute_variables(subject)
+ return subject
+
+ def substitute_variables(self, value):
+ pattern = r"\$\{([^}]+)\}"
+ return re.sub(pattern, lambda match: self.get_value(match.group(1), ""), value)
+
+ def get_value(self, field_id, default=None):
+ if self.block.get("@type") == "schemaForm":
+ return self.form_data.get(field_id, default)
+
+ for field in self.form_data:
+ if field.get("field_id") == field_id:
+ return field.get("value", default)
+ return default
+
+ def get_bcc(self):
+ # todo: handle bcc for schemaForm
+ subblocks = self.block.get("subblocks", [])
+ if not subblocks:
+ return []
+
+ bcc = []
+ bcc_fields = []
+ for field in self.block.get("subblocks", []):
+ if field.get("use_as_bcc", False):
+ field_id = field.get("field_id", "")
+ if field_id not in bcc_fields:
+ bcc_fields.append(field_id)
+ bcc = []
+ for field in self.form_data:
+ value = field.get("value", "")
+ if not value:
+ continue
+ if field.get("field_id", "") in bcc_fields:
+ bcc.append(field["value"])
+ return bcc
+
+ def prepare_message(self):
+ mail_header = self.block.get("mail_header", {}).get("data", "")
+ mail_footer = self.block.get("mail_footer", {}).get("data", "")
+
+ # Check if there is content
+ mail_header = BeautifulSoup(mail_header).get_text() if mail_header else None
+ mail_footer = BeautifulSoup(mail_footer).get_text() if mail_footer else None
+
+ # TODO
+ email_format_page_template_mapping = {
+ "list": "send_mail_template",
+ "table": "send_mail_template_table",
+ }
+ email_format = self.block.get("email_format", "")
+ template_name = email_format_page_template_mapping.get(
+ email_format, "send_mail_template"
+ )
+
+ message_template = api.content.get_view(
+ name=template_name,
+ context=self.context,
+ request=self.request,
+ )
+ parameters = {
+ "parameters": filter_parameters(self.form_data, self.block),
+ "url": self.context.absolute_url(),
+ "title": self.context.Title(),
+ "mail_header": mail_header,
+ "mail_footer": mail_footer,
+ }
+ return message_template(**parameters)
+
+ def manage_attachments(self, msg):
+ attachments = self.attachments
+
+ if not attachments:
+ return []
+ for _key, value in attachments.items():
+ content_type = "application/octet-stream"
+ filename = None
+ if isinstance(value, dict):
+ file_data = value.get("data", "")
+ if not file_data:
+ continue
+ content_type = value.get("content-type", content_type)
+ filename = value.get("filename", filename)
+ if isinstance(file_data, str):
+ file_data = file_data.encode("utf-8")
+ if "encoding" in value:
+ file_data = codecs.decode(file_data, value["encoding"])
+ if isinstance(file_data, str):
+ file_data = file_data.encode("utf-8")
+ else:
+ file_data = value
+ maintype, subtype = content_type.split("/")
+ msg.add_attachment(
+ file_data,
+ maintype=maintype,
+ subtype=subtype,
+ filename=filename,
+ )
+
+ def send_mail(self, msg, charset):
+ host = api.portal.get_tool(name="MailHost")
+ # we set immediate=True because we need to catch exceptions.
+ # by default (False) exceptions are handled by MailHost and we can't catch them.
+ host.send(msg, charset=charset, immediate=True)
+
+ def get_acknowledgement_field_value(self):
+ acknowledgementField = self.block["acknowledgementFields"]
+ for field in self.block.get("subblocks", []):
+ if field.get("field_id") == acknowledgementField:
+ for submitted in self.form_data:
+ if submitted.get("field_id", "") == field.get("field_id"):
+ return submitted.get("value")
diff --git a/backend/src/collective/volto/formsupport/processors/store.py b/backend/src/collective/volto/formsupport/processors/store.py
new file mode 100644
index 0000000..55493db
--- /dev/null
+++ b/backend/src/collective/volto/formsupport/processors/store.py
@@ -0,0 +1,31 @@
+from collective.volto.formsupport.interfaces import IFormDataStore
+from collective.volto.formsupport.interfaces import IFormSubmissionProcessor
+from collective.volto.formsupport.interfaces import FormSubmissionContext
+from collective.volto.formsupport.processors import filter_parameters
+from zExceptions import BadRequest
+from zope.component import adapter
+from zope.component import getMultiAdapter
+from zope.interface import implementer
+
+
+@implementer(IFormSubmissionProcessor)
+@adapter(FormSubmissionContext)
+class StoreFormProcessor:
+ """Stores submitted form data"""
+
+ order = 2
+
+ def __init__(self, context):
+ self.context = context.context
+ self.request = context.request
+ self.block = context.block
+ self.form_data = context.form_data
+
+ def __call__(self):
+ if not self.block.get("store"):
+ return
+
+ store = getMultiAdapter((self.context, self.request), IFormDataStore)
+ res = store.add(data=filter_parameters(self.form_data, self.block))
+ if not res:
+ raise BadRequest("Unable to store data")
diff --git a/backend/src/collective/volto/formsupport/restapi/serializer/blocks.py b/backend/src/collective/volto/formsupport/restapi/serializer/blocks.py
index 7148ef4..31b0f49 100644
--- a/backend/src/collective/volto/formsupport/restapi/serializer/blocks.py
+++ b/backend/src/collective/volto/formsupport/restapi/serializer/blocks.py
@@ -1,5 +1,6 @@
from collective.volto.formsupport.interfaces import ICaptchaSupport
from collective.volto.formsupport.interfaces import ICollectiveVoltoFormsupportLayer
+from copy import deepcopy
from plone import api
@@ -57,3 +58,55 @@ class FormSerializerContents(FormSerializer):
@adapter(IPloneSiteRoot, ICollectiveVoltoFormsupportLayer)
class FormSerializerRoot(FormSerializer):
"""Deserializer for site-root"""
+
+
+class SchemaFormBlockSerializer:
+ """ """
+
+ order = 200 # after standard ones
+ block_type = "schemaForm"
+
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
+
+ def __call__(self, value):
+ """
+ If user can edit the context, return the full block data.
+ Otherwise, skip default values because we need them only in edit and
+ to send emails from the backend.
+ """
+ if value.get("captcha"):
+ value["captcha_props"] = getMultiAdapter(
+ (self.context, self.request),
+ ICaptchaSupport,
+ name=value["captcha"],
+ ).serialize()
+
+ new_schema = deepcopy(value["schema"])
+ new_schema["properties"]["captchaWidget"] = {
+ "title": value["captcha"],
+ "widget": value["captcha"],
+ "captcha_props": value["captcha_props"],
+ }
+ if "captchaWidget" not in new_schema["fieldsets"][0]["fields"]:
+ new_schema["fieldsets"][0]["fields"].append("captchaWidget")
+ value["schema"] = new_schema
+ attachments_limit = os.environ.get("FORM_ATTACHMENTS_LIMIT", "")
+ if attachments_limit:
+ value["attachments_limit"] = attachments_limit
+ if api.user.has_permission("Modify portal content", obj=self.context):
+ return value
+ return {k: v for k, v in value.items() if not k.startswith("default_")}
+
+
+@implementer(IBlockFieldSerializationTransformer)
+@adapter(IBlocks, ICollectiveVoltoFormsupportLayer)
+class SchemaFormBlockSerializerContents(SchemaFormBlockSerializer):
+ """Deserializer for content-types that implements IBlocks behavior"""
+
+
+@implementer(IBlockFieldSerializationTransformer)
+@adapter(IPloneSiteRoot, ICollectiveVoltoFormsupportLayer)
+class SchemaFormBlockSerializerRoot(SchemaFormBlockSerializer):
+ """Deserializer for site-root"""
diff --git a/backend/src/collective/volto/formsupport/restapi/serializer/configure.zcml b/backend/src/collective/volto/formsupport/restapi/serializer/configure.zcml
index 860ca2a..1ee14c4 100644
--- a/backend/src/collective/volto/formsupport/restapi/serializer/configure.zcml
+++ b/backend/src/collective/volto/formsupport/restapi/serializer/configure.zcml
@@ -13,4 +13,13 @@
provides="plone.restapi.interfaces.IBlockFieldSerializationTransformer"
/>
+
+
+
diff --git a/backend/src/collective/volto/formsupport/restapi/services/form_data/form_data.py b/backend/src/collective/volto/formsupport/restapi/services/form_data/form_data.py
index b8e997b..f85e534 100644
--- a/backend/src/collective/volto/formsupport/restapi/services/form_data/form_data.py
+++ b/backend/src/collective/volto/formsupport/restapi/services/form_data/form_data.py
@@ -29,10 +29,10 @@ def get_items(self):
items = []
if block:
store = getMultiAdapter((self.context, self.request), IFormDataStore)
- remove_data_after_days = int(block.get("remove_data_after_days") or 0)
+ data_wipe = int(block.get("data_wipe") or 0)
data = store.search()
- if remove_data_after_days > 0:
- expire_date = datetime.now() - timedelta(days=remove_data_after_days)
+ if data_wipe > 0:
+ expire_date = datetime.now() - timedelta(days=data_wipe)
else:
expire_date = None
for record in data:
@@ -55,7 +55,7 @@ def __call__(self, expand=False):
return {}
if self.block_id:
service_id = (
- f"{self.context.absolute_url()}/@form-data?block_id{self.block_id}"
+ f"{self.context.absolute_url()}/@form-data?block_id={self.block_id}"
)
else:
service_id = f"{self.context.absolute_url()}/@form-data"
@@ -81,7 +81,8 @@ def form_block(self):
if not blocks:
return {}
for id_, block in blocks.items():
- if block.get("@type", "") == "form" and block.get("store", False):
+ is_form_block = block.get("@type", "") in ("form", "schemaForm")
+ if is_form_block and block.get("store", False):
if not self.block_id or self.block_id == id_:
return block
return {}
diff --git a/backend/src/collective/volto/formsupport/restapi/services/submit_form/configure.zcml b/backend/src/collective/volto/formsupport/restapi/services/submit_form/configure.zcml
index 8e566ba..625752f 100644
--- a/backend/src/collective/volto/formsupport/restapi/services/submit_form/configure.zcml
+++ b/backend/src/collective/volto/formsupport/restapi/services/submit_form/configure.zcml
@@ -10,7 +10,7 @@
for="plone.restapi.behaviors.IBlocks"
permission="zope2.View"
layer="collective.volto.formsupport.interfaces.ICollectiveVoltoFormsupportLayer"
- name="@submit-form"
+ name="@schemaform-data"
/>
diff --git a/backend/src/collective/volto/formsupport/restapi/services/submit_form/post.py b/backend/src/collective/volto/formsupport/restapi/services/submit_form/post.py
index 833adc0..877346f 100644
--- a/backend/src/collective/volto/formsupport/restapi/services/submit_form/post.py
+++ b/backend/src/collective/volto/formsupport/restapi/services/submit_form/post.py
@@ -1,44 +1,31 @@
-from bs4 import BeautifulSoup
from collective.volto.formsupport import _
+from collective.volto.formsupport.interfaces import FormSubmissionContext
from collective.volto.formsupport.interfaces import ICaptchaSupport
-from collective.volto.formsupport.interfaces import IFormDataStore
+from collective.volto.formsupport.interfaces import IFormSubmissionProcessor
from collective.volto.formsupport.interfaces import IPostEvent
from collective.volto.formsupport.utils import get_blocks
from collective.volto.formsupport.utils import validate_email_token
from copy import deepcopy
-from datetime import datetime
-from email import policy
-from email.message import EmailMessage
-from io import BytesIO
from plone import api
-try:
- from plone.base.interfaces.controlpanel import IMailSchema
-except ImportError:
- from Products.CMFPlone.interfaces.controlpanel import IMailSchema
-
from plone.protect.interfaces import IDisableCSRFProtection
-from plone.registry.interfaces import IRegistry
from plone.restapi.deserializer import json_body
from plone.restapi.services import Service
from plone.schema.email import _isemail
-from xml.etree.ElementTree import Element
-from xml.etree.ElementTree import ElementTree
-from xml.etree.ElementTree import SubElement
from zExceptions import BadRequest
from zope.component import getMultiAdapter
-from zope.component import getUtility
+from zope.component import subscribers
from zope.event import notify
from zope.i18n import translate
from zope.interface import alsoProvides
from zope.interface import implementer
-import codecs
+import json
+import jsonschema
import logging
import math
import os
-import re
logger = logging.getLogger(__name__)
@@ -53,44 +40,43 @@ def __init__(self, context, data):
class SubmitPost(Service):
- def __init__(self, context, request):
- super().__init__(context, request)
-
+ def reply(self):
self.block = {}
self.form_data = self.cleanup_data()
self.block_id = self.form_data.get("block_id", "")
if self.block_id:
self.block = self.get_block_data(block_id=self.block_id)
- def reply(self):
self.validate_form()
- store_action = self.block.get("store", False)
- send_action = self.block.get("send", [])
-
# Disable CSRF protection
alsoProvides(self.request, IDisableCSRFProtection)
notify(PostEventService(self.context, self.form_data))
- if send_action:
+ form_submission_context = FormSubmissionContext(
+ context=self.context,
+ request=self.request,
+ block=self.block,
+ form_data=self.form_data.get("data", {}),
+ attachments=self.form_data.get("attachments", {}),
+ )
+ for handler in sorted(subscribers((form_submission_context,), IFormSubmissionProcessor), key=lambda h: h.order):
try:
- self.send_data()
- except BadRequest as e:
- raise e
- except Exception as e:
- logger.exception(e)
+ handler()
+ except BadRequest:
+ raise
+ except Exception as err:
+ logger.exception(err)
message = translate(
_(
- "mail_send_exception",
- default="Unable to send confirm email. Please retry later or contact site administrator.", # noqa: E501
+ "form_action_exception",
+ default="Unable to process form. Please retry later or contact site administrator.", # noqa: E501
),
context=self.request,
)
self.request.response.setStatus(500)
return {"type": "InternalServerError", "message": message}
- if store_action:
- self.store_data()
return {"data": self.form_data.get("data", [])}
@@ -106,19 +92,25 @@ def cleanup_data(self):
transforms = api.portal.get_tool(name="portal_transforms")
block = self.get_block_data(block_id=form_data.get("block_id", ""))
- block_fields = [x.get("field_id", "") for x in block.get("subblocks", [])]
- for form_field in form_data.get("data", []):
- if form_field.get("field_id", "") not in block_fields:
- # unknown field, skip it
- continue
- new_field = deepcopy(form_field)
- value = new_field.get("value", "")
- if isinstance(value, str):
- stream = transforms.convertTo("text/plain", value, mimetype="text/html")
- new_field["value"] = stream.getData().strip()
- fixed_fields.append(new_field)
- form_data["data"] = fixed_fields
+ if block.get("@type") == "form":
+ block_fields = [x.get("field_id", "") for x in block.get("subblocks", [])]
+ # cleanup form data if it's a form block
+ for form_field in form_data.get("data", []):
+ if form_field.get("field_id", "") not in block_fields:
+ # unknown field, skip it
+ continue
+ new_field = deepcopy(form_field)
+ value = new_field.get("value", "")
+ if isinstance(value, str):
+ stream = transforms.convertTo(
+ "text/plain", value, mimetype="text/html"
+ )
+ new_field["value"] = stream.getData().strip()
+ fixed_fields.append(new_field)
+ form_data["data"] = fixed_fields
+
+ # TODO: cleanup form data if it's a schemaForm block
return form_data
def validate_form(self):
@@ -147,17 +139,6 @@ def validate_form(self):
),
)
- if not self.block.get("store", False) and not self.block.get("send", []):
- raise BadRequest(
- translate(
- _(
- "missing_action",
- default='You need to set at least one form action between "send" and "store".', # noqa: E501
- ),
- context=self.request,
- )
- )
-
if not self.form_data.get("data", []):
raise BadRequest(
translate(
@@ -169,6 +150,7 @@ def validate_form(self):
)
)
+ self.validate_schema()
self.validate_attachments()
if self.block.get("captcha", False):
getMultiAdapter(
@@ -180,7 +162,23 @@ def validate_form(self):
self.validate_email_fields()
self.validate_bcc()
+ def validate_schema(self):
+ if self.block.get("@type") != "schemaForm":
+ return
+ validator = jsonschema.Draft202012Validator(self.block["schema"])
+ errors = []
+ for err in validator.iter_errors(self.form_data["data"]):
+ error = {"message": err.message}
+ if err.path:
+ error["field"] = ".".join(err.path)
+ errors.append(error)
+ if errors:
+ raise BadRequest(json.dumps(errors))
+
def validate_email_fields(self):
+ # TODO: validate email fields for schemaForm block
+ if self.block["@type"] == "schemaForm":
+ return
email_fields = [
x.get("field_id", "")
for x in self.block.get("subblocks", [])
@@ -234,6 +232,10 @@ def validate_attachments(self):
)
def validate_bcc(self):
+ # TODO: validate email fields for schemaForm block
+ if self.block["@type"] == "schemaForm":
+ return
+
bcc_fields = []
for field in self.block.get("subblocks", []):
if field.get("use_as_bcc", False):
@@ -262,281 +264,7 @@ def get_block_data(self, block_id):
if id_ != block_id:
continue
block_type = block.get("@type", "")
- if block_type != "form":
+ if not (block_type == "form" or block_type == "schemaForm"):
continue
return block
return {}
-
- def get_reply_to(self):
- """This method retrieves the correct field to be used as 'reply to'.
-
- Three "levels" of logic:
- 1. If there is a field marked with 'use_as_reply_to' set to True, that
- field wins and we use that.
- If not:
- 2. We search for the "from" field.
- If not present:
- 3. We use the fallback field: "default_from"
- """
-
- subblocks = self.block.get("subblocks", "")
- if subblocks:
- for field in subblocks:
- if field.get("use_as_reply_to", False):
- field_id = field.get("field_id", "")
- if field_id:
- for data in self.form_data.get("data", ""):
- if data.get("field_id", "") == field_id:
- return data.get("value", "")
-
- return self.form_data.get("from", "") or self.block.get("default_from", "")
-
- def get_bcc(self):
- bcc = []
- bcc_fields = []
- for field in self.block.get("subblocks", []):
- if field.get("use_as_bcc", False):
- field_id = field.get("field_id", "")
- if field_id not in bcc_fields:
- bcc_fields.append(field_id)
- bcc = []
- for data in self.form_data.get("data", []):
- value = data.get("value", "")
- if not value:
- continue
- if data.get("field_id", "") in bcc_fields:
- bcc.append(data["value"])
- return bcc
-
- def get_acknowledgement_field_value(self):
- acknowledgementField = self.block["acknowledgementFields"]
- for field in self.block.get("subblocks", []):
- if field.get("field_id") == acknowledgementField:
- for data in self.form_data.get("data", []):
- if data.get("field_id", "") == field.get("field_id"):
- return data.get("value")
-
- def get_subject(self):
- subject = self.form_data.get("subject", "") or self.block.get(
- "default_subject", ""
- )
-
- for i in self.form_data.get("data", []):
- field_id = i.get("field_id")
-
- if not field_id:
- continue
-
- # Handle this kind of id format: `field_name_123321,
- # which is used by frontend package logics
- pattern = r"\$\{[^}]+\}"
- matches = re.findall(pattern, subject)
-
- for match in matches:
- if field_id in match:
- subject = subject.replace(match, i.get("value"))
-
- return subject
-
- def send_data(self): # noQA: C901
- subject = self.get_subject()
-
- mfrom = self.form_data.get("from", "") or self.block.get("default_from", "")
- mreply_to = self.get_reply_to()
-
- if not subject or not mfrom:
- raise BadRequest(
- translate(
- _(
- "send_required_field_missing",
- default="Missing required field: subject or from.",
- ),
- context=self.request,
- )
- )
-
- portal = api.portal.get()
- overview_controlpanel = getMultiAdapter(
- (portal, self.request), name="overview-controlpanel"
- )
- if overview_controlpanel.mailhost_warning():
- raise BadRequest("MailHost is not configured.")
-
- registry = getUtility(IRegistry)
- mail_settings = registry.forInterface(IMailSchema, prefix="plone")
- charset = registry.get("plone.email_charset", "utf-8")
-
- should_send = self.block.get("send", [])
- if should_send:
- portal_transforms = api.portal.get_tool(name="portal_transforms")
- mto = self.block.get("default_to", mail_settings.email_from_address)
- message = self.prepare_message()
- text_message = (
- portal_transforms.convertTo("text/plain", message, mimetype="text/html")
- .getData()
- .strip()
- )
- msg = EmailMessage(policy=policy.SMTP)
- msg.set_content(text_message, cte=CTE)
- msg.add_alternative(message, subtype="html", cte=CTE)
- msg["Subject"] = subject
- msg["From"] = mfrom
- msg["To"] = mto
- msg["Reply-To"] = mreply_to
-
- headers_to_forward = self.block.get("httpHeaders", [])
- for header in headers_to_forward:
- header_value = self.request.get(header)
- if header_value:
- msg[header] = header_value
-
- self.manage_attachments(msg=msg)
-
- if isinstance(should_send, list):
- if "recipient" in self.block.get("send", []):
- self.send_mail(msg=msg, charset=charset)
- # Backwards compatibility for forms before 'acknowledgement' sending
- else:
- self.send_mail(msg=msg, charset=charset)
-
- # send a copy also to the fields with bcc flag
- for bcc in self.get_bcc():
- msg.replace_header("To", bcc)
- self.send_mail(msg=msg, charset=charset)
-
- acknowledgement_message = self.block.get("acknowledgementMessage")
- if acknowledgement_message and "acknowledgement" in self.block.get("send", []):
- acknowledgement_address = self.get_acknowledgement_field_value()
- if acknowledgement_address:
- acknowledgement_mail = EmailMessage(policy=policy.SMTP)
- acknowledgement_mail["Subject"] = subject
- acknowledgement_mail["From"] = mfrom
- acknowledgement_mail["To"] = acknowledgement_address
- ack_msg = acknowledgement_message.get("data")
- ack_msg_text = (
- portal_transforms.convertTo(
- "text/plain", ack_msg, mimetype="text/html"
- )
- .getData()
- .strip()
- )
- acknowledgement_mail.set_content(ack_msg_text, cte=CTE)
- acknowledgement_mail.add_alternative(ack_msg, subtype="html", cte=CTE)
- self.send_mail(msg=acknowledgement_mail, charset=charset)
-
- def prepare_message(self):
- mail_header = self.block.get("mail_header", {}).get("data", "")
- mail_footer = self.block.get("mail_footer", {}).get("data", "")
-
- # Check if there is content
- mail_header = BeautifulSoup(mail_header).get_text() if mail_header else None
- mail_footer = BeautifulSoup(mail_footer).get_text() if mail_footer else None
-
- email_format_page_template_mapping = {
- "list": "send_mail_template",
- "table": "send_mail_template_table",
- }
- email_format = self.block.get("email_format", "")
- template_name = email_format_page_template_mapping.get(
- email_format, "send_mail_template"
- )
-
- message_template = api.content.get_view(
- name=template_name,
- context=self.context,
- request=self.request,
- )
- parameters = {
- "parameters": self.filter_parameters(),
- "url": self.context.absolute_url(),
- "title": self.context.Title(),
- "mail_header": mail_header,
- "mail_footer": mail_footer,
- }
- return message_template(**parameters)
-
- def filter_parameters(self):
- """
- do not send attachments fields.
- """
- skip_fields = [
- x.get("field_id", "")
- for x in self.block.get("subblocks", [])
- if x.get("field_type", "") == "attachment"
- ]
- return [
- x
- for x in self.form_data.get("data", [])
- if x.get("field_id", "") not in skip_fields
- ]
-
- def send_mail(self, msg, charset):
- host = api.portal.get_tool(name="MailHost")
- # we set immediate=True because we need to catch exceptions.
- # by default (False) exceptions are handled by MailHost and we can't catch them.
- host.send(msg, charset=charset, immediate=True)
-
- def manage_attachments(self, msg):
- attachments = self.form_data.get("attachments", {})
-
- if self.block.get("attachXml", False):
- self.attach_xml(msg=msg)
-
- if not attachments:
- return []
- for _key, value in attachments.items():
- content_type = "application/octet-stream"
- filename = None
- if isinstance(value, dict):
- file_data = value.get("data", "")
- if not file_data:
- continue
- content_type = value.get("content-type", content_type)
- filename = value.get("filename", filename)
- if isinstance(file_data, str):
- file_data = file_data.encode("utf-8")
- if "encoding" in value:
- file_data = codecs.decode(file_data, value["encoding"])
- if isinstance(file_data, str):
- file_data = file_data.encode("utf-8")
- else:
- file_data = value
- maintype, subtype = content_type.split("/")
- msg.add_attachment(
- file_data,
- maintype=maintype,
- subtype=subtype,
- filename=filename,
- )
-
- def attach_xml(self, msg):
- now = (
- datetime.now()
- .isoformat(timespec="seconds")
- .replace(" ", "-")
- .replace(":", "")
- )
- filename = f"formdata_{now}.xml"
- output = BytesIO()
- xmlRoot = Element("form")
-
- for field in self.filter_parameters():
- SubElement(
- xmlRoot, "field", name=field.get("custom_field_id", field["label"])
- ).text = str(field.get("value", ""))
-
- doc = ElementTree(xmlRoot)
- doc.write(output, encoding="utf-8", xml_declaration=True)
- xmlstr = output.getvalue()
- msg.add_attachment(
- xmlstr,
- maintype="application",
- subtype="xml",
- filename=filename,
- )
-
- def store_data(self):
- store = getMultiAdapter((self.context, self.request), IFormDataStore)
- res = store.add(data=self.filter_parameters())
- if not res:
- raise BadRequest("Unable to store data")
diff --git a/backend/src/collective/volto/formsupport/scripts/cleansing.py b/backend/src/collective/volto/formsupport/scripts/cleansing.py
index 43648e0..f981537 100644
--- a/backend/src/collective/volto/formsupport/scripts/cleansing.py
+++ b/backend/src/collective/volto/formsupport/scripts/cleansing.py
@@ -43,10 +43,10 @@ def main(dryrun): # noqa: C901
continue
if not block.get("store", False):
continue
- remove_data_after_days = int(block.get("remove_data_after_days") or 0)
+ data_wipe = int(block.get("data_wipe") or 0)
# 0/None -> default value
# -1 -> don't remove
- if remove_data_after_days <= 0:
+ if data_wipe <= 0:
print(
f"SKIP record cleanup from {brain.getPath()} block: {block_id}"
)
diff --git a/backend/src/collective/volto/formsupport/testing/__init__.py b/backend/src/collective/volto/formsupport/testing/__init__.py
index 89dde79..47fb8f9 100644
--- a/backend/src/collective/volto/formsupport/testing/__init__.py
+++ b/backend/src/collective/volto/formsupport/testing/__init__.py
@@ -29,7 +29,7 @@ def setUpPloneSite(self, portal):
applyProfile(portal, "plone.restapi:blocks")
applyProfile(portal, "collective.volto.formsupport:default")
- # Mock the validate email tocken function
+ # Mock the validate email token function
def validate_email_token_mock(*args, **kwargs):
return True
diff --git a/docs/form-block-chooser.png b/docs/form-block-chooser.png
new file mode 100644
index 0000000..9a16a93
Binary files /dev/null and b/docs/form-block-chooser.png differ
diff --git a/docs/form-block-view.png b/docs/form-block-view.png
new file mode 100644
index 0000000..9deab08
Binary files /dev/null and b/docs/form-block-view.png differ
diff --git a/docs/form-static-fields.png b/docs/form-static-fields.png
new file mode 100644
index 0000000..d6898e7
Binary files /dev/null and b/docs/form-static-fields.png differ
diff --git a/docs/store-export-data.png b/docs/store-export-data.png
new file mode 100644
index 0000000..cd3d9b3
Binary files /dev/null and b/docs/store-export-data.png differ
diff --git a/frontend/mrs.developer.json b/frontend/mrs.developer.json
index a84c586..d826a12 100644
--- a/frontend/mrs.developer.json
+++ b/frontend/mrs.developer.json
@@ -4,6 +4,6 @@
"package": "@plone/volto",
"url": "git@github.com:plone/volto.git",
"https": "https://github.com/plone/volto.git",
- "tag": "18.0.0-alpha.40"
+ "branch": "volto-form-block-fixes"
}
}
diff --git a/frontend/packages/volto-form-block/locales/de/LC_MESSAGES/volto.po b/frontend/packages/volto-form-block/locales/de/LC_MESSAGES/volto.po
index 76a77d5..73796ae 100644
--- a/frontend/packages/volto-form-block/locales/de/LC_MESSAGES/volto.po
+++ b/frontend/packages/volto-form-block/locales/de/LC_MESSAGES/volto.po
@@ -16,11 +16,23 @@ msgstr ""
msgid "Add field"
msgstr "Feld Hinzufügen"
+#. Default: "Blind carbon copy"
+#: schemaFormBlock/schema
+msgid "Blind carbon copy"
+msgstr ""
+
#. Default: "Cancel"
#: components/Sidebar
+#: schemaFormBlock/EditSchemaForm
+#: schemaFormBlock/ViewSchemaForm
msgid "Cancel"
msgstr "Abbrechen"
+#. Default: "Cancel button label"
+#: schemaFormBlock/schema
+msgid "Cancel button label"
+msgstr ""
+
#. Default: "Choices"
#: components/Widget/SelectWidget
msgid "Choices"
@@ -36,6 +48,11 @@ msgstr "Datei auswählen"
msgid "Close"
msgstr "Schließen"
+#. Default: "Data wipe"
+#: schemaFormBlock/schema
+msgid "Data wipe"
+msgstr ""
+
#. Default: "Date"
#: components/Widget/DatetimeWidget
msgid "Date"
@@ -48,6 +65,7 @@ msgstr "Standard"
#. Default: "Description"
#: components/Widget/SelectWidget
+#: schemaFormBlock/schema
msgid "Description"
msgstr "Beschreibung"
@@ -66,13 +84,25 @@ msgstr "Datei hier ablegen um eine neue Datei hochzuladen"
msgid "Drop files here ..."
msgstr "Datei hier ablegen um die bestehende Datei zu ersetzen"
+#. Default: "Email footer"
+#: schemaFormBlock/schema
+msgid "Email footer"
+msgstr ""
+
+#. Default: "Email header"
+#: schemaFormBlock/schema
+msgid "Email header"
+msgstr ""
+
#. Default: "Error"
#: components/FormView
+#: schemaFormBlock/ViewSchemaForm
msgid "Error"
msgstr "Fehler"
#. Default: "Form"
#: components/Sidebar
+#: schemaFormBlock/schema
msgid "Form"
msgstr "Formular"
@@ -86,6 +116,16 @@ msgstr "Diese Website ist durch hCaptcha geschützt und es gelten die Pr
msgid "No value"
msgstr "Ez du baliorik"
+#. Default: "Number of days after which, the data should be deleted. Enter -1 to store indefinitely."
+#: schemaFormBlock/schema
+msgid "Number of days after which, the data should be deleted. Enter -1 to store indefinitely."
+msgstr ""
+
+#. Default: "Recipients"
+#: schemaFormBlock/schema
+msgid "Recipients"
+msgstr ""
+
#. Default: "Replace existing file"
#: components/Widget/FileWidget
msgid "Replace existing file"
@@ -103,6 +143,87 @@ msgstr "Beharrezkoa"
msgid "Select…"
msgstr "Aukeratu..."
+#. Default: "Send email"
+#: schemaFormBlock/schema
+msgid "Send email"
+msgstr ""
+
+#. Default: "Send email to recipients"
+#: schemaFormBlock/schema
+msgid "Send email to recipients"
+msgstr ""
+
+#. Default: "Sender"
+#: schemaFormBlock/schema
+msgid "Sender"
+msgstr ""
+
+#. Default: "Sender name"
+#: schemaFormBlock/schema
+msgid "Sender name"
+msgstr ""
+
+#. Default: "Show cancel button"
+#: schemaFormBlock/schema
+msgid "Show cancel button"
+msgstr ""
+
+#. Default: "Store data"
+#: schemaFormBlock/schema
+msgid "Store data"
+msgstr ""
+
+#. Default: "Subject"
+#: schemaFormBlock/schema
+msgid "Subject"
+msgstr ""
+
+#. Default: "Submit"
+#: schemaFormBlock/EditSchemaForm
+#: schemaFormBlock/ViewSchemaForm
+msgid "Submit"
+msgstr ""
+
+#. Default: "Submit button label"
+#: schemaFormBlock/schema
+msgid "Submit button label"
+msgstr ""
+
+#. Default: "Text at the beginning of the email. Use the ${field_id} syntax to add a form value."
+#: schemaFormBlock/schema
+msgid "Text at the beginning of the email. Use the ${field_id} syntax to add a form value."
+msgstr ""
+
+#. Default: "Text at the end of the email. Use the ${field_id} syntax to add a form value."
+#: schemaFormBlock/schema
+msgid "Text at the end of the email. Use the ${field_id} syntax to add a form value."
+msgstr ""
+
+#. Default: "The email address of the sender"
+#: schemaFormBlock/schema
+msgid "The email address of the sender"
+msgstr ""
+
+#. Default: "The email addresses the submitted form data will be sent to as blind carbon copy. Multiple email addresses can be entered separated by a semicolon."
+#: schemaFormBlock/schema
+msgid "The email addresses the submitted form data will be sent to as blind carbon copy. Multiple email addresses can be entered separated by a semicolon."
+msgstr ""
+
+#. Default: "The email addresses the submitted form data will be sent to. Multiple email addresses can be entered separated by a semicolon."
+#: schemaFormBlock/schema
+msgid "The email addresses the submitted form data will be sent to. Multiple email addresses can be entered separated by a semicolon."
+msgstr ""
+
+#. Default: "The name of the sender"
+#: schemaFormBlock/schema
+msgid "The name of the sender"
+msgstr ""
+
+#. Default: "The subject used in the sent email. Use the ${field_id} syntax to add a form value to the email subject."
+#: schemaFormBlock/schema
+msgid "The subject used in the sent email. Use the ${field_id} syntax to add a form value to the email subject."
+msgstr ""
+
#. Default: "Time"
#: components/Widget/DatetimeWidget
msgid "Time"
@@ -110,6 +231,7 @@ msgstr "Ordua"
#. Default: "Title"
#: components/Widget/SelectWidget
+#: schemaFormBlock/schema
msgid "Title"
msgstr "Titulua"
@@ -118,6 +240,16 @@ msgstr "Titulua"
msgid "Used for programmatic access to the fieldset."
msgstr "Eremu-multzoa programaziotik atzitzeko izena"
+#. Default: "When activated, an email will be sent to the given recipients when a form is submitted"
+#: schemaFormBlock/schema
+msgid "When activated, an email will be sent to the given recipients when a form is submitted"
+msgstr ""
+
+#. Default: "When activated, the data will be stored for later use when the form is submitted"
+#: schemaFormBlock/schema
+msgid "When activated, the data will be stored for later use when the form is submitted"
+msgstr ""
+
#. Default: "Use Up and Down to choose options"
#: helpers/react-select
msgid "ay11_Use Up and Down to choose options"
@@ -225,6 +357,7 @@ msgstr "sakatu ezkerrera aukeratutako balioetan fokua jartzeko"
#. Default: "Captcha provider"
#: formSchema
+#: schemaFormBlock/schema
msgid "captcha"
msgstr ""
diff --git a/frontend/packages/volto-form-block/locales/fr/LC_MESSAGES/volto.po b/frontend/packages/volto-form-block/locales/fr/LC_MESSAGES/volto.po
index 7b2d56e..e5577b3 100644
--- a/frontend/packages/volto-form-block/locales/fr/LC_MESSAGES/volto.po
+++ b/frontend/packages/volto-form-block/locales/fr/LC_MESSAGES/volto.po
@@ -16,11 +16,23 @@ msgstr ""
msgid "Add field"
msgstr "Ajouter un champ"
+#. Default: "Blind carbon copy"
+#: schemaFormBlock/schema
+msgid "Blind carbon copy"
+msgstr ""
+
#. Default: "Cancel"
#: components/Sidebar
+#: schemaFormBlock/EditSchemaForm
+#: schemaFormBlock/ViewSchemaForm
msgid "Cancel"
msgstr "Annuler"
+#. Default: "Cancel button label"
+#: schemaFormBlock/schema
+msgid "Cancel button label"
+msgstr ""
+
#. Default: "Choices"
#: components/Widget/SelectWidget
msgid "Choices"
@@ -36,6 +48,11 @@ msgstr ""
msgid "Close"
msgstr ""
+#. Default: "Data wipe"
+#: schemaFormBlock/schema
+msgid "Data wipe"
+msgstr ""
+
#. Default: "Date"
#: components/Widget/DatetimeWidget
msgid "Date"
@@ -48,6 +65,7 @@ msgstr ""
#. Default: "Description"
#: components/Widget/SelectWidget
+#: schemaFormBlock/schema
msgid "Description"
msgstr ""
@@ -66,13 +84,25 @@ msgstr ""
msgid "Drop files here ..."
msgstr ""
+#. Default: "Email footer"
+#: schemaFormBlock/schema
+msgid "Email footer"
+msgstr ""
+
+#. Default: "Email header"
+#: schemaFormBlock/schema
+msgid "Email header"
+msgstr ""
+
#. Default: "Error"
#: components/FormView
+#: schemaFormBlock/ViewSchemaForm
msgid "Error"
msgstr "Erreur"
#. Default: "Form"
#: components/Sidebar
+#: schemaFormBlock/schema
msgid "Form"
msgstr "Formulaire"
@@ -86,6 +116,16 @@ msgstr ""
msgid "No value"
msgstr ""
+#. Default: "Number of days after which, the data should be deleted. Enter -1 to store indefinitely."
+#: schemaFormBlock/schema
+msgid "Number of days after which, the data should be deleted. Enter -1 to store indefinitely."
+msgstr ""
+
+#. Default: "Recipients"
+#: schemaFormBlock/schema
+msgid "Recipients"
+msgstr ""
+
#. Default: "Replace existing file"
#: components/Widget/FileWidget
msgid "Replace existing file"
@@ -101,6 +141,87 @@ msgstr ""
msgid "Select…"
msgstr ""
+#. Default: "Send email"
+#: schemaFormBlock/schema
+msgid "Send email"
+msgstr ""
+
+#. Default: "Send email to recipients"
+#: schemaFormBlock/schema
+msgid "Send email to recipients"
+msgstr ""
+
+#. Default: "Sender"
+#: schemaFormBlock/schema
+msgid "Sender"
+msgstr ""
+
+#. Default: "Sender name"
+#: schemaFormBlock/schema
+msgid "Sender name"
+msgstr ""
+
+#. Default: "Show cancel button"
+#: schemaFormBlock/schema
+msgid "Show cancel button"
+msgstr ""
+
+#. Default: "Store data"
+#: schemaFormBlock/schema
+msgid "Store data"
+msgstr ""
+
+#. Default: "Subject"
+#: schemaFormBlock/schema
+msgid "Subject"
+msgstr ""
+
+#. Default: "Submit"
+#: schemaFormBlock/EditSchemaForm
+#: schemaFormBlock/ViewSchemaForm
+msgid "Submit"
+msgstr ""
+
+#. Default: "Submit button label"
+#: schemaFormBlock/schema
+msgid "Submit button label"
+msgstr ""
+
+#. Default: "Text at the beginning of the email. Use the ${field_id} syntax to add a form value."
+#: schemaFormBlock/schema
+msgid "Text at the beginning of the email. Use the ${field_id} syntax to add a form value."
+msgstr ""
+
+#. Default: "Text at the end of the email. Use the ${field_id} syntax to add a form value."
+#: schemaFormBlock/schema
+msgid "Text at the end of the email. Use the ${field_id} syntax to add a form value."
+msgstr ""
+
+#. Default: "The email address of the sender"
+#: schemaFormBlock/schema
+msgid "The email address of the sender"
+msgstr ""
+
+#. Default: "The email addresses the submitted form data will be sent to as blind carbon copy. Multiple email addresses can be entered separated by a semicolon."
+#: schemaFormBlock/schema
+msgid "The email addresses the submitted form data will be sent to as blind carbon copy. Multiple email addresses can be entered separated by a semicolon."
+msgstr ""
+
+#. Default: "The email addresses the submitted form data will be sent to. Multiple email addresses can be entered separated by a semicolon."
+#: schemaFormBlock/schema
+msgid "The email addresses the submitted form data will be sent to. Multiple email addresses can be entered separated by a semicolon."
+msgstr ""
+
+#. Default: "The name of the sender"
+#: schemaFormBlock/schema
+msgid "The name of the sender"
+msgstr ""
+
+#. Default: "The subject used in the sent email. Use the ${field_id} syntax to add a form value to the email subject."
+#: schemaFormBlock/schema
+msgid "The subject used in the sent email. Use the ${field_id} syntax to add a form value to the email subject."
+msgstr ""
+
#. Default: "Time"
#: components/Widget/DatetimeWidget
msgid "Time"
@@ -108,6 +229,7 @@ msgstr ""
#. Default: "Title"
#: components/Widget/SelectWidget
+#: schemaFormBlock/schema
msgid "Title"
msgstr ""
@@ -116,6 +238,16 @@ msgstr ""
msgid "Used for programmatic access to the fieldset."
msgstr ""
+#. Default: "When activated, an email will be sent to the given recipients when a form is submitted"
+#: schemaFormBlock/schema
+msgid "When activated, an email will be sent to the given recipients when a form is submitted"
+msgstr ""
+
+#. Default: "When activated, the data will be stored for later use when the form is submitted"
+#: schemaFormBlock/schema
+msgid "When activated, the data will be stored for later use when the form is submitted"
+msgstr ""
+
#. Default: "Use Up and Down to choose options"
#: helpers/react-select
msgid "ay11_Use Up and Down to choose options"
@@ -223,6 +355,7 @@ msgstr ""
#. Default: "Captcha provider"
#: formSchema
+#: schemaFormBlock/schema
msgid "captcha"
msgstr ""
diff --git a/frontend/packages/volto-form-block/locales/it/LC_MESSAGES/volto.po b/frontend/packages/volto-form-block/locales/it/LC_MESSAGES/volto.po
index 3d8d661..5ef7c17 100644
--- a/frontend/packages/volto-form-block/locales/it/LC_MESSAGES/volto.po
+++ b/frontend/packages/volto-form-block/locales/it/LC_MESSAGES/volto.po
@@ -16,11 +16,23 @@ msgstr ""
msgid "Add field"
msgstr "Aggiungi campo"
+#. Default: "Blind carbon copy"
+#: schemaFormBlock/schema
+msgid "Blind carbon copy"
+msgstr ""
+
#. Default: "Cancel"
#: components/Sidebar
+#: schemaFormBlock/EditSchemaForm
+#: schemaFormBlock/ViewSchemaForm
msgid "Cancel"
msgstr "Annulla"
+#. Default: "Cancel button label"
+#: schemaFormBlock/schema
+msgid "Cancel button label"
+msgstr ""
+
#. Default: "Choices"
#: components/Widget/SelectWidget
msgid "Choices"
@@ -36,6 +48,11 @@ msgstr "Scegli un file"
msgid "Close"
msgstr "Chiudi"
+#. Default: "Data wipe"
+#: schemaFormBlock/schema
+msgid "Data wipe"
+msgstr ""
+
#. Default: "Date"
#: components/Widget/DatetimeWidget
msgid "Date"
@@ -48,6 +65,7 @@ msgstr ""
#. Default: "Description"
#: components/Widget/SelectWidget
+#: schemaFormBlock/schema
msgid "Description"
msgstr "Descrizione"
@@ -66,13 +84,25 @@ msgstr "Trascina il file qui per caricare un nuovo file"
msgid "Drop files here ..."
msgstr "Trascina i file qui"
+#. Default: "Email footer"
+#: schemaFormBlock/schema
+msgid "Email footer"
+msgstr ""
+
+#. Default: "Email header"
+#: schemaFormBlock/schema
+msgid "Email header"
+msgstr ""
+
#. Default: "Error"
#: components/FormView
+#: schemaFormBlock/ViewSchemaForm
msgid "Error"
msgstr "Errore"
#. Default: "Form"
#: components/Sidebar
+#: schemaFormBlock/schema
msgid "Form"
msgstr "Form"
@@ -86,6 +116,16 @@ msgstr ""
msgid "No value"
msgstr "Nessun valore"
+#. Default: "Number of days after which, the data should be deleted. Enter -1 to store indefinitely."
+#: schemaFormBlock/schema
+msgid "Number of days after which, the data should be deleted. Enter -1 to store indefinitely."
+msgstr ""
+
+#. Default: "Recipients"
+#: schemaFormBlock/schema
+msgid "Recipients"
+msgstr ""
+
#. Default: "Replace existing file"
#: components/Widget/FileWidget
msgid "Replace existing file"
@@ -101,6 +141,87 @@ msgstr "Obbligatorio"
msgid "Select…"
msgstr "Selezionare…"
+#. Default: "Send email"
+#: schemaFormBlock/schema
+msgid "Send email"
+msgstr ""
+
+#. Default: "Send email to recipients"
+#: schemaFormBlock/schema
+msgid "Send email to recipients"
+msgstr ""
+
+#. Default: "Sender"
+#: schemaFormBlock/schema
+msgid "Sender"
+msgstr ""
+
+#. Default: "Sender name"
+#: schemaFormBlock/schema
+msgid "Sender name"
+msgstr ""
+
+#. Default: "Show cancel button"
+#: schemaFormBlock/schema
+msgid "Show cancel button"
+msgstr ""
+
+#. Default: "Store data"
+#: schemaFormBlock/schema
+msgid "Store data"
+msgstr ""
+
+#. Default: "Subject"
+#: schemaFormBlock/schema
+msgid "Subject"
+msgstr ""
+
+#. Default: "Submit"
+#: schemaFormBlock/EditSchemaForm
+#: schemaFormBlock/ViewSchemaForm
+msgid "Submit"
+msgstr ""
+
+#. Default: "Submit button label"
+#: schemaFormBlock/schema
+msgid "Submit button label"
+msgstr ""
+
+#. Default: "Text at the beginning of the email. Use the ${field_id} syntax to add a form value."
+#: schemaFormBlock/schema
+msgid "Text at the beginning of the email. Use the ${field_id} syntax to add a form value."
+msgstr ""
+
+#. Default: "Text at the end of the email. Use the ${field_id} syntax to add a form value."
+#: schemaFormBlock/schema
+msgid "Text at the end of the email. Use the ${field_id} syntax to add a form value."
+msgstr ""
+
+#. Default: "The email address of the sender"
+#: schemaFormBlock/schema
+msgid "The email address of the sender"
+msgstr ""
+
+#. Default: "The email addresses the submitted form data will be sent to as blind carbon copy. Multiple email addresses can be entered separated by a semicolon."
+#: schemaFormBlock/schema
+msgid "The email addresses the submitted form data will be sent to as blind carbon copy. Multiple email addresses can be entered separated by a semicolon."
+msgstr ""
+
+#. Default: "The email addresses the submitted form data will be sent to. Multiple email addresses can be entered separated by a semicolon."
+#: schemaFormBlock/schema
+msgid "The email addresses the submitted form data will be sent to. Multiple email addresses can be entered separated by a semicolon."
+msgstr ""
+
+#. Default: "The name of the sender"
+#: schemaFormBlock/schema
+msgid "The name of the sender"
+msgstr ""
+
+#. Default: "The subject used in the sent email. Use the ${field_id} syntax to add a form value to the email subject."
+#: schemaFormBlock/schema
+msgid "The subject used in the sent email. Use the ${field_id} syntax to add a form value to the email subject."
+msgstr ""
+
#. Default: "Time"
#: components/Widget/DatetimeWidget
msgid "Time"
@@ -108,6 +229,7 @@ msgstr "Ora"
#. Default: "Title"
#: components/Widget/SelectWidget
+#: schemaFormBlock/schema
msgid "Title"
msgstr "Titolo"
@@ -116,6 +238,16 @@ msgstr "Titolo"
msgid "Used for programmatic access to the fieldset."
msgstr "Utilizzato per l'accesso programmatico al fieldset."
+#. Default: "When activated, an email will be sent to the given recipients when a form is submitted"
+#: schemaFormBlock/schema
+msgid "When activated, an email will be sent to the given recipients when a form is submitted"
+msgstr ""
+
+#. Default: "When activated, the data will be stored for later use when the form is submitted"
+#: schemaFormBlock/schema
+msgid "When activated, the data will be stored for later use when the form is submitted"
+msgstr ""
+
#. Default: "Use Up and Down to choose options"
#: helpers/react-select
msgid "ay11_Use Up and Down to choose options"
@@ -223,6 +355,7 @@ msgstr "premi la freccia a sinistra per evidenziare i valori selezionati"
#. Default: "Captcha provider"
#: formSchema
+#: schemaFormBlock/schema
msgid "captcha"
msgstr ""
diff --git a/frontend/packages/volto-form-block/locales/ja/LC_MESSAGES/volto.po b/frontend/packages/volto-form-block/locales/ja/LC_MESSAGES/volto.po
index 2c8479a..d04f57f 100644
--- a/frontend/packages/volto-form-block/locales/ja/LC_MESSAGES/volto.po
+++ b/frontend/packages/volto-form-block/locales/ja/LC_MESSAGES/volto.po
@@ -16,11 +16,23 @@ msgstr ""
msgid "Add field"
msgstr ""
+#. Default: "Blind carbon copy"
+#: schemaFormBlock/schema
+msgid "Blind carbon copy"
+msgstr ""
+
#. Default: "Cancel"
#: components/Sidebar
+#: schemaFormBlock/EditSchemaForm
+#: schemaFormBlock/ViewSchemaForm
msgid "Cancel"
msgstr ""
+#. Default: "Cancel button label"
+#: schemaFormBlock/schema
+msgid "Cancel button label"
+msgstr ""
+
#. Default: "Choices"
#: components/Widget/SelectWidget
msgid "Choices"
@@ -36,6 +48,11 @@ msgstr ""
msgid "Close"
msgstr ""
+#. Default: "Data wipe"
+#: schemaFormBlock/schema
+msgid "Data wipe"
+msgstr ""
+
#. Default: "Date"
#: components/Widget/DatetimeWidget
msgid "Date"
@@ -48,6 +65,7 @@ msgstr ""
#. Default: "Description"
#: components/Widget/SelectWidget
+#: schemaFormBlock/schema
msgid "Description"
msgstr ""
@@ -66,13 +84,25 @@ msgstr ""
msgid "Drop files here ..."
msgstr ""
+#. Default: "Email footer"
+#: schemaFormBlock/schema
+msgid "Email footer"
+msgstr ""
+
+#. Default: "Email header"
+#: schemaFormBlock/schema
+msgid "Email header"
+msgstr ""
+
#. Default: "Error"
#: components/FormView
+#: schemaFormBlock/ViewSchemaForm
msgid "Error"
msgstr ""
#. Default: "Form"
#: components/Sidebar
+#: schemaFormBlock/schema
msgid "Form"
msgstr ""
@@ -86,6 +116,16 @@ msgstr ""
msgid "No value"
msgstr ""
+#. Default: "Number of days after which, the data should be deleted. Enter -1 to store indefinitely."
+#: schemaFormBlock/schema
+msgid "Number of days after which, the data should be deleted. Enter -1 to store indefinitely."
+msgstr ""
+
+#. Default: "Recipients"
+#: schemaFormBlock/schema
+msgid "Recipients"
+msgstr ""
+
#. Default: "Replace existing file"
#: components/Widget/FileWidget
msgid "Replace existing file"
@@ -101,6 +141,87 @@ msgstr ""
msgid "Select…"
msgstr ""
+#. Default: "Send email"
+#: schemaFormBlock/schema
+msgid "Send email"
+msgstr ""
+
+#. Default: "Send email to recipients"
+#: schemaFormBlock/schema
+msgid "Send email to recipients"
+msgstr ""
+
+#. Default: "Sender"
+#: schemaFormBlock/schema
+msgid "Sender"
+msgstr ""
+
+#. Default: "Sender name"
+#: schemaFormBlock/schema
+msgid "Sender name"
+msgstr ""
+
+#. Default: "Show cancel button"
+#: schemaFormBlock/schema
+msgid "Show cancel button"
+msgstr ""
+
+#. Default: "Store data"
+#: schemaFormBlock/schema
+msgid "Store data"
+msgstr ""
+
+#. Default: "Subject"
+#: schemaFormBlock/schema
+msgid "Subject"
+msgstr ""
+
+#. Default: "Submit"
+#: schemaFormBlock/EditSchemaForm
+#: schemaFormBlock/ViewSchemaForm
+msgid "Submit"
+msgstr ""
+
+#. Default: "Submit button label"
+#: schemaFormBlock/schema
+msgid "Submit button label"
+msgstr ""
+
+#. Default: "Text at the beginning of the email. Use the ${field_id} syntax to add a form value."
+#: schemaFormBlock/schema
+msgid "Text at the beginning of the email. Use the ${field_id} syntax to add a form value."
+msgstr ""
+
+#. Default: "Text at the end of the email. Use the ${field_id} syntax to add a form value."
+#: schemaFormBlock/schema
+msgid "Text at the end of the email. Use the ${field_id} syntax to add a form value."
+msgstr ""
+
+#. Default: "The email address of the sender"
+#: schemaFormBlock/schema
+msgid "The email address of the sender"
+msgstr ""
+
+#. Default: "The email addresses the submitted form data will be sent to as blind carbon copy. Multiple email addresses can be entered separated by a semicolon."
+#: schemaFormBlock/schema
+msgid "The email addresses the submitted form data will be sent to as blind carbon copy. Multiple email addresses can be entered separated by a semicolon."
+msgstr ""
+
+#. Default: "The email addresses the submitted form data will be sent to. Multiple email addresses can be entered separated by a semicolon."
+#: schemaFormBlock/schema
+msgid "The email addresses the submitted form data will be sent to. Multiple email addresses can be entered separated by a semicolon."
+msgstr ""
+
+#. Default: "The name of the sender"
+#: schemaFormBlock/schema
+msgid "The name of the sender"
+msgstr ""
+
+#. Default: "The subject used in the sent email. Use the ${field_id} syntax to add a form value to the email subject."
+#: schemaFormBlock/schema
+msgid "The subject used in the sent email. Use the ${field_id} syntax to add a form value to the email subject."
+msgstr ""
+
#. Default: "Time"
#: components/Widget/DatetimeWidget
msgid "Time"
@@ -108,6 +229,7 @@ msgstr ""
#. Default: "Title"
#: components/Widget/SelectWidget
+#: schemaFormBlock/schema
msgid "Title"
msgstr ""
@@ -116,6 +238,16 @@ msgstr ""
msgid "Used for programmatic access to the fieldset."
msgstr ""
+#. Default: "When activated, an email will be sent to the given recipients when a form is submitted"
+#: schemaFormBlock/schema
+msgid "When activated, an email will be sent to the given recipients when a form is submitted"
+msgstr ""
+
+#. Default: "When activated, the data will be stored for later use when the form is submitted"
+#: schemaFormBlock/schema
+msgid "When activated, the data will be stored for later use when the form is submitted"
+msgstr ""
+
#. Default: "Use Up and Down to choose options"
#: helpers/react-select
msgid "ay11_Use Up and Down to choose options"
@@ -223,6 +355,7 @@ msgstr ""
#. Default: "Captcha provider"
#: formSchema
+#: schemaFormBlock/schema
msgid "captcha"
msgstr ""
diff --git a/frontend/packages/volto-form-block/locales/nl/LC_MESSAGES/volto.po b/frontend/packages/volto-form-block/locales/nl/LC_MESSAGES/volto.po
index fc5ddb4..4322e73 100644
--- a/frontend/packages/volto-form-block/locales/nl/LC_MESSAGES/volto.po
+++ b/frontend/packages/volto-form-block/locales/nl/LC_MESSAGES/volto.po
@@ -16,11 +16,23 @@ msgstr ""
msgid "Add field"
msgstr "Voeg veld toe"
+#. Default: "Blind carbon copy"
+#: schemaFormBlock/schema
+msgid "Blind carbon copy"
+msgstr ""
+
#. Default: "Cancel"
#: components/Sidebar
+#: schemaFormBlock/EditSchemaForm
+#: schemaFormBlock/ViewSchemaForm
msgid "Cancel"
msgstr "Annuleren"
+#. Default: "Cancel button label"
+#: schemaFormBlock/schema
+msgid "Cancel button label"
+msgstr ""
+
#. Default: "Choices"
#: components/Widget/SelectWidget
msgid "Choices"
@@ -36,6 +48,11 @@ msgstr "Kies een bestand"
msgid "Close"
msgstr "Sluiten"
+#. Default: "Data wipe"
+#: schemaFormBlock/schema
+msgid "Data wipe"
+msgstr ""
+
#. Default: "Date"
#: components/Widget/DatetimeWidget
msgid "Date"
@@ -48,6 +65,7 @@ msgstr "Standaard"
#. Default: "Description"
#: components/Widget/SelectWidget
+#: schemaFormBlock/schema
msgid "Description"
msgstr "Omschrijving"
@@ -66,13 +84,25 @@ msgstr ""
msgid "Drop files here ..."
msgstr ""
+#. Default: "Email footer"
+#: schemaFormBlock/schema
+msgid "Email footer"
+msgstr ""
+
+#. Default: "Email header"
+#: schemaFormBlock/schema
+msgid "Email header"
+msgstr ""
+
#. Default: "Error"
#: components/FormView
+#: schemaFormBlock/ViewSchemaForm
msgid "Error"
msgstr ""
#. Default: "Form"
#: components/Sidebar
+#: schemaFormBlock/schema
msgid "Form"
msgstr ""
@@ -86,6 +116,16 @@ msgstr ""
msgid "No value"
msgstr ""
+#. Default: "Number of days after which, the data should be deleted. Enter -1 to store indefinitely."
+#: schemaFormBlock/schema
+msgid "Number of days after which, the data should be deleted. Enter -1 to store indefinitely."
+msgstr ""
+
+#. Default: "Recipients"
+#: schemaFormBlock/schema
+msgid "Recipients"
+msgstr ""
+
#. Default: "Replace existing file"
#: components/Widget/FileWidget
msgid "Replace existing file"
@@ -101,6 +141,87 @@ msgstr ""
msgid "Select…"
msgstr ""
+#. Default: "Send email"
+#: schemaFormBlock/schema
+msgid "Send email"
+msgstr ""
+
+#. Default: "Send email to recipients"
+#: schemaFormBlock/schema
+msgid "Send email to recipients"
+msgstr ""
+
+#. Default: "Sender"
+#: schemaFormBlock/schema
+msgid "Sender"
+msgstr ""
+
+#. Default: "Sender name"
+#: schemaFormBlock/schema
+msgid "Sender name"
+msgstr ""
+
+#. Default: "Show cancel button"
+#: schemaFormBlock/schema
+msgid "Show cancel button"
+msgstr ""
+
+#. Default: "Store data"
+#: schemaFormBlock/schema
+msgid "Store data"
+msgstr ""
+
+#. Default: "Subject"
+#: schemaFormBlock/schema
+msgid "Subject"
+msgstr ""
+
+#. Default: "Submit"
+#: schemaFormBlock/EditSchemaForm
+#: schemaFormBlock/ViewSchemaForm
+msgid "Submit"
+msgstr ""
+
+#. Default: "Submit button label"
+#: schemaFormBlock/schema
+msgid "Submit button label"
+msgstr ""
+
+#. Default: "Text at the beginning of the email. Use the ${field_id} syntax to add a form value."
+#: schemaFormBlock/schema
+msgid "Text at the beginning of the email. Use the ${field_id} syntax to add a form value."
+msgstr ""
+
+#. Default: "Text at the end of the email. Use the ${field_id} syntax to add a form value."
+#: schemaFormBlock/schema
+msgid "Text at the end of the email. Use the ${field_id} syntax to add a form value."
+msgstr ""
+
+#. Default: "The email address of the sender"
+#: schemaFormBlock/schema
+msgid "The email address of the sender"
+msgstr ""
+
+#. Default: "The email addresses the submitted form data will be sent to as blind carbon copy. Multiple email addresses can be entered separated by a semicolon."
+#: schemaFormBlock/schema
+msgid "The email addresses the submitted form data will be sent to as blind carbon copy. Multiple email addresses can be entered separated by a semicolon."
+msgstr ""
+
+#. Default: "The email addresses the submitted form data will be sent to. Multiple email addresses can be entered separated by a semicolon."
+#: schemaFormBlock/schema
+msgid "The email addresses the submitted form data will be sent to. Multiple email addresses can be entered separated by a semicolon."
+msgstr ""
+
+#. Default: "The name of the sender"
+#: schemaFormBlock/schema
+msgid "The name of the sender"
+msgstr ""
+
+#. Default: "The subject used in the sent email. Use the ${field_id} syntax to add a form value to the email subject."
+#: schemaFormBlock/schema
+msgid "The subject used in the sent email. Use the ${field_id} syntax to add a form value to the email subject."
+msgstr ""
+
#. Default: "Time"
#: components/Widget/DatetimeWidget
msgid "Time"
@@ -108,6 +229,7 @@ msgstr ""
#. Default: "Title"
#: components/Widget/SelectWidget
+#: schemaFormBlock/schema
msgid "Title"
msgstr ""
@@ -116,6 +238,16 @@ msgstr ""
msgid "Used for programmatic access to the fieldset."
msgstr ""
+#. Default: "When activated, an email will be sent to the given recipients when a form is submitted"
+#: schemaFormBlock/schema
+msgid "When activated, an email will be sent to the given recipients when a form is submitted"
+msgstr ""
+
+#. Default: "When activated, the data will be stored for later use when the form is submitted"
+#: schemaFormBlock/schema
+msgid "When activated, the data will be stored for later use when the form is submitted"
+msgstr ""
+
#. Default: "Use Up and Down to choose options"
#: helpers/react-select
msgid "ay11_Use Up and Down to choose options"
@@ -223,6 +355,7 @@ msgstr ""
#. Default: "Captcha provider"
#: formSchema
+#: schemaFormBlock/schema
msgid "captcha"
msgstr ""
diff --git a/frontend/packages/volto-form-block/locales/pt/LC_MESSAGES/volto.po b/frontend/packages/volto-form-block/locales/pt/LC_MESSAGES/volto.po
index 2c8479a..d04f57f 100644
--- a/frontend/packages/volto-form-block/locales/pt/LC_MESSAGES/volto.po
+++ b/frontend/packages/volto-form-block/locales/pt/LC_MESSAGES/volto.po
@@ -16,11 +16,23 @@ msgstr ""
msgid "Add field"
msgstr ""
+#. Default: "Blind carbon copy"
+#: schemaFormBlock/schema
+msgid "Blind carbon copy"
+msgstr ""
+
#. Default: "Cancel"
#: components/Sidebar
+#: schemaFormBlock/EditSchemaForm
+#: schemaFormBlock/ViewSchemaForm
msgid "Cancel"
msgstr ""
+#. Default: "Cancel button label"
+#: schemaFormBlock/schema
+msgid "Cancel button label"
+msgstr ""
+
#. Default: "Choices"
#: components/Widget/SelectWidget
msgid "Choices"
@@ -36,6 +48,11 @@ msgstr ""
msgid "Close"
msgstr ""
+#. Default: "Data wipe"
+#: schemaFormBlock/schema
+msgid "Data wipe"
+msgstr ""
+
#. Default: "Date"
#: components/Widget/DatetimeWidget
msgid "Date"
@@ -48,6 +65,7 @@ msgstr ""
#. Default: "Description"
#: components/Widget/SelectWidget
+#: schemaFormBlock/schema
msgid "Description"
msgstr ""
@@ -66,13 +84,25 @@ msgstr ""
msgid "Drop files here ..."
msgstr ""
+#. Default: "Email footer"
+#: schemaFormBlock/schema
+msgid "Email footer"
+msgstr ""
+
+#. Default: "Email header"
+#: schemaFormBlock/schema
+msgid "Email header"
+msgstr ""
+
#. Default: "Error"
#: components/FormView
+#: schemaFormBlock/ViewSchemaForm
msgid "Error"
msgstr ""
#. Default: "Form"
#: components/Sidebar
+#: schemaFormBlock/schema
msgid "Form"
msgstr ""
@@ -86,6 +116,16 @@ msgstr ""
msgid "No value"
msgstr ""
+#. Default: "Number of days after which, the data should be deleted. Enter -1 to store indefinitely."
+#: schemaFormBlock/schema
+msgid "Number of days after which, the data should be deleted. Enter -1 to store indefinitely."
+msgstr ""
+
+#. Default: "Recipients"
+#: schemaFormBlock/schema
+msgid "Recipients"
+msgstr ""
+
#. Default: "Replace existing file"
#: components/Widget/FileWidget
msgid "Replace existing file"
@@ -101,6 +141,87 @@ msgstr ""
msgid "Select…"
msgstr ""
+#. Default: "Send email"
+#: schemaFormBlock/schema
+msgid "Send email"
+msgstr ""
+
+#. Default: "Send email to recipients"
+#: schemaFormBlock/schema
+msgid "Send email to recipients"
+msgstr ""
+
+#. Default: "Sender"
+#: schemaFormBlock/schema
+msgid "Sender"
+msgstr ""
+
+#. Default: "Sender name"
+#: schemaFormBlock/schema
+msgid "Sender name"
+msgstr ""
+
+#. Default: "Show cancel button"
+#: schemaFormBlock/schema
+msgid "Show cancel button"
+msgstr ""
+
+#. Default: "Store data"
+#: schemaFormBlock/schema
+msgid "Store data"
+msgstr ""
+
+#. Default: "Subject"
+#: schemaFormBlock/schema
+msgid "Subject"
+msgstr ""
+
+#. Default: "Submit"
+#: schemaFormBlock/EditSchemaForm
+#: schemaFormBlock/ViewSchemaForm
+msgid "Submit"
+msgstr ""
+
+#. Default: "Submit button label"
+#: schemaFormBlock/schema
+msgid "Submit button label"
+msgstr ""
+
+#. Default: "Text at the beginning of the email. Use the ${field_id} syntax to add a form value."
+#: schemaFormBlock/schema
+msgid "Text at the beginning of the email. Use the ${field_id} syntax to add a form value."
+msgstr ""
+
+#. Default: "Text at the end of the email. Use the ${field_id} syntax to add a form value."
+#: schemaFormBlock/schema
+msgid "Text at the end of the email. Use the ${field_id} syntax to add a form value."
+msgstr ""
+
+#. Default: "The email address of the sender"
+#: schemaFormBlock/schema
+msgid "The email address of the sender"
+msgstr ""
+
+#. Default: "The email addresses the submitted form data will be sent to as blind carbon copy. Multiple email addresses can be entered separated by a semicolon."
+#: schemaFormBlock/schema
+msgid "The email addresses the submitted form data will be sent to as blind carbon copy. Multiple email addresses can be entered separated by a semicolon."
+msgstr ""
+
+#. Default: "The email addresses the submitted form data will be sent to. Multiple email addresses can be entered separated by a semicolon."
+#: schemaFormBlock/schema
+msgid "The email addresses the submitted form data will be sent to. Multiple email addresses can be entered separated by a semicolon."
+msgstr ""
+
+#. Default: "The name of the sender"
+#: schemaFormBlock/schema
+msgid "The name of the sender"
+msgstr ""
+
+#. Default: "The subject used in the sent email. Use the ${field_id} syntax to add a form value to the email subject."
+#: schemaFormBlock/schema
+msgid "The subject used in the sent email. Use the ${field_id} syntax to add a form value to the email subject."
+msgstr ""
+
#. Default: "Time"
#: components/Widget/DatetimeWidget
msgid "Time"
@@ -108,6 +229,7 @@ msgstr ""
#. Default: "Title"
#: components/Widget/SelectWidget
+#: schemaFormBlock/schema
msgid "Title"
msgstr ""
@@ -116,6 +238,16 @@ msgstr ""
msgid "Used for programmatic access to the fieldset."
msgstr ""
+#. Default: "When activated, an email will be sent to the given recipients when a form is submitted"
+#: schemaFormBlock/schema
+msgid "When activated, an email will be sent to the given recipients when a form is submitted"
+msgstr ""
+
+#. Default: "When activated, the data will be stored for later use when the form is submitted"
+#: schemaFormBlock/schema
+msgid "When activated, the data will be stored for later use when the form is submitted"
+msgstr ""
+
#. Default: "Use Up and Down to choose options"
#: helpers/react-select
msgid "ay11_Use Up and Down to choose options"
@@ -223,6 +355,7 @@ msgstr ""
#. Default: "Captcha provider"
#: formSchema
+#: schemaFormBlock/schema
msgid "captcha"
msgstr ""
diff --git a/frontend/packages/volto-form-block/locales/pt_BR/LC_MESSAGES/volto.po b/frontend/packages/volto-form-block/locales/pt_BR/LC_MESSAGES/volto.po
index 9b1ea41..520f7f1 100644
--- a/frontend/packages/volto-form-block/locales/pt_BR/LC_MESSAGES/volto.po
+++ b/frontend/packages/volto-form-block/locales/pt_BR/LC_MESSAGES/volto.po
@@ -22,11 +22,23 @@ msgstr ""
msgid "Add field"
msgstr "Adicionar campo"
+#. Default: "Blind carbon copy"
+#: schemaFormBlock/schema
+msgid "Blind carbon copy"
+msgstr ""
+
#. Default: "Cancel"
#: components/Sidebar
+#: schemaFormBlock/EditSchemaForm
+#: schemaFormBlock/ViewSchemaForm
msgid "Cancel"
msgstr "Cancelar"
+#. Default: "Cancel button label"
+#: schemaFormBlock/schema
+msgid "Cancel button label"
+msgstr ""
+
#. Default: "Choices"
#: components/Widget/SelectWidget
msgid "Choices"
@@ -42,6 +54,11 @@ msgstr ""
msgid "Close"
msgstr ""
+#. Default: "Data wipe"
+#: schemaFormBlock/schema
+msgid "Data wipe"
+msgstr ""
+
#. Default: "Date"
#: components/Widget/DatetimeWidget
msgid "Date"
@@ -54,6 +71,7 @@ msgstr ""
#. Default: "Description"
#: components/Widget/SelectWidget
+#: schemaFormBlock/schema
msgid "Description"
msgstr ""
@@ -72,13 +90,25 @@ msgstr ""
msgid "Drop files here ..."
msgstr ""
+#. Default: "Email footer"
+#: schemaFormBlock/schema
+msgid "Email footer"
+msgstr ""
+
+#. Default: "Email header"
+#: schemaFormBlock/schema
+msgid "Email header"
+msgstr ""
+
#. Default: "Error"
#: components/FormView
+#: schemaFormBlock/ViewSchemaForm
msgid "Error"
msgstr "Erro"
#. Default: "Form"
#: components/Sidebar
+#: schemaFormBlock/schema
msgid "Form"
msgstr "Formulário"
@@ -92,6 +122,16 @@ msgstr ""
msgid "No value"
msgstr ""
+#. Default: "Number of days after which, the data should be deleted. Enter -1 to store indefinitely."
+#: schemaFormBlock/schema
+msgid "Number of days after which, the data should be deleted. Enter -1 to store indefinitely."
+msgstr ""
+
+#. Default: "Recipients"
+#: schemaFormBlock/schema
+msgid "Recipients"
+msgstr ""
+
#. Default: "Replace existing file"
#: components/Widget/FileWidget
msgid "Replace existing file"
@@ -107,6 +147,87 @@ msgstr ""
msgid "Select…"
msgstr ""
+#. Default: "Send email"
+#: schemaFormBlock/schema
+msgid "Send email"
+msgstr ""
+
+#. Default: "Send email to recipients"
+#: schemaFormBlock/schema
+msgid "Send email to recipients"
+msgstr ""
+
+#. Default: "Sender"
+#: schemaFormBlock/schema
+msgid "Sender"
+msgstr ""
+
+#. Default: "Sender name"
+#: schemaFormBlock/schema
+msgid "Sender name"
+msgstr ""
+
+#. Default: "Show cancel button"
+#: schemaFormBlock/schema
+msgid "Show cancel button"
+msgstr ""
+
+#. Default: "Store data"
+#: schemaFormBlock/schema
+msgid "Store data"
+msgstr ""
+
+#. Default: "Subject"
+#: schemaFormBlock/schema
+msgid "Subject"
+msgstr ""
+
+#. Default: "Submit"
+#: schemaFormBlock/EditSchemaForm
+#: schemaFormBlock/ViewSchemaForm
+msgid "Submit"
+msgstr ""
+
+#. Default: "Submit button label"
+#: schemaFormBlock/schema
+msgid "Submit button label"
+msgstr ""
+
+#. Default: "Text at the beginning of the email. Use the ${field_id} syntax to add a form value."
+#: schemaFormBlock/schema
+msgid "Text at the beginning of the email. Use the ${field_id} syntax to add a form value."
+msgstr ""
+
+#. Default: "Text at the end of the email. Use the ${field_id} syntax to add a form value."
+#: schemaFormBlock/schema
+msgid "Text at the end of the email. Use the ${field_id} syntax to add a form value."
+msgstr ""
+
+#. Default: "The email address of the sender"
+#: schemaFormBlock/schema
+msgid "The email address of the sender"
+msgstr ""
+
+#. Default: "The email addresses the submitted form data will be sent to as blind carbon copy. Multiple email addresses can be entered separated by a semicolon."
+#: schemaFormBlock/schema
+msgid "The email addresses the submitted form data will be sent to as blind carbon copy. Multiple email addresses can be entered separated by a semicolon."
+msgstr ""
+
+#. Default: "The email addresses the submitted form data will be sent to. Multiple email addresses can be entered separated by a semicolon."
+#: schemaFormBlock/schema
+msgid "The email addresses the submitted form data will be sent to. Multiple email addresses can be entered separated by a semicolon."
+msgstr ""
+
+#. Default: "The name of the sender"
+#: schemaFormBlock/schema
+msgid "The name of the sender"
+msgstr ""
+
+#. Default: "The subject used in the sent email. Use the ${field_id} syntax to add a form value to the email subject."
+#: schemaFormBlock/schema
+msgid "The subject used in the sent email. Use the ${field_id} syntax to add a form value to the email subject."
+msgstr ""
+
#. Default: "Time"
#: components/Widget/DatetimeWidget
msgid "Time"
@@ -114,6 +235,7 @@ msgstr ""
#. Default: "Title"
#: components/Widget/SelectWidget
+#: schemaFormBlock/schema
msgid "Title"
msgstr ""
@@ -122,6 +244,16 @@ msgstr ""
msgid "Used for programmatic access to the fieldset."
msgstr ""
+#. Default: "When activated, an email will be sent to the given recipients when a form is submitted"
+#: schemaFormBlock/schema
+msgid "When activated, an email will be sent to the given recipients when a form is submitted"
+msgstr ""
+
+#. Default: "When activated, the data will be stored for later use when the form is submitted"
+#: schemaFormBlock/schema
+msgid "When activated, the data will be stored for later use when the form is submitted"
+msgstr ""
+
#. Default: "Use Up and Down to choose options"
#: helpers/react-select
msgid "ay11_Use Up and Down to choose options"
@@ -229,6 +361,7 @@ msgstr ""
#. Default: "Captcha provider"
#: formSchema
+#: schemaFormBlock/schema
msgid "captcha"
msgstr ""
diff --git a/frontend/packages/volto-form-block/locales/ro/LC_MESSAGES/volto.po b/frontend/packages/volto-form-block/locales/ro/LC_MESSAGES/volto.po
index 2c8479a..d04f57f 100644
--- a/frontend/packages/volto-form-block/locales/ro/LC_MESSAGES/volto.po
+++ b/frontend/packages/volto-form-block/locales/ro/LC_MESSAGES/volto.po
@@ -16,11 +16,23 @@ msgstr ""
msgid "Add field"
msgstr ""
+#. Default: "Blind carbon copy"
+#: schemaFormBlock/schema
+msgid "Blind carbon copy"
+msgstr ""
+
#. Default: "Cancel"
#: components/Sidebar
+#: schemaFormBlock/EditSchemaForm
+#: schemaFormBlock/ViewSchemaForm
msgid "Cancel"
msgstr ""
+#. Default: "Cancel button label"
+#: schemaFormBlock/schema
+msgid "Cancel button label"
+msgstr ""
+
#. Default: "Choices"
#: components/Widget/SelectWidget
msgid "Choices"
@@ -36,6 +48,11 @@ msgstr ""
msgid "Close"
msgstr ""
+#. Default: "Data wipe"
+#: schemaFormBlock/schema
+msgid "Data wipe"
+msgstr ""
+
#. Default: "Date"
#: components/Widget/DatetimeWidget
msgid "Date"
@@ -48,6 +65,7 @@ msgstr ""
#. Default: "Description"
#: components/Widget/SelectWidget
+#: schemaFormBlock/schema
msgid "Description"
msgstr ""
@@ -66,13 +84,25 @@ msgstr ""
msgid "Drop files here ..."
msgstr ""
+#. Default: "Email footer"
+#: schemaFormBlock/schema
+msgid "Email footer"
+msgstr ""
+
+#. Default: "Email header"
+#: schemaFormBlock/schema
+msgid "Email header"
+msgstr ""
+
#. Default: "Error"
#: components/FormView
+#: schemaFormBlock/ViewSchemaForm
msgid "Error"
msgstr ""
#. Default: "Form"
#: components/Sidebar
+#: schemaFormBlock/schema
msgid "Form"
msgstr ""
@@ -86,6 +116,16 @@ msgstr ""
msgid "No value"
msgstr ""
+#. Default: "Number of days after which, the data should be deleted. Enter -1 to store indefinitely."
+#: schemaFormBlock/schema
+msgid "Number of days after which, the data should be deleted. Enter -1 to store indefinitely."
+msgstr ""
+
+#. Default: "Recipients"
+#: schemaFormBlock/schema
+msgid "Recipients"
+msgstr ""
+
#. Default: "Replace existing file"
#: components/Widget/FileWidget
msgid "Replace existing file"
@@ -101,6 +141,87 @@ msgstr ""
msgid "Select…"
msgstr ""
+#. Default: "Send email"
+#: schemaFormBlock/schema
+msgid "Send email"
+msgstr ""
+
+#. Default: "Send email to recipients"
+#: schemaFormBlock/schema
+msgid "Send email to recipients"
+msgstr ""
+
+#. Default: "Sender"
+#: schemaFormBlock/schema
+msgid "Sender"
+msgstr ""
+
+#. Default: "Sender name"
+#: schemaFormBlock/schema
+msgid "Sender name"
+msgstr ""
+
+#. Default: "Show cancel button"
+#: schemaFormBlock/schema
+msgid "Show cancel button"
+msgstr ""
+
+#. Default: "Store data"
+#: schemaFormBlock/schema
+msgid "Store data"
+msgstr ""
+
+#. Default: "Subject"
+#: schemaFormBlock/schema
+msgid "Subject"
+msgstr ""
+
+#. Default: "Submit"
+#: schemaFormBlock/EditSchemaForm
+#: schemaFormBlock/ViewSchemaForm
+msgid "Submit"
+msgstr ""
+
+#. Default: "Submit button label"
+#: schemaFormBlock/schema
+msgid "Submit button label"
+msgstr ""
+
+#. Default: "Text at the beginning of the email. Use the ${field_id} syntax to add a form value."
+#: schemaFormBlock/schema
+msgid "Text at the beginning of the email. Use the ${field_id} syntax to add a form value."
+msgstr ""
+
+#. Default: "Text at the end of the email. Use the ${field_id} syntax to add a form value."
+#: schemaFormBlock/schema
+msgid "Text at the end of the email. Use the ${field_id} syntax to add a form value."
+msgstr ""
+
+#. Default: "The email address of the sender"
+#: schemaFormBlock/schema
+msgid "The email address of the sender"
+msgstr ""
+
+#. Default: "The email addresses the submitted form data will be sent to as blind carbon copy. Multiple email addresses can be entered separated by a semicolon."
+#: schemaFormBlock/schema
+msgid "The email addresses the submitted form data will be sent to as blind carbon copy. Multiple email addresses can be entered separated by a semicolon."
+msgstr ""
+
+#. Default: "The email addresses the submitted form data will be sent to. Multiple email addresses can be entered separated by a semicolon."
+#: schemaFormBlock/schema
+msgid "The email addresses the submitted form data will be sent to. Multiple email addresses can be entered separated by a semicolon."
+msgstr ""
+
+#. Default: "The name of the sender"
+#: schemaFormBlock/schema
+msgid "The name of the sender"
+msgstr ""
+
+#. Default: "The subject used in the sent email. Use the ${field_id} syntax to add a form value to the email subject."
+#: schemaFormBlock/schema
+msgid "The subject used in the sent email. Use the ${field_id} syntax to add a form value to the email subject."
+msgstr ""
+
#. Default: "Time"
#: components/Widget/DatetimeWidget
msgid "Time"
@@ -108,6 +229,7 @@ msgstr ""
#. Default: "Title"
#: components/Widget/SelectWidget
+#: schemaFormBlock/schema
msgid "Title"
msgstr ""
@@ -116,6 +238,16 @@ msgstr ""
msgid "Used for programmatic access to the fieldset."
msgstr ""
+#. Default: "When activated, an email will be sent to the given recipients when a form is submitted"
+#: schemaFormBlock/schema
+msgid "When activated, an email will be sent to the given recipients when a form is submitted"
+msgstr ""
+
+#. Default: "When activated, the data will be stored for later use when the form is submitted"
+#: schemaFormBlock/schema
+msgid "When activated, the data will be stored for later use when the form is submitted"
+msgstr ""
+
#. Default: "Use Up and Down to choose options"
#: helpers/react-select
msgid "ay11_Use Up and Down to choose options"
@@ -223,6 +355,7 @@ msgstr ""
#. Default: "Captcha provider"
#: formSchema
+#: schemaFormBlock/schema
msgid "captcha"
msgstr ""
diff --git a/frontend/packages/volto-form-block/locales/volto.pot b/frontend/packages/volto-form-block/locales/volto.pot
index 4d94268..2684e8b 100644
--- a/frontend/packages/volto-form-block/locales/volto.pot
+++ b/frontend/packages/volto-form-block/locales/volto.pot
@@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: Plone\n"
-"POT-Creation-Date: 2024-07-04T09:29:55.227Z\n"
+"POT-Creation-Date: 2024-09-11T09:06:00.713Z\n"
"Last-Translator: Plone i18n \n"
"Language-Team: Plone i18n \n"
"Content-Type: text/plain; charset=utf-8\n"
@@ -18,11 +18,23 @@ msgstr ""
msgid "Add field"
msgstr ""
+#. Default: "Blind carbon copy"
+#: schemaFormBlock/schema
+msgid "Blind carbon copy"
+msgstr ""
+
#. Default: "Cancel"
#: components/Sidebar
+#: schemaFormBlock/EditSchemaForm
+#: schemaFormBlock/ViewSchemaForm
msgid "Cancel"
msgstr ""
+#. Default: "Cancel button label"
+#: schemaFormBlock/schema
+msgid "Cancel button label"
+msgstr ""
+
#. Default: "Choices"
#: components/Widget/SelectWidget
msgid "Choices"
@@ -38,6 +50,11 @@ msgstr ""
msgid "Close"
msgstr ""
+#. Default: "Data wipe"
+#: schemaFormBlock/schema
+msgid "Data wipe"
+msgstr ""
+
#. Default: "Date"
#: components/Widget/DatetimeWidget
msgid "Date"
@@ -50,6 +67,7 @@ msgstr ""
#. Default: "Description"
#: components/Widget/SelectWidget
+#: schemaFormBlock/schema
msgid "Description"
msgstr ""
@@ -68,13 +86,25 @@ msgstr ""
msgid "Drop files here ..."
msgstr ""
+#. Default: "Email footer"
+#: schemaFormBlock/schema
+msgid "Email footer"
+msgstr ""
+
+#. Default: "Email header"
+#: schemaFormBlock/schema
+msgid "Email header"
+msgstr ""
+
#. Default: "Error"
#: components/FormView
+#: schemaFormBlock/ViewSchemaForm
msgid "Error"
msgstr ""
#. Default: "Form"
#: components/Sidebar
+#: schemaFormBlock/schema
msgid "Form"
msgstr ""
@@ -88,6 +118,16 @@ msgstr ""
msgid "No value"
msgstr ""
+#. Default: "Number of days after which, the data should be deleted. Enter -1 to store indefinitely."
+#: schemaFormBlock/schema
+msgid "Number of days after which, the data should be deleted. Enter -1 to store indefinitely."
+msgstr ""
+
+#. Default: "Recipients"
+#: schemaFormBlock/schema
+msgid "Recipients"
+msgstr ""
+
#. Default: "Replace existing file"
#: components/Widget/FileWidget
msgid "Replace existing file"
@@ -103,6 +143,87 @@ msgstr ""
msgid "Select…"
msgstr ""
+#. Default: "Send email"
+#: schemaFormBlock/schema
+msgid "Send email"
+msgstr ""
+
+#. Default: "Send email to recipients"
+#: schemaFormBlock/schema
+msgid "Send email to recipients"
+msgstr ""
+
+#. Default: "Sender"
+#: schemaFormBlock/schema
+msgid "Sender"
+msgstr ""
+
+#. Default: "Sender name"
+#: schemaFormBlock/schema
+msgid "Sender name"
+msgstr ""
+
+#. Default: "Show cancel button"
+#: schemaFormBlock/schema
+msgid "Show cancel button"
+msgstr ""
+
+#. Default: "Store data"
+#: schemaFormBlock/schema
+msgid "Store data"
+msgstr ""
+
+#. Default: "Subject"
+#: schemaFormBlock/schema
+msgid "Subject"
+msgstr ""
+
+#. Default: "Submit"
+#: schemaFormBlock/EditSchemaForm
+#: schemaFormBlock/ViewSchemaForm
+msgid "Submit"
+msgstr ""
+
+#. Default: "Submit button label"
+#: schemaFormBlock/schema
+msgid "Submit button label"
+msgstr ""
+
+#. Default: "Text at the beginning of the email. Use the ${field_id} syntax to add a form value."
+#: schemaFormBlock/schema
+msgid "Text at the beginning of the email. Use the ${field_id} syntax to add a form value."
+msgstr ""
+
+#. Default: "Text at the end of the email. Use the ${field_id} syntax to add a form value."
+#: schemaFormBlock/schema
+msgid "Text at the end of the email. Use the ${field_id} syntax to add a form value."
+msgstr ""
+
+#. Default: "The email address of the sender"
+#: schemaFormBlock/schema
+msgid "The email address of the sender"
+msgstr ""
+
+#. Default: "The email addresses the submitted form data will be sent to as blind carbon copy. Multiple email addresses can be entered separated by a semicolon."
+#: schemaFormBlock/schema
+msgid "The email addresses the submitted form data will be sent to as blind carbon copy. Multiple email addresses can be entered separated by a semicolon."
+msgstr ""
+
+#. Default: "The email addresses the submitted form data will be sent to. Multiple email addresses can be entered separated by a semicolon."
+#: schemaFormBlock/schema
+msgid "The email addresses the submitted form data will be sent to. Multiple email addresses can be entered separated by a semicolon."
+msgstr ""
+
+#. Default: "The name of the sender"
+#: schemaFormBlock/schema
+msgid "The name of the sender"
+msgstr ""
+
+#. Default: "The subject used in the sent email. Use the ${field_id} syntax to add a form value to the email subject."
+#: schemaFormBlock/schema
+msgid "The subject used in the sent email. Use the ${field_id} syntax to add a form value to the email subject."
+msgstr ""
+
#. Default: "Time"
#: components/Widget/DatetimeWidget
msgid "Time"
@@ -110,6 +231,7 @@ msgstr ""
#. Default: "Title"
#: components/Widget/SelectWidget
+#: schemaFormBlock/schema
msgid "Title"
msgstr ""
@@ -118,6 +240,16 @@ msgstr ""
msgid "Used for programmatic access to the fieldset."
msgstr ""
+#. Default: "When activated, an email will be sent to the given recipients when a form is submitted"
+#: schemaFormBlock/schema
+msgid "When activated, an email will be sent to the given recipients when a form is submitted"
+msgstr ""
+
+#. Default: "When activated, the data will be stored for later use when the form is submitted"
+#: schemaFormBlock/schema
+msgid "When activated, the data will be stored for later use when the form is submitted"
+msgstr ""
+
#. Default: "Use Up and Down to choose options"
#: helpers/react-select
msgid "ay11_Use Up and Down to choose options"
@@ -225,6 +357,7 @@ msgstr ""
#. Default: "Captcha provider"
#: formSchema
+#: schemaFormBlock/schema
msgid "captcha"
msgstr ""
diff --git a/frontend/packages/volto-form-block/src/actions/index.js b/frontend/packages/volto-form-block/src/actions/index.js
index 08d5921..29dab5c 100644
--- a/frontend/packages/volto-form-block/src/actions/index.js
+++ b/frontend/packages/volto-form-block/src/actions/index.js
@@ -19,7 +19,7 @@ export function submitForm(path = '', block_id, data, attachments, captcha) {
subrequest: block_id,
request: {
op: 'post',
- path: path + '/@submit-form',
+ path: path + '/@schemaform-data',
data: {
block_id,
data,
diff --git a/frontend/packages/volto-form-block/src/components/Widget/HoneypotCaptchaWidget.jsx b/frontend/packages/volto-form-block/src/components/Widget/HoneypotCaptchaWidget.jsx
index d6781c4..a8e65ec 100644
--- a/frontend/packages/volto-form-block/src/components/Widget/HoneypotCaptchaWidget.jsx
+++ b/frontend/packages/volto-form-block/src/components/Widget/HoneypotCaptchaWidget.jsx
@@ -40,6 +40,7 @@ const HoneypotCaptchaWidget = ({
}, []);
const [value, setValue] = useState();
+
return (
{
+ config.widgets.widget.honeypot = HoneypotCaptchaWidget;
+
config.blocks.blocksConfig = {
...config.blocks.blocksConfig,
+ schemaForm: {
+ id: 'schemaForm',
+ title: 'schemaForm',
+ icon: formSVG,
+ group: 'text',
+ view: schemaFormBlockView,
+ edit: schemaFormBlockEdit,
+ formSchema: FormSchema,
+ blockSchema: schemaFormBlockSchema,
+ fieldSchema: FieldSchema,
+ filterFactory: [
+ 'label_textline_field',
+ 'label_text_field',
+ 'label_choice_field',
+ 'label_multi_choice_field',
+ 'label_boolean_field',
+ 'label_date_field',
+ 'label_datetime_field',
+ 'File Upload',
+ 'label_email',
+ 'hidden',
+ 'static_text',
+ ],
+ additionalFactory: [
+ { value: 'hidden', label: 'Hidden' },
+ { value: 'static_text', label: 'Static Text' },
+ ],
+ defaultSender: 'noreply@plone.org',
+ defaultSenderName: 'Plone',
+ additionalFields: [],
+ fieldTypeSchemaExtenders: {
+ select: SelectionSchemaExtender,
+ single_choice: SelectionSchemaExtender,
+ multiple_choice: SelectionSchemaExtender,
+ from: FromSchemaExtender,
+ hidden: HiddenSchemaExtender,
+ },
+ schemaValidators: {
+ /*fieldname: validationFN(data)*/
+ default_from: (data, intl) => {
+ return validateDefaultFrom(data.default_from, intl);
+ },
+ default_to: (data, intl) => {
+ return validateDefaultTo(data.default_to, intl);
+ },
+ },
+ attachment_fields: ['attachment'],
+ restricted: false,
+ mostUsed: true,
+ security: {
+ addPermission: [],
+ view: [],
+ },
+ sidebarTab: 1,
+ },
form: {
id: 'form',
title: 'Form',
diff --git a/frontend/packages/volto-form-block/src/schemaFormBlock/EditSchemaForm.jsx b/frontend/packages/volto-form-block/src/schemaFormBlock/EditSchemaForm.jsx
new file mode 100644
index 0000000..1a3f53c
--- /dev/null
+++ b/frontend/packages/volto-form-block/src/schemaFormBlock/EditSchemaForm.jsx
@@ -0,0 +1,115 @@
+import React, { Component } from 'react';
+import { isEmpty } from 'lodash';
+import { compose } from 'redux';
+import { defineMessages, injectIntl } from 'react-intl';
+import { SidebarPortal } from '@plone/volto/components';
+import { Form, BlockDataForm } from '@plone/volto/components/manage/Form';
+import { withBlockExtensions } from '@plone/volto/helpers';
+import config from '@plone/volto/registry';
+
+const messages = defineMessages({
+ submit: {
+ id: 'Submit',
+ defaultMessage: 'Submit',
+ },
+ cancel: {
+ id: 'Cancel',
+ defaultMessage: 'Cancel',
+ },
+});
+
+class Edit extends Component {
+ render() {
+ const FormSchema = config.blocks.blocksConfig.schemaForm.blockSchema;
+ const filterFactory = config.blocks.blocksConfig.schemaForm.filterFactory;
+ const additionalFactory =
+ config.blocks.blocksConfig.schemaForm.additionalFactory;
+ const schema = FormSchema(this.props);
+ const { data } = this.props;
+
+ const defaultEmptyData = {
+ fieldsets: [
+ {
+ id: 'default',
+ title: 'Default',
+ fields: [],
+ },
+ ],
+ properties: {},
+ required: [],
+ };
+
+ const dummyHandler = () => {};
+
+ return (
+ <>
+
+ );
+};
+
+export default FormBlockView;
diff --git a/frontend/packages/volto-form-block/src/schemaFormBlock/schema.js b/frontend/packages/volto-form-block/src/schemaFormBlock/schema.js
new file mode 100644
index 0000000..2e759af
--- /dev/null
+++ b/frontend/packages/volto-form-block/src/schemaFormBlock/schema.js
@@ -0,0 +1,284 @@
+import { defineMessages } from 'react-intl';
+import config from '@plone/volto/registry';
+
+const messages = defineMessages({
+ form: {
+ id: 'Form',
+ defaultMessage: 'Form',
+ },
+ title: {
+ id: 'Title',
+ defaultMessage: 'Title',
+ },
+ description: {
+ id: 'Description',
+ defaultMessage: 'Description',
+ },
+ submit_label: {
+ id: 'Submit button label',
+ defaultMessage: 'Submit button label',
+ },
+ show_cancel: {
+ id: 'Show cancel button',
+ defaultMessage: 'Show cancel button',
+ },
+ cancel_label: {
+ id: 'Cancel button label',
+ defaultMessage: 'Cancel button label',
+ },
+ captcha: {
+ id: 'captcha',
+ defaultMessage: 'Captcha provider',
+ },
+
+ fieldset_email: {
+ id: 'Send email',
+ defaultMessage: 'Send email',
+ },
+ send: {
+ id: 'Send email to recipients',
+ defaultMessage: 'Send email to recipients',
+ },
+ send_description: {
+ id: 'When activated, an email will be sent to the given recipients when a form is submitted',
+ defaultMessage:
+ 'When activated, an email will be sent to the given recipients when a form is submitted',
+ },
+ recipients: {
+ id: 'Recipients',
+ defaultMessage: 'Recipients',
+ },
+ recipients_description: {
+ id: 'The email addresses the submitted form data will be sent to. Multiple email addresses can be entered separated by a semicolon.',
+ defaultMessage:
+ 'The email addresses the submitted form data will be sent to. Multiple email addresses can be entered separated by a semicolon.',
+ },
+ bcc: {
+ id: 'Blind carbon copy',
+ defaultMessage: 'Blind carbon copy',
+ },
+ bcc_description: {
+ id: 'The email addresses the submitted form data will be sent to as blind carbon copy. Multiple email addresses can be entered separated by a semicolon.',
+ defaultMessage:
+ 'The email addresses the submitted form data will be sent to as blind carbon copy. Multiple email addresses can be entered separated by a semicolon.',
+ },
+ sender: {
+ id: 'Sender',
+ defaultMessage: 'Sender',
+ },
+ sender_description: {
+ id: 'The email address of the sender',
+ defaultMessage: 'The email address of the sender',
+ },
+ sender_name: {
+ id: 'Sender name',
+ defaultMessage: 'Sender name',
+ },
+ sender_name_description: {
+ id: 'The name of the sender',
+ defaultMessage: 'The name of the sender',
+ },
+ subject: {
+ id: 'Subject',
+ defaultMessage: 'Subject',
+ },
+ subject_description: {
+ id:
+ // eslint-disable-next-line no-template-curly-in-string
+ 'The subject used in the sent email. Use the ${field_id} syntax to add a form value to the email subject.',
+ defaultMessage:
+ // eslint-disable-next-line no-template-curly-in-string
+ 'The subject used in the sent email. Use the ${field_id} syntax to add a form value to the email subject.',
+ },
+ mail_header: {
+ id: 'Email header',
+ defaultMessage: 'Email header',
+ },
+ mail_header_description: {
+ // eslint-disable-next-line no-template-curly-in-string
+ id: 'Text at the beginning of the email. Use the ${field_id} syntax to add a form value.',
+ // eslint-disable-next-line no-template-curly-in-string
+ defaultMessage:
+ // eslint-disable-next-line no-template-curly-in-string
+ 'Text at the beginning of the email. Use the ${field_id} syntax to add a form value.',
+ },
+ mail_footer: {
+ id: 'Email footer',
+ defaultMessage: 'Email footer',
+ },
+ mail_footer_description: {
+ // eslint-disable-next-line no-template-curly-in-string
+ id: 'Text at the end of the email. Use the ${field_id} syntax to add a form value.',
+ defaultMessage:
+ // eslint-disable-next-line no-template-curly-in-string
+ 'Text at the end of the email. Use the ${field_id} syntax to add a form value.',
+ },
+
+ fieldset_store: {
+ id: 'Store data',
+ defaultMessage: 'Store data',
+ },
+ store: {
+ id: 'Store data',
+ defaultMessage: 'Store data',
+ },
+ store_description: {
+ id: 'When activated, the data will be stored for later use when the form is submitted',
+ defaultMessage:
+ 'When activated, the data will be stored for later use when the form is submitted',
+ },
+ data_wipe: {
+ id: 'Data wipe',
+ defaultMessage: 'Data wipe',
+ },
+ data_wipe_description: {
+ id: 'Number of days after which, the data should be deleted. Enter -1 to store indefinitely.',
+ defaultMessage:
+ 'Number of days after which, the data should be deleted. Enter -1 to store indefinitely.',
+ },
+});
+
+const defaultEmptyData = {
+ fieldsets: [
+ {
+ id: 'default',
+ title: 'Default',
+ fields: [],
+ },
+ ],
+ properties: {},
+ required: [],
+};
+
+export const schemaFormBlockSchema = ({ data, intl }) => {
+ let conditional_required = [];
+ if (!data?.store && !data?.send) {
+ conditional_required.push('store');
+ conditional_required.push('send');
+ }
+
+ return {
+ title: intl.formatMessage(messages.form),
+ fieldsets: [
+ {
+ id: 'default',
+ title: 'Default',
+ fields: [
+ 'title',
+ 'description',
+ 'submit_label',
+ 'show_cancel',
+ ...(data?.show_cancel ? ['cancel_label'] : []),
+ 'captcha',
+ ],
+ },
+ {
+ id: 'email',
+ title: intl.formatMessage(messages.fieldset_email),
+ fields: [
+ 'send',
+ ...(data?.send
+ ? [
+ 'recipients',
+ 'bcc',
+ 'sender',
+ 'sender_name',
+ 'subject',
+ 'mail_header',
+ 'mail_footer',
+ ]
+ : []),
+ ],
+ },
+ {
+ id: 'savedata',
+ title: intl.formatMessage(messages.fieldset_store),
+ fields: ['store', ...(data?.store ? ['data_wipe'] : [])],
+ },
+ ],
+ properties: {
+ schema: {
+ title: 'Schema',
+ default: defaultEmptyData,
+ },
+ title: {
+ title: intl.formatMessage(messages.title),
+ },
+ description: {
+ title: intl.formatMessage(messages.description),
+ type: 'textarea',
+ },
+ submit_label: {
+ title: intl.formatMessage(messages.submit_label),
+ },
+ show_cancel: {
+ type: 'boolean',
+ title: intl.formatMessage(messages.show_cancel),
+ default: false,
+ },
+ cancel_label: {
+ title: intl.formatMessage(messages.cancel_label),
+ },
+ captcha: {
+ title: intl.formatMessage(messages.captcha),
+ type: 'string',
+ vocabulary: {
+ '@id': 'collective.volto.formsupport.captcha.providers',
+ },
+ },
+
+ send: {
+ type: 'boolean',
+ title: intl.formatMessage(messages.send),
+ description: intl.formatMessage(messages.send_description),
+ },
+ recipients: {
+ title: intl.formatMessage(messages.recipients),
+ description: intl.formatMessage(messages.recipients_description),
+ },
+ bcc: {
+ title: intl.formatMessage(messages.bcc),
+ description: intl.formatMessage(messages.bcc_description),
+ },
+ sender: {
+ title: intl.formatMessage(messages.sender),
+ description: intl.formatMessage(messages.sender_description),
+ default: config.blocks?.blocksConfig?.schemaForm?.defaultSender,
+ },
+ sender_name: {
+ title: intl.formatMessage(messages.sender_name),
+ description: intl.formatMessage(messages.sender_name_description),
+ default: config.blocks?.blocksConfig?.schemaForm?.defaultSenderName,
+ },
+ subject: {
+ title: intl.formatMessage(messages.subject),
+ description: intl.formatMessage(messages.subject_description),
+ },
+ mail_header: {
+ title: intl.formatMessage(messages.mail_header),
+ widget: 'richtext',
+ type: 'string',
+ description: intl.formatMessage(messages.mail_header_description),
+ },
+ mail_footer: {
+ title: intl.formatMessage(messages.mail_footer),
+ widget: 'richtext',
+ type: 'string',
+ description: intl.formatMessage(messages.mail_footer_description),
+ },
+
+ store: {
+ type: 'boolean',
+ title: intl.formatMessage(messages.store),
+ description: intl.formatMessage(messages.store_description),
+ },
+ data_wipe: {
+ type: 'integer',
+ title: intl.formatMessage(messages.data_wipe),
+ description: intl.formatMessage(messages.data_wipe_description),
+ default: -1,
+ },
+ },
+ required: ['default_from', ...conditional_required],
+ };
+};
diff --git a/frontend/packages/volto-form-block/tsconfig.json b/frontend/packages/volto-form-block/tsconfig.json
index ddb0f54..1874161 100644
--- a/frontend/packages/volto-form-block/tsconfig.json
+++ b/frontend/packages/volto-form-block/tsconfig.json
@@ -16,7 +16,7 @@
"@plone/volto/*": ["../../core/packages/volto/src/*"]
}
},
- "include": ["**/*.ts", "**/*.tsx"],
+ "include": ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"],
"exclude": [
"node_modules",
"build",
diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml
index fcaa21f..589ed22 100644
--- a/frontend/pnpm-lock.yaml
+++ b/frontend/pnpm-lock.yaml
@@ -882,9 +882,6 @@ importers:
react-select-async-paginate:
specifier: 0.5.3
version: 0.5.3(react-dom@18.2.0(react@18.2.0))(react-select@4.3.1(@types/react@18.2.27)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0)
- react-share:
- specifier: 2.3.1
- version: 2.3.1(react@18.2.0)
react-side-effect:
specifier: 2.1.2
version: 2.1.2(react@18.2.0)
@@ -1059,7 +1056,7 @@ importers:
version: 8.1.11(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
'@testing-library/cypress':
specifier: 10.0.1
- version: 10.0.1(cypress@13.6.6)
+ version: 10.0.1(cypress@13.13.2)
'@testing-library/jest-dom':
specifier: 6.4.2
version: 6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@26.6.3)(vitest@1.6.0(jsdom@16.7.0)(less@3.11.1)(sass@1.77.6))
@@ -1136,14 +1133,14 @@ importers:
specifier: 5.2.7
version: 5.2.7(webpack@5.90.1)
cypress:
- specifier: 13.6.6
- version: 13.6.6
+ specifier: 13.13.2
+ version: 13.13.2
cypress-axe:
specifier: 1.5.0
- version: 1.5.0(axe-core@4.4.2)(cypress@13.6.6)
+ version: 1.5.0(axe-core@4.4.2)(cypress@13.13.2)
cypress-file-upload:
specifier: 5.0.8
- version: 5.0.8(cypress@13.6.6)
+ version: 5.0.8(cypress@13.13.2)
deep-freeze:
specifier: 0.0.1
version: 0.0.1
@@ -1417,7 +1414,7 @@ importers:
dependencies:
'@testing-library/cypress':
specifier: 10.0.1
- version: 10.0.1(cypress@13.6.6)
+ version: 10.0.1(cypress@13.13.2)
'@testing-library/jest-dom':
specifier: 6.4.2
version: 6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(vitest@1.6.0)
@@ -1428,14 +1425,14 @@ importers:
specifier: 4.8.4
version: 4.8.4
cypress:
- specifier: 13.6.6
- version: 13.6.6
+ specifier: 13.13.2
+ version: 13.13.2
cypress-axe:
specifier: 1.5.0
- version: 1.5.0(axe-core@4.8.4)(cypress@13.6.6)
+ version: 1.5.0(axe-core@4.8.4)(cypress@13.13.2)
cypress-file-upload:
specifier: 5.0.8
- version: 5.0.8(cypress@13.6.6)
+ version: 5.0.8(cypress@13.13.2)
devDependencies:
release-it:
specifier: ^17.1.1
@@ -1460,7 +1457,7 @@ importers:
version: 1.10.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
volto-subblocks:
specifier: ^2.1.0
- version: 2.1.0(@plone/volto@18.0.0-alpha.40(@babel/runtime@7.24.7)(@popperjs/core@2.11.8)(@types/react-dom@18.2.12)(@types/react@18.2.27)(react-with-direction@1.4.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(seamless-immutable@7.1.4))(react@18.2.0)
+ version: 2.1.0(@plone/volto@18.0.0-alpha.42(@babel/runtime@7.24.7)(@popperjs/core@2.11.8)(@types/react-dom@18.2.12)(@types/react@18.2.27)(react-with-direction@1.4.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(seamless-immutable@7.1.4))(react@18.2.0)
devDependencies:
'@plone/scripts':
specifier: ^3.6.1
@@ -3652,8 +3649,8 @@ packages:
resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==}
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
- '@plone/registry@1.7.0':
- resolution: {integrity: sha512-Ar5eXwtGitYbj9yHQTX1bs7FZfdmSW3YSrG6HOP/FNwdM47m9ES4vfkliS2rvuC8TVpWn27U0DK5v7I+mlSZeQ==}
+ '@plone/registry@1.8.0':
+ resolution: {integrity: sha512-xQH7vhnzQpxPxZLZtObpN/jv4JOIBhYEKsdWUCYmL1e8wlbxb+Xk2C6qNK9+i+kyjmLdAUzDH0v5Xl9Y7igxKw==}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
@@ -3665,11 +3662,11 @@ packages:
resolution: {integrity: sha512-52S2Nb8sUDnHobzoYBstn6UkXxri+UGEh5DWZfy0xJ9h/ia6n9XI+mjtSEG3vKkr+hsbLH9sO8RlX4tpG3Kyhg==}
hasBin: true
- '@plone/volto-slate@18.0.0-alpha.16':
- resolution: {integrity: sha512-c0I2/iZ94Ozoxsc+K2ODPeRKDyg4yUJL0shuCHXro7VIM0Q48j6v8dGoT+p+XKVwGKEDkPEhMNrCciR42jhhWw==}
+ '@plone/volto-slate@18.0.0-alpha.17':
+ resolution: {integrity: sha512-ztO3BwN1vZ0q+ZVOPcU7Yz0PVaIpMj4xzsGr1+6/cAdCIxBD9JXaoI7fu3QJQFDHXDKNTg4cLWKQzjiyslczHw==}
- '@plone/volto@18.0.0-alpha.40':
- resolution: {integrity: sha512-ZthD2KjA8qrdiXFx+RGCsJQyGy5E9Ig0YSAuBzO2cJw1NRNSrirHEaxcB1PlR+OXcwfG6oF3jkfoC7QeazG1Ig==}
+ '@plone/volto@18.0.0-alpha.42':
+ resolution: {integrity: sha512-PXuHWSgI7ggGYbpN8NwnqM5mL0QX4SjD/yx+i0U7UWSexfeAs6RgRyZJSDW6A8QkzRN+qvctjaqZv6vimg90vw==}
engines: {node: ^16 || ^18 || ^20}
'@pmmmwh/react-refresh-webpack-plugin@0.4.3':
@@ -7177,8 +7174,8 @@ packages:
peerDependencies:
cypress: '>3.0.0'
- cypress@13.6.6:
- resolution: {integrity: sha512-S+2S9S94611hXimH9a3EAYt81QM913ZVA03pUmGDfLTFa5gyp85NJ8dJGSlEAEmyRsYkioS1TtnWtbv/Fzt11A==}
+ cypress@13.13.2:
+ resolution: {integrity: sha512-PvJQU33933NvS1StfzEb8/mu2kMy4dABwCF+yd5Bi7Qly1HOVf+Bufrygee/tlmty/6j5lX+KIi8j9Q3JUMbhA==}
engines: {node: ^16.0.0 || ^18.0.0 || >=20.0.0}
hasBin: true
@@ -10112,9 +10109,6 @@ packages:
jsonfile@6.1.0:
resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
- jsonp@0.2.1:
- resolution: {integrity: sha512-pfog5gdDxPdV4eP7Kg87M8/bHgshlZ5pybl+yKxAnCZ5O7lCIn7Ixydj03wOlnDQesky2BPyA91SQ+5Y/mNwzw==}
-
jsonpack@1.1.5:
resolution: {integrity: sha512-d2vwomK605ks7Q+uCpbwGyoIF5j+UZuJjlYcugISBt3CxM+eBo/W6y63yVPIyIvbYON+pvJYsYZjCYbzqJj/xQ==}
@@ -12653,12 +12647,6 @@ packages:
peerDependencies:
react: ^16.0.0 || ^17.0.0 || ^18.0.0
- react-share@2.3.1:
- resolution: {integrity: sha512-iLUQwCaeVgOkXJxa+8B0iyIIlUajY6BxO9TRb2j8erM+q1ORe0akQZ1gtjEfWYMG4UnGTMU1fOstqes+X0AStw==}
- engines: {node: '>=6.9.0', npm: '>=5.0.0'}
- peerDependencies:
- react: ^0.13.0 || ^0.14.0 || ^15.0.0 || ^16.0.0-0
-
react-side-effect@2.1.2:
resolution: {integrity: sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw==}
peerDependencies:
@@ -14127,6 +14115,10 @@ packages:
resolution: {integrity: sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==}
engines: {node: '>=8.17.0'}
+ tmp@0.2.3:
+ resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==}
+ engines: {node: '>=14.14'}
+
tmpl@1.0.5:
resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==}
@@ -18659,7 +18651,7 @@ snapshots:
'@pkgr/core@0.1.1': {}
- '@plone/registry@1.7.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
+ '@plone/registry@1.8.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
dependencies:
crypto-random-string: 3.2.0
debug: 4.3.2
@@ -18713,7 +18705,7 @@ snapshots:
- debug
- supports-color
- '@plone/volto-slate@18.0.0-alpha.16(@types/react-dom@18.2.12)(@types/react@18.2.27)(redux@4.2.1)':
+ '@plone/volto-slate@18.0.0-alpha.17(@types/react-dom@18.2.12)(@types/react@18.2.27)(redux@4.2.1)':
dependencies:
classnames: 2.2.6
github-slugger: 1.4.0
@@ -18747,13 +18739,13 @@ snapshots:
- supports-color
- utf-8-validate
- '@plone/volto@18.0.0-alpha.40(@babel/runtime@7.24.7)(@popperjs/core@2.11.8)(@types/react-dom@18.2.12)(@types/react@18.2.27)(react-with-direction@1.4.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(seamless-immutable@7.1.4)':
+ '@plone/volto@18.0.0-alpha.42(@babel/runtime@7.24.7)(@popperjs/core@2.11.8)(@types/react-dom@18.2.12)(@types/react@18.2.27)(react-with-direction@1.4.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(seamless-immutable@7.1.4)':
dependencies:
'@loadable/component': 5.14.1(react@18.2.0)
'@loadable/server': 5.14.0(@loadable/component@5.14.1(react@18.2.0))(react@18.2.0)
- '@plone/registry': 1.7.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+ '@plone/registry': 1.8.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
'@plone/scripts': 3.6.2(debug@4.3.2)
- '@plone/volto-slate': 18.0.0-alpha.16(@types/react-dom@18.2.12)(@types/react@18.2.27)(redux@4.2.1)
+ '@plone/volto-slate': 18.0.0-alpha.17(@types/react-dom@18.2.12)(@types/react@18.2.27)(redux@4.2.1)
'@redux-devtools/extension': 3.3.0(redux@4.2.1)
classnames: 2.2.6
connected-react-router: 6.8.0(history@4.10.1)(immutable@3.8.2)(react-redux@8.1.2(@types/react-dom@18.2.12)(@types/react@18.2.27)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(redux@4.2.1))(react-router@5.2.0(react@18.2.0))(react@18.2.0)(redux@4.2.1)(seamless-immutable@7.1.4)
@@ -18813,7 +18805,6 @@ snapshots:
react-router-hash-link: 2.4.3(react-router-dom@5.2.0(react@18.2.0))(react@18.2.0)
react-select: 4.3.1(@types/react@18.2.27)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
react-select-async-paginate: 0.5.3(react-dom@18.2.0(react@18.2.0))(react-select@4.3.1(@types/react@18.2.27)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0)
- react-share: 2.3.1(react@18.2.0)
react-side-effect: 2.1.2(react@18.2.0)
react-simple-code-editor: 0.7.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
react-sortable-hoc: 2.0.0(prop-types@15.7.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
@@ -20958,11 +20949,11 @@ snapshots:
'@tanstack/query-core': 5.49.1
react: 18.2.0
- '@testing-library/cypress@10.0.1(cypress@13.6.6)':
+ '@testing-library/cypress@10.0.1(cypress@13.13.2)':
dependencies:
'@babel/runtime': 7.20.6
'@testing-library/dom': 9.3.4
- cypress: 13.6.6
+ cypress: 13.13.2
'@testing-library/dom@10.1.0':
dependencies:
@@ -23819,21 +23810,21 @@ snapshots:
csstype@3.1.3: {}
- cypress-axe@1.5.0(axe-core@4.4.2)(cypress@13.6.6):
+ cypress-axe@1.5.0(axe-core@4.4.2)(cypress@13.13.2):
dependencies:
axe-core: 4.4.2
- cypress: 13.6.6
+ cypress: 13.13.2
- cypress-axe@1.5.0(axe-core@4.8.4)(cypress@13.6.6):
+ cypress-axe@1.5.0(axe-core@4.8.4)(cypress@13.13.2):
dependencies:
axe-core: 4.8.4
- cypress: 13.6.6
+ cypress: 13.13.2
- cypress-file-upload@5.0.8(cypress@13.6.6):
+ cypress-file-upload@5.0.8(cypress@13.13.2):
dependencies:
- cypress: 13.6.6
+ cypress: 13.13.2
- cypress@13.6.6:
+ cypress@13.13.2:
dependencies:
'@cypress/request': 3.0.1
'@cypress/xvfb': 1.2.4(supports-color@8.1.1)
@@ -23874,7 +23865,7 @@ snapshots:
request-progress: 3.0.0
semver: 7.6.2
supports-color: 8.1.1
- tmp: 0.2.1
+ tmp: 0.2.3
untildify: 4.0.0
yauzl: 2.10.0
@@ -27859,12 +27850,6 @@ snapshots:
optionalDependencies:
graceful-fs: 4.2.11
- jsonp@0.2.1:
- dependencies:
- debug: 2.6.9
- transitivePeerDependencies:
- - supports-color
-
jsonpack@1.1.5: {}
jsonparse@1.3.1: {}
@@ -31260,16 +31245,6 @@ snapshots:
react: 18.2.0
react-is: 18.3.1
- react-share@2.3.1(react@18.2.0):
- dependencies:
- babel-runtime: 6.26.0
- classnames: 2.2.6
- jsonp: 0.2.1
- prop-types: 15.7.2
- react: 18.2.0
- transitivePeerDependencies:
- - supports-color
-
react-side-effect@2.1.2(react@18.2.0):
dependencies:
react: 18.2.0
@@ -33240,6 +33215,8 @@ snapshots:
dependencies:
rimraf: 3.0.2
+ tmp@0.2.3: {}
+
tmpl@1.0.5: {}
to-fast-properties@1.0.3: {}
@@ -34082,9 +34059,9 @@ snapshots:
- terser
optional: true
- volto-subblocks@2.1.0(@plone/volto@18.0.0-alpha.40(@babel/runtime@7.24.7)(@popperjs/core@2.11.8)(@types/react-dom@18.2.12)(@types/react@18.2.27)(react-with-direction@1.4.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(seamless-immutable@7.1.4))(react@18.2.0):
+ volto-subblocks@2.1.0(@plone/volto@18.0.0-alpha.42(@babel/runtime@7.24.7)(@popperjs/core@2.11.8)(@types/react-dom@18.2.12)(@types/react@18.2.27)(react-with-direction@1.4.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(seamless-immutable@7.1.4))(react@18.2.0):
dependencies:
- '@plone/volto': 18.0.0-alpha.40(@babel/runtime@7.24.7)(@popperjs/core@2.11.8)(@types/react-dom@18.2.12)(@types/react@18.2.27)(react-with-direction@1.4.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(seamless-immutable@7.1.4)
+ '@plone/volto': 18.0.0-alpha.42(@babel/runtime@7.24.7)(@popperjs/core@2.11.8)(@types/react-dom@18.2.12)(@types/react@18.2.27)(react-with-direction@1.4.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(seamless-immutable@7.1.4)
react-dnd: 5.0.0(react@18.2.0)
react-dnd-html5-backend: 5.0.1
transitivePeerDependencies: