From 6db957245f5a2caebc328225866d836fccfe0336 Mon Sep 17 00:00:00 2001 From: "me@jeffersonbledsoe.com" Date: Fri, 31 Jan 2025 02:00:17 +0000 Subject: [PATCH 1/8] Store forms in global store --- .../volto/formsupport/interfaces.py | 8 +++++++ .../profiles/default/registry/main.xml | 1 + .../restapi/deserializer/blocks.py | 23 +++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/src/collective/volto/formsupport/interfaces.py b/src/collective/volto/formsupport/interfaces.py index 16197df5..2f99771b 100644 --- a/src/collective/volto/formsupport/interfaces.py +++ b/src/collective/volto/formsupport/interfaces.py @@ -1,3 +1,5 @@ +from plone.restapi.controlpanels.interfaces import IControlpanel +from plone.schema import JSONField from zope.interface import Attribute from zope.interface import Interface from zope.interface.interfaces import IObjectEvent @@ -69,3 +71,9 @@ def data(): class IDataAdapter(Interface): def __call__(result, block_id=None): pass + + +class IGlobalFormStore(IControlpanel): + global_forms_config = JSONField( + title="Global forms", description="", required=True, default={} + ) diff --git a/src/collective/volto/formsupport/profiles/default/registry/main.xml b/src/collective/volto/formsupport/profiles/default/registry/main.xml index b6314fd3..938fc285 100644 --- a/src/collective/volto/formsupport/profiles/default/registry/main.xml +++ b/src/collective/volto/formsupport/profiles/default/registry/main.xml @@ -4,5 +4,6 @@ > + diff --git a/src/collective/volto/formsupport/restapi/deserializer/blocks.py b/src/collective/volto/formsupport/restapi/deserializer/blocks.py index 943ec940..95e76e5a 100644 --- a/src/collective/volto/formsupport/restapi/deserializer/blocks.py +++ b/src/collective/volto/formsupport/restapi/deserializer/blocks.py @@ -1,12 +1,34 @@ +from plone.api.portal import get_registry_record +from plone.api.portal import set_registry_record from plone.dexterity.interfaces import IDexterityContent from plone.restapi.bbb import IPloneSiteRoot from plone.restapi.interfaces import IBlockFieldDeserializationTransformer from Products.PortalTransforms.transforms.safe_html import SafeHTML +from uuid import uuid4 from zope.component import adapter from zope.interface import implementer from zope.publisher.interfaces.browser import IBrowserRequest +GLOBAL_FORM_REGISTRY_RECORD_ID = ( + "collective.volto.formsupport.interfaces.IGlobalFormStore.global_forms_config" +) + + +def update_global_forms(value): + global_form_id = value.get("global_form_id") + + if not global_form_id: + global_form_id = str(uuid4()) + + global_forms_record = get_registry_record(GLOBAL_FORM_REGISTRY_RECORD_ID) + global_forms_record[global_form_id] = value + set_registry_record(GLOBAL_FORM_REGISTRY_RECORD_ID, global_forms_record) + + value["global_form_id"] = global_form_id + return value + + class FormBlockDeserializerBase: """FormBlockDeserializerBase.""" @@ -25,6 +47,7 @@ def __call__(self, value): if value.get("send_message", ""): transform = SafeHTML() value["send_message"] = transform.scrub_html(value["send_message"]) + value = update_global_forms(value) return value From 50d1d13471d93423cb9ef98fa245bc8919dc270a Mon Sep 17 00:00:00 2001 From: "me@jeffersonbledsoe.com" Date: Fri, 31 Jan 2025 02:00:41 +0000 Subject: [PATCH 2/8] Use global forms if they're available for sending --- .../volto/formsupport/adapters/post.py | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/src/collective/volto/formsupport/adapters/post.py b/src/collective/volto/formsupport/adapters/post.py index c7717541..a2979a00 100644 --- a/src/collective/volto/formsupport/adapters/post.py +++ b/src/collective/volto/formsupport/adapters/post.py @@ -18,6 +18,11 @@ import os +GLOBAL_FORM_REGISTRY_RECORD_ID = ( + "collective.volto.formsupport.interfaces.IGlobalFormStore.global_forms_config" +) + + @implementer(IPostAdapter) @adapter(Interface, Interface) class PostAdapter: @@ -29,8 +34,12 @@ def __init__(self, context, request): self.request = request self.form_data = self.extract_data_from_request() self.block_id = self.form_data.get("block_id", "") + self.global_form_id = self.extract_data_from_request().get("global_form_id", "") if self.block_id: - self.block = self.get_block_data(block_id=self.block_id) + self.block = self.get_block_data( + block_id=self.block_id, + global_form_id=self.form_data.get("global_form_id"), + ) def __call__(self): """ @@ -50,7 +59,10 @@ def extract_data_from_request(self): fixed_fields = [] transforms = api.portal.get_tool(name="portal_transforms") - block = self.get_block_data(block_id=form_data.get("block_id", "")) + block = self.get_block_data( + block_id=form_data.get("block_id", ""), + global_form_id=form_data.get("global_form_id"), + ) block_fields = [x.get("field_id", "") for x in block.get("subblocks", [])] for form_field in form_data.get("data", []): @@ -68,12 +80,23 @@ def extract_data_from_request(self): return form_data - def get_block_data(self, block_id): + def get_block_data(self, block_id, global_form_id): blocks = get_blocks(self.context) if not blocks: - return {} + global_form_id = global_form_id + if global_form_id: + global_forms = api.portal.get_registry_record( + GLOBAL_FORM_REGISTRY_RECORD_ID + ) + if global_forms: + blocks = global_forms + else: + return {} + else: + return {} for id, block in blocks.items(): - if id != block_id: + # Prefer local forms it they're available, fall back to global form + if id != block_id and id != global_form_id: continue block_type = block.get("@type", "") if block_type != "form": From 7c17baa20c7a3c71778a74276f57b75017b5927c Mon Sep 17 00:00:00 2001 From: "me@jeffersonbledsoe.com" Date: Fri, 31 Jan 2025 02:01:03 +0000 Subject: [PATCH 3/8] Fix sending not working by re-using the logic from the adapter rather than re-computing everything --- .../formsupport/restapi/services/submit_form/post.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/collective/volto/formsupport/restapi/services/submit_form/post.py b/src/collective/volto/formsupport/restapi/services/submit_form/post.py index 5cef8c43..09d10ace 100644 --- a/src/collective/volto/formsupport/restapi/services/submit_form/post.py +++ b/src/collective/volto/formsupport/restapi/services/submit_form/post.py @@ -56,11 +56,10 @@ def __init__(self, context, request): self.form_data_adapter = getMultiAdapter( (self.context, self.request), IPostAdapter ) - self.form_data = self.get_form_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) + # We've already done all the work to get this data, let's re-use it. + self.form_data = self.form_data_adapter.form_data + self.block_id = self.form_data_adapter.block_id + self.block = self.form_data_adapter.block def reply(self): store_action = self.block.get("store", False) From de03c07f689add2ae411dda0b0f3000f44bcac2c Mon Sep 17 00:00:00 2001 From: "me@jeffersonbledsoe.com" Date: Fri, 31 Jan 2025 02:01:55 +0000 Subject: [PATCH 4/8] lint --- .../volto/formsupport/restapi/services/submit_form/post.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/collective/volto/formsupport/restapi/services/submit_form/post.py b/src/collective/volto/formsupport/restapi/services/submit_form/post.py index 09d10ace..a8d45079 100644 --- a/src/collective/volto/formsupport/restapi/services/submit_form/post.py +++ b/src/collective/volto/formsupport/restapi/services/submit_form/post.py @@ -56,7 +56,7 @@ def __init__(self, context, request): self.form_data_adapter = getMultiAdapter( (self.context, self.request), IPostAdapter ) - # We've already done all the work to get this data, let's re-use it. + # We've already done all the work to get this data, let's reuse it. self.form_data = self.form_data_adapter.form_data self.block_id = self.form_data_adapter.block_id self.block = self.form_data_adapter.block From 1053f5f90650cc670f17ce47d69e1ab9bfcbd2ab Mon Sep 17 00:00:00 2001 From: "me@jeffersonbledsoe.com" Date: Tue, 4 Feb 2025 20:49:54 +0000 Subject: [PATCH 5/8] Add upgrade step for installing registry entry --- .../volto/formsupport/profiles/default/metadata.xml | 2 +- src/collective/volto/formsupport/upgrades.zcml | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/collective/volto/formsupport/profiles/default/metadata.xml b/src/collective/volto/formsupport/profiles/default/metadata.xml index 4a9d2560..d640ec01 100644 --- a/src/collective/volto/formsupport/profiles/default/metadata.xml +++ b/src/collective/volto/formsupport/profiles/default/metadata.xml @@ -1,6 +1,6 @@ - 1301 + 1302 profile-collective.volto.otp:default diff --git a/src/collective/volto/formsupport/upgrades.zcml b/src/collective/volto/formsupport/upgrades.zcml index b5991637..4212ab77 100644 --- a/src/collective/volto/formsupport/upgrades.zcml +++ b/src/collective/volto/formsupport/upgrades.zcml @@ -40,4 +40,12 @@ handler=".upgrades.to_1301" /> + + From 758a85a1b5eb21e9e9e3487a75a1bda67ca39ebd Mon Sep 17 00:00:00 2001 From: "me@jeffersonbledsoe.com" Date: Tue, 4 Feb 2025 22:13:17 +0000 Subject: [PATCH 6/8] Fix some global forms not sending data --- src/collective/volto/formsupport/adapters/post.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/collective/volto/formsupport/adapters/post.py b/src/collective/volto/formsupport/adapters/post.py index a2979a00..396d1398 100644 --- a/src/collective/volto/formsupport/adapters/post.py +++ b/src/collective/volto/formsupport/adapters/post.py @@ -96,7 +96,7 @@ def get_block_data(self, block_id, global_form_id): return {} for id, block in blocks.items(): # Prefer local forms it they're available, fall back to global form - if id != block_id and id != global_form_id: + if id != block_id and id != global_form_id and block.get("global_form_id" != global_form_id): continue block_type = block.get("@type", "") if block_type != "form": From 351a43c1e46cab4e4e7271152f61b63ed441e368 Mon Sep 17 00:00:00 2001 From: "me@jeffersonbledsoe.com" Date: Wed, 5 Feb 2025 00:11:50 +0000 Subject: [PATCH 7/8] Fix typo in form check --- src/collective/volto/formsupport/adapters/post.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/collective/volto/formsupport/adapters/post.py b/src/collective/volto/formsupport/adapters/post.py index 396d1398..429dade0 100644 --- a/src/collective/volto/formsupport/adapters/post.py +++ b/src/collective/volto/formsupport/adapters/post.py @@ -96,7 +96,7 @@ def get_block_data(self, block_id, global_form_id): return {} for id, block in blocks.items(): # Prefer local forms it they're available, fall back to global form - if id != block_id and id != global_form_id and block.get("global_form_id" != global_form_id): + if id != block_id and id != global_form_id and block.get("global_form_id") != global_form_id: continue block_type = block.get("@type", "") if block_type != "form": From 29d389bdf4e4a30db3add58c6f12bf6d7233975c Mon Sep 17 00:00:00 2001 From: "me@jeffersonbledsoe.com" Date: Wed, 5 Feb 2025 02:40:20 +0000 Subject: [PATCH 8/8] Fix not getting global form if context ends up being a page --- .../volto/formsupport/adapters/post.py | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/collective/volto/formsupport/adapters/post.py b/src/collective/volto/formsupport/adapters/post.py index 429dade0..7681f38d 100644 --- a/src/collective/volto/formsupport/adapters/post.py +++ b/src/collective/volto/formsupport/adapters/post.py @@ -82,21 +82,22 @@ def extract_data_from_request(self): def get_block_data(self, block_id, global_form_id): blocks = get_blocks(self.context) + global_form_id = global_form_id + if global_form_id: + global_forms = api.portal.get_registry_record( + GLOBAL_FORM_REGISTRY_RECORD_ID + ) + if global_forms: + blocks = {**blocks, **global_forms} if not blocks: - global_form_id = global_form_id - if global_form_id: - global_forms = api.portal.get_registry_record( - GLOBAL_FORM_REGISTRY_RECORD_ID - ) - if global_forms: - blocks = global_forms - else: - return {} - else: - return {} + return {} for id, block in blocks.items(): # Prefer local forms it they're available, fall back to global form - if id != block_id and id != global_form_id and block.get("global_form_id") != global_form_id: + if ( + id != block_id + and id != global_form_id + and block.get("global_form_id") != global_form_id + ): continue block_type = block.get("@type", "") if block_type != "form":