Skip to content

Commit 8c914a5

Browse files
committed
Add initial form variations(templates).
1 parent b7f7e3b commit 8c914a5

File tree

6 files changed

+257
-7
lines changed

6 files changed

+257
-7
lines changed

includes/blocks/class-mailchimp-list-subscribe-form-blocks.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ public function register_blocks() {
7878
'double_opt_in' => (bool) get_option( 'mc_double_optin', true ),
7979
'merge_fields_visibility' => $merge_fields_visibility,
8080
'interest_groups_visibility' => $interest_groups_visibility,
81+
'merge_fields' => $merge_fields,
82+
'interest_groups' => $interest_groups,
8183
);
8284
$data = 'window.mailchimp_sf_block_data = ' . wp_json_encode( $data );
8385
wp_add_inline_script( 'mailchimp-mailchimp-editor-script', $data, 'before' );

includes/blocks/mailchimp/edit.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import apiFetch from '@wordpress/api-fetch';
1818
import { useDispatch, useSelect } from '@wordpress/data';
1919
import { createBlock } from '@wordpress/blocks';
2020
import Icon from './icon';
21+
import { VariationPicker } from './variation-picker';
2122

2223
const SelectListPlaceholder = () => {
2324
return (
@@ -161,19 +162,14 @@ export const BlockEdit = (props) => {
161162
tag: field.tag,
162163
label: field.name,
163164
type: field.type,
164-
visible:
165-
(field.required ||
166-
merge_fields_visibility?.[field.tag] === 'on') &&
167-
field.public,
165+
visible: field.required, // Keep newly added fields hidden by default, except for required fields.
168166
}),
169167
);
170168
const newGroupBlocks = newFormGroups.map((group) =>
171169
createBlock('mailchimp/mailchimp-audience-group', {
172170
id: group.id,
173171
label: group.title,
174-
visible:
175-
interest_groups_visibility?.[group.id] === 'on' &&
176-
group.type !== 'hidden',
172+
visible: false, // Keep newly added groups hidden by default.
177173
}),
178174
);
179175

@@ -279,6 +275,11 @@ export const BlockEdit = (props) => {
279275
);
280276
}
281277

278+
// Display the variation picker if there are no innerBlocks.
279+
if (innerBlocks.length === 0) {
280+
return <VariationPicker {...props} />;
281+
}
282+
282283
// Create a template for innerBlocks based on list data and visibility settings.
283284
const templateFields =
284285
listData?.merge_fields?.map((field) => [

includes/blocks/mailchimp/editor.css

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,38 @@ select.mc_select {
151151
width:100%;
152152
margin-top: 1em;
153153
}
154+
155+
.wp-block-mailchimp-mailchimp .block-editor-block-variation-picker .components-placeholder__fieldset .block-editor-block-variation-picker__variations {
156+
gap: 20px 0;
157+
justify-content: center;
158+
margin: 16px auto;
159+
max-width: 560px;
160+
}
161+
162+
.wp-block-mailchimp-mailchimp .block-editor-block-variation-picker .components-placeholder__fieldset .block-editor-block-variation-picker__variations>li {
163+
flex: 0;
164+
margin: 0;
165+
max-width: none;
166+
padding: 0 4px;
167+
text-align: center;
168+
width: unset
169+
}
170+
171+
.wp-block-mailchimp-mailchimp .block-editor-block-variation-picker .components-placeholder__fieldset .block-editor-block-variation-picker__variations .block-editor-block-variation-picker__variation {
172+
margin-left: 4px;
173+
margin-right: 4px;
174+
padding: 22px
175+
}
176+
177+
.wp-block-mailchimp-mailchimp .block-editor-block-variation-picker .components-placeholder__fieldset .block-editor-block-variation-picker__variations .block-editor-block-variation-picker__variation span.dashicon::before {
178+
font-size: 24px;
179+
}
180+
181+
.wp-block-mailchimp-mailchimp .block-editor-block-variation-picker .components-placeholder__fieldset .block-editor-block-variation-picker__variations .block-editor-block-variation-picker__variation svg {
182+
height: auto;
183+
width: 24px
184+
}
185+
186+
.wp-block-mailchimp-mailchimp .block-editor-block-variation-picker .components-placeholder__fieldset .block-editor-block-variation-picker__variations .block-editor-block-variation-picker__variation-label {
187+
margin-right: 0
188+
}

includes/blocks/mailchimp/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ import { InnerBlocks } from '@wordpress/block-editor';
44
import { BlockEdit } from './edit';
55
import metadata from './block.json';
66
import Icon from './icon';
7+
import { variations } from './variations';
78

89
registerBlockType(metadata, {
910
icon: Icon,
11+
variations,
1012
transforms: {
1113
from: [
1214
{
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import {
2+
__experimentalBlockVariationPicker as BlockVariationPicker, // eslint-disable-line @wordpress/no-unsafe-wp-apis
3+
store as blockEditorStore,
4+
useBlockProps,
5+
} from '@wordpress/block-editor';
6+
import { createBlocksFromInnerBlocksTemplate, store as blocksStore } from '@wordpress/blocks';
7+
import { useDispatch, useSelect } from '@wordpress/data';
8+
import { __, _n, sprintf } from '@wordpress/i18n';
9+
import { formFields, formFieldTitles } from './variations';
10+
11+
const getMissingFields = (variation) => {
12+
const variationName = variation.name;
13+
const variationFields = formFields[variationName] || [];
14+
const formFieldsTags = variation.innerBlocks
15+
.filter((block) => block[0] === 'mailchimp/mailchimp-form-field')
16+
.map((block) => {
17+
const [, attributes] = block;
18+
const { tag } = attributes;
19+
return tag;
20+
});
21+
22+
return variationFields.filter((field) => !formFieldsTags.includes(field));
23+
};
24+
25+
export const VariationPicker = ({ name, setAttributes, clientId }) => {
26+
const { blockType, defaultVariation, variations } = useSelect(
27+
(select) => {
28+
const { getBlockVariations, getBlockType, getDefaultBlockVariation } =
29+
select(blocksStore);
30+
31+
return {
32+
blockType: getBlockType(name),
33+
defaultVariation: getDefaultBlockVariation(name, 'block'),
34+
variations: getBlockVariations(name, 'block'),
35+
};
36+
},
37+
[name],
38+
);
39+
const { replaceInnerBlocks } = useDispatch(blockEditorStore);
40+
const { createNotice } = useDispatch('core/notices');
41+
const blockProps = useBlockProps();
42+
43+
return (
44+
<div {...blockProps}>
45+
<BlockVariationPicker
46+
icon={blockType?.icon?.src}
47+
label={blockType?.title}
48+
instructions={__('Start by selecting one of these templates', 'mailchimp')}
49+
variations={variations}
50+
onSelect={(nextVariation = defaultVariation) => {
51+
if (nextVariation.attributes) {
52+
setAttributes(nextVariation.attributes);
53+
}
54+
55+
if (nextVariation.innerBlocks) {
56+
const missingFields = getMissingFields(nextVariation);
57+
58+
replaceInnerBlocks(
59+
clientId,
60+
createBlocksFromInnerBlocksTemplate(nextVariation.innerBlocks),
61+
);
62+
63+
// Add a notice if there are missing fields from the selected form template.
64+
if (missingFields.length > 0) {
65+
createNotice(
66+
'warning',
67+
sprintf(
68+
_n(
69+
"%s form field is missing from the selected form template. Please create this field in the Mailchimp dashboard, then click the 'Fetch list settings' button on the plugin settings page to update the list and include the missing field.",
70+
"Some form fields are missing from the selected form template: %s. Please create these fields in the Mailchimp dashboard, then click the 'Fetch list settings' button on the plugin settings page to update the list and include the missing fields.",
71+
missingFields.length,
72+
'mailchimp',
73+
),
74+
missingFields
75+
.map(
76+
(field) =>
77+
`${formFieldTitles[field] || field} (${field})`,
78+
)
79+
.join(', '),
80+
),
81+
{
82+
id: 'mailchimp-form-template-field-notice',
83+
isDismissible: true,
84+
},
85+
);
86+
}
87+
}
88+
}}
89+
allowSkip
90+
/>
91+
</div>
92+
);
93+
};
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/**
2+
* WordPress dependencies
3+
*/
4+
import { __ } from '@wordpress/i18n';
5+
6+
const { mailchimp_sf_block_data } = window;
7+
const {
8+
merge_fields = [],
9+
interest_groups = [],
10+
merge_fields_visibility = {},
11+
} = mailchimp_sf_block_data;
12+
13+
/** @typedef {import('@wordpress/blocks').WPBlockVariation} WPBlockVariation */
14+
15+
const groupInnerBlocks = interest_groups.map((group) => [
16+
'mailchimp/mailchimp-audience-group',
17+
{
18+
id: group.id,
19+
label: group.title,
20+
visible: false,
21+
},
22+
]);
23+
24+
const prepareInnerBlocks = (merge_fields = [], fields = []) => {
25+
return [...merge_fields]
26+
.sort((a, b) => {
27+
const aIndex = fields.indexOf(a.tag);
28+
const bIndex = fields.indexOf(b.tag);
29+
return (aIndex === -1 ? Infinity : aIndex) - (bIndex === -1 ? Infinity : bIndex);
30+
})
31+
.map((field) => {
32+
let visible =
33+
field.required ||
34+
fields.includes(field.tag) ||
35+
fields.includes(field.type?.toUpperCase());
36+
if (fields.length === 0) {
37+
visible = field.required || merge_fields_visibility?.[field.tag] === 'on';
38+
}
39+
return [
40+
'mailchimp/mailchimp-form-field',
41+
{
42+
tag: field.tag,
43+
label: field.name,
44+
type: field.type,
45+
visible,
46+
},
47+
];
48+
});
49+
};
50+
51+
export const formFields = {
52+
'email-only-form': ['EMAIL'],
53+
'name-and-email-form': ['FNAME', 'LNAME', 'EMAIL'],
54+
'contact-form': ['FNAME', 'LNAME', 'EMAIL', 'PHONE', 'ADDRESS'],
55+
default: [],
56+
};
57+
58+
export const formFieldTitles = {
59+
FNAME: __('First Name', 'mailchimp'),
60+
LNAME: __('Last Name', 'mailchimp'),
61+
EMAIL: __('Email', 'mailchimp'),
62+
PHONE: __('Phone', 'mailchimp'),
63+
ADDRESS: __('Address', 'mailchimp'),
64+
};
65+
66+
/**
67+
* Template option choices for predefined columns layouts.
68+
*
69+
* @type {WPBlockVariation[]}
70+
*/
71+
export const variations = [
72+
{
73+
name: 'email-only-form',
74+
title: __('Quick Signup (Email Only)', 'mailchimp'),
75+
description: __('A quick signup form with only an email field.', 'mailchimp'),
76+
icon: 'email',
77+
innerBlocks: [
78+
...prepareInnerBlocks(merge_fields, formFields['email-only-form']),
79+
...groupInnerBlocks,
80+
],
81+
scope: ['block'],
82+
},
83+
{
84+
name: 'name-and-email-form',
85+
title: __('Personal Signup (Name and Email)', 'mailchimp'),
86+
description: __('A personal signup form with only a name and email fields', 'mailchimp'),
87+
icon: 'admin-users',
88+
innerBlocks: [
89+
...prepareInnerBlocks(merge_fields, formFields['name-and-email-form']),
90+
...groupInnerBlocks,
91+
],
92+
scope: ['block'],
93+
},
94+
{
95+
name: 'contact-form',
96+
title: __('Contact Form (Contact Details)', 'mailchimp'),
97+
description: __(
98+
'A full contact details form with name, email, phone and address fields',
99+
'mailchimp',
100+
),
101+
icon: 'id',
102+
innerBlocks: [
103+
...prepareInnerBlocks(merge_fields, formFields['contact-form']),
104+
...groupInnerBlocks,
105+
],
106+
scope: ['block'],
107+
},
108+
{
109+
name: 'default',
110+
title: __('Default Form (All Fields)', 'mailchimp'),
111+
description: __('A default form, Fields based on settings.', 'mailchimp'),
112+
icon: 'admin-settings',
113+
isDefault: true,
114+
innerBlocks: [...prepareInnerBlocks(merge_fields, formFields.default), ...groupInnerBlocks],
115+
scope: ['block'],
116+
},
117+
];

0 commit comments

Comments
 (0)