Add checkbox custom field

[MAILPOET-2453]
This commit is contained in:
Pavel Dohnal
2019-12-18 09:34:33 +01:00
committed by Rostislav Wolný
parent 712ea07d17
commit 81c75fafc2
8 changed files with 374 additions and 17 deletions

View File

@@ -14,6 +14,7 @@ import * as html from './html/html.jsx';
import * as customText from './custom_text/custom_text.jsx';
import * as customTextArea from './custom_textarea/custom_textarea.jsx';
import * as customRadio from './custom_radio/custom_radio.jsx';
import * as customCheckbox from './custom_checkbox/custom_checkbox.jsx';
const registerCustomFieldBlock = (customField) => {
const namesMap = {
@@ -29,6 +30,10 @@ const registerCustomFieldBlock = (customField) => {
name: customRadio.name,
settings: customRadio.getSettings(customField),
},
checkbox: {
name: customCheckbox.name,
settings: customCheckbox.getSettings(customField),
},
};
if (!namesMap[customField.type]) return;

View File

@@ -0,0 +1,44 @@
import Icon from '../custom_text/icon.jsx';
import Edit from './edit.jsx';
export const name = 'mailpoet-form/custom-checkbox';
export function getSettings(customField) {
return {
title: customField.name,
description: '',
icon: Icon,
category: 'custom-fields',
attributes: {
label: {
type: 'string',
default: customField.name,
},
hideLabel: {
type: 'boolean',
default: false,
},
values: {
type: 'array',
default: [],
},
mandatory: {
type: 'boolean',
default: false,
},
customFieldId: {
type: 'string',
default: customField.id,
},
},
supports: {
html: false,
customClassName: false,
multiple: false,
},
edit: Edit,
save() {
return null;
},
};
}

View File

@@ -0,0 +1,50 @@
import React, { useState } from 'react';
import {
Button,
ToggleControl,
} from '@wordpress/components';
import PropTypes from 'prop-types';
import MailPoet from 'mailpoet';
const CustomFieldSettings = ({
mandatory,
isSaving,
onSave,
}) => {
const [localMandatory, setLocalMandatory] = useState(mandatory);
return (
<div className="custom-field-settings">
<Button
isPrimary
isDefault
onClick={() => onSave({
mandatory: localMandatory,
})}
isBusy={isSaving}
disabled={isSaving}
className="button-on-top"
>
{MailPoet.I18n.t('customFieldSaveCTA')}
</Button>
<ToggleControl
label={MailPoet.I18n.t('blockMandatory')}
checked={localMandatory}
onChange={setLocalMandatory}
/>
</div>
);
};
CustomFieldSettings.propTypes = {
mandatory: PropTypes.bool,
onSave: PropTypes.func.isRequired,
isSaving: PropTypes.bool,
};
CustomFieldSettings.defaultProps = {
mandatory: false,
isSaving: false,
};
export default CustomFieldSettings;

View File

@@ -0,0 +1,142 @@
import React from 'react';
import {
Panel,
PanelBody,
TextControl,
ToggleControl,
} from '@wordpress/components';
import { InspectorControls } from '@wordpress/block-editor';
import PropTypes from 'prop-types';
import MailPoet from 'mailpoet';
import { useDispatch, useSelect } from '@wordpress/data';
import CustomFieldSettings from './custom_field_settings.jsx';
const CustomCheckboxEdit = ({ attributes, setAttributes }) => {
const isSaving = useSelect(
(sel) => sel('mailpoet-form-editor').getIsCustomFieldSaving(),
[]
);
const { saveCustomField } = useDispatch('mailpoet-form-editor');
const getCheckboxLabel = () => {
if (Array.isArray(attributes.values)) {
const value = attributes.values[0];
if (value) {
return value.name;
}
}
return '';
};
const isChecked = () => {
let checked = false;
if (Array.isArray(attributes.values)) {
const value = attributes.values[0];
if (value && value.isChecked) {
checked = true;
}
}
return checked;
};
const inspectorControls = (
<InspectorControls>
<Panel>
<PanelBody title={MailPoet.I18n.t('customFieldSettings')} initialOpen>
<CustomFieldSettings
mandatory={attributes.mandatory}
isSaving={isSaving}
onSave={(params) => saveCustomField({
customFieldId: attributes.customFieldId,
data: {
params: {
required: params.mandatory ? '1' : undefined,
},
},
onFinish: () => setAttributes({
mandatory: params.mandatory,
}),
})}
/>
</PanelBody>
</Panel>
<Panel>
<PanelBody title={MailPoet.I18n.t('formSettings')} initialOpen>
<TextControl
label={MailPoet.I18n.t('label')}
value={attributes.label}
data-automation-id="settings_custom_text_label_input"
onChange={(label) => (setAttributes({ label }))}
/>
<ToggleControl
label={MailPoet.I18n.t('displayLabel')}
checked={!attributes.hideLabel}
onChange={(hideLabel) => (setAttributes({ hideLabel: !hideLabel }))}
/>
<input
type="checkbox"
checked={isChecked()}
onChange={(event) => setAttributes({
values: [{
name: getCheckboxLabel(),
checked: !!event.target.checked,
}],
})}
/>
<input
value={getCheckboxLabel()}
onChange={(event) => setAttributes({
values: [{
name: event.target.value,
checked: isChecked(),
}],
})}
/>
</PanelBody>
</Panel>
</InspectorControls>
);
const getLabel = () => {
if (attributes.hideLabel) return null;
return attributes.label;
};
let checkboxLabel = getCheckboxLabel();
if (attributes.mandatory) {
checkboxLabel += ' *';
}
return (
<>
{inspectorControls}
<p>{getLabel()}</p>
<div>
<label>
<input
type="checkbox"
disabled
checked={isChecked()}
/>
{checkboxLabel}
</label>
</div>
</>
);
};
CustomCheckboxEdit.propTypes = {
attributes: PropTypes.shape({
label: PropTypes.string.isRequired,
mandatory: PropTypes.bool.isRequired,
hideLabel: PropTypes.bool,
values: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string.isRequired,
isChecked: PropTypes.bool,
})),
}).isRequired,
setAttributes: PropTypes.func.isRequired,
};
export default CustomCheckboxEdit;

View File

@@ -1,3 +1,4 @@
import { has } from 'lodash';
const mapCustomField = (block, customFields, mappedCommonProperties) => {
const customField = customFields.find((cf) => cf.id === block.attributes.customFieldId);
@@ -16,16 +17,25 @@ const mapCustomField = (block, customFields, mappedCommonProperties) => {
if (block.name.startsWith('mailpoet-form/custom-radio')) {
mapped.type = 'radio';
}
if (Object.prototype.hasOwnProperty.call(block.attributes, 'validate')) {
if (block.name.startsWith('mailpoet-form/custom-checkbox')) {
mapped.type = 'checkbox';
}
if (has(block.attributes, 'validate')) {
mapped.params.validate = block.attributes.validate;
}
if (Object.prototype.hasOwnProperty.call(block.attributes, 'hideLabel') && block.attributes.hideLabel) {
if (has(block.attributes, 'hideLabel') && block.attributes.hideLabel) {
mapped.params.hide_label = '1';
}
if (Object.prototype.hasOwnProperty.call(block.attributes, 'values')) {
mapped.params.values = block.attributes.values.map((value) => ({
value: value.name,
}));
if (has(block.attributes, 'values')) {
mapped.params.values = block.attributes.values.map((value) => {
const mappedValue = {
value: value.name,
};
if (has(value, 'isChecked') && value.isChecked) {
mappedValue.is_checked = '1';
}
return mappedValue;
});
}
return mapped;
};

View File

@@ -1,3 +1,4 @@
import { has } from 'lodash';
import formatCustomFieldBlockName from '../blocks/format_custom_field_block_name.jsx';
const mapCustomField = (item, customFields, mappedCommonProperties) => {
@@ -8,6 +9,7 @@ const mapCustomField = (item, customFields, mappedCommonProperties) => {
text: 'mailpoet-form/custom-text',
textarea: 'mailpoet-form/custom-textarea',
radio: 'mailpoet-form/custom-radio',
checkbox: 'mailpoet-form/custom-checkbox',
};
const mapped = {
...mappedCommonProperties,
@@ -15,17 +17,23 @@ const mapCustomField = (item, customFields, mappedCommonProperties) => {
};
mapped.attributes.customFieldId = customField.id;
if (item.params) {
if (Object.prototype.hasOwnProperty.call(item.params, 'validate') && !!item.params.validate) {
if (has(item.params, 'validate') && !!item.params.validate) {
mapped.attributes.validate = item.params.validate;
}
if (Object.prototype.hasOwnProperty.call(item.params, 'hide_label')) {
if (has(item.params, 'hide_label')) {
mapped.attributes.hideLabel = !!item.params.hide_label;
}
if (Object.prototype.hasOwnProperty.call(item.params, 'values') && Array.isArray(item.params.values)) {
mapped.attributes.values = item.params.values.map((value) => ({
name: value.value,
id: `${Math.random().toString()}-${Date.now()}`,
}));
if (has(item.params, 'values') && Array.isArray(item.params.values)) {
mapped.attributes.values = item.params.values.map((value) => {
const mappedValue = {
name: value.value,
id: `${Math.random().toString()}-${Date.now()}`,
};
if (has(value, 'is_checked') && value.is_checked) {
mappedValue.isChecked = true;
}
return mappedValue;
});
}
}
return mapped;
@@ -53,13 +61,13 @@ export default (data, customFields = []) => {
mandatory: false,
},
};
if (item.params && Object.prototype.hasOwnProperty.call(item.params, 'required')) {
if (item.params && has(item.params, 'required')) {
mapped.attributes.mandatory = !!item.params.required;
}
if (item.params && Object.prototype.hasOwnProperty.call(item.params, 'label_within')) {
if (item.params && has(item.params, 'label_within')) {
mapped.attributes.labelWithinInput = !!item.params.label_within;
}
if (item.params && Object.prototype.hasOwnProperty.call(item.params, 'label')) {
if (item.params && has(item.params, 'label')) {
mapped.attributes.label = item.params.label;
}
switch (item.id) {
@@ -81,7 +89,7 @@ export default (data, customFields = []) => {
case 'segments':
if (
item.params
&& Object.prototype.hasOwnProperty.call(item.params, 'values')
&& has(item.params, 'values')
&& Array.isArray(item.params.values)
) {
mapped.attributes.values = item.params.values.map((value) => ({