diff --git a/build/blocks/rsvp-status/index.asset.php b/build/blocks/rsvp-status/index.asset.php
index bf374f8b7..9ca840789 100644
--- a/build/blocks/rsvp-status/index.asset.php
+++ b/build/blocks/rsvp-status/index.asset.php
@@ -1 +1 @@
- array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-i18n'), 'version' => '980c9982f495280b9cf9');
+ array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-i18n'), 'version' => '647c9e73475f1342072f');
diff --git a/build/blocks/rsvp-status/index.js b/build/blocks/rsvp-status/index.js
index b3356ac2c..30d30c971 100644
--- a/build/blocks/rsvp-status/index.js
+++ b/build/blocks/rsvp-status/index.js
@@ -1 +1 @@
-(()=>{"use strict";const e=window.wp.blocks,t=window.wp.blockEditor,s=JSON.parse('{"$schema":"https://schemas.wp.org/trunk/block.json","apiVersion":3,"name":"gatherpress/rsvp-status","version":"1.0.0","title":"RSVP Status","category":"gatherpress","icon":"megaphone","example":{},"description":"Displays the RSVP status of a user.","attributes":{"content":{"type":"string","default":""}},"supports":{"html":false,"color":{"text":true,"background":true},"spacing":{"padding":true,"margin":true},"typography":{"fontSize":true,"lineHeight":true}},"textdomain":"gatherpress","editorScript":"file:./index.js","style":"file:./style-index.css","viewScriptModule":"file:./view.js"}'),r=window.wp.i18n,i=window.ReactJSXRuntime;(0,e.registerBlockType)(s.name,{...s,edit:({attributes:e,setAttributes:s})=>{const{content:n}=e,o=(0,t.useBlockProps)();return(0,i.jsx)("div",{...o,children:(0,i.jsx)(t.RichText,{tagName:"div",value:n,onChange:e=>s({content:e}),placeholder:(0,r.__)("Write RSVP status…","gatherpress")})})},save:()=>{const e=t.useBlockProps.save();return(0,i.jsx)("div",{...e})}})})();
\ No newline at end of file
+(()=>{"use strict";const e=window.wp.blocks,t=window.wp.blockEditor,s=JSON.parse('{"$schema":"https://schemas.wp.org/trunk/block.json","apiVersion":3,"name":"gatherpress/rsvp-status","version":"1.0.0","title":"RSVP Status","category":"gatherpress","icon":"megaphone","example":{},"description":"Displays the RSVP status of a user.","attributes":{"content":{"type":"string","default":""}},"supports":{"html":false,"color":{"text":true,"background":true},"spacing":{"padding":true,"margin":true},"typography":{"fontSize":true,"lineHeight":true}},"textdomain":"gatherpress","editorScript":"file:./index.js","style":"file:./style-index.css","viewScriptModule":"file:./view.js"}'),r=window.wp.i18n,i=window.ReactJSXRuntime;(0,e.registerBlockType)(s,{edit:({attributes:e,setAttributes:s})=>{const{content:o}=e,n=(0,t.useBlockProps)();return(0,i.jsx)("div",{...n,children:(0,i.jsx)(t.RichText,{tagName:"div",value:o,onChange:e=>s({content:e}),placeholder:(0,r.__)("Write RSVP status…","gatherpress")})})},save:()=>{const e=t.useBlockProps.save();return(0,i.jsx)("div",{...e})}})})();
\ No newline at end of file
diff --git a/build/blocks/rsvp-v2/block.json b/build/blocks/rsvp-v2/block.json
index 69006e66f..90f635802 100644
--- a/build/blocks/rsvp-v2/block.json
+++ b/build/blocks/rsvp-v2/block.json
@@ -9,21 +9,9 @@
"example": {},
"description": "Enables members to easily confirm their attendance for an event.",
"attributes": {
- "noStatusLabel": {
+ "serializedInnerBlocks": {
"type": "string",
- "default": "RSVP"
- },
- "attendingLabel": {
- "type": "string",
- "default": "Edit RSVP"
- },
- "waitingListLabel": {
- "type": "string",
- "default": "Edit RSVP"
- },
- "notAttendingLabel": {
- "type": "string",
- "default": "Edit RSVP"
+ "default": "[]"
}
},
"supports": {
diff --git a/build/blocks/rsvp-v2/index.asset.php b/build/blocks/rsvp-v2/index.asset.php
index 2f6d7721b..8ebffea58 100644
--- a/build/blocks/rsvp-v2/index.asset.php
+++ b/build/blocks/rsvp-v2/index.asset.php
@@ -1 +1 @@
- array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n'), 'version' => 'e342b20ef97f7ae4fc71');
+ array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n'), 'version' => '9da56d3f11ea2a058a0c');
diff --git a/build/blocks/rsvp-v2/index.js b/build/blocks/rsvp-v2/index.js
index cd62a6f71..49dfae18f 100644
--- a/build/blocks/rsvp-v2/index.js
+++ b/build/blocks/rsvp-v2/index.js
@@ -1 +1 @@
-(()=>{"use strict";var e,t={5212:()=>{const e=window.wp.blocks,t=window.wp.blockEditor,s=window.wp.components,r=window.wp.i18n,n=window.wp.element,a=window.wp.data,o=[["core/buttons",{align:"center",layout:{type:"flex",justifyContent:"center"}},[["core/button",{text:(0,r.__)("RSVP","gatherpress"),tagName:"button",className:"gatherpress-rsvp--js-open-modal"}]]],["core/paragraph",{content:(0,r.__)("Attending","gatherpress")}],["gatherpress/modal",{className:"gatherpress-rsvp-modal"},[["gatherpress/modal-content",{className:"gatherpress-rsvp-modal-content"},[["core/heading",{level:3,content:(0,r.__)("Update your RSVP","gatherpress")}],["core/paragraph",{content:(0,r.__)("To set or change your attending status, simply click the Not Attending button below.","gatherpress")}],["core/buttons",{align:"left",layout:{type:"flex",justifyContent:"flex-start"}},[["core/button",{text:(0,r.__)("Attend","gatherpress"),tagName:"button",className:"gatherpress-rsvp--js-status-attending"}],["core/button",{text:(0,r.__)("Close","gatherpress"),tagName:"button",className:"gatherpress-rsvp--js-close-modal"}]]]]]]]],i=window.ReactJSXRuntime,l=JSON.parse('{"$schema":"https://schemas.wp.org/trunk/block.json","apiVersion":3,"name":"gatherpress/rsvp-v2","version":"2.0.0","title":"RSVP V2","category":"gatherpress","icon":"insert","example":{},"description":"Enables members to easily confirm their attendance for an event.","attributes":{"noStatusLabel":{"type":"string","default":"RSVP"},"attendingLabel":{"type":"string","default":"Edit RSVP"},"waitingListLabel":{"type":"string","default":"Edit RSVP"},"notAttendingLabel":{"type":"string","default":"Edit RSVP"}},"supports":{"align":["wide","full"],"layout":{"allowSwitching":false,"allowInheriting":false,"default":{"justifyContent":"center","type":"flex"}},"html":false,"interactivity":true},"textdomain":"gatherpress","editorScript":"file:./index.js","style":"file:./style-index.css","viewScriptModule":"file:./view.js"}');(0,e.registerBlockType)(l,{edit:({setAttributes:e})=>{const l=(0,t.useBlockProps)(),c=(0,a.useDispatch)(),{setStatus:p}=c("gatherpress/rsvp-status"),{status:g}=(0,a.useSelect)((e=>({status:e("gatherpress/rsvp-status").getStatus()})),[]),u=(0,a.useSelect)((e=>e("core/block-editor").getSelectedBlock()?.clientId),[]),d=(0,a.useSelect)((e=>u?e("core/block-editor").getBlocks(u):[]),[u]),h=e=>{for(const t of e){if("core/button"===t.name)return t;if(t.innerBlocks.length>0){const e=h(t.innerBlocks);if(e)return e}}return null},f=h(d);return(0,n.useEffect)((()=>{if(f){const t=f.attributes.text;switch(g){case"no_status":e({noStatusLabel:t});break;case"attending":e({attendingLabel:t});break;case"waiting_list":e({waitingListLabel:t});break;case"not_attending":e({notAttendingLabel:t})}}}),[f,e,g]),(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.InspectorControls,{children:(0,i.jsx)(s.PanelBody,{children:(0,i.jsx)(s.SelectControl,{label:(0,r.__)("RSVP Status","gatherpress"),value:g,options:[{label:(0,r.__)("No Status (User has not responded)","gatherpress"),value:"no_status"},{label:(0,r.__)("Attending (User is confirmed)","gatherpress"),value:"attending"},{label:(0,r.__)("Waiting List (Pending confirmation)","gatherpress"),value:"waiting_list"},{label:(0,r.__)("Not Attending (User declined)","gatherpress"),value:"not_attending"}],onChange:e=>p(e)})})}),(0,i.jsx)("div",{...l,children:(0,i.jsx)(t.InnerBlocks,{template:o})})]})},save:()=>(0,i.jsx)("div",{...t.useBlockProps.save(),children:(0,i.jsx)(t.InnerBlocks.Content,{})})})}},s={};function r(e){var n=s[e];if(void 0!==n)return n.exports;var a=s[e]={exports:{}};return t[e](a,a.exports,r),a.exports}r.m=t,e=[],r.O=(t,s,n,a)=>{if(!s){var o=1/0;for(p=0;p=a)&&Object.keys(r.O).every((e=>r.O[e](s[l])))?s.splice(l--,1):(i=!1,a0&&e[p-1][2]>a;p--)e[p]=e[p-1];e[p]=[s,n,a]},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={345:0,525:0};r.O.j=t=>0===e[t];var t=(t,s)=>{var n,a,o=s[0],i=s[1],l=s[2],c=0;if(o.some((t=>0!==e[t]))){for(n in i)r.o(i,n)&&(r.m[n]=i[n]);if(l)var p=l(r)}for(t&&t(s);cr(5212)));n=r.O(n)})();
\ No newline at end of file
+(()=>{"use strict";var e,t={5212:()=>{const e=window.wp.blocks,t=window.wp.blockEditor,s=window.wp.components,r=window.wp.i18n,n=window.wp.element,a=window.wp.data,o=[["core/buttons",{align:"center",layout:{type:"flex",justifyContent:"center"}},[["core/button",{text:(0,r.__)("RSVP","gatherpress"),tagName:"button",className:"gatherpress-rsvp--js-open-modal"}]]],["core/paragraph",{content:(0,r.__)("Attending","gatherpress")}],["gatherpress/modal",{className:"gatherpress-rsvp-modal"},[["gatherpress/modal-content",{className:"gatherpress-rsvp-modal-content"},[["core/heading",{level:3,content:(0,r.__)("Update your RSVP","gatherpress")}],["core/paragraph",{content:(0,r.__)("To set or change your attending status, simply click the Not Attending button below.","gatherpress")}],["core/buttons",{align:"left",layout:{type:"flex",justifyContent:"flex-start"}},[["core/button",{text:(0,r.__)("Attend","gatherpress"),tagName:"button",className:"gatherpress-rsvp--js-status-attending"}],["core/button",{text:(0,r.__)("Close","gatherpress"),tagName:"button",className:"gatherpress-rsvp--js-close-modal"}]]]]]]]],l=window.ReactJSXRuntime,i=JSON.parse('{"$schema":"https://schemas.wp.org/trunk/block.json","apiVersion":3,"name":"gatherpress/rsvp-v2","version":"2.0.0","title":"RSVP V2","category":"gatherpress","icon":"insert","example":{},"description":"Enables members to easily confirm their attendance for an event.","attributes":{"serializedInnerBlocks":{"type":"string","default":"[]"}},"supports":{"align":["wide","full"],"layout":{"allowSwitching":false,"allowInheriting":false,"default":{"justifyContent":"center","type":"flex"}},"html":false,"interactivity":true},"textdomain":"gatherpress","editorScript":"file:./index.js","style":"file:./style-index.css","viewScriptModule":"file:./view.js"}');(0,e.registerBlockType)(i,{edit:({attributes:e,setAttributes:i,clientId:c})=>{const{serializedInnerBlocks:p="{}"}=e,[d,g]=(0,n.useState)("no_status"),u=(0,t.useBlockProps)(),{replaceInnerBlocks:h}=(0,a.useDispatch)(t.store),f=(0,a.useSelect)((e=>e(t.store).getBlocks(c)),[c]),v=(0,n.useCallback)((e=>{const t=JSON.parse(p||"{}")[e];t&&t.length>0&&h(c,t)}),[c,h,p]);return(0,n.useEffect)((()=>{v(d)}),[d,v]),(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(t.InspectorControls,{children:(0,l.jsx)(s.PanelBody,{children:(0,l.jsx)(s.SelectControl,{label:(0,r.__)("RSVP Status","gatherpress"),value:d,options:[{label:(0,r.__)("No Status (User has not responded)","gatherpress"),value:"no_status"},{label:(0,r.__)("Attending (User is confirmed)","gatherpress"),value:"attending"},{label:(0,r.__)("Waiting List (Pending confirmation)","gatherpress"),value:"waiting_list"},{label:(0,r.__)("Not Attending (User declined)","gatherpress"),value:"not_attending"}],onChange:e=>{((e,t)=>{const s={...JSON.parse(p||"{}"),[e]:t};i({serializedInnerBlocks:JSON.stringify(s)})})(d,f),g(e),v(e)}})})}),(0,l.jsx)("div",{...u,children:(0,l.jsx)(t.InnerBlocks,{template:o})})]})},save:({attributes:e})=>{const s=t.useBlockProps.save(),{serializedInnerBlocks:r}=e;return(0,l.jsx)("div",{...s,"data-serialized-inner-blocks":r,children:(0,l.jsx)(t.InnerBlocks.Content,{})})}})}},s={};function r(e){var n=s[e];if(void 0!==n)return n.exports;var a=s[e]={exports:{}};return t[e](a,a.exports,r),a.exports}r.m=t,e=[],r.O=(t,s,n,a)=>{if(!s){var o=1/0;for(p=0;p=a)&&Object.keys(r.O).every((e=>r.O[e](s[i])))?s.splice(i--,1):(l=!1,a0&&e[p-1][2]>a;p--)e[p]=e[p-1];e[p]=[s,n,a]},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={345:0,525:0};r.O.j=t=>0===e[t];var t=(t,s)=>{var n,a,o=s[0],l=s[1],i=s[2],c=0;if(o.some((t=>0!==e[t]))){for(n in l)r.o(l,n)&&(r.m[n]=l[n]);if(i)var p=i(r)}for(t&&t(s);cr(5212)));n=r.O(n)})();
\ No newline at end of file
diff --git a/includes/core/classes/class-assets.php b/includes/core/classes/class-assets.php
index a1b05af89..268942105 100644
--- a/includes/core/classes/class-assets.php
+++ b/includes/core/classes/class-assets.php
@@ -396,7 +396,9 @@ protected function unregister_blocks(): array {
'gatherpress/event-date',
'gatherpress/online-event',
'gatherpress/rsvp',
+ 'gatherpress/rsvp-v2',
'gatherpress/rsvp-response',
+ 'gatherpress/rsvp-response-v2',
'gatherpress/rsvp-status',
);
break;
diff --git a/src/blocks/rsvp-status/index.js b/src/blocks/rsvp-status/index.js
index 5f83ed717..a816e5a3a 100644
--- a/src/blocks/rsvp-status/index.js
+++ b/src/blocks/rsvp-status/index.js
@@ -10,8 +10,7 @@ import { useBlockProps } from '@wordpress/block-editor';
import metadata from './block.json';
import Edit from './edit';
-registerBlockType(metadata.name, {
- ...metadata,
+registerBlockType(metadata, {
edit: Edit,
save: () => {
// Use blockProps to ensure proper WordPress class handling
diff --git a/src/blocks/rsvp-v2/block.json b/src/blocks/rsvp-v2/block.json
index cdabe8de5..1fae058ff 100644
--- a/src/blocks/rsvp-v2/block.json
+++ b/src/blocks/rsvp-v2/block.json
@@ -9,21 +9,9 @@
"example": {},
"description": "Enables members to easily confirm their attendance for an event.",
"attributes": {
- "noStatusLabel": {
+ "serializedInnerBlocks": {
"type": "string",
- "default": "RSVP"
- },
- "attendingLabel": {
- "type": "string",
- "default": "Edit RSVP"
- },
- "waitingListLabel": {
- "type": "string",
- "default": "Edit RSVP"
- },
- "notAttendingLabel": {
- "type": "string",
- "default": "Edit RSVP"
+ "default": "[]"
}
},
"supports": {
diff --git a/src/blocks/rsvp-v2/edit.js b/src/blocks/rsvp-v2/edit.js
index 4a62bb1fe..d79be1009 100644
--- a/src/blocks/rsvp-v2/edit.js
+++ b/src/blocks/rsvp-v2/edit.js
@@ -5,95 +5,81 @@ import {
InnerBlocks,
InspectorControls,
useBlockProps,
+ store as blockEditorStore,
} from '@wordpress/block-editor';
import { PanelBody, SelectControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
-import { useEffect } from '@wordpress/element';
+import { useEffect, useState, useCallback } from '@wordpress/element';
+import { useDispatch, useSelect } from '@wordpress/data';
/**
* Internal dependencies.
*/
-import { useDispatch, useSelect } from '@wordpress/data';
import TEMPLATE from './template';
/**
* Edit component for the GatherPress RSVP block.
*
- * This component defines the edit interface for the GatherPress RSVP block in the block editor.
- * It dynamically manages and updates block attributes based on user input and the status of
- * nested blocks. The component includes:
- * - `InspectorControls` for managing RSVP statuses via a dropdown.
- * - Logic to locate and update text labels of nested `core/button` blocks based on the current RSVP status.
- * - `InnerBlocks` to allow nested content within the RSVP block.
- *
- * The `useEffect` hook ensures that changes to the RSVP status or inner blocks dynamically update
- * the block attributes, ensuring consistent behavior and text labels.
- *
* @param {Object} props The props passed to the component.
+ * @param {Object} props.attributes Block attributes.
* @param {Function} props.setAttributes Function to update block attributes.
+ * @param {string} props.clientId The unique ID of the block instance.
*
* @since 1.0.0
*
* @return {JSX.Element} The rendered edit interface for the RSVP block.
*/
-const Edit = ({ setAttributes }) => {
+const Edit = ({ attributes, setAttributes, clientId }) => {
+ const { serializedInnerBlocks = '{}' } = attributes;
+ const [status, setStatus] = useState('no_status');
const blockProps = useBlockProps();
- const dispatch = useDispatch();
- const { setStatus } = dispatch('gatherpress/rsvp-status');
- const { status } = useSelect(
- (select) => ({
- status: select('gatherpress/rsvp-status').getStatus(),
- }),
- []
- );
-
- const clientId = useSelect(
- (select) => select('core/block-editor').getSelectedBlock()?.clientId,
- []
- );
+ const { replaceInnerBlocks } = useDispatch(blockEditorStore);
+ // Get the current inner blocks
const innerBlocks = useSelect(
- (select) =>
- clientId ? select('core/block-editor').getBlocks(clientId) : [],
+ (select) => select(blockEditorStore).getBlocks(clientId),
[clientId]
);
- const locateButtonBlock = (blocks) => {
- for (const block of blocks) {
- if (block.name === 'core/button') {
- return block;
- }
- if (block.innerBlocks.length > 0) {
- const found = locateButtonBlock(block.innerBlocks);
- if (found) {
- return found;
- }
+ // Save the provided inner blocks to the serializedInnerBlocks attribute
+ const saveInnerBlocks = (state, blocks) => {
+ const currentSerializedBlocks = JSON.parse(
+ serializedInnerBlocks || '{}'
+ );
+ const updatedBlocks = {
+ ...currentSerializedBlocks,
+ [state]: blocks,
+ };
+
+ setAttributes({
+ serializedInnerBlocks: JSON.stringify(updatedBlocks),
+ });
+ };
+
+ // Load inner blocks for a given state
+ const loadInnerBlocksForState = useCallback(
+ (state) => {
+ const savedBlocks = JSON.parse(serializedInnerBlocks || '{}')[
+ state
+ ];
+ if (savedBlocks && savedBlocks.length > 0) {
+ replaceInnerBlocks(clientId, savedBlocks);
}
- }
- return null;
+ },
+ [clientId, replaceInnerBlocks, serializedInnerBlocks]
+ );
+
+ // Handle status change: save current inner blocks and load new ones
+ const handleStatusChange = (newStatus) => {
+ saveInnerBlocks(status, innerBlocks); // Save current inner blocks before switching state
+ setStatus(newStatus); // Update the state
+ loadInnerBlocksForState(newStatus); // Load blocks for the new state
};
- const buttonBlock = locateButtonBlock(innerBlocks);
+ // On initial render, ensure correct blocks are loaded
useEffect(() => {
- if (buttonBlock) {
- const buttonText = buttonBlock.attributes.text;
-
- switch (status) {
- case 'no_status':
- setAttributes({ noStatusLabel: buttonText });
- break;
- case 'attending':
- setAttributes({ attendingLabel: buttonText });
- break;
- case 'waiting_list':
- setAttributes({ waitingListLabel: buttonText });
- break;
- case 'not_attending':
- setAttributes({ notAttendingLabel: buttonText });
- break;
- }
- }
- }, [buttonBlock, setAttributes, status]);
+ loadInnerBlocksForState(status);
+ }, [status, loadInnerBlocksForState]);
return (
<>
@@ -132,7 +118,7 @@ const Edit = ({ setAttributes }) => {
value: 'not_attending',
},
]}
- onChange={(newStatus) => setStatus(newStatus)}
+ onChange={handleStatusChange}
/>
@@ -142,4 +128,5 @@ const Edit = ({ setAttributes }) => {
>
);
};
+
export default Edit;
diff --git a/src/blocks/rsvp-v2/index.js b/src/blocks/rsvp-v2/index.js
index ca4d9c5b3..f958a7cf6 100644
--- a/src/blocks/rsvp-v2/index.js
+++ b/src/blocks/rsvp-v2/index.js
@@ -22,9 +22,15 @@ import './style.scss';
*/
registerBlockType(metadata, {
edit,
- save: () => {
+ save: ({ attributes }) => {
+ const blockProps = useBlockProps.save();
+ const { serializedInnerBlocks } = attributes;
+
return (
-