From b6bf2624c67f64761847c19a8ffc01b73f263022 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Sun, 28 Nov 2021 14:21:34 +0000 Subject: [PATCH] Site Editor: Template list add rename action (#36879) * Site Editor: Template list add rename action * Update modal class * Address feedback * Only allow renaming of user created templates * Fix empty title issue * Fix condition * Use is_custom --- .../src/components/list/actions/index.js | 95 +++++++++++++ .../list/actions/rename-menu-item.js | 134 ++++++++++++++++++ .../edit-site/src/components/list/style.scss | 26 ++++ .../edit-site/src/components/list/table.js | 83 +---------- 4 files changed, 257 insertions(+), 81 deletions(-) create mode 100644 packages/edit-site/src/components/list/actions/index.js create mode 100644 packages/edit-site/src/components/list/actions/rename-menu-item.js diff --git a/packages/edit-site/src/components/list/actions/index.js b/packages/edit-site/src/components/list/actions/index.js new file mode 100644 index 0000000000000..016196fb57c10 --- /dev/null +++ b/packages/edit-site/src/components/list/actions/index.js @@ -0,0 +1,95 @@ +/** + * WordPress dependencies + */ +import { useDispatch } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; +import { __ } from '@wordpress/i18n'; +import { DropdownMenu, MenuGroup, MenuItem } from '@wordpress/components'; +import { moreVertical } from '@wordpress/icons'; +import { store as noticesStore } from '@wordpress/notices'; + +/** + * Internal dependencies + */ +import { store as editSiteStore } from '../../../store'; +import isTemplateRemovable from '../../../utils/is-template-removable'; +import isTemplateRevertable from '../../../utils/is-template-revertable'; +import RenameMenuItem from './rename-menu-item'; + +export default function Actions( { template } ) { + const { removeTemplate, revertTemplate } = useDispatch( editSiteStore ); + const { saveEditedEntityRecord } = useDispatch( coreStore ); + const { createSuccessNotice, createErrorNotice } = useDispatch( + noticesStore + ); + + const isRemovable = isTemplateRemovable( template ); + const isRevertable = isTemplateRevertable( template ); + + if ( ! isRemovable && ! isRevertable ) { + return null; + } + + async function revertAndSaveTemplate() { + try { + await revertTemplate( template, { allowUndo: false } ); + await saveEditedEntityRecord( + 'postType', + template.type, + template.id + ); + + createSuccessNotice( __( 'Template reverted.' ), { + type: 'snackbar', + } ); + } catch ( error ) { + const errorMessage = + error.message && error.code !== 'unknown_error' + ? error.message + : __( 'An error occurred while reverting the template.' ); + + createErrorNotice( errorMessage, { type: 'snackbar' } ); + } + } + + return ( + + { ( { onClose } ) => ( + + { isRemovable && ( + <> + + { + removeTemplate( template ); + onClose(); + } } + > + { __( 'Delete template' ) } + + + ) } + { isRevertable && ( + { + revertAndSaveTemplate(); + onClose(); + } } + > + { __( 'Clear customizations' ) } + + ) } + + ) } + + ); +} diff --git a/packages/edit-site/src/components/list/actions/rename-menu-item.js b/packages/edit-site/src/components/list/actions/rename-menu-item.js new file mode 100644 index 0000000000000..6d6b98edbb661 --- /dev/null +++ b/packages/edit-site/src/components/list/actions/rename-menu-item.js @@ -0,0 +1,134 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { useState } from '@wordpress/element'; +import { useDispatch, useSelect } from '@wordpress/data'; +import { + Button, + Flex, + FlexItem, + MenuItem, + Modal, + TextControl, +} from '@wordpress/components'; +import { store as coreStore } from '@wordpress/core-data'; +import { store as noticesStore } from '@wordpress/notices'; + +export default function RenameMenuItem( { template, onClose } ) { + const [ title, setTitle ] = useState( () => template.title.rendered ); + const [ isModalOpen, setIsModalOpen ] = useState( false ); + + const { getLastEntitySaveError } = useSelect( coreStore ); + const { editEntityRecord, saveEditedEntityRecord } = useDispatch( + coreStore + ); + const { createSuccessNotice, createErrorNotice } = useDispatch( + noticesStore + ); + + if ( ! template.is_custom ) { + return null; + } + + async function onTemplateRename( event ) { + event.preventDefault(); + + try { + await editEntityRecord( 'postType', template.type, template.id, { + title, + } ); + + // Update state before saving rerenders the list. + setTitle( '' ); + setIsModalOpen( false ); + onClose(); + + // Persist edited entity. + await saveEditedEntityRecord( + 'postType', + template.type, + template.id + ); + + const lastError = getLastEntitySaveError( + 'postType', + template.type, + template.id + ); + + if ( lastError ) { + throw lastError; + } + + createSuccessNotice( __( 'Template has been renamed.' ), { + type: 'snackbar', + } ); + } catch ( error ) { + const errorMessage = + error.message && error.code !== 'unknown_error' + ? error.message + : __( 'An error occurred while renaming the template.' ); + + createErrorNotice( errorMessage, { type: 'snackbar' } ); + } + } + + return ( + <> + { + setIsModalOpen( true ); + setTitle( template.title.rendered ); + } } + > + { __( 'Rename' ) } + + { isModalOpen && ( + { + setIsModalOpen( false ); + } } + overlayClassName="edit-site-list__rename-modal" + > +
+ + + + + + + + + + + + + + +
+
+ ) } + + ); +} diff --git a/packages/edit-site/src/components/list/style.scss b/packages/edit-site/src/components/list/style.scss index 92af509852969..575348c7f65ad 100644 --- a/packages/edit-site/src/components/list/style.scss +++ b/packages/edit-site/src/components/list/style.scss @@ -128,3 +128,29 @@ margin-left: $nav-sidebar-width; } } + +.edit-site-list__rename-modal { + .components-base-control { + @include break-medium() { + width: $grid-unit * 40; + } + } + + .components-modal__header { + border-bottom: none; + } + + .components-modal__content::before { + margin-bottom: $grid-unit-05; + } +} + +.edit-site-list__rename-modal-actions { + margin-top: $grid-unit-15; +} + +.edit-site-template__actions { + button:not(:last-child) { + margin-right: $grid-unit-10; + } +} diff --git a/packages/edit-site/src/components/list/table.js b/packages/edit-site/src/components/list/table.js index ce243e157f0e4..148b6b460c0ff 100644 --- a/packages/edit-site/src/components/list/table.js +++ b/packages/edit-site/src/components/list/table.js @@ -1,98 +1,19 @@ /** * WordPress dependencies */ -import { useSelect, useDispatch } from '@wordpress/data'; +import { useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; import { __, sprintf } from '@wordpress/i18n'; import { VisuallyHidden, - DropdownMenu, - MenuGroup, - MenuItem, __experimentalHeading as Heading, } from '@wordpress/components'; -import { moreVertical } from '@wordpress/icons'; import { addQueryArgs } from '@wordpress/url'; -import { store as noticesStore } from '@wordpress/notices'; /** * Internal dependencies */ -import { store as editSiteStore } from '../../store'; -import isTemplateRemovable from '../../utils/is-template-removable'; -import isTemplateRevertable from '../../utils/is-template-revertable'; - -function Actions( { template } ) { - const { removeTemplate, revertTemplate } = useDispatch( editSiteStore ); - const { saveEditedEntityRecord } = useDispatch( coreStore ); - const { createSuccessNotice, createErrorNotice } = useDispatch( - noticesStore - ); - - const isRemovable = isTemplateRemovable( template ); - const isRevertable = isTemplateRevertable( template ); - - if ( ! isRemovable && ! isRevertable ) { - return null; - } - - async function revertAndSaveTemplate() { - try { - await revertTemplate( template, { allowUndo: false } ); - await saveEditedEntityRecord( - 'postType', - template.type, - template.id - ); - - createSuccessNotice( __( 'Template reverted.' ), { - type: 'snackbar', - } ); - } catch ( error ) { - const errorMessage = - error.message && error.code !== 'unknown_error' - ? error.message - : __( 'An error occurred while reverting the template.' ); - - createErrorNotice( errorMessage, { type: 'snackbar' } ); - } - } - - return ( - - { ( { onClose } ) => ( - - { isRemovable && ( - { - removeTemplate( template ); - onClose(); - } } - > - { __( 'Delete template' ) } - - ) } - { isRevertable && ( - { - revertAndSaveTemplate(); - onClose(); - } } - > - { __( 'Clear customizations' ) } - - ) } - - ) } - - ); -} +import Actions from './actions'; export default function Table( { templateType } ) { const { templates, isLoading, postType } = useSelect(