Skip to content

Commit

Permalink
Site Editor: Template list add rename action (#36879)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
Mamaduka authored and noisysocks committed Nov 29, 2021
1 parent 6d1521e commit b6bf262
Show file tree
Hide file tree
Showing 4 changed files with 257 additions and 81 deletions.
95 changes: 95 additions & 0 deletions packages/edit-site/src/components/list/actions/index.js
Original file line number Diff line number Diff line change
@@ -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 (
<DropdownMenu
icon={ moreVertical }
label={ __( 'Actions' ) }
className="edit-site-list-table__actions"
>
{ ( { onClose } ) => (
<MenuGroup>
{ isRemovable && (
<>
<RenameMenuItem
template={ template }
onClose={ onClose }
/>
<MenuItem
isDestructive
onClick={ () => {
removeTemplate( template );
onClose();
} }
>
{ __( 'Delete template' ) }
</MenuItem>
</>
) }
{ isRevertable && (
<MenuItem
info={ __( 'Restore template to theme default' ) }
onClick={ () => {
revertAndSaveTemplate();
onClose();
} }
>
{ __( 'Clear customizations' ) }
</MenuItem>
) }
</MenuGroup>
) }
</DropdownMenu>
);
}
134 changes: 134 additions & 0 deletions packages/edit-site/src/components/list/actions/rename-menu-item.js
Original file line number Diff line number Diff line change
@@ -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 (
<>
<MenuItem
onClick={ () => {
setIsModalOpen( true );
setTitle( template.title.rendered );
} }
>
{ __( 'Rename' ) }
</MenuItem>
{ isModalOpen && (
<Modal
title={ __( 'Rename template' ) }
closeLabel={ __( 'Close' ) }
onRequestClose={ () => {
setIsModalOpen( false );
} }
overlayClassName="edit-site-list__rename-modal"
>
<form onSubmit={ onTemplateRename }>
<Flex align="flex-start" gap={ 8 }>
<FlexItem>
<TextControl
label={ __( 'Name' ) }
value={ title }
onChange={ setTitle }
required
/>
</FlexItem>
</Flex>

<Flex
className="edit-site-list__rename-modal-actions"
justify="flex-end"
expanded={ false }
>
<FlexItem>
<Button
variant="tertiary"
onClick={ () => {
setIsModalOpen( false );
} }
>
{ __( 'Cancel' ) }
</Button>
</FlexItem>
<FlexItem>
<Button variant="primary" type="submit">
{ __( 'Save' ) }
</Button>
</FlexItem>
</Flex>
</form>
</Modal>
) }
</>
);
}
26 changes: 26 additions & 0 deletions packages/edit-site/src/components/list/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
83 changes: 2 additions & 81 deletions packages/edit-site/src/components/list/table.js
Original file line number Diff line number Diff line change
@@ -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 (
<DropdownMenu
icon={ moreVertical }
label={ __( 'Actions' ) }
className="edit-site-list-table__actions"
>
{ ( { onClose } ) => (
<MenuGroup>
{ isRemovable && (
<MenuItem
isDestructive
onClick={ () => {
removeTemplate( template );
onClose();
} }
>
{ __( 'Delete template' ) }
</MenuItem>
) }
{ isRevertable && (
<MenuItem
info={ __( 'Restore template to theme default' ) }
onClick={ () => {
revertAndSaveTemplate();
onClose();
} }
>
{ __( 'Clear customizations' ) }
</MenuItem>
) }
</MenuGroup>
) }
</DropdownMenu>
);
}
import Actions from './actions';

export default function Table( { templateType } ) {
const { templates, isLoading, postType } = useSelect(
Expand Down

0 comments on commit b6bf262

Please sign in to comment.