Skip to content

Commit

Permalink
DataViews: Register the reset template and template part action like …
Browse files Browse the repository at this point in the history
…any third-party action
  • Loading branch information
youknowriad committed Jul 1, 2024
1 parent 4bc4099 commit 99a30cb
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 145 deletions.
2 changes: 1 addition & 1 deletion docs/reference-guides/data/data-core.md
Original file line number Diff line number Diff line change
Expand Up @@ -790,7 +790,7 @@ _Parameters_
- _kind_ `string`: Kind of the entity.
- _name_ `string`: Name of the entity.
- _recordId_ `Object`: ID of the record.
- _options_ `Object`: Saving options.
- _options_ `Object=`: Saving options.

### saveEntityRecord

Expand Down
2 changes: 1 addition & 1 deletion packages/core-data/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ _Parameters_
- _kind_ `string`: Kind of the entity.
- _name_ `string`: Name of the entity.
- _recordId_ `Object`: ID of the record.
- _options_ `Object`: Saving options.
- _options_ `Object=`: Saving options.

### saveEntityRecord

Expand Down
8 changes: 4 additions & 4 deletions packages/core-data/src/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -773,10 +773,10 @@ export const __experimentalBatch =
/**
* Action triggered to save an entity record's edits.
*
* @param {string} kind Kind of the entity.
* @param {string} name Name of the entity.
* @param {Object} recordId ID of the record.
* @param {Object} options Saving options.
* @param {string} kind Kind of the entity.
* @param {string} name Name of the entity.
* @param {Object} recordId ID of the record.
* @param {Object=} options Saving options.
*/
export const saveEditedEntityRecord =
( kind, name, recordId, options ) =>
Expand Down
139 changes: 1 addition & 138 deletions packages/editor/src/components/post-actions/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import {
} from '../../store/constants';
import { store as editorStore } from '../../store';
import { unlock } from '../../lock-unlock';
import isTemplateRevertable from '../../store/utils/is-template-revertable';
import { exportPatternAsJSONAction } from './export-pattern-action';
import { CreateTemplatePartModalContents } from '../create-template-part-modal';

Expand All @@ -57,14 +56,6 @@ function isTemplateRemovable( template ) {
! template?.has_theme_file
);
}
const canDeleteOrReset = ( item ) => {
const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE;
const isUserPattern = item.type === PATTERN_TYPES.user;
return (
isUserPattern ||
( isTemplatePart && item.source === TEMPLATE_ORIGINS.custom )
);
};

function getItemTitle( item ) {
if ( typeof item.title === 'string' ) {
Expand Down Expand Up @@ -795,132 +786,6 @@ const useDuplicatePostAction = ( postType ) => {
);
};

const isTemplatePartRevertable = ( item ) => {
if ( ! item ) {
return false;
}
const hasThemeFile = item?.has_theme_file;
return canDeleteOrReset( item ) && hasThemeFile;
};

const resetTemplateAction = {
id: 'reset-template',
label: __( 'Reset' ),
isEligible: ( item ) => {
return item.type === TEMPLATE_PART_POST_TYPE
? isTemplatePartRevertable( item )
: isTemplateRevertable( item );
},
icon: backup,
supportsBulk: true,
hideModalHeader: true,
RenderModal: ( { items, closeModal, onActionPerformed } ) => {
const [ isBusy, setIsBusy ] = useState( false );
const { revertTemplate, removeTemplates } = unlock(
useDispatch( editorStore )
);
const { saveEditedEntityRecord } = useDispatch( coreStore );
const { createSuccessNotice, createErrorNotice } =
useDispatch( noticesStore );
const onConfirm = async () => {
try {
if ( items[ 0 ].type === TEMPLATE_PART_POST_TYPE ) {
await removeTemplates( items );
} else {
for ( const template of items ) {
if ( template.type === TEMPLATE_POST_TYPE ) {
await revertTemplate( template, {
allowUndo: false,
} );
await saveEditedEntityRecord(
'postType',
template.type,
template.id
);
}
}
createSuccessNotice(
items.length > 1
? sprintf(
/* translators: The number of items. */
__( '%s items reset.' ),
items.length
)
: sprintf(
/* translators: The template/part's name. */
__( '"%s" reset.' ),
decodeEntities( getItemTitle( items[ 0 ] ) )
),
{
type: 'snackbar',
id: 'revert-template-action',
}
);
}
} catch ( error ) {
let fallbackErrorMessage;
if ( items[ 0 ].type === TEMPLATE_POST_TYPE ) {
fallbackErrorMessage =
items.length === 1
? __(
'An error occurred while reverting the template.'
)
: __(
'An error occurred while reverting the templates.'
);
} else {
fallbackErrorMessage =
items.length === 1
? __(
'An error occurred while reverting the template part.'
)
: __(
'An error occurred while reverting the template parts.'
);
}
const errorMessage =
error.message && error.code !== 'unknown_error'
? error.message
: fallbackErrorMessage;

createErrorNotice( errorMessage, { type: 'snackbar' } );
}
};
return (
<VStack spacing="5">
<Text>
{ __( 'Reset to default and clear all customizations?' ) }
</Text>
<HStack justify="right">
<Button
variant="tertiary"
onClick={ closeModal }
disabled={ isBusy }
__experimentalIsFocusable
>
{ __( 'Cancel' ) }
</Button>
<Button
variant="primary"
onClick={ async () => {
setIsBusy( true );
await onConfirm( items );
onActionPerformed?.( items );
setIsBusy( false );
closeModal();
} }
isBusy={ isBusy }
disabled={ isBusy }
__experimentalIsFocusable
>
{ __( 'Reset' ) }
</Button>
</HStack>
</VStack>
);
},
};

export const duplicatePatternAction = {
id: 'duplicate-pattern',
label: _x( 'Duplicate', 'action label' ),
Expand Down Expand Up @@ -1046,9 +911,7 @@ export function usePostActions( { postType, onActionPerformed, context } ) {
isPattern && userCanCreatePostType && duplicatePatternAction,
supportsTitle && renamePostActionForPostType,
isPattern && exportPatternAsJSONAction,
isTemplateOrTemplatePart
? resetTemplateAction
: restorePostActionForPostType,
! isTemplateOrTemplatePart && restorePostActionForPostType,
! isTemplateOrTemplatePart &&
! isPattern &&
trashPostActionForPostType,
Expand Down
3 changes: 3 additions & 0 deletions packages/editor/src/dataviews/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { type StoreDescriptor, dispatch } from '@wordpress/data';
* Internal dependencies
*/
import deletePost from './delete-post';
import resetPost from './reset-post';

// @ts-ignore
import { store as editorStore } from '../../store';
import { unlock } from '../../lock-unlock';
Expand All @@ -16,5 +18,6 @@ export default function registerDefaultActions() {
dispatch( editorStore as StoreDescriptor )
);

registerEntityAction( 'postType', '*', resetPost );
registerEntityAction( 'postType', '*', deletePost );
}
153 changes: 153 additions & 0 deletions packages/editor/src/dataviews/actions/reset-post.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/**
* WordPress dependencies
*/
import { backup } from '@wordpress/icons';
import { useDispatch } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';
import { __, _n, sprintf, _x } from '@wordpress/i18n';
import { store as noticesStore } from '@wordpress/notices';
import { useState } from '@wordpress/element';
import {
Button,
__experimentalText as Text,
__experimentalHStack as HStack,
__experimentalVStack as VStack,
} from '@wordpress/components';
import type { Action } from '@wordpress/dataviews';
import type { StoreDescriptor } from '@wordpress/data';

/**
* Internal dependencies
*/
import {
TEMPLATE_PART_POST_TYPE,
TEMPLATE_POST_TYPE,
TEMPLATE_ORIGINS,
} from '../../store/constants';
import { store as editorStore } from '../../store';
import { unlock } from '../../lock-unlock';
import type { Post, CoreDataError } from '../types';
import { isTemplateOrTemplatePart, getItemTitle } from './utils';

const resetPost: Action< Post > = {
id: 'reset-post',
label: __( 'Reset' ),
isEligible: ( item ) => {
return (
isTemplateOrTemplatePart( item ) &&
item?.source === TEMPLATE_ORIGINS.custom &&
item?.has_theme_file
);
},
icon: backup,
supportsBulk: true,
hideModalHeader: true,
RenderModal: ( { items, closeModal, onActionPerformed } ) => {
const [ isBusy, setIsBusy ] = useState( false );
const { revertTemplate, removeTemplates } = unlock(
useDispatch( editorStore as StoreDescriptor )
);
const { saveEditedEntityRecord } = useDispatch( coreStore );
const { createSuccessNotice, createErrorNotice } =
useDispatch( noticesStore );
const onConfirm = async () => {
try {
if ( items[ 0 ].type === TEMPLATE_PART_POST_TYPE ) {
await removeTemplates( items );
} else {
for ( const template of items ) {
if ( template.type === TEMPLATE_POST_TYPE ) {
await revertTemplate( template, {
allowUndo: false,
} );
await saveEditedEntityRecord(
'postType',
template.type,
template.id
);
}
}
createSuccessNotice(
items.length > 1
? sprintf(
/* translators: The number of items. */
__( '%s items reset.' ),
items.length
)
: sprintf(
/* translators: The template/part's name. */
__( '"%s" reset.' ),
getItemTitle( items[ 0 ] )
),
{
type: 'snackbar',
id: 'revert-template-action',
}
);
}
} catch ( error ) {
const typedError = error as CoreDataError;
let fallbackErrorMessage;
if ( items[ 0 ].type === TEMPLATE_POST_TYPE ) {
fallbackErrorMessage =
items.length === 1
? __(
'An error occurred while reverting the template.'
)
: __(
'An error occurred while reverting the templates.'
);
} else {
fallbackErrorMessage =
items.length === 1
? __(
'An error occurred while reverting the template part.'
)
: __(
'An error occurred while reverting the template parts.'
);
}
const errorMessage =
typedError.message && typedError.code !== 'unknown_error'
? typedError.message
: fallbackErrorMessage;

createErrorNotice( errorMessage, { type: 'snackbar' } );
}
};
return (
<VStack spacing="5">
<Text>
{ __( 'Reset to default and clear all customizations?' ) }
</Text>
<HStack justify="right">
<Button
variant="tertiary"
onClick={ closeModal }
disabled={ isBusy }
__experimentalIsFocusable
>
{ __( 'Cancel' ) }
</Button>
<Button
variant="primary"
onClick={ async () => {
setIsBusy( true );
await onConfirm();
onActionPerformed?.( items );
setIsBusy( false );
closeModal?.();
} }
isBusy={ isBusy }
disabled={ isBusy }
__experimentalIsFocusable
>
{ __( 'Reset' ) }
</Button>
</HStack>
</VStack>
);
},
};

export default resetPost;
7 changes: 6 additions & 1 deletion packages/editor/src/dataviews/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@ export interface BasePost {
status?: PostStatus;
title: string | { rendered: string };
type: string;
id: string | number;
}
export interface TemplateOrTemplatePart extends BasePost {
type: 'template' | 'template-part';
type: 'wp_template' | 'wp_template_part';
source: string;
has_theme_file: boolean;
ud: string;
}

export type Post = TemplateOrTemplatePart | BasePost;

// Will be unnecessary after typescript 5.0 upgrade.
export type CoreDataError = { message?: string; code?: string };

0 comments on commit 99a30cb

Please sign in to comment.