Skip to content

Commit 99a30cb

Browse files
committed
DataViews: Register the reset template and template part action like any third-party action
1 parent 4bc4099 commit 99a30cb

File tree

7 files changed

+169
-145
lines changed

7 files changed

+169
-145
lines changed

docs/reference-guides/data/data-core.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,7 @@ _Parameters_
790790
- _kind_ `string`: Kind of the entity.
791791
- _name_ `string`: Name of the entity.
792792
- _recordId_ `Object`: ID of the record.
793-
- _options_ `Object`: Saving options.
793+
- _options_ `Object=`: Saving options.
794794

795795
### saveEntityRecord
796796

packages/core-data/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ _Parameters_
299299
- _kind_ `string`: Kind of the entity.
300300
- _name_ `string`: Name of the entity.
301301
- _recordId_ `Object`: ID of the record.
302-
- _options_ `Object`: Saving options.
302+
- _options_ `Object=`: Saving options.
303303

304304
### saveEntityRecord
305305

packages/core-data/src/actions.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -773,10 +773,10 @@ export const __experimentalBatch =
773773
/**
774774
* Action triggered to save an entity record's edits.
775775
*
776-
* @param {string} kind Kind of the entity.
777-
* @param {string} name Name of the entity.
778-
* @param {Object} recordId ID of the record.
779-
* @param {Object} options Saving options.
776+
* @param {string} kind Kind of the entity.
777+
* @param {string} name Name of the entity.
778+
* @param {Object} recordId ID of the record.
779+
* @param {Object=} options Saving options.
780780
*/
781781
export const saveEditedEntityRecord =
782782
( kind, name, recordId, options ) =>

packages/editor/src/components/post-actions/actions.js

Lines changed: 1 addition & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import {
3131
} from '../../store/constants';
3232
import { store as editorStore } from '../../store';
3333
import { unlock } from '../../lock-unlock';
34-
import isTemplateRevertable from '../../store/utils/is-template-revertable';
3534
import { exportPatternAsJSONAction } from './export-pattern-action';
3635
import { CreateTemplatePartModalContents } from '../create-template-part-modal';
3736

@@ -57,14 +56,6 @@ function isTemplateRemovable( template ) {
5756
! template?.has_theme_file
5857
);
5958
}
60-
const canDeleteOrReset = ( item ) => {
61-
const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE;
62-
const isUserPattern = item.type === PATTERN_TYPES.user;
63-
return (
64-
isUserPattern ||
65-
( isTemplatePart && item.source === TEMPLATE_ORIGINS.custom )
66-
);
67-
};
6859

6960
function getItemTitle( item ) {
7061
if ( typeof item.title === 'string' ) {
@@ -795,132 +786,6 @@ const useDuplicatePostAction = ( postType ) => {
795786
);
796787
};
797788

798-
const isTemplatePartRevertable = ( item ) => {
799-
if ( ! item ) {
800-
return false;
801-
}
802-
const hasThemeFile = item?.has_theme_file;
803-
return canDeleteOrReset( item ) && hasThemeFile;
804-
};
805-
806-
const resetTemplateAction = {
807-
id: 'reset-template',
808-
label: __( 'Reset' ),
809-
isEligible: ( item ) => {
810-
return item.type === TEMPLATE_PART_POST_TYPE
811-
? isTemplatePartRevertable( item )
812-
: isTemplateRevertable( item );
813-
},
814-
icon: backup,
815-
supportsBulk: true,
816-
hideModalHeader: true,
817-
RenderModal: ( { items, closeModal, onActionPerformed } ) => {
818-
const [ isBusy, setIsBusy ] = useState( false );
819-
const { revertTemplate, removeTemplates } = unlock(
820-
useDispatch( editorStore )
821-
);
822-
const { saveEditedEntityRecord } = useDispatch( coreStore );
823-
const { createSuccessNotice, createErrorNotice } =
824-
useDispatch( noticesStore );
825-
const onConfirm = async () => {
826-
try {
827-
if ( items[ 0 ].type === TEMPLATE_PART_POST_TYPE ) {
828-
await removeTemplates( items );
829-
} else {
830-
for ( const template of items ) {
831-
if ( template.type === TEMPLATE_POST_TYPE ) {
832-
await revertTemplate( template, {
833-
allowUndo: false,
834-
} );
835-
await saveEditedEntityRecord(
836-
'postType',
837-
template.type,
838-
template.id
839-
);
840-
}
841-
}
842-
createSuccessNotice(
843-
items.length > 1
844-
? sprintf(
845-
/* translators: The number of items. */
846-
__( '%s items reset.' ),
847-
items.length
848-
)
849-
: sprintf(
850-
/* translators: The template/part's name. */
851-
__( '"%s" reset.' ),
852-
decodeEntities( getItemTitle( items[ 0 ] ) )
853-
),
854-
{
855-
type: 'snackbar',
856-
id: 'revert-template-action',
857-
}
858-
);
859-
}
860-
} catch ( error ) {
861-
let fallbackErrorMessage;
862-
if ( items[ 0 ].type === TEMPLATE_POST_TYPE ) {
863-
fallbackErrorMessage =
864-
items.length === 1
865-
? __(
866-
'An error occurred while reverting the template.'
867-
)
868-
: __(
869-
'An error occurred while reverting the templates.'
870-
);
871-
} else {
872-
fallbackErrorMessage =
873-
items.length === 1
874-
? __(
875-
'An error occurred while reverting the template part.'
876-
)
877-
: __(
878-
'An error occurred while reverting the template parts.'
879-
);
880-
}
881-
const errorMessage =
882-
error.message && error.code !== 'unknown_error'
883-
? error.message
884-
: fallbackErrorMessage;
885-
886-
createErrorNotice( errorMessage, { type: 'snackbar' } );
887-
}
888-
};
889-
return (
890-
<VStack spacing="5">
891-
<Text>
892-
{ __( 'Reset to default and clear all customizations?' ) }
893-
</Text>
894-
<HStack justify="right">
895-
<Button
896-
variant="tertiary"
897-
onClick={ closeModal }
898-
disabled={ isBusy }
899-
__experimentalIsFocusable
900-
>
901-
{ __( 'Cancel' ) }
902-
</Button>
903-
<Button
904-
variant="primary"
905-
onClick={ async () => {
906-
setIsBusy( true );
907-
await onConfirm( items );
908-
onActionPerformed?.( items );
909-
setIsBusy( false );
910-
closeModal();
911-
} }
912-
isBusy={ isBusy }
913-
disabled={ isBusy }
914-
__experimentalIsFocusable
915-
>
916-
{ __( 'Reset' ) }
917-
</Button>
918-
</HStack>
919-
</VStack>
920-
);
921-
},
922-
};
923-
924789
export const duplicatePatternAction = {
925790
id: 'duplicate-pattern',
926791
label: _x( 'Duplicate', 'action label' ),
@@ -1046,9 +911,7 @@ export function usePostActions( { postType, onActionPerformed, context } ) {
1046911
isPattern && userCanCreatePostType && duplicatePatternAction,
1047912
supportsTitle && renamePostActionForPostType,
1048913
isPattern && exportPatternAsJSONAction,
1049-
isTemplateOrTemplatePart
1050-
? resetTemplateAction
1051-
: restorePostActionForPostType,
914+
! isTemplateOrTemplatePart && restorePostActionForPostType,
1052915
! isTemplateOrTemplatePart &&
1053916
! isPattern &&
1054917
trashPostActionForPostType,

packages/editor/src/dataviews/actions/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { type StoreDescriptor, dispatch } from '@wordpress/data';
77
* Internal dependencies
88
*/
99
import deletePost from './delete-post';
10+
import resetPost from './reset-post';
11+
1012
// @ts-ignore
1113
import { store as editorStore } from '../../store';
1214
import { unlock } from '../../lock-unlock';
@@ -16,5 +18,6 @@ export default function registerDefaultActions() {
1618
dispatch( editorStore as StoreDescriptor )
1719
);
1820

21+
registerEntityAction( 'postType', '*', resetPost );
1922
registerEntityAction( 'postType', '*', deletePost );
2023
}
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/**
2+
* WordPress dependencies
3+
*/
4+
import { backup } from '@wordpress/icons';
5+
import { useDispatch } from '@wordpress/data';
6+
import { store as coreStore } from '@wordpress/core-data';
7+
import { __, _n, sprintf, _x } from '@wordpress/i18n';
8+
import { store as noticesStore } from '@wordpress/notices';
9+
import { useState } from '@wordpress/element';
10+
import {
11+
Button,
12+
__experimentalText as Text,
13+
__experimentalHStack as HStack,
14+
__experimentalVStack as VStack,
15+
} from '@wordpress/components';
16+
import type { Action } from '@wordpress/dataviews';
17+
import type { StoreDescriptor } from '@wordpress/data';
18+
19+
/**
20+
* Internal dependencies
21+
*/
22+
import {
23+
TEMPLATE_PART_POST_TYPE,
24+
TEMPLATE_POST_TYPE,
25+
TEMPLATE_ORIGINS,
26+
} from '../../store/constants';
27+
import { store as editorStore } from '../../store';
28+
import { unlock } from '../../lock-unlock';
29+
import type { Post, CoreDataError } from '../types';
30+
import { isTemplateOrTemplatePart, getItemTitle } from './utils';
31+
32+
const resetPost: Action< Post > = {
33+
id: 'reset-post',
34+
label: __( 'Reset' ),
35+
isEligible: ( item ) => {
36+
return (
37+
isTemplateOrTemplatePart( item ) &&
38+
item?.source === TEMPLATE_ORIGINS.custom &&
39+
item?.has_theme_file
40+
);
41+
},
42+
icon: backup,
43+
supportsBulk: true,
44+
hideModalHeader: true,
45+
RenderModal: ( { items, closeModal, onActionPerformed } ) => {
46+
const [ isBusy, setIsBusy ] = useState( false );
47+
const { revertTemplate, removeTemplates } = unlock(
48+
useDispatch( editorStore as StoreDescriptor )
49+
);
50+
const { saveEditedEntityRecord } = useDispatch( coreStore );
51+
const { createSuccessNotice, createErrorNotice } =
52+
useDispatch( noticesStore );
53+
const onConfirm = async () => {
54+
try {
55+
if ( items[ 0 ].type === TEMPLATE_PART_POST_TYPE ) {
56+
await removeTemplates( items );
57+
} else {
58+
for ( const template of items ) {
59+
if ( template.type === TEMPLATE_POST_TYPE ) {
60+
await revertTemplate( template, {
61+
allowUndo: false,
62+
} );
63+
await saveEditedEntityRecord(
64+
'postType',
65+
template.type,
66+
template.id
67+
);
68+
}
69+
}
70+
createSuccessNotice(
71+
items.length > 1
72+
? sprintf(
73+
/* translators: The number of items. */
74+
__( '%s items reset.' ),
75+
items.length
76+
)
77+
: sprintf(
78+
/* translators: The template/part's name. */
79+
__( '"%s" reset.' ),
80+
getItemTitle( items[ 0 ] )
81+
),
82+
{
83+
type: 'snackbar',
84+
id: 'revert-template-action',
85+
}
86+
);
87+
}
88+
} catch ( error ) {
89+
const typedError = error as CoreDataError;
90+
let fallbackErrorMessage;
91+
if ( items[ 0 ].type === TEMPLATE_POST_TYPE ) {
92+
fallbackErrorMessage =
93+
items.length === 1
94+
? __(
95+
'An error occurred while reverting the template.'
96+
)
97+
: __(
98+
'An error occurred while reverting the templates.'
99+
);
100+
} else {
101+
fallbackErrorMessage =
102+
items.length === 1
103+
? __(
104+
'An error occurred while reverting the template part.'
105+
)
106+
: __(
107+
'An error occurred while reverting the template parts.'
108+
);
109+
}
110+
const errorMessage =
111+
typedError.message && typedError.code !== 'unknown_error'
112+
? typedError.message
113+
: fallbackErrorMessage;
114+
115+
createErrorNotice( errorMessage, { type: 'snackbar' } );
116+
}
117+
};
118+
return (
119+
<VStack spacing="5">
120+
<Text>
121+
{ __( 'Reset to default and clear all customizations?' ) }
122+
</Text>
123+
<HStack justify="right">
124+
<Button
125+
variant="tertiary"
126+
onClick={ closeModal }
127+
disabled={ isBusy }
128+
__experimentalIsFocusable
129+
>
130+
{ __( 'Cancel' ) }
131+
</Button>
132+
<Button
133+
variant="primary"
134+
onClick={ async () => {
135+
setIsBusy( true );
136+
await onConfirm();
137+
onActionPerformed?.( items );
138+
setIsBusy( false );
139+
closeModal?.();
140+
} }
141+
isBusy={ isBusy }
142+
disabled={ isBusy }
143+
__experimentalIsFocusable
144+
>
145+
{ __( 'Reset' ) }
146+
</Button>
147+
</HStack>
148+
</VStack>
149+
);
150+
},
151+
};
152+
153+
export default resetPost;

packages/editor/src/dataviews/types.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,16 @@ export interface BasePost {
1111
status?: PostStatus;
1212
title: string | { rendered: string };
1313
type: string;
14+
id: string | number;
1415
}
1516
export interface TemplateOrTemplatePart extends BasePost {
16-
type: 'template' | 'template-part';
17+
type: 'wp_template' | 'wp_template_part';
1718
source: string;
1819
has_theme_file: boolean;
20+
ud: string;
1921
}
2022

2123
export type Post = TemplateOrTemplatePart | BasePost;
24+
25+
// Will be unnecessary after typescript 5.0 upgrade.
26+
export type CoreDataError = { message?: string; code?: string };

0 commit comments

Comments
 (0)