diff --git a/assets/js/src/form_editor/blocks/blocks.jsx b/assets/js/src/form_editor/blocks/blocks.jsx index 54c36e43e8..b56994edf6 100644 --- a/assets/js/src/form_editor/blocks/blocks.jsx +++ b/assets/js/src/form_editor/blocks/blocks.jsx @@ -26,6 +26,8 @@ const registerCustomFieldBlock = (customField) => { }, }; + if (!namesMap[customField.type]) return; + registerBlockType( formatCustomFieldBlockName(namesMap[customField.type].name, customField), namesMap[customField.type].settings diff --git a/assets/js/src/form_editor/store/actions.jsx b/assets/js/src/form_editor/store/actions.jsx index 84a8613bb4..3c1d40c1d1 100644 --- a/assets/js/src/form_editor/store/actions.jsx +++ b/assets/js/src/form_editor/store/actions.jsx @@ -27,6 +27,27 @@ export function changeFormStyles(styles) { }; } +export function saveCustomFieldDone(customFieldId, response) { + return { + type: 'SAVE_CUSTOM_FIELD_DONE', + customFieldId, + response, + }; +} + +export function saveCustomFieldStarted() { + return { + type: 'SAVE_CUSTOM_FIELD_STARTED', + }; +} + +export function saveCustomFieldFailed(message = undefined) { + return { + type: 'SAVE_CUSTOM_FIELD_FAILED', + message, + }; +} + export function changeFormSettings(settings) { return { type: 'CHANGE_FORM_SETTINGS', @@ -87,3 +108,10 @@ export function* saveForm() { type: 'SAVE_FORM', }; } + +export function* saveCustomField(data) { + yield { + type: 'SAVE_CUSTOM_FIELD', + ...data, + }; +} diff --git a/assets/js/src/form_editor/store/controls.jsx b/assets/js/src/form_editor/store/controls.jsx index 7dee4841d1..5a566b0231 100644 --- a/assets/js/src/form_editor/store/controls.jsx +++ b/assets/js/src/form_editor/store/controls.jsx @@ -1,5 +1,6 @@ import { select, dispatch } from '@wordpress/data'; import MailPoet from 'mailpoet'; +import { merge } from 'lodash'; import blocksToFormBody from './blocks_to_form_body.jsx'; export default { @@ -34,4 +35,27 @@ export default { dispatch('mailpoet-form-editor').saveFormFailed(errorMessage); }); }, + + SAVE_CUSTOM_FIELD(actionData) { + dispatch('mailpoet-form-editor').saveCustomFieldStarted(); + const customFields = select('mailpoet-form-editor').getAllAvailableCustomFields(); + const customField = customFields.find((cf) => cf.id === actionData.customFieldId); + const requestData = {}; + merge(requestData, customField, actionData.data); + MailPoet.Ajax.post({ + api_version: window.mailpoet_api_version, + endpoint: 'customFields', + action: 'save', + data: requestData, + }).done((response) => { + dispatch('mailpoet-form-editor').saveCustomFieldDone(customField.id, response.data); + if (typeof actionData.onFinish === 'function') actionData.onFinish(); + }).fail((response) => { + let errorMessage = null; + if (response.errors.length > 0) { + errorMessage = response.errors.map((error) => (error.message)); + } + dispatch('mailpoet-form-editor').saveCustomFieldFailed(errorMessage); + }); + }, }; diff --git a/assets/js/src/form_editor/store/form_body_to_blocks.jsx b/assets/js/src/form_editor/store/form_body_to_blocks.jsx index 7e09904ca8..a1e4393f47 100644 --- a/assets/js/src/form_editor/store/form_body_to_blocks.jsx +++ b/assets/js/src/form_editor/store/form_body_to_blocks.jsx @@ -8,12 +8,11 @@ const mapCustomField = (item, customFields, mappedCommonProperties) => { text: 'mailpoet-form/custom-text', textarea: 'mailpoet-form/custom-textarea', }; - const mapped = { ...mappedCommonProperties, name: formatCustomFieldBlockName(namesMap[customField.type], customField), - customFieldId: customField.id, }; + mapped.attributes.customFieldId = customField.id; if ( item.params && Object.prototype.hasOwnProperty.call(item.params, 'validate') diff --git a/assets/js/src/form_editor/store/reducer.jsx b/assets/js/src/form_editor/store/reducer.jsx index d8bf0a4f71..7919286fa7 100644 --- a/assets/js/src/form_editor/store/reducer.jsx +++ b/assets/js/src/form_editor/store/reducer.jsx @@ -10,6 +10,9 @@ import switchSidebarTab from './reducers/switch_sidebar_tab.jsx'; import toggleSidebar from './reducers/toggle_sidebar.jsx'; import toggleSidebarPanel from './reducers/toggle_sidebar_panel.jsx'; import changeFormBlocks from './reducers/change_form_blocks.jsx'; +import saveCustomFieldDone from './reducers/save_custom_field_done.jsx'; +import saveCustomFieldFailed from './reducers/save_custom_field_failed.jsx'; +import saveCustomFieldStarted from './reducers/save_custom_field_started.jsx'; const saveFormStarted = saveFormStartedFactory(MailPoet); @@ -23,6 +26,9 @@ export default (defaultState) => (state = defaultState, action) => { case 'SAVE_FORM_DONE': return saveFormDone(state); case 'SAVE_FORM_FAILED': return saveFormFailed(state, action); case 'SAVE_FORM_STARTED': return saveFormStarted(state); + case 'SAVE_CUSTOM_FIELD_DONE': return saveCustomFieldDone(state, action); + case 'SAVE_CUSTOM_FIELD_FAILED': return saveCustomFieldFailed(state, action); + case 'SAVE_CUSTOM_FIELD_STARTED': return saveCustomFieldStarted(state); case 'SWITCH_SIDEBAR_TAB': return switchSidebarTab(state, action); case 'TOGGLE_SIDEBAR': return toggleSidebar(state, action); case 'TOGGLE_SIDEBAR_PANEL': return toggleSidebarPanel(state, action); diff --git a/assets/js/src/form_editor/store/reducers/save_custom_field_done.jsx b/assets/js/src/form_editor/store/reducers/save_custom_field_done.jsx new file mode 100644 index 0000000000..094f1d1a1a --- /dev/null +++ b/assets/js/src/form_editor/store/reducers/save_custom_field_done.jsx @@ -0,0 +1,26 @@ +import MailPoet from 'mailpoet'; + +export default (state, action) => { + const notices = state.notices.filter((notice) => notice.id !== 'custom-field'); + notices.push({ + id: 'custom-field', + content: MailPoet.I18n.t('customFieldSaved'), + isDismissible: true, + status: 'success', + }); + + const customFields = state.customFields.map((customField) => { + if (customField.id === action.customFieldId) { + return action.response; + } + return customField; + }); + + return { + ...state, + isCustomFieldSaving: false, + isFormSaving: false, + notices, + customFields, + }; +}; diff --git a/assets/js/src/form_editor/store/reducers/save_custom_field_failed.jsx b/assets/js/src/form_editor/store/reducers/save_custom_field_failed.jsx new file mode 100644 index 0000000000..87f40a56ad --- /dev/null +++ b/assets/js/src/form_editor/store/reducers/save_custom_field_failed.jsx @@ -0,0 +1,15 @@ +export default (state, action) => { + const notices = state.notices.filter((notice) => notice.id !== 'custom-field'); + notices.push({ + id: 'custom-field', + content: action.message, + isDismissible: true, + status: 'error', + }); + return { + ...state, + isFormSaving: false, + isCustomFieldSaving: false, + notices, + }; +}; diff --git a/assets/js/src/form_editor/store/reducers/save_custom_field_started.jsx b/assets/js/src/form_editor/store/reducers/save_custom_field_started.jsx new file mode 100644 index 0000000000..c5082e7e2b --- /dev/null +++ b/assets/js/src/form_editor/store/reducers/save_custom_field_started.jsx @@ -0,0 +1,9 @@ +export default (state) => { + const notices = state.notices.filter((notice) => notice.id !== 'custom-field'); + return { + ...state, + isFormSaving: true, + isCustomFieldSaving: true, + notices, + }; +}; diff --git a/assets/js/src/form_editor/store/selectors.jsx b/assets/js/src/form_editor/store/selectors.jsx index b901bb0a47..b23e3ada3d 100644 --- a/assets/js/src/form_editor/store/selectors.jsx +++ b/assets/js/src/form_editor/store/selectors.jsx @@ -29,6 +29,9 @@ export default { getIsFormSaving(state) { return state.isFormSaving; }, + getIsCustomFieldSaving(state) { + return state.isCustomFieldSaving; + }, getDismissibleNotices(state) { return state.notices.filter((notice) => notice.isDismissible === true); }, diff --git a/assets/js/src/form_editor/store/store.jsx b/assets/js/src/form_editor/store/store.jsx index 666f3b174f..88e5b111fd 100644 --- a/assets/js/src/form_editor/store/store.jsx +++ b/assets/js/src/form_editor/store/store.jsx @@ -25,6 +25,7 @@ export default () => { pages: window.mailpoet_form_pages, customFields: window.mailpoet_custom_fields, isFormSaving: false, + isCustomFieldSaving: false, notices: [], sidebar: { activeTab: 'form', diff --git a/views/form/editor.html b/views/form/editor.html index 05d8097fa0..883356d7c3 100644 --- a/views/form/editor.html +++ b/views/form/editor.html @@ -30,9 +30,12 @@ 'addFormName': _x('Add form name', 'A placeholder for form name input'), 'form': __('Form'), 'formSettings': _x('Settings', 'A settings section heading'), + 'customFieldSettings': _x('Custom field settings', 'A settings section heading'), + 'customFieldsFormSettings': _x('Form settings', 'A settings section heading'), 'formPlacement': _x('Form Placement', 'A settings section heading'), 'customCss': _x('Custom CSS', 'A settings section heading'), 'formSaved': __('Form saved.'), + 'customFieldSaved': __('Custom field saved.'), 'addFormWidgetHint': __('Add this form to your sidebar or footer on the [link]Widgets page[/link].'), 'addFormShortcodeHint': __('Copy and paste this [link]shortcode[/link] on to a post or page.'), 'addFormPhpIframeHint': __('[link]PHP[/link] and [link]iFrame[/link] versions are also available.'), @@ -44,6 +47,8 @@ 'fieldsBlocksCategory': __('Fields'), 'customFieldsBlocksCategory': __('Custom Fields'), 'customFieldNumberOfLines': __('Number of lines'), + 'customFieldSaveCTA': _x('Update custom field', 'Text on the save button'), + 'customFieldSaveCTA': _x('Update custom field', 'Text on the save button'), 'customField1Line': _x('1 line', 'Number of rows in textarea'), 'customField2Lines': _x('2 lines', 'Number of rows in textarea'), 'customField3Lines': _x('3 lines', 'Number of rows in textarea'),