Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update: Reuse and unify template actions. #60754

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ import { useAsyncList } from '@wordpress/compose';
import { serialize } from '@wordpress/blocks';
import { __experimentalBlockPatternsList as BlockPatternsList } from '@wordpress/block-editor';
import { privateApis as routerPrivateApis } from '@wordpress/router';
import { useCallback } from '@wordpress/element';

/**
* Internal dependencies
*/
import { store as editSiteStore } from '../../../store';
import TemplateActions from '../../template-actions';
import PluginTemplateSettingPanel from '../../plugin-template-setting-panel';
import { useAvailablePatterns } from './hooks';
import { TEMPLATE_PART_POST_TYPE } from '../../../utils/constants';
import { unlock } from '../../../lock-unlock';

const { PostCardPanel } = unlock( editorPrivateApis );
const { PostCardPanel, PostActions } = unlock( editorPrivateApis );
const { PatternOverridesPanel } = unlock( editorPrivateApis );
const { useHistory } = unlock( routerPrivateApis );

Expand All @@ -50,11 +50,6 @@ function TemplatesList( { availableTemplates, onSelect } ) {
);
}

const POST_TYPE_PATH = {
wp_template: '/wp_template',
wp_template_part: '/patterns',
};

export default function TemplatePanel() {
const { title, description, record, postType, postId } = useSelect(
( select ) => {
Expand All @@ -81,6 +76,22 @@ export default function TemplatePanel() {
[]
);
const history = useHistory();
const onActionPerformed = useCallback(
( actionId, items ) => {
if ( actionId === 'delete-template' ) {
history.push( {
path:
items[ 0 ].type === TEMPLATE_PART_POST_TYPE
? '/' + TEMPLATE_PART_POST_TYPE + '/all'
: '/' + items[ 0 ].type,
Comment on lines +84 to +86
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem in line with the latest changes (#60667), nor with the deleted hunk of this patch. I expected something like:

items[ 0 ].type === TEMPLATE_PART_POST_TYPE
  ? '/patterns'
  : '/' + items[ 0 ].type

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm right, the same comment applies to other similar parts of the patch.

Copy link
Member

@oandregal oandregal Apr 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, as of #60689 and related work, the parts should go back always to /patterns. We should not use /wp_template_part/all anymore, it only exists (temporarily) for hybrid themes (classic themes that declare block-template-parts theme support), so they can access that particular site editor screen.

I've also checked that hybrid themes cannot access the delete action anywhere (index page, details page, editor), in case we needed to go back to a different place if the theme was hybrid. Unless I'm missing some flows, we don't need that action for those themes.

postId: undefined,
postType: undefined,
canvas: 'view',
} );
}
},
[ history ]
);
const availablePatterns = useAvailablePatterns( record );
const { editEntityRecord } = useDispatch( coreStore );

Expand All @@ -100,17 +111,7 @@ export default function TemplatePanel() {
<PostCardPanel
className="edit-site-template-card"
actions={
<TemplateActions
postType={ postType }
postId={ postId }
className="edit-site-template-card__actions"
toggleProps={ { size: 'small' } }
onRemove={ () => {
history.push( {
path: POST_TYPE_PATH[ postType ],
} );
} }
/>
<PostActions onActionPerformed={ onActionPerformed } />
}
/>
<PluginTemplateSettingPanel.Slot />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import { useDispatch, useSelect } from '@wordpress/data';
import { pencil } from '@wordpress/icons';
import { Icon } from '@wordpress/components';
import { store as coreStore } from '@wordpress/core-data';
import { useCallback } from '@wordpress/element';
import { privateApis as editorPrivateApis } from '@wordpress/editor';

import { privateApis as routerPrivateApis } from '@wordpress/router';

/**
Expand All @@ -18,9 +21,11 @@ import { unlock } from '../../lock-unlock';
import { store as editSiteStore } from '../../store';
import SidebarButton from '../sidebar-button';
import { useAddedBy } from '../page-templates-template-parts/hooks';
import TemplateActions from '../template-actions';
import HomeTemplateDetails from './home-template-details';
import SidebarNavigationScreenDetailsFooter from '../sidebar-navigation-screen-details-footer';
import { TEMPLATE_PART_POST_TYPE } from '../../utils/constants';

const { PostActions } = unlock( editorPrivateApis );

const { useHistory, useLocation } = unlock( routerPrivateApis );

Expand Down Expand Up @@ -104,20 +109,26 @@ export default function SidebarNavigationScreenTemplate() {
postType,
postId
);
const onActionPerformed = useCallback(
( actionId, items ) => {
if ( actionId === 'delete-template' ) {
history.push( {
path:
items[ 0 ].type === TEMPLATE_PART_POST_TYPE
? '/' + TEMPLATE_PART_POST_TYPE + '/all'
: '/' + items[ 0 ],
} );
}
},
[ history ]
);

return (
<SidebarNavigationScreen
title={ title }
actions={
<>
<TemplateActions
postType={ postType }
postId={ postId }
toggleProps={ { as: SidebarButton } }
onRemove={ () => {
history.push( { path: '/' + postType } );
} }
/>
<PostActions onActionPerformed={ onActionPerformed } />
<SidebarButton
onClick={ () => setCanvasMode( 'edit' ) }
label={ __( 'Edit' ) }
Expand Down
65 changes: 47 additions & 18 deletions packages/editor/src/components/post-actions/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ import {
/**
* Internal dependencies
*/
import { TEMPLATE_ORIGINS, TEMPLATE_POST_TYPE } from '../../store/constants';
import {
TEMPLATE_ORIGINS,
TEMPLATE_POST_TYPE,
TEMPLATE_PART_POST_TYPE,
PATTERN_POST_TYPE,
} from '../../store/constants';
import { store as editorStore } from '../../store';
import { unlock } from '../../lock-unlock';
import isTemplateRevertable from '../../store/utils/is-template-revertable';
Expand All @@ -33,13 +38,19 @@ function getItemTitle( item ) {
return decodeEntities( item.title?.rendered || '' );
}

const SITE_EDITING_POST_TYPES = [
TEMPLATE_POST_TYPE,
TEMPLATE_PART_POST_TYPE,
PATTERN_POST_TYPE,
];

const trashPostAction = {
id: 'move-to-trash',
label: __( 'Move to Trash' ),
isPrimary: true,
icon: trash,
isEligible( { status } ) {
return status !== 'trash';
isEligible( { type, status } ) {
return status !== 'trash' && ! SITE_EDITING_POST_TYPES.includes( type );
},
supportsBulk: true,
hideModalHeader: true,
Expand Down Expand Up @@ -182,8 +193,11 @@ function usePermanentlyDeletePostAction() {
id: 'permanently-delete',
label: __( 'Permanently delete' ),
supportsBulk: true,
isEligible( { status } ) {
return status === 'trash';
isEligible( { status, type } ) {
return (
status === 'trash' &&
! SITE_EDITING_POST_TYPES.includes( type )
);
},
async callback( posts, onActionPerformed ) {
const promiseResult = await Promise.allSettled(
Expand Down Expand Up @@ -292,8 +306,11 @@ function useRestorePostAction() {
isPrimary: true,
icon: backup,
supportsBulk: true,
isEligible( { status } ) {
return status === 'trash';
isEligible( { status, type } ) {
return (
status === 'trash' &&
! SITE_EDITING_POST_TYPES.includes( type )
);
},
async callback( posts, onActionPerformed ) {
try {
Expand Down Expand Up @@ -371,7 +388,10 @@ const viewPostAction = {
isPrimary: true,
icon: external,
isEligible( post ) {
return post.status !== 'trash';
return (
post.status !== 'trash' &&
! SITE_EDITING_POST_TYPES.includes( post.type )
);
},
callback( posts, onActionPerformed ) {
const post = posts[ 0 ];
Expand All @@ -387,21 +407,25 @@ const editPostAction = {
label: __( 'Edit' ),
isPrimary: true,
icon: edit,
isEligible( { status } ) {
return status !== 'trash';
isEligible( { status, type } ) {
return status !== 'trash' && ! SITE_EDITING_POST_TYPES.includes( type );
},
callback( posts, onActionPerformed ) {
if ( onActionPerformed ) {
onActionPerformed( posts );
}
},
};

const postRevisionsAction = {
id: 'view-post-revisions',
label: __( 'View revisions' ),
isPrimary: false,
isEligible: ( post ) => {
if ( post.status === 'trash' ) {
if (
post.status === 'trash' ||
SITE_EDITING_POST_TYPES.includes( post.type )
) {
return false;
}
const lastRevisionId =
Expand All @@ -426,7 +450,10 @@ const renamePostAction = {
id: 'rename-post',
label: __( 'Rename' ),
isEligible( post ) {
return post.status !== 'trash';
return (
post.status !== 'trash' &&
! SITE_EDITING_POST_TYPES.includes( post.type )
);
},
RenderModal: ( { items, closeModal, onActionPerformed } ) => {
const [ item ] = items;
Expand Down Expand Up @@ -534,7 +561,7 @@ const resetTemplateAction = {
: sprintf(
/* translators: The template/part's name. */
__( '"%s" reset.' ),
decodeEntities( items[ 0 ].title.rendered )
getItemTitle( items[ 0 ] )
),
{
type: 'snackbar',
Expand Down Expand Up @@ -603,7 +630,11 @@ const resetTemplateAction = {
* @return {boolean} Whether the template is revertable.
*/
function isTemplateRemovable( template ) {
if ( ! template ) {
if (
! template ||
( template.type !== TEMPLATE_POST_TYPE &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels weird to be inside a function called isTemplateRemovable.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch 😅 I will fix this.

template.type !== TEMPLATE_PART_POST_TYPE )
) {
return false;
}

Expand Down Expand Up @@ -636,9 +667,7 @@ const deleteTemplateAction = {
: sprintf(
// translators: %s: The template or template part's titles
__( 'Delete "%s"?' ),
decodeEntities(
templates?.[ 0 ]?.title?.rendered
)
getItemTitle( templates[ 0 ] )
) }
</Text>
<HStack justify="right">
Expand Down Expand Up @@ -679,7 +708,7 @@ const renameTemplateAction = {
},
RenderModal: ( { items: templates, closeModal, onActionPerformed } ) => {
const template = templates[ 0 ];
const title = decodeEntities( template.title.rendered );
const title = getItemTitle( template );
const [ editedTitle, setEditedTitle ] = useState( title );
const {
editEntityRecord,
Expand Down
17 changes: 5 additions & 12 deletions packages/editor/src/components/post-actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,7 @@ import { moreVertical } from '@wordpress/icons';
import { unlock } from '../../lock-unlock';
import { usePostActions } from './actions';
import { store as editorStore } from '../../store';
import {
TEMPLATE_POST_TYPE,
TEMPLATE_PART_POST_TYPE,
PATTERN_POST_TYPE,
} from '../../store/constants';
import { PATTERN_POST_TYPE } from '../../store/constants';

const {
DropdownMenuV2: DropdownMenu,
Expand All @@ -35,7 +31,10 @@ const POST_ACTIONS_WHILE_EDITING = [
'view-post',
'view-post-revisions',
'rename-post',
'rename-template',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll ramble a bit and might be missing things, and I will check the code and changes better, but it seems too complex to me at first glance.

I don't get the end goal with some of this code. Is it to have for example a single delete-post action and apply to every post type and check if isEligible? How the edit scope affects the implementation and what other scopes we can have?

I think it's apparent that we need to reuse some actions and know some context (such as 'edit' mode, or 'post vs site' editor for redirections). Can we extract this info somehow to avoid such explicit declarations? If we cannot avoid that, shouldn't it be part of the actions API?

As I said I'll have to look more the code to get a better understanding.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll ramble a bit and might be missing things, and I will check the code and changes better, but it seems too complex to me at first glance.

[…]

I think it's apparent that we need to reuse some actions and know some context (such as 'edit' mode, or 'post vs site' editor for redirections). Can we extract this info somehow to avoid such explicit declarations? If we cannot avoid that, shouldn't it be part of the actions API?

I think your outside perspective is very useful, don't ignore your intuition. We need more red teams, in fact.

Taking a step back, there are several things we can do, as well as some questions to ask ourselves now that we have concrete experience with the unification:

  • You touched on the idea of context (edit, post, etc.). You also touched on the idea of a generic action provider potentially conflicting with type-specific requirements: is it a code smell if a function called isTemplateRevertable needs to validate its argument as template-like?
  • Meanwhile, the current system is very flexible in that each action is a set of methods callable on any data: isEligible( item ), onActionPerformed: (actionId, items) => switch (actionId) {.... So we are defaulting to giving consumers almost maximum control with the goal of making Data Views versatile and post-type-agnostic.
  • Now that we've put things in, how much can we take out? Could we do the exercise of removing as much of that control as possible, with the goal of minimising moving parts? Then we would be forced to make assumptions about the data and the permissible set of actions. For example, how do we reuse actions across screens and entities (and how much should we)? As another example, what would it take to kill onActionPerformed and let the system navigate when necessary or intelligently perform other kinds of post-action cleanup?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems I had accidentally deleted a small part of my first comment. My main issue is what we are trying to unify.

Meanwhile, the current system is very flexible in that each action is a set of methods callable on any data: isEligible( item ), onActionPerformed: (actionId, items) => switch (actionId) {.... So we are defaulting to giving consumers almost maximum control with the goal of making Data Views versatile and post-type-agnostic.

That's one of the issues here. This PR (and at least this merged one) is not about DataViews, but it tries to do what DataViews do.

I worked on the DataViews actions API and you can say it consists of two main parts:

  1. The actions API - how we define actions, isEligible, RenderModal, etc..
  2. The component that takes as input the above actions and can render them in form of a dialog, inline, etc.. based on the action's properties.

The component that renders the actions is reused from all consumers, but the actions are provided by the consumers. What I'm trying to say is that we should probably have a reusable component to render the actions, but the actions unification is a whole different matter and the unification of them would involve questions like:

is it to have for example a single delete-post action and apply to every post type and check if isEligible

Right now in trunk and with this PR, we are taking an approach where we duplicate (almost) the rendering component, which is not necessarily bad to start with, if we don't want the UI to match, but if we want it to match we could consider extracting this to a private component package. Again it's probably fine to just duplicate for now and update the comments to have in mind if we'll need to create a shared component.

I think we should clarify the vision about actions unification. I don't think it's great to have renamePostAction, renameTemplateAction in the same array. It feels weird to me that we already have override actionIds in usePostActions and POST_ACTIONS_WHILE_EDITING to pass. It feels like we don't have clear answers about the use cases and we rush into abstractions, which add complexity. We should either for start have a single rename action etc.. or we could just start by separating the actions per our conditions (probably by checking post type? 🤔 ). If the context matters, we should also check this if/how to incorporate this..

Finally maybe this is the time that we should also just think about a bit, how the actions API is similar to the commands API and if it would be possible to converge/unify a bit there or even take inspiration, or even see gaps in that API 😄

To sum up, I think we should take things step by step and try to avoid unnecessary complexity.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finally maybe this is the time that we should also just think about a bit, how the actions API is similar to the commands API and if it would be possible to converge/unify a bit there or even take inspiration, or even see gaps in that API

This reminded me of Riad's proposal: a single API to describe actions/commands and reuse them.

Copy link
Member Author

@jorgefilipecosta jorgefilipecosta Apr 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ntsekouras,

I don't get the end goal with some of this code.

The end goal of this code is to provide the same actions on dataviews, edit site inspector, edit site site details panel, and edit post inspector. Which was on mockups. This means that actions like delete template and revert a template should be available on edit post too. So the editor package seemed to be the best package to have the actions.

Is it to have for example a single delete-post action and apply to every post type and check if isEligible? How the edit scope affect the implementation and what other scopes we can have?

Yes in the future we may join the delete-post, delete-template, and delete-pattern action in a single action that can be applied to every post. It leaves the possibility for that and I think it may make sense. But it is not the goal. My goal was just not to duplicate the code of the actions while keeping exactly the actions API (object structure the same as before).

I think we should clarify the vision about actions unification. I don't think it's great to have renamePostAction, renameTemplateAction in the same array. It feels weird to me that we already have override actionIds in usePostActions and POST_ACTIONS_WHILE_EDITING to pass. It feels like we don't have clear answers about the use cases and we rush into abstractions, which add complexity. We should either for start have a single rename action etc.. or we could just start by separating the actions per our conditions (probably by checking post type? 🤔 ). If the context matters, we should also check this if/how to incorporate this..

While editing for UX purposes we don't want some actions shown. usePostActions allows the consumer to select the actions that wants to use in a given case. Previously the consumer could also import some actions and not others. usePostActions is like an import of actions.

I agree in the future we may have a single renameItem or deleteItem that can be done as a follow-up.

Finally maybe this is the time that we should also just think about a bit, how the actions API is similar to the commands API and if it would be possible to converge/unify a bit there or even take inspiration, or even see gaps in that API 😄

The command API and actions API are very similar and we already have some inconsistencies, like on the actions we ask for user confirmation on some destructive actions, and on commands we don't. We can explore making the actions available as a command or on the command code callbacks call the action callbacks and or RenderModal.
If the actions are on the editor package it will also make it easy to add commands like revert template to edit post which for now just exist on the edit site package. These commands could just call the actions.
But that does not seem related to this PR as I'm not changing the actions API.

The points you raised are valid and are things we can look. The set of action-related PR's I worked on focused on a specific goal to bring the same actions to the 4 different places we have. I agree sometimes duplication is better than adding complexity and for example, I opted to duplicate the UI that renders the actions menus, but that is only 150 lines of code. And I feel that code does not make sense as a WordPress component and exposing it as a private package just increases the maitainability.
For the actions them selfs the goal is exactly the same across the 4 use cases (dataviews, edit site inspector, edit site site details panel) given an item or set of items check if some action is executable on it, execute the action or render UI to confirm its execution.
Given that the goal is exactly the same I don't think it makes sense to repeat 1200 lines of code (+- 800 for now but will increase when the 400 lines of pattern actions are also moved). What was happening before was that for each place where we needed an action, it was being reimplemented from scratch e.g.: #60232.
@Mamaduka brings up a good point, we will need to check for capabilities e.g: does the current user have delete capabilities? I think if actions are in a single place it is easier to add these capability checks
check than if they are repeated across multiple places (we will end up adding checks in some places but missing them in other places like currently we ask user confirmation on some places but don't on others).

It seems to reuse the actions across the different places we could have duplicated them or moved them to a package where they can be reused. I opted for the latter and that was done without any changes added to the actions API. The actions object passed to the dataviews is exactly the same (this PR or the one it depends on #60395 did not touch the dataviews package at all).

The only artifact that was added is a usePostActions in the editor package that returns an array of action objects with the same shape we already have. That artifact is private and can easily be changed or even removed, it just exists as a way to export actions from the editor package to edit-site and edit-post. The artifact just provides an easier way to import an array of actions. Instead of import{ usePostActions } usePostActions( onActionPerformed, [delete-template, revert-template]), we could have import{ deleteTemplate, revertTemplate}; useMemo( add my action performed callback to the delete action; [deleteTemplate,revertTemplate] ); and not have usePostActions at all we would just repeat some code inside useMemo.
Given that the actions API is the same, where do you feel that complexity was added?

I think duplicating all the actions code would not have been a good choice, as the code has exactly the same goal and we have a place where we can put that code that makes sense and allows that reusability. The fact that actions could just work across the for different places with only minimal checks added in isEligible keeping the same action object passed to dataviews without changes there also is an argument in favor of reusing them.

I understand it may feel strange to have 'rename-post', 'rename-template', on the same array. But both actions exist and that array can have any action that is available. Previously I could also have somewhere import {renamePost, renameTemplate}. Probably we should not have had different actions to rename a post, a template, and a pattern and it would have been better to just have a single rename action. That was an issue that we already had. I can have a look into joining some of the actions I think that would be a good code-quality enhancement.

Do you think exploring joint rename/delete|post/template in a follow-up or a parallel PR would be enough to unblock the current PR? Or are there any other changes you think we should do?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @mcsf,
Adding the template check on isTemplateRevertable does not make sense at all 😅 It is something I will change.

Now that we've put things in, how much can we take out? Could we do the exercise of removing as much of that control as possible, with the goal of minimising moving parts? Then we would be forced to make assumptions about the data and the permissible set of actions. For example, how do we reuse actions across screens and entities (and how much should we)? As another example, what would it take to kill onActionPerformed and let the system navigate when necessary or intelligently perform other kinds of post-action cleanup?

I feel we can not take out onActionPerformed it is very dependent on the context of where the action is executed. E.g: when I delete a template that is assigned to a page I should not navigate anywhere I should just switch to page editing and assign the default template to that page, on data views when a template is deleted I should do nothing at all, and on site editor, I should navigate to the template list. In the view of another plugin that also offers a way to delete templates, I may need to do something totally different. Detecting all these cases and doing the right thing all the time seems "too magic" to me. But I'm open to suggestions of other things we can remove, and or enhancements we could do. The onActionPerformed is part of usePostActions which is private and leaves the door open for enhancements.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The end goal of this code is to provide the same actions on dataviews, edit site inspector, edit site site details panel, and edit post inspector. Which was on mockups. This means that actions like delete template and revert a template should be available on edit post too. So the editor package seemed to be the best package to have the actions.

Probably yes, but are we 100% sure that every DataViews action should be the same? Probably they should.. It's good to have them in editor package and that wasn't the problem for me.

Yes in the future we may join the delete-post, delete-template, and delete-pattern action in a single action that can be applied to every post. It leaves the possibility for that and I think it may make sense. But it is not the goal.

I think we should do that and that's the goal. I agree we can do it iteratively, but that means we should separate these actions for start (ex. Template actions, post actions, etc..) and then (if not from that iteration) have shared actions.

For me the complexity stems from the fact that we're trying to infer some info in places but on the same time we have hardcoded strings/actions etc.. I think for start we should:

  1. Move the actions to editor package and organise(export) them based on post type probably
  2. Let the consumer pass the actions and have a dumb component to render actions

'move-to-trash',
'reset-template',
'delete-template',
];

export default function PostActions( { onActionPerformed, buttonProps } ) {
Expand All @@ -51,13 +50,7 @@ export default function PostActions( { onActionPerformed, buttonProps } ) {
POST_ACTIONS_WHILE_EDITING
);

if (
[
TEMPLATE_POST_TYPE,
TEMPLATE_PART_POST_TYPE,
PATTERN_POST_TYPE,
].includes( postType )
) {
if ( PATTERN_POST_TYPE === postType ) {
return null;
}
return (
Expand Down
12 changes: 10 additions & 2 deletions packages/editor/src/store/utils/is-template-revertable.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
/**
* Internal dependencies
*/
import { TEMPLATE_ORIGINS } from '../constants';
import {
TEMPLATE_ORIGINS,
TEMPLATE_POST_TYPE,
TEMPLATE_PART_POST_TYPE,
} from '../constants';

// Copy of the function from packages/edit-site/src/utils/is-template-revertable.js

Expand All @@ -12,7 +16,11 @@ import { TEMPLATE_ORIGINS } from '../constants';
* @return {boolean} Whether the template is revertable.
*/
export default function isTemplateRevertable( template ) {
if ( ! template ) {
if (
! template ||
( template.type !== TEMPLATE_POST_TYPE &&
template.type !== TEMPLATE_PART_POST_TYPE )
) {
return false;
}
/* eslint-disable camelcase */
Expand Down
Loading