@wordpress/fields 0.0.7 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +20 -0
  3. package/build/actions/delete-post.js +130 -0
  4. package/build/actions/delete-post.js.map +1 -0
  5. package/build/actions/{pattern/duplicate-pattern.js → duplicate-pattern.js} +1 -1
  6. package/build/actions/duplicate-pattern.js.map +1 -0
  7. package/build/actions/{base-post/duplicate-post.js → duplicate-post.js} +3 -3
  8. package/build/actions/duplicate-post.js.map +1 -0
  9. package/build/actions/duplicate-post.native.js.map +1 -0
  10. package/build/actions/{pattern/export-pattern.js → export-pattern.js} +1 -1
  11. package/build/actions/export-pattern.js.map +1 -0
  12. package/build/actions/export-pattern.native.js.map +1 -0
  13. package/build/actions/index.js +105 -32
  14. package/build/actions/index.js.map +1 -1
  15. package/build/actions/{common/permanently-delete-post.js → permanently-delete-post.js} +5 -4
  16. package/build/actions/permanently-delete-post.js.map +1 -0
  17. package/build/actions/rename-post.js +124 -0
  18. package/build/actions/rename-post.js.map +1 -0
  19. package/build/actions/{base-post/reorder-page.js → reorder-page.js} +1 -1
  20. package/build/actions/reorder-page.js.map +1 -0
  21. package/build/actions/reorder-page.native.js.map +1 -0
  22. package/build/actions/reset-post.js +206 -0
  23. package/build/actions/reset-post.js.map +1 -0
  24. package/build/actions/restore-post.js +113 -0
  25. package/build/actions/restore-post.js.map +1 -0
  26. package/build/actions/trash-post.js +145 -0
  27. package/build/actions/trash-post.js.map +1 -0
  28. package/build/actions/{common/view-post-revisions.js → view-post-revisions.js} +1 -1
  29. package/build/actions/view-post-revisions.js.map +1 -0
  30. package/build/actions/view-post.js.map +1 -0
  31. package/build/index.native.js +2 -2
  32. package/build/index.native.js.map +1 -1
  33. package/build/mutation/index.js +140 -0
  34. package/build/mutation/index.js.map +1 -0
  35. package/build/types.js.map +1 -1
  36. package/build-module/actions/delete-post.js +122 -0
  37. package/build-module/actions/delete-post.js.map +1 -0
  38. package/build-module/actions/{pattern/duplicate-pattern.js → duplicate-pattern.js} +1 -1
  39. package/build-module/actions/duplicate-pattern.js.map +1 -0
  40. package/build-module/actions/{base-post/duplicate-post.js → duplicate-post.js} +4 -5
  41. package/build-module/actions/duplicate-post.js.map +1 -0
  42. package/build-module/actions/duplicate-post.native.js.map +1 -0
  43. package/build-module/actions/{pattern/export-pattern.js → export-pattern.js} +1 -1
  44. package/build-module/actions/export-pattern.js.map +1 -0
  45. package/build-module/actions/export-pattern.native.js.map +1 -0
  46. package/build-module/actions/index.js +15 -3
  47. package/build-module/actions/index.js.map +1 -1
  48. package/build-module/actions/{common/permanently-delete-post.js → permanently-delete-post.js} +5 -4
  49. package/build-module/actions/permanently-delete-post.js.map +1 -0
  50. package/build-module/actions/rename-post.js +117 -0
  51. package/build-module/actions/rename-post.js.map +1 -0
  52. package/build-module/actions/{base-post/reorder-page.js → reorder-page.js} +2 -3
  53. package/build-module/actions/reorder-page.js.map +1 -0
  54. package/build-module/actions/reorder-page.native.js.map +1 -0
  55. package/build-module/actions/reset-post.js +197 -0
  56. package/build-module/actions/reset-post.js.map +1 -0
  57. package/build-module/actions/restore-post.js +105 -0
  58. package/build-module/actions/restore-post.js.map +1 -0
  59. package/build-module/actions/trash-post.js +137 -0
  60. package/build-module/actions/trash-post.js.map +1 -0
  61. package/build-module/actions/{common/view-post-revisions.js → view-post-revisions.js} +1 -1
  62. package/build-module/actions/view-post-revisions.js.map +1 -0
  63. package/build-module/actions/view-post.js.map +1 -0
  64. package/build-module/index.native.js +2 -2
  65. package/build-module/index.native.js.map +1 -1
  66. package/build-module/mutation/index.js +132 -0
  67. package/build-module/mutation/index.js.map +1 -0
  68. package/build-module/types.js.map +1 -1
  69. package/build-types/actions/delete-post.d.ts +5 -0
  70. package/build-types/actions/delete-post.d.ts.map +1 -0
  71. package/build-types/actions/{pattern/duplicate-pattern.d.ts → duplicate-pattern.d.ts} +1 -1
  72. package/build-types/actions/duplicate-pattern.d.ts.map +1 -0
  73. package/build-types/actions/{base-post/duplicate-post.d.ts → duplicate-post.d.ts} +1 -1
  74. package/build-types/actions/duplicate-post.d.ts.map +1 -0
  75. package/build-types/actions/duplicate-post.native.d.ts.map +1 -0
  76. package/build-types/actions/{pattern/export-pattern.d.ts → export-pattern.d.ts} +1 -1
  77. package/build-types/actions/export-pattern.d.ts.map +1 -0
  78. package/build-types/actions/export-pattern.native.d.ts.map +1 -0
  79. package/build-types/actions/index.d.ts +15 -3
  80. package/build-types/actions/index.d.ts.map +1 -1
  81. package/build-types/actions/{common/permanently-delete-post.d.ts → permanently-delete-post.d.ts} +1 -1
  82. package/build-types/actions/permanently-delete-post.d.ts.map +1 -0
  83. package/build-types/actions/rename-post.d.ts +5 -0
  84. package/build-types/actions/rename-post.d.ts.map +1 -0
  85. package/build-types/actions/{base-post/reorder-page.d.ts → reorder-page.d.ts} +1 -1
  86. package/build-types/actions/reorder-page.d.ts.map +1 -0
  87. package/build-types/actions/reorder-page.native.d.ts.map +1 -0
  88. package/build-types/actions/reset-post.d.ts +5 -0
  89. package/build-types/actions/reset-post.d.ts.map +1 -0
  90. package/build-types/actions/restore-post.d.ts +5 -0
  91. package/build-types/actions/restore-post.d.ts.map +1 -0
  92. package/build-types/actions/trash-post.d.ts +5 -0
  93. package/build-types/actions/trash-post.d.ts.map +1 -0
  94. package/build-types/actions/{common/view-post-revisions.d.ts → view-post-revisions.d.ts} +1 -1
  95. package/build-types/actions/view-post-revisions.d.ts.map +1 -0
  96. package/build-types/actions/{base-post/view-post.d.ts → view-post.d.ts} +1 -1
  97. package/build-types/actions/view-post.d.ts.map +1 -0
  98. package/build-types/index.native.d.ts +2 -2
  99. package/build-types/index.native.d.ts.map +1 -1
  100. package/build-types/mutation/index.d.ts +34 -0
  101. package/build-types/mutation/index.d.ts.map +1 -0
  102. package/build-types/types.d.ts +1 -0
  103. package/build-types/types.d.ts.map +1 -1
  104. package/package.json +22 -21
  105. package/src/actions/delete-post.tsx +203 -0
  106. package/src/actions/{pattern/duplicate-pattern.tsx → duplicate-pattern.tsx} +2 -2
  107. package/src/actions/{base-post/duplicate-post.tsx → duplicate-post.tsx} +3 -3
  108. package/src/actions/{pattern/export-pattern.tsx → export-pattern.tsx} +2 -2
  109. package/src/actions/index.ts +15 -3
  110. package/src/actions/{common/permanently-delete-post.tsx → permanently-delete-post.tsx} +2 -2
  111. package/src/actions/rename-post.tsx +145 -0
  112. package/src/actions/{base-post/reorder-page.tsx → reorder-page.tsx} +2 -2
  113. package/src/actions/reset-post.tsx +300 -0
  114. package/src/actions/restore-post.tsx +134 -0
  115. package/src/actions/trash-post.tsx +198 -0
  116. package/src/actions/{common/view-post-revisions.tsx → view-post-revisions.tsx} +1 -1
  117. package/src/actions/{base-post/view-post.tsx → view-post.tsx} +1 -1
  118. package/src/index.native.ts +2 -2
  119. package/src/mutation/index.ts +184 -0
  120. package/src/types.ts +1 -0
  121. package/tsconfig.json +2 -2
  122. package/tsconfig.tsbuildinfo +1 -1
  123. package/build/actions/base-post/duplicate-post.js.map +0 -1
  124. package/build/actions/base-post/duplicate-post.native.js.map +0 -1
  125. package/build/actions/base-post/index.js +0 -42
  126. package/build/actions/base-post/index.js.map +0 -1
  127. package/build/actions/base-post/reorder-page.js.map +0 -1
  128. package/build/actions/base-post/reorder-page.native.js.map +0 -1
  129. package/build/actions/base-post/view-post.js.map +0 -1
  130. package/build/actions/common/index.js +0 -21
  131. package/build/actions/common/index.js.map +0 -1
  132. package/build/actions/common/permanently-delete-post.js.map +0 -1
  133. package/build/actions/common/view-post-revisions.js.map +0 -1
  134. package/build/actions/pattern/duplicate-pattern.js.map +0 -1
  135. package/build/actions/pattern/export-pattern.js.map +0 -1
  136. package/build/actions/pattern/export-pattern.native.js.map +0 -1
  137. package/build/actions/pattern/index.js +0 -28
  138. package/build/actions/pattern/index.js.map +0 -1
  139. package/build/wordpress-editor.d.js +0 -2
  140. package/build/wordpress-editor.d.js.map +0 -1
  141. package/build-module/actions/base-post/duplicate-post.js.map +0 -1
  142. package/build-module/actions/base-post/duplicate-post.native.js.map +0 -1
  143. package/build-module/actions/base-post/index.js +0 -6
  144. package/build-module/actions/base-post/index.js.map +0 -1
  145. package/build-module/actions/base-post/reorder-page.js.map +0 -1
  146. package/build-module/actions/base-post/reorder-page.native.js.map +0 -1
  147. package/build-module/actions/base-post/view-post.js.map +0 -1
  148. package/build-module/actions/common/index.js +0 -3
  149. package/build-module/actions/common/index.js.map +0 -1
  150. package/build-module/actions/common/permanently-delete-post.js.map +0 -1
  151. package/build-module/actions/common/view-post-revisions.js.map +0 -1
  152. package/build-module/actions/pattern/duplicate-pattern.js.map +0 -1
  153. package/build-module/actions/pattern/export-pattern.js.map +0 -1
  154. package/build-module/actions/pattern/export-pattern.native.js.map +0 -1
  155. package/build-module/actions/pattern/index.js +0 -4
  156. package/build-module/actions/pattern/index.js.map +0 -1
  157. package/build-module/wordpress-editor.d.js +0 -2
  158. package/build-module/wordpress-editor.d.js.map +0 -1
  159. package/build-types/actions/base-post/duplicate-post.d.ts.map +0 -1
  160. package/build-types/actions/base-post/duplicate-post.native.d.ts.map +0 -1
  161. package/build-types/actions/base-post/index.d.ts +0 -6
  162. package/build-types/actions/base-post/index.d.ts.map +0 -1
  163. package/build-types/actions/base-post/reorder-page.d.ts.map +0 -1
  164. package/build-types/actions/base-post/reorder-page.native.d.ts.map +0 -1
  165. package/build-types/actions/base-post/view-post.d.ts.map +0 -1
  166. package/build-types/actions/common/index.d.ts +0 -3
  167. package/build-types/actions/common/index.d.ts.map +0 -1
  168. package/build-types/actions/common/permanently-delete-post.d.ts.map +0 -1
  169. package/build-types/actions/common/view-post-revisions.d.ts.map +0 -1
  170. package/build-types/actions/pattern/duplicate-pattern.d.ts.map +0 -1
  171. package/build-types/actions/pattern/export-pattern.d.ts.map +0 -1
  172. package/build-types/actions/pattern/export-pattern.native.d.ts.map +0 -1
  173. package/build-types/actions/pattern/index.d.ts +0 -4
  174. package/build-types/actions/pattern/index.d.ts.map +0 -1
  175. package/src/actions/base-post/index.ts +0 -5
  176. package/src/actions/common/index.ts +0 -2
  177. package/src/actions/pattern/index.ts +0 -3
  178. package/src/wordpress-editor.d.ts +0 -1
  179. /package/build/actions/{base-post/duplicate-post.native.js → duplicate-post.native.js} +0 -0
  180. /package/build/actions/{pattern/export-pattern.native.js → export-pattern.native.js} +0 -0
  181. /package/build/actions/{base-post/reorder-page.native.js → reorder-page.native.js} +0 -0
  182. /package/build/actions/{base-post/view-post.js → view-post.js} +0 -0
  183. /package/build-module/actions/{base-post/duplicate-post.native.js → duplicate-post.native.js} +0 -0
  184. /package/build-module/actions/{pattern/export-pattern.native.js → export-pattern.native.js} +0 -0
  185. /package/build-module/actions/{base-post/reorder-page.native.js → reorder-page.native.js} +0 -0
  186. /package/build-module/actions/{base-post/view-post.js → view-post.js} +0 -0
  187. /package/build-types/actions/{base-post/duplicate-post.native.d.ts → duplicate-post.native.d.ts} +0 -0
  188. /package/build-types/actions/{pattern/export-pattern.native.d.ts → export-pattern.native.d.ts} +0 -0
  189. /package/build-types/actions/{base-post/reorder-page.native.d.ts → reorder-page.native.d.ts} +0 -0
  190. /package/src/actions/{base-post/duplicate-post.native.tsx → duplicate-post.native.tsx} +0 -0
  191. /package/src/actions/{pattern/export-pattern.native.tsx → export-pattern.native.tsx} +0 -0
  192. /package/src/actions/{base-post/reorder-page.native.tsx → reorder-page.native.tsx} +0 -0
@@ -0,0 +1,300 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { backup } from '@wordpress/icons';
5
+ import { dispatch, select, useDispatch } from '@wordpress/data';
6
+ import { store as coreStore } from '@wordpress/core-data';
7
+ import { __, sprintf } from '@wordpress/i18n';
8
+ import { store as noticesStore } from '@wordpress/notices';
9
+ import { useState } from '@wordpress/element';
10
+ // @ts-ignore
11
+ import { parse, __unstableSerializeAndClean } from '@wordpress/blocks';
12
+ import {
13
+ Button,
14
+ __experimentalText as Text,
15
+ __experimentalHStack as HStack,
16
+ __experimentalVStack as VStack,
17
+ } from '@wordpress/components';
18
+ import type { Action } from '@wordpress/dataviews';
19
+ import { addQueryArgs } from '@wordpress/url';
20
+ import apiFetch from '@wordpress/api-fetch';
21
+
22
+ /**
23
+ * Internal dependencies
24
+ */
25
+ import {
26
+ getItemTitle,
27
+ isTemplateOrTemplatePart,
28
+ TEMPLATE_ORIGINS,
29
+ TEMPLATE_POST_TYPE,
30
+ } from './utils';
31
+ import type { CoreDataError, Template, TemplatePart } from '../types';
32
+
33
+ const isTemplateRevertable = (
34
+ templateOrTemplatePart: Template | TemplatePart
35
+ ) => {
36
+ if ( ! templateOrTemplatePart ) {
37
+ return false;
38
+ }
39
+
40
+ return (
41
+ templateOrTemplatePart.source === TEMPLATE_ORIGINS.custom &&
42
+ ( Boolean( templateOrTemplatePart?.plugin ) ||
43
+ templateOrTemplatePart?.has_theme_file )
44
+ );
45
+ };
46
+
47
+ /**
48
+ * Copied - pasted from https://github.com/WordPress/gutenberg/blob/bf1462ad37d4637ebbf63270b9c244b23c69e2a8/packages/editor/src/store/private-actions.js#L233-L365
49
+ *
50
+ * @param {Object} template The template to revert.
51
+ * @param {Object} [options]
52
+ * @param {boolean} [options.allowUndo] Whether to allow the user to undo
53
+ * reverting the template. Default true.
54
+ */
55
+ const revertTemplate = async (
56
+ template: TemplatePart | Template,
57
+ { allowUndo = true } = {}
58
+ ) => {
59
+ const noticeId = 'edit-site-template-reverted';
60
+ dispatch( noticesStore ).removeNotice( noticeId );
61
+ if ( ! isTemplateRevertable( template ) ) {
62
+ dispatch( noticesStore ).createErrorNotice(
63
+ __( 'This template is not revertable.' ),
64
+ {
65
+ type: 'snackbar',
66
+ }
67
+ );
68
+ return;
69
+ }
70
+
71
+ try {
72
+ const templateEntityConfig = select( coreStore ).getEntityConfig(
73
+ 'postType',
74
+ template.type
75
+ );
76
+
77
+ if ( ! templateEntityConfig ) {
78
+ dispatch( noticesStore ).createErrorNotice(
79
+ __(
80
+ 'The editor has encountered an unexpected error. Please reload.'
81
+ ),
82
+ { type: 'snackbar' }
83
+ );
84
+ return;
85
+ }
86
+
87
+ const fileTemplatePath = addQueryArgs(
88
+ `${ templateEntityConfig.baseURL }/${ template.id }`,
89
+ { context: 'edit', source: template.origin }
90
+ );
91
+
92
+ const fileTemplate = ( await apiFetch( {
93
+ path: fileTemplatePath,
94
+ } ) ) as any;
95
+ if ( ! fileTemplate ) {
96
+ dispatch( noticesStore ).createErrorNotice(
97
+ __(
98
+ 'The editor has encountered an unexpected error. Please reload.'
99
+ ),
100
+ { type: 'snackbar' }
101
+ );
102
+ return;
103
+ }
104
+
105
+ const serializeBlocks = ( { blocks: blocksForSerialization = [] } ) =>
106
+ __unstableSerializeAndClean( blocksForSerialization );
107
+
108
+ const edited = select( coreStore ).getEditedEntityRecord(
109
+ 'postType',
110
+ template.type,
111
+ template.id
112
+ ) as any;
113
+
114
+ // We are fixing up the undo level here to make sure we can undo
115
+ // the revert in the header toolbar correctly.
116
+ dispatch( coreStore ).editEntityRecord(
117
+ 'postType',
118
+ template.type,
119
+ template.id,
120
+ {
121
+ content: serializeBlocks, // Required to make the `undo` behave correctly.
122
+ blocks: edited.blocks, // Required to revert the blocks in the editor.
123
+ source: 'custom', // required to avoid turning the editor into a dirty state
124
+ },
125
+ {
126
+ undoIgnore: true, // Required to merge this edit with the last undo level.
127
+ }
128
+ );
129
+
130
+ const blocks = parse( fileTemplate?.content?.raw );
131
+
132
+ dispatch( coreStore ).editEntityRecord(
133
+ 'postType',
134
+ template.type,
135
+ fileTemplate.id,
136
+ {
137
+ content: serializeBlocks,
138
+ blocks,
139
+ source: 'theme',
140
+ }
141
+ );
142
+
143
+ if ( allowUndo ) {
144
+ const undoRevert = () => {
145
+ dispatch( coreStore ).editEntityRecord(
146
+ 'postType',
147
+ template.type,
148
+ edited.id,
149
+ {
150
+ content: serializeBlocks,
151
+ blocks: edited.blocks,
152
+ source: 'custom',
153
+ }
154
+ );
155
+ };
156
+
157
+ dispatch( noticesStore ).createSuccessNotice(
158
+ __( 'Template reset.' ),
159
+ {
160
+ type: 'snackbar',
161
+ id: noticeId,
162
+ actions: [
163
+ {
164
+ label: __( 'Undo' ),
165
+ onClick: undoRevert,
166
+ },
167
+ ],
168
+ }
169
+ );
170
+ }
171
+ } catch ( error: any ) {
172
+ const errorMessage =
173
+ error.message && error.code !== 'unknown_error'
174
+ ? error.message
175
+ : __( 'Template revert failed. Please reload.' );
176
+
177
+ dispatch( noticesStore ).createErrorNotice( errorMessage, {
178
+ type: 'snackbar',
179
+ } );
180
+ }
181
+ };
182
+
183
+ const resetPostAction: Action< Template | TemplatePart > = {
184
+ id: 'reset-post',
185
+ label: __( 'Reset' ),
186
+ isEligible: ( item ) => {
187
+ return (
188
+ isTemplateOrTemplatePart( item ) &&
189
+ item?.source === TEMPLATE_ORIGINS.custom &&
190
+ ( Boolean( item.type === 'wp_template' && item?.plugin ) ||
191
+ item?.has_theme_file )
192
+ );
193
+ },
194
+ icon: backup,
195
+ supportsBulk: true,
196
+ hideModalHeader: true,
197
+ RenderModal: ( { items, closeModal, onActionPerformed } ) => {
198
+ const [ isBusy, setIsBusy ] = useState( false );
199
+
200
+ const { saveEditedEntityRecord } = useDispatch( coreStore );
201
+ const { createSuccessNotice, createErrorNotice } =
202
+ useDispatch( noticesStore );
203
+ const onConfirm = async () => {
204
+ try {
205
+ for ( const template of items ) {
206
+ await revertTemplate( template, {
207
+ allowUndo: false,
208
+ } );
209
+ await saveEditedEntityRecord(
210
+ 'postType',
211
+ template.type,
212
+ template.id
213
+ );
214
+ }
215
+ createSuccessNotice(
216
+ items.length > 1
217
+ ? sprintf(
218
+ /* translators: The number of items. */
219
+ __( '%s items reset.' ),
220
+ items.length
221
+ )
222
+ : sprintf(
223
+ /* translators: The template/part's name. */
224
+ __( '"%s" reset.' ),
225
+ getItemTitle( items[ 0 ] )
226
+ ),
227
+ {
228
+ type: 'snackbar',
229
+ id: 'revert-template-action',
230
+ }
231
+ );
232
+ } catch ( error ) {
233
+ let fallbackErrorMessage;
234
+ if ( items[ 0 ].type === TEMPLATE_POST_TYPE ) {
235
+ fallbackErrorMessage =
236
+ items.length === 1
237
+ ? __(
238
+ 'An error occurred while reverting the template.'
239
+ )
240
+ : __(
241
+ 'An error occurred while reverting the templates.'
242
+ );
243
+ } else {
244
+ fallbackErrorMessage =
245
+ items.length === 1
246
+ ? __(
247
+ 'An error occurred while reverting the template part.'
248
+ )
249
+ : __(
250
+ 'An error occurred while reverting the template parts.'
251
+ );
252
+ }
253
+
254
+ const typedError = error as CoreDataError;
255
+ const errorMessage =
256
+ typedError.message && typedError.code !== 'unknown_error'
257
+ ? typedError.message
258
+ : fallbackErrorMessage;
259
+
260
+ createErrorNotice( errorMessage, { type: 'snackbar' } );
261
+ }
262
+ };
263
+ return (
264
+ <VStack spacing="5">
265
+ <Text>
266
+ { __( 'Reset to default and clear all customizations?' ) }
267
+ </Text>
268
+ <HStack justify="right">
269
+ <Button
270
+ __next40pxDefaultSize
271
+ variant="tertiary"
272
+ onClick={ closeModal }
273
+ disabled={ isBusy }
274
+ accessibleWhenDisabled
275
+ >
276
+ { __( 'Cancel' ) }
277
+ </Button>
278
+ <Button
279
+ __next40pxDefaultSize
280
+ variant="primary"
281
+ onClick={ async () => {
282
+ setIsBusy( true );
283
+ await onConfirm();
284
+ onActionPerformed?.( items );
285
+ setIsBusy( false );
286
+ closeModal?.();
287
+ } }
288
+ isBusy={ isBusy }
289
+ disabled={ isBusy }
290
+ accessibleWhenDisabled
291
+ >
292
+ { __( 'Reset' ) }
293
+ </Button>
294
+ </HStack>
295
+ </VStack>
296
+ );
297
+ },
298
+ };
299
+
300
+ export default resetPostAction;
@@ -0,0 +1,134 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { backup } from '@wordpress/icons';
5
+ import { store as coreStore } from '@wordpress/core-data';
6
+ import { __, sprintf } from '@wordpress/i18n';
7
+ import { store as noticesStore } from '@wordpress/notices';
8
+ import type { Action } from '@wordpress/dataviews';
9
+
10
+ /**
11
+ * Internal dependencies
12
+ */
13
+ import { getItemTitle, isTemplateOrTemplatePart } from './utils';
14
+ import type { CoreDataError, PostWithPermissions } from '../types';
15
+
16
+ const restorePost: Action< PostWithPermissions > = {
17
+ id: 'restore',
18
+ label: __( 'Restore' ),
19
+ isPrimary: true,
20
+ icon: backup,
21
+ supportsBulk: true,
22
+ isEligible( item ) {
23
+ return (
24
+ ! isTemplateOrTemplatePart( item ) &&
25
+ item.type !== 'wp_block' &&
26
+ item.status === 'trash' &&
27
+ item.permissions?.update
28
+ );
29
+ },
30
+ async callback( posts, { registry, onActionPerformed } ) {
31
+ const { createSuccessNotice, createErrorNotice } =
32
+ registry.dispatch( noticesStore );
33
+ const { editEntityRecord, saveEditedEntityRecord } =
34
+ registry.dispatch( coreStore );
35
+ await Promise.allSettled(
36
+ posts.map( ( post ) => {
37
+ return editEntityRecord( 'postType', post.type, post.id, {
38
+ status: 'draft',
39
+ } );
40
+ } )
41
+ );
42
+ const promiseResult = await Promise.allSettled(
43
+ posts.map( ( post ) => {
44
+ return saveEditedEntityRecord( 'postType', post.type, post.id, {
45
+ throwOnError: true,
46
+ } );
47
+ } )
48
+ );
49
+
50
+ if ( promiseResult.every( ( { status } ) => status === 'fulfilled' ) ) {
51
+ let successMessage;
52
+ if ( posts.length === 1 ) {
53
+ successMessage = sprintf(
54
+ /* translators: The number of posts. */
55
+ __( '"%s" has been restored.' ),
56
+ getItemTitle( posts[ 0 ] )
57
+ );
58
+ } else if ( posts[ 0 ].type === 'page' ) {
59
+ successMessage = sprintf(
60
+ /* translators: The number of posts. */
61
+ __( '%d pages have been restored.' ),
62
+ posts.length
63
+ );
64
+ } else {
65
+ successMessage = sprintf(
66
+ /* translators: The number of posts. */
67
+ __( '%d posts have been restored.' ),
68
+ posts.length
69
+ );
70
+ }
71
+ createSuccessNotice( successMessage, {
72
+ type: 'snackbar',
73
+ id: 'restore-post-action',
74
+ } );
75
+ if ( onActionPerformed ) {
76
+ onActionPerformed( posts );
77
+ }
78
+ } else {
79
+ // If there was at lease one failure.
80
+ let errorMessage;
81
+ // If we were trying to move a single post to the trash.
82
+ if ( promiseResult.length === 1 ) {
83
+ const typedError = promiseResult[ 0 ] as {
84
+ reason?: CoreDataError;
85
+ };
86
+ if ( typedError.reason?.message ) {
87
+ errorMessage = typedError.reason.message;
88
+ } else {
89
+ errorMessage = __(
90
+ 'An error occurred while restoring the post.'
91
+ );
92
+ }
93
+ // If we were trying to move multiple posts to the trash
94
+ } else {
95
+ const errorMessages = new Set();
96
+ const failedPromises = promiseResult.filter(
97
+ ( { status } ) => status === 'rejected'
98
+ );
99
+ for ( const failedPromise of failedPromises ) {
100
+ const typedError = failedPromise as {
101
+ reason?: CoreDataError;
102
+ };
103
+ if ( typedError.reason?.message ) {
104
+ errorMessages.add( typedError.reason.message );
105
+ }
106
+ }
107
+ if ( errorMessages.size === 0 ) {
108
+ errorMessage = __(
109
+ 'An error occurred while restoring the posts.'
110
+ );
111
+ } else if ( errorMessages.size === 1 ) {
112
+ errorMessage = sprintf(
113
+ /* translators: %s: an error message */
114
+ __( 'An error occurred while restoring the posts: %s' ),
115
+ [ ...errorMessages ][ 0 ]
116
+ );
117
+ } else {
118
+ errorMessage = sprintf(
119
+ /* translators: %s: a list of comma separated error messages */
120
+ __(
121
+ 'Some errors occurred while restoring the posts: %s'
122
+ ),
123
+ [ ...errorMessages ].join( ',' )
124
+ );
125
+ }
126
+ }
127
+ createErrorNotice( errorMessage, {
128
+ type: 'snackbar',
129
+ } );
130
+ }
131
+ },
132
+ };
133
+
134
+ export default restorePost;
@@ -0,0 +1,198 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { trash } 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
+
18
+ /**
19
+ * Internal dependencies
20
+ */
21
+ import { getItemTitle, isTemplateOrTemplatePart } from './utils';
22
+ import type { CoreDataError, PostWithPermissions } from '../types';
23
+
24
+ const trashPost: Action< PostWithPermissions > = {
25
+ id: 'move-to-trash',
26
+ label: __( 'Move to trash' ),
27
+ isPrimary: true,
28
+ icon: trash,
29
+ isEligible( item ) {
30
+ if ( isTemplateOrTemplatePart( item ) || item.type === 'wp_block' ) {
31
+ return false;
32
+ }
33
+
34
+ return (
35
+ !! item.status &&
36
+ ! [ 'auto-draft', 'trash' ].includes( item.status ) &&
37
+ item.permissions?.delete
38
+ );
39
+ },
40
+ supportsBulk: true,
41
+ hideModalHeader: true,
42
+ RenderModal: ( { items, closeModal, onActionPerformed } ) => {
43
+ const [ isBusy, setIsBusy ] = useState( false );
44
+ const { createSuccessNotice, createErrorNotice } =
45
+ useDispatch( noticesStore );
46
+ const { deleteEntityRecord } = useDispatch( coreStore );
47
+ return (
48
+ <VStack spacing="5">
49
+ <Text>
50
+ { items.length === 1
51
+ ? sprintf(
52
+ // translators: %s: The item's title.
53
+ __(
54
+ 'Are you sure you want to move "%s" to the trash?'
55
+ ),
56
+ getItemTitle( items[ 0 ] )
57
+ )
58
+ : sprintf(
59
+ // translators: %d: The number of items (2 or more).
60
+ _n(
61
+ 'Are you sure you want to move %d item to the trash ?',
62
+ 'Are you sure you want to move %d items to the trash ?',
63
+ items.length
64
+ ),
65
+ items.length
66
+ ) }
67
+ </Text>
68
+ <HStack justify="right">
69
+ <Button
70
+ __next40pxDefaultSize
71
+ variant="tertiary"
72
+ onClick={ closeModal }
73
+ disabled={ isBusy }
74
+ accessibleWhenDisabled
75
+ >
76
+ { __( 'Cancel' ) }
77
+ </Button>
78
+ <Button
79
+ __next40pxDefaultSize
80
+ variant="primary"
81
+ onClick={ async () => {
82
+ setIsBusy( true );
83
+ const promiseResult = await Promise.allSettled(
84
+ items.map( ( item ) =>
85
+ deleteEntityRecord(
86
+ 'postType',
87
+ item.type,
88
+ item.id.toString(),
89
+ {},
90
+ { throwOnError: true }
91
+ )
92
+ )
93
+ );
94
+ // If all the promises were fulfilled with success.
95
+ if (
96
+ promiseResult.every(
97
+ ( { status } ) => status === 'fulfilled'
98
+ )
99
+ ) {
100
+ let successMessage;
101
+ if ( promiseResult.length === 1 ) {
102
+ successMessage = sprintf(
103
+ /* translators: The item's title. */
104
+ __( '"%s" moved to the trash.' ),
105
+ getItemTitle( items[ 0 ] )
106
+ );
107
+ } else {
108
+ successMessage = sprintf(
109
+ /* translators: The number of items. */
110
+ _n(
111
+ '%s item moved to the trash.',
112
+ '%s items moved to the trash.',
113
+ items.length
114
+ ),
115
+ items.length
116
+ );
117
+ }
118
+ createSuccessNotice( successMessage, {
119
+ type: 'snackbar',
120
+ id: 'move-to-trash-action',
121
+ } );
122
+ } else {
123
+ // If there was at least one failure.
124
+ let errorMessage;
125
+ // If we were trying to delete a single item.
126
+ if ( promiseResult.length === 1 ) {
127
+ const typedError = promiseResult[ 0 ] as {
128
+ reason?: CoreDataError;
129
+ };
130
+ if ( typedError.reason?.message ) {
131
+ errorMessage =
132
+ typedError.reason.message;
133
+ } else {
134
+ errorMessage = __(
135
+ 'An error occurred while moving the item to the trash.'
136
+ );
137
+ }
138
+ // If we were trying to delete multiple items.
139
+ } else {
140
+ const errorMessages = new Set();
141
+ const failedPromises = promiseResult.filter(
142
+ ( { status } ) => status === 'rejected'
143
+ );
144
+ for ( const failedPromise of failedPromises ) {
145
+ const typedError = failedPromise as {
146
+ reason?: CoreDataError;
147
+ };
148
+ if ( typedError.reason?.message ) {
149
+ errorMessages.add(
150
+ typedError.reason.message
151
+ );
152
+ }
153
+ }
154
+ if ( errorMessages.size === 0 ) {
155
+ errorMessage = __(
156
+ 'An error occurred while moving the items to the trash.'
157
+ );
158
+ } else if ( errorMessages.size === 1 ) {
159
+ errorMessage = sprintf(
160
+ /* translators: %s: an error message */
161
+ __(
162
+ 'An error occurred while moving the item to the trash: %s'
163
+ ),
164
+ [ ...errorMessages ][ 0 ]
165
+ );
166
+ } else {
167
+ errorMessage = sprintf(
168
+ /* translators: %s: a list of comma separated error messages */
169
+ __(
170
+ 'Some errors occurred while moving the items to the trash: %s'
171
+ ),
172
+ [ ...errorMessages ].join( ',' )
173
+ );
174
+ }
175
+ }
176
+ createErrorNotice( errorMessage, {
177
+ type: 'snackbar',
178
+ } );
179
+ }
180
+ if ( onActionPerformed ) {
181
+ onActionPerformed( items );
182
+ }
183
+ setIsBusy( false );
184
+ closeModal?.();
185
+ } }
186
+ isBusy={ isBusy }
187
+ disabled={ isBusy }
188
+ accessibleWhenDisabled
189
+ >
190
+ { _x( 'Trash', 'verb' ) }
191
+ </Button>
192
+ </HStack>
193
+ </VStack>
194
+ );
195
+ },
196
+ };
197
+
198
+ export default trashPost;
@@ -8,7 +8,7 @@ import type { Action } from '@wordpress/dataviews';
8
8
  /**
9
9
  * Internal dependencies
10
10
  */
11
- import type { Post } from '../../types';
11
+ import type { Post } from '../types';
12
12
 
13
13
  const viewPostRevisions: Action< Post > = {
14
14
  id: 'view-post-revisions',
@@ -8,7 +8,7 @@ import type { Action } from '@wordpress/dataviews';
8
8
  /**
9
9
  * Internal dependencies
10
10
  */
11
- import type { BasePost } from '../../types';
11
+ import type { BasePost } from '../types';
12
12
 
13
13
  const viewPost: Action< BasePost > = {
14
14
  id: 'view-post',
@@ -1,2 +1,2 @@
1
- export * from './actions/base-post/duplicate-post.native';
2
- export * from './actions/base-post/reorder-page.native';
1
+ export * from './actions/duplicate-post.native';
2
+ export * from './actions/reorder-page.native';