diff --git a/js/src/edit-block/components/field-panel.js b/js/src/edit-block/components/field-panel.js index ce665d011..ecdb99b8b 100644 --- a/js/src/edit-block/components/field-panel.js +++ b/js/src/edit-block/components/field-panel.js @@ -38,6 +38,7 @@ const FieldPanel = ( { changeFieldSettings, controls, deleteField, + duplicateField, getField, } = useField(); @@ -105,6 +106,7 @@ const FieldPanel = ( { controls={ controls } changeFieldSettings={ changeFieldSettings } deleteField={ () => deleteField( selectedField ) } + duplicateField={ () => duplicateField( selectedField ) } field={ field } setCurrentLocation={ setCurrentLocation } setSelectedField={ setSelectedField } diff --git a/js/src/edit-block/components/field-settings.js b/js/src/edit-block/components/field-settings.js index 212e0aa23..96b5ea3cf 100644 --- a/js/src/edit-block/components/field-settings.js +++ b/js/src/edit-block/components/field-settings.js @@ -16,6 +16,7 @@ import { NO_FIELD_SELECTED } from '../constants'; /** * @callback onClickDelete Handler for deleting a field. + * @callback onClickDuplicate Handler for duplicating a field. * @return {void} */ @@ -23,6 +24,7 @@ import { NO_FIELD_SELECTED } from '../constants'; * @typedef {Object} FieldSettingsProps The component props. * @property {Object} controls All of the possible controls. * @property {onClickDelete} deleteField Deletes this field. + * @property {onClickDuplicate} duplicateField Duplicates this field. * @property {Object} field The current field. * @property {Function} changeFieldSettings Edits a given field's value. * @property {Function} setCurrentLocation Sets the current location, like 'editor'. @@ -39,6 +41,7 @@ const FieldSettings = ( { controls, changeFieldSettings, deleteField, + duplicateField, field, setCurrentLocation, setSelectedField, @@ -85,7 +88,10 @@ const FieldSettings = ( { > { __( 'Delete', 'genesis-custom-blocks' ) } - diff --git a/js/src/edit-block/helpers/getNewFieldNumber.js b/js/src/edit-block/helpers/getNewFieldNumber.js index eca2e3073..985d9b592 100644 --- a/js/src/edit-block/helpers/getNewFieldNumber.js +++ b/js/src/edit-block/helpers/getNewFieldNumber.js @@ -5,17 +5,18 @@ * the name 'new-field', they have a number after. * Like 'new-field', 'new-field-1', 'new-field-2', etc... * - * @param {Object} fields The existing fields. + * @param {Object} fields The existing fields. + * @param {string} fieldName The field name. * @return {number|null} The new field number as a string, or null. */ -const getNewFieldNumber = ( fields ) => { +const getNewFieldNumber = ( fields, fieldName = 'new-field' ) => { const numberOfFields = Object.values( fields ).length; - if ( ! numberOfFields || ! fields.hasOwnProperty( 'new-field' ) ) { + if ( ! numberOfFields || ! fields.hasOwnProperty( fieldName ) ) { return null; } for ( let i = 1; i <= numberOfFields; i++ ) { - if ( ! fields.hasOwnProperty( `new-field-${ i.toString() }` ) ) { + if ( ! fields.hasOwnProperty( `${ fieldName }-${ i.toString() }` ) ) { return i; } } diff --git a/js/src/edit-block/hooks/useField.js b/js/src/edit-block/hooks/useField.js index 8f4292bb7..6c6530a8f 100644 --- a/js/src/edit-block/hooks/useField.js +++ b/js/src/edit-block/hooks/useField.js @@ -24,6 +24,7 @@ import { getFieldsAsArray, getFieldsAsObject } from '../../common/helpers'; * @property {Function} addNewField Adds a new field. * @property {Object} controls All of the possible controls. * @property {Function} deleteField Deletes this field. + * @property {Function} duplicateField Deletes this field. * @property {Function} changeControl Changes the control of the field. * @property {Function} changeFieldSettings Changes field settings. * @property {Function} getField Gets the selected field. @@ -223,6 +224,29 @@ const useField = () => { editPost( { content: JSON.stringify( fullBlock ) } ); }, [ blockNameWithNameSpace, editPost, fullBlock ] ); + /** + * Duplicates this field. + */ + const duplicateField = useCallback( ( fieldName ) => { + const currentField = getField( fieldName ); + const { fields = {} } = block; + const newFieldNumber = getNewFieldNumber( fields, 'duplicated-field' ); + const newFieldName = newFieldNumber + ? `duplicated-field-${ newFieldNumber.toString() }` + : 'duplicated-field'; + + fields[ newFieldName ] = { + ...currentField, + name: newFieldName, + order: Object.values( fields ).length, + }; + + block.fields = fields; + fullBlock[ blockNameWithNameSpace ] = block; + + editPost( { content: JSON.stringify( fullBlock ) } ); + }, [ blockNameWithNameSpace, editPost, fullBlock, block, getField ] ); + /** * Gets a field, if it exists. * @@ -262,6 +286,7 @@ const useField = () => { changeControl, changeFieldSettings, deleteField, + duplicateField, getField, getFieldsForLocation, reorderFields,