@wordpress/fields 0.0.2

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 (165) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/LICENSE.md +788 -0
  3. package/README.md +73 -0
  4. package/build/actions/base-post/duplicate-post.js +146 -0
  5. package/build/actions/base-post/duplicate-post.js.map +1 -0
  6. package/build/actions/base-post/duplicate-post.native.js +9 -0
  7. package/build/actions/base-post/duplicate-post.native.js.map +1 -0
  8. package/build/actions/base-post/index.js +42 -0
  9. package/build/actions/base-post/index.js.map +1 -0
  10. package/build/actions/base-post/reorder-page.js +116 -0
  11. package/build/actions/base-post/reorder-page.js.map +1 -0
  12. package/build/actions/base-post/reorder-page.native.js +9 -0
  13. package/build/actions/base-post/reorder-page.native.js.map +1 -0
  14. package/build/actions/base-post/view-post.js +36 -0
  15. package/build/actions/base-post/view-post.js.map +1 -0
  16. package/build/actions/common/index.js +21 -0
  17. package/build/actions/common/index.js.map +1 -0
  18. package/build/actions/common/permanently-delete-post.js +109 -0
  19. package/build/actions/common/permanently-delete-post.js.map +1 -0
  20. package/build/actions/common/view-post-revisions.js +49 -0
  21. package/build/actions/common/view-post-revisions.js.map +1 -0
  22. package/build/actions/index.js +39 -0
  23. package/build/actions/index.js.map +1 -0
  24. package/build/actions/pattern/duplicate-pattern.js +48 -0
  25. package/build/actions/pattern/duplicate-pattern.js.map +1 -0
  26. package/build/actions/pattern/export-pattern.js +57 -0
  27. package/build/actions/pattern/export-pattern.js.map +1 -0
  28. package/build/actions/pattern/export-pattern.native.js +9 -0
  29. package/build/actions/pattern/export-pattern.native.js.map +1 -0
  30. package/build/actions/pattern/index.js +28 -0
  31. package/build/actions/pattern/index.js.map +1 -0
  32. package/build/actions/utils.js +65 -0
  33. package/build/actions/utils.js.map +1 -0
  34. package/build/fields/index.js +21 -0
  35. package/build/fields/index.js.map +1 -0
  36. package/build/fields/order/index.js +23 -0
  37. package/build/fields/order/index.js.map +1 -0
  38. package/build/fields/title/index.js +27 -0
  39. package/build/fields/title/index.js.map +1 -0
  40. package/build/index.js +28 -0
  41. package/build/index.js.map +1 -0
  42. package/build/index.native.js +28 -0
  43. package/build/index.native.js.map +1 -0
  44. package/build/lock-unlock.js +18 -0
  45. package/build/lock-unlock.js.map +1 -0
  46. package/build/types.js +6 -0
  47. package/build/types.js.map +1 -0
  48. package/build/wordpress-editor.d.js +2 -0
  49. package/build/wordpress-editor.d.js.map +1 -0
  50. package/build-module/actions/base-post/duplicate-post.js +139 -0
  51. package/build-module/actions/base-post/duplicate-post.js.map +1 -0
  52. package/build-module/actions/base-post/duplicate-post.native.js +3 -0
  53. package/build-module/actions/base-post/duplicate-post.native.js.map +1 -0
  54. package/build-module/actions/base-post/index.js +6 -0
  55. package/build-module/actions/base-post/index.js.map +1 -0
  56. package/build-module/actions/base-post/reorder-page.js +111 -0
  57. package/build-module/actions/base-post/reorder-page.js.map +1 -0
  58. package/build-module/actions/base-post/reorder-page.native.js +3 -0
  59. package/build-module/actions/base-post/reorder-page.native.js.map +1 -0
  60. package/build-module/actions/base-post/view-post.js +30 -0
  61. package/build-module/actions/base-post/view-post.js.map +1 -0
  62. package/build-module/actions/common/index.js +3 -0
  63. package/build-module/actions/common/index.js.map +1 -0
  64. package/build-module/actions/common/permanently-delete-post.js +102 -0
  65. package/build-module/actions/common/permanently-delete-post.js.map +1 -0
  66. package/build-module/actions/common/view-post-revisions.js +43 -0
  67. package/build-module/actions/common/view-post-revisions.js.map +1 -0
  68. package/build-module/actions/index.js +4 -0
  69. package/build-module/actions/index.js.map +1 -0
  70. package/build-module/actions/pattern/duplicate-pattern.js +39 -0
  71. package/build-module/actions/pattern/duplicate-pattern.js.map +1 -0
  72. package/build-module/actions/pattern/export-pattern.js +51 -0
  73. package/build-module/actions/pattern/export-pattern.js.map +1 -0
  74. package/build-module/actions/pattern/export-pattern.native.js +3 -0
  75. package/build-module/actions/pattern/export-pattern.native.js.map +1 -0
  76. package/build-module/actions/pattern/index.js +4 -0
  77. package/build-module/actions/pattern/index.js.map +1 -0
  78. package/build-module/actions/utils.js +54 -0
  79. package/build-module/actions/utils.js.map +1 -0
  80. package/build-module/fields/index.js +3 -0
  81. package/build-module/fields/index.js.map +1 -0
  82. package/build-module/fields/order/index.js +17 -0
  83. package/build-module/fields/order/index.js.map +1 -0
  84. package/build-module/fields/title/index.js +22 -0
  85. package/build-module/fields/title/index.js.map +1 -0
  86. package/build-module/index.js +3 -0
  87. package/build-module/index.js.map +1 -0
  88. package/build-module/index.native.js +3 -0
  89. package/build-module/index.native.js.map +1 -0
  90. package/build-module/lock-unlock.js +9 -0
  91. package/build-module/lock-unlock.js.map +1 -0
  92. package/build-module/types.js +2 -0
  93. package/build-module/types.js.map +1 -0
  94. package/build-module/wordpress-editor.d.js +2 -0
  95. package/build-module/wordpress-editor.d.js.map +1 -0
  96. package/build-types/actions/base-post/duplicate-post.d.ts +5 -0
  97. package/build-types/actions/base-post/duplicate-post.d.ts.map +1 -0
  98. package/build-types/actions/base-post/duplicate-post.native.d.ts +3 -0
  99. package/build-types/actions/base-post/duplicate-post.native.d.ts.map +1 -0
  100. package/build-types/actions/base-post/index.d.ts +6 -0
  101. package/build-types/actions/base-post/index.d.ts.map +1 -0
  102. package/build-types/actions/base-post/reorder-page.d.ts +8 -0
  103. package/build-types/actions/base-post/reorder-page.d.ts.map +1 -0
  104. package/build-types/actions/base-post/reorder-page.native.d.ts +3 -0
  105. package/build-types/actions/base-post/reorder-page.native.d.ts.map +1 -0
  106. package/build-types/actions/base-post/view-post.d.ts +8 -0
  107. package/build-types/actions/base-post/view-post.d.ts.map +1 -0
  108. package/build-types/actions/common/index.d.ts +3 -0
  109. package/build-types/actions/common/index.d.ts.map +1 -0
  110. package/build-types/actions/common/permanently-delete-post.d.ts +5 -0
  111. package/build-types/actions/common/permanently-delete-post.d.ts.map +1 -0
  112. package/build-types/actions/common/view-post-revisions.d.ts +8 -0
  113. package/build-types/actions/common/view-post-revisions.d.ts.map +1 -0
  114. package/build-types/actions/index.d.ts +4 -0
  115. package/build-types/actions/index.d.ts.map +1 -0
  116. package/build-types/actions/pattern/duplicate-pattern.d.ts +5 -0
  117. package/build-types/actions/pattern/duplicate-pattern.d.ts.map +1 -0
  118. package/build-types/actions/pattern/export-pattern.d.ts +8 -0
  119. package/build-types/actions/pattern/export-pattern.d.ts.map +1 -0
  120. package/build-types/actions/pattern/export-pattern.native.d.ts +3 -0
  121. package/build-types/actions/pattern/export-pattern.native.d.ts.map +1 -0
  122. package/build-types/actions/pattern/index.d.ts +4 -0
  123. package/build-types/actions/pattern/index.d.ts.map +1 -0
  124. package/build-types/actions/utils.d.ts +23 -0
  125. package/build-types/actions/utils.d.ts.map +1 -0
  126. package/build-types/fields/index.d.ts +3 -0
  127. package/build-types/fields/index.d.ts.map +1 -0
  128. package/build-types/fields/order/index.d.ts +11 -0
  129. package/build-types/fields/order/index.d.ts.map +1 -0
  130. package/build-types/fields/title/index.d.ts +11 -0
  131. package/build-types/fields/title/index.d.ts.map +1 -0
  132. package/build-types/index.d.ts +3 -0
  133. package/build-types/index.d.ts.map +1 -0
  134. package/build-types/index.native.d.ts +3 -0
  135. package/build-types/index.native.d.ts.map +1 -0
  136. package/build-types/lock-unlock.d.ts +2 -0
  137. package/build-types/lock-unlock.d.ts.map +1 -0
  138. package/build-types/types.d.ts +92 -0
  139. package/build-types/types.d.ts.map +1 -0
  140. package/package.json +63 -0
  141. package/src/actions/base-post/duplicate-post.native.tsx +3 -0
  142. package/src/actions/base-post/duplicate-post.tsx +174 -0
  143. package/src/actions/base-post/index.ts +5 -0
  144. package/src/actions/base-post/reorder-page.native.tsx +3 -0
  145. package/src/actions/base-post/reorder-page.tsx +125 -0
  146. package/src/actions/base-post/view-post.tsx +30 -0
  147. package/src/actions/common/index.ts +2 -0
  148. package/src/actions/common/permanently-delete-post.tsx +118 -0
  149. package/src/actions/common/view-post-revisions.tsx +47 -0
  150. package/src/actions/index.ts +3 -0
  151. package/src/actions/pattern/duplicate-pattern.tsx +40 -0
  152. package/src/actions/pattern/export-pattern.native.tsx +3 -0
  153. package/src/actions/pattern/export-pattern.tsx +76 -0
  154. package/src/actions/pattern/index.ts +3 -0
  155. package/src/actions/utils.ts +66 -0
  156. package/src/fields/index.ts +2 -0
  157. package/src/fields/order/index.ts +18 -0
  158. package/src/fields/title/index.ts +21 -0
  159. package/src/index.native.ts +2 -0
  160. package/src/index.ts +2 -0
  161. package/src/lock-unlock.ts +9 -0
  162. package/src/types.ts +85 -0
  163. package/src/wordpress-editor.d.ts +1 -0
  164. package/tsconfig.json +29 -0
  165. package/tsconfig.tsbuildinfo +1 -0
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@wordpress/fields",
3
+ "version": "0.0.2",
4
+ "description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).",
5
+ "author": "The WordPress Contributors",
6
+ "license": "GPL-2.0-or-later",
7
+ "keywords": [
8
+ "wordpress",
9
+ "gutenberg",
10
+ "dataviews"
11
+ ],
12
+ "homepage": "https://github.com/WordPress/gutenberg/tree/HEAD/packages/fields/README.md",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/WordPress/gutenberg.git",
16
+ "directory": "packages/fields"
17
+ },
18
+ "bugs": {
19
+ "url": "https://github.com/WordPress/gutenberg/issues"
20
+ },
21
+ "engines": {
22
+ "node": ">=18.12.0",
23
+ "npm": ">=8.19.2"
24
+ },
25
+ "main": "build/index.js",
26
+ "module": "build-module/index.js",
27
+ "react-native": "src/index",
28
+ "types": "build-types",
29
+ "sideEffects": [
30
+ "build-style/**",
31
+ "src/**/*.scss"
32
+ ],
33
+ "dependencies": {
34
+ "@babel/runtime": "^7.16.0",
35
+ "@wordpress/blob": "^4.8.1",
36
+ "@wordpress/blocks": "^13.8.1",
37
+ "@wordpress/components": "^28.8.1",
38
+ "@wordpress/compose": "^7.8.1",
39
+ "@wordpress/core-data": "^7.8.1",
40
+ "@wordpress/data": "^10.8.1",
41
+ "@wordpress/dataviews": "^4.4.1",
42
+ "@wordpress/element": "^6.8.1",
43
+ "@wordpress/hooks": "^4.8.1",
44
+ "@wordpress/html-entities": "^4.8.1",
45
+ "@wordpress/i18n": "^5.8.1",
46
+ "@wordpress/icons": "^10.8.1",
47
+ "@wordpress/notices": "^5.8.1",
48
+ "@wordpress/patterns": "^2.8.1",
49
+ "@wordpress/primitives": "^4.8.1",
50
+ "@wordpress/private-apis": "^1.8.1",
51
+ "@wordpress/url": "^4.8.1",
52
+ "@wordpress/warning": "^3.8.1",
53
+ "change-case": "4.1.2",
54
+ "client-zip": "^2.4.5"
55
+ },
56
+ "peerDependencies": {
57
+ "react": "^18.0.0"
58
+ },
59
+ "publishConfig": {
60
+ "access": "public"
61
+ },
62
+ "gitHead": "41c3dae7f55523427acd45044ec0e4813c86449b"
63
+ }
@@ -0,0 +1,3 @@
1
+ const duplicatePost = undefined;
2
+
3
+ export default duplicatePost;
@@ -0,0 +1,174 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useDispatch } from '@wordpress/data';
5
+ import { decodeEntities } from '@wordpress/html-entities';
6
+ import { store as coreStore } from '@wordpress/core-data';
7
+ import { __, sprintf, _x } from '@wordpress/i18n';
8
+ import { store as noticesStore } from '@wordpress/notices';
9
+ import { useState } from '@wordpress/element';
10
+ import { DataForm } from '@wordpress/dataviews';
11
+ import {
12
+ Button,
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 { titleField } from '../../fields';
22
+ import type { BasePost, CoreDataError } from '../../types';
23
+ import { getItemTitle } from '../utils';
24
+
25
+ const fields = [ titleField ];
26
+ const formDuplicateAction = {
27
+ fields: [ 'title' ],
28
+ };
29
+
30
+ const duplicatePost: Action< BasePost > = {
31
+ id: 'duplicate-post',
32
+ label: _x( 'Duplicate', 'action label' ),
33
+ isEligible( { status } ) {
34
+ return status !== 'trash';
35
+ },
36
+ RenderModal: ( { items, closeModal, onActionPerformed } ) => {
37
+ const [ item, setItem ] = useState< BasePost >( {
38
+ ...items[ 0 ],
39
+ title: sprintf(
40
+ /* translators: %s: Existing template title */
41
+ __( '%s (Copy)' ),
42
+ getItemTitle( items[ 0 ] )
43
+ ),
44
+ } );
45
+
46
+ const [ isCreatingPage, setIsCreatingPage ] = useState( false );
47
+ const { saveEntityRecord } = useDispatch( coreStore );
48
+ const { createSuccessNotice, createErrorNotice } =
49
+ useDispatch( noticesStore );
50
+
51
+ async function createPage( event: React.FormEvent ) {
52
+ event.preventDefault();
53
+
54
+ if ( isCreatingPage ) {
55
+ return;
56
+ }
57
+
58
+ const newItemOject = {
59
+ status: 'draft',
60
+ title: item.title,
61
+ slug: item.title || __( 'No title' ),
62
+ comment_status: item.comment_status,
63
+ content:
64
+ typeof item.content === 'string'
65
+ ? item.content
66
+ : item.content.raw,
67
+ excerpt:
68
+ typeof item.excerpt === 'string'
69
+ ? item.excerpt
70
+ : item.excerpt?.raw,
71
+ meta: item.meta,
72
+ parent: item.parent,
73
+ password: item.password,
74
+ template: item.template,
75
+ format: item.format,
76
+ featured_media: item.featured_media,
77
+ menu_order: item.menu_order,
78
+ ping_status: item.ping_status,
79
+ };
80
+ const assignablePropertiesPrefix = 'wp:action-assign-';
81
+ // Get all the properties that the current user is able to assign normally author, categories, tags,
82
+ // and custom taxonomies.
83
+ const assignableProperties = Object.keys( item?._links || {} )
84
+ .filter( ( property ) =>
85
+ property.startsWith( assignablePropertiesPrefix )
86
+ )
87
+ .map( ( property ) =>
88
+ property.slice( assignablePropertiesPrefix.length )
89
+ );
90
+ assignableProperties.forEach( ( property ) => {
91
+ if ( item.hasOwnProperty( property ) ) {
92
+ // @ts-ignore
93
+ newItemOject[ property ] = item[ property ];
94
+ }
95
+ } );
96
+ setIsCreatingPage( true );
97
+ try {
98
+ const newItem = await saveEntityRecord(
99
+ 'postType',
100
+ item.type,
101
+ newItemOject,
102
+ { throwOnError: true }
103
+ );
104
+
105
+ createSuccessNotice(
106
+ sprintf(
107
+ // translators: %s: Title of the created template e.g: "Category".
108
+ __( '"%s" successfully created.' ),
109
+ decodeEntities( newItem.title?.rendered || item.title )
110
+ ),
111
+ {
112
+ id: 'duplicate-post-action',
113
+ type: 'snackbar',
114
+ }
115
+ );
116
+
117
+ if ( onActionPerformed ) {
118
+ onActionPerformed( [ newItem ] );
119
+ }
120
+ } catch ( error ) {
121
+ const typedError = error as CoreDataError;
122
+ const errorMessage =
123
+ typedError.message && typedError.code !== 'unknown_error'
124
+ ? typedError.message
125
+ : __( 'An error occurred while duplicating the page.' );
126
+
127
+ createErrorNotice( errorMessage, {
128
+ type: 'snackbar',
129
+ } );
130
+ } finally {
131
+ setIsCreatingPage( false );
132
+ closeModal?.();
133
+ }
134
+ }
135
+
136
+ return (
137
+ <form onSubmit={ createPage }>
138
+ <VStack spacing={ 3 }>
139
+ <DataForm
140
+ data={ item }
141
+ fields={ fields }
142
+ form={ formDuplicateAction }
143
+ onChange={ ( changes ) =>
144
+ setItem( ( prev ) => ( {
145
+ ...prev,
146
+ ...changes,
147
+ } ) )
148
+ }
149
+ />
150
+ <HStack spacing={ 2 } justify="end">
151
+ <Button
152
+ variant="tertiary"
153
+ onClick={ closeModal }
154
+ __next40pxDefaultSize
155
+ >
156
+ { __( 'Cancel' ) }
157
+ </Button>
158
+ <Button
159
+ variant="primary"
160
+ type="submit"
161
+ isBusy={ isCreatingPage }
162
+ aria-disabled={ isCreatingPage }
163
+ __next40pxDefaultSize
164
+ >
165
+ { _x( 'Duplicate', 'action label' ) }
166
+ </Button>
167
+ </HStack>
168
+ </VStack>
169
+ </form>
170
+ );
171
+ },
172
+ };
173
+
174
+ export default duplicatePost;
@@ -0,0 +1,5 @@
1
+ export { default as viewPost } from './view-post';
2
+ export { default as reorderPage } from './reorder-page';
3
+ export { default as reorderPageNative } from './reorder-page.native';
4
+ export { default as duplicatePost } from './duplicate-post';
5
+ export { default as duplicatePostNative } from './duplicate-post.native';
@@ -0,0 +1,3 @@
1
+ const reorderPage = undefined;
2
+
3
+ export default reorderPage;
@@ -0,0 +1,125 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useDispatch } from '@wordpress/data';
5
+ import { store as coreStore } from '@wordpress/core-data';
6
+ import { __ } from '@wordpress/i18n';
7
+ import { store as noticesStore } from '@wordpress/notices';
8
+ import { useState } from '@wordpress/element';
9
+ import { DataForm, isItemValid } from '@wordpress/dataviews';
10
+ import {
11
+ Button,
12
+ __experimentalHStack as HStack,
13
+ __experimentalVStack as VStack,
14
+ } from '@wordpress/components';
15
+ import type { Action, RenderModalProps } from '@wordpress/dataviews';
16
+
17
+ /**
18
+ * Internal dependencies
19
+ */
20
+ import type { CoreDataError, BasePost } from '../../types';
21
+ import { orderField } from '../../fields';
22
+
23
+ const fields = [ orderField ];
24
+ const formOrderAction = {
25
+ fields: [ 'menu_order' ],
26
+ };
27
+
28
+ function ReorderModal( {
29
+ items,
30
+ closeModal,
31
+ onActionPerformed,
32
+ }: RenderModalProps< BasePost > ) {
33
+ const [ item, setItem ] = useState( items[ 0 ] );
34
+ const orderInput = item.menu_order;
35
+ const { editEntityRecord, saveEditedEntityRecord } =
36
+ useDispatch( coreStore );
37
+ const { createSuccessNotice, createErrorNotice } =
38
+ useDispatch( noticesStore );
39
+
40
+ async function onOrder( event: React.FormEvent ) {
41
+ event.preventDefault();
42
+
43
+ if ( ! isItemValid( item, fields, formOrderAction ) ) {
44
+ return;
45
+ }
46
+
47
+ try {
48
+ await editEntityRecord( 'postType', item.type, item.id, {
49
+ menu_order: orderInput,
50
+ } );
51
+ closeModal?.();
52
+ // Persist edited entity.
53
+ await saveEditedEntityRecord( 'postType', item.type, item.id, {
54
+ throwOnError: true,
55
+ } );
56
+ createSuccessNotice( __( 'Order updated.' ), {
57
+ type: 'snackbar',
58
+ } );
59
+ onActionPerformed?.( items );
60
+ } catch ( error ) {
61
+ const typedError = error as CoreDataError;
62
+ const errorMessage =
63
+ typedError.message && typedError.code !== 'unknown_error'
64
+ ? typedError.message
65
+ : __( 'An error occurred while updating the order' );
66
+ createErrorNotice( errorMessage, {
67
+ type: 'snackbar',
68
+ } );
69
+ }
70
+ }
71
+ const isSaveDisabled = ! isItemValid( item, fields, formOrderAction );
72
+ return (
73
+ <form onSubmit={ onOrder }>
74
+ <VStack spacing="5">
75
+ <div>
76
+ { __(
77
+ 'Determines the order of pages. Pages with the same order value are sorted alphabetically. Negative order values are supported.'
78
+ ) }
79
+ </div>
80
+ <DataForm
81
+ data={ item }
82
+ fields={ fields }
83
+ form={ formOrderAction }
84
+ onChange={ ( changes ) =>
85
+ setItem( {
86
+ ...item,
87
+ ...changes,
88
+ } )
89
+ }
90
+ />
91
+ <HStack justify="right">
92
+ <Button
93
+ __next40pxDefaultSize
94
+ variant="tertiary"
95
+ onClick={ () => {
96
+ closeModal?.();
97
+ } }
98
+ >
99
+ { __( 'Cancel' ) }
100
+ </Button>
101
+ <Button
102
+ __next40pxDefaultSize
103
+ variant="primary"
104
+ type="submit"
105
+ accessibleWhenDisabled
106
+ disabled={ isSaveDisabled }
107
+ >
108
+ { __( 'Save' ) }
109
+ </Button>
110
+ </HStack>
111
+ </VStack>
112
+ </form>
113
+ );
114
+ }
115
+
116
+ const reorderPage: Action< BasePost > = {
117
+ id: 'order-pages',
118
+ label: __( 'Order' ),
119
+ isEligible( { status } ) {
120
+ return status !== 'trash';
121
+ },
122
+ RenderModal: ReorderModal,
123
+ };
124
+
125
+ export default reorderPage;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { external } from '@wordpress/icons';
5
+ import { _x } from '@wordpress/i18n';
6
+ import type { Action } from '@wordpress/dataviews';
7
+
8
+ /**
9
+ * Internal dependencies
10
+ */
11
+ import type { BasePost } from '../../types';
12
+
13
+ const viewPost: Action< BasePost > = {
14
+ id: 'view-post',
15
+ label: _x( 'View', 'verb' ),
16
+ isPrimary: true,
17
+ icon: external,
18
+ isEligible( post ) {
19
+ return post.status !== 'trash';
20
+ },
21
+ callback( posts, { onActionPerformed } ) {
22
+ const post = posts[ 0 ];
23
+ window.open( post?.link, '_blank' );
24
+ if ( onActionPerformed ) {
25
+ onActionPerformed( posts );
26
+ }
27
+ },
28
+ };
29
+
30
+ export default viewPost;
@@ -0,0 +1,2 @@
1
+ export { default as viewPostRevisions } from './view-post-revisions';
2
+ export { default as permanentlyDeletePost } from './permanently-delete-post';
@@ -0,0 +1,118 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { store as coreStore } from '@wordpress/core-data';
5
+ import { __, sprintf } from '@wordpress/i18n';
6
+ import { store as noticesStore } from '@wordpress/notices';
7
+ import type { Action } from '@wordpress/dataviews';
8
+ import { trash } from '@wordpress/icons';
9
+
10
+ /**
11
+ * Internal dependencies
12
+ */
13
+ import { getItemTitle, isTemplateOrTemplatePart } from '../utils';
14
+ import type { CoreDataError, PostWithPermissions } from '../../types';
15
+
16
+ const permanentlyDeletePost: Action< PostWithPermissions > = {
17
+ id: 'permanently-delete',
18
+ label: __( 'Permanently delete' ),
19
+ supportsBulk: true,
20
+ icon: trash,
21
+ isEligible( item ) {
22
+ if ( isTemplateOrTemplatePart( item ) || item.type === 'wp_block' ) {
23
+ return false;
24
+ }
25
+ const { status, permissions } = item;
26
+ return status === 'trash' && permissions?.delete;
27
+ },
28
+ async callback( posts, { registry, onActionPerformed } ) {
29
+ const { createSuccessNotice, createErrorNotice } =
30
+ registry.dispatch( noticesStore );
31
+ const { deleteEntityRecord } = registry.dispatch( coreStore );
32
+ const promiseResult = await Promise.allSettled(
33
+ posts.map( ( post ) => {
34
+ return deleteEntityRecord(
35
+ 'postType',
36
+ post.type,
37
+ post.id,
38
+ { force: true },
39
+ { throwOnError: true }
40
+ );
41
+ } )
42
+ );
43
+ // If all the promises were fulfilled with success.
44
+ if ( promiseResult.every( ( { status } ) => status === 'fulfilled' ) ) {
45
+ let successMessage;
46
+ if ( promiseResult.length === 1 ) {
47
+ successMessage = sprintf(
48
+ /* translators: The posts's title. */
49
+ __( '"%s" permanently deleted.' ),
50
+ getItemTitle( posts[ 0 ] )
51
+ );
52
+ } else {
53
+ successMessage = __( 'The items were permanently deleted.' );
54
+ }
55
+ createSuccessNotice( successMessage, {
56
+ type: 'snackbar',
57
+ id: 'permanently-delete-post-action',
58
+ } );
59
+ onActionPerformed?.( posts );
60
+ } else {
61
+ // If there was at lease one failure.
62
+ let errorMessage;
63
+ // If we were trying to permanently delete a single post.
64
+ if ( promiseResult.length === 1 ) {
65
+ const typedError = promiseResult[ 0 ] as {
66
+ reason?: CoreDataError;
67
+ };
68
+ if ( typedError.reason?.message ) {
69
+ errorMessage = typedError.reason.message;
70
+ } else {
71
+ errorMessage = __(
72
+ 'An error occurred while permanently deleting the item.'
73
+ );
74
+ }
75
+ // If we were trying to permanently delete multiple posts
76
+ } else {
77
+ const errorMessages = new Set();
78
+ const failedPromises = promiseResult.filter(
79
+ ( { status } ) => status === 'rejected'
80
+ );
81
+ for ( const failedPromise of failedPromises ) {
82
+ const typedError = failedPromise as {
83
+ reason?: CoreDataError;
84
+ };
85
+ if ( typedError.reason?.message ) {
86
+ errorMessages.add( typedError.reason.message );
87
+ }
88
+ }
89
+ if ( errorMessages.size === 0 ) {
90
+ errorMessage = __(
91
+ 'An error occurred while permanently deleting the items.'
92
+ );
93
+ } else if ( errorMessages.size === 1 ) {
94
+ errorMessage = sprintf(
95
+ /* translators: %s: an error message */
96
+ __(
97
+ 'An error occurred while permanently deleting the items: %s'
98
+ ),
99
+ [ ...errorMessages ][ 0 ]
100
+ );
101
+ } else {
102
+ errorMessage = sprintf(
103
+ /* translators: %s: a list of comma separated error messages */
104
+ __(
105
+ 'Some errors occurred while permanently deleting the items: %s'
106
+ ),
107
+ [ ...errorMessages ].join( ',' )
108
+ );
109
+ }
110
+ }
111
+ createErrorNotice( errorMessage, {
112
+ type: 'snackbar',
113
+ } );
114
+ }
115
+ },
116
+ };
117
+
118
+ export default permanentlyDeletePost;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { addQueryArgs } from '@wordpress/url';
5
+ import { __, sprintf } from '@wordpress/i18n';
6
+ import type { Action } from '@wordpress/dataviews';
7
+
8
+ /**
9
+ * Internal dependencies
10
+ */
11
+ import type { Post } from '../../types';
12
+
13
+ const viewPostRevisions: Action< Post > = {
14
+ id: 'view-post-revisions',
15
+ context: 'list',
16
+ label( items ) {
17
+ const revisionsCount =
18
+ items[ 0 ]._links?.[ 'version-history' ]?.[ 0 ]?.count ?? 0;
19
+ return sprintf(
20
+ /* translators: %s: number of revisions */
21
+ __( 'View revisions (%s)' ),
22
+ revisionsCount
23
+ );
24
+ },
25
+ isEligible( post ) {
26
+ if ( post.status === 'trash' ) {
27
+ return false;
28
+ }
29
+ const lastRevisionId =
30
+ post?._links?.[ 'predecessor-version' ]?.[ 0 ]?.id ?? null;
31
+ const revisionsCount =
32
+ post?._links?.[ 'version-history' ]?.[ 0 ]?.count ?? 0;
33
+ return !! lastRevisionId && revisionsCount > 1;
34
+ },
35
+ callback( posts, { onActionPerformed } ) {
36
+ const post = posts[ 0 ];
37
+ const href = addQueryArgs( 'revision.php', {
38
+ revision: post?._links?.[ 'predecessor-version' ]?.[ 0 ]?.id,
39
+ } );
40
+ document.location.href = href;
41
+ if ( onActionPerformed ) {
42
+ onActionPerformed( posts );
43
+ }
44
+ },
45
+ };
46
+
47
+ export default viewPostRevisions;
@@ -0,0 +1,3 @@
1
+ export * from './base-post';
2
+ export * from './common';
3
+ export * from './pattern';
@@ -0,0 +1,40 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { _x } from '@wordpress/i18n';
5
+ // @ts-ignore
6
+ import { privateApis as patternsPrivateApis } from '@wordpress/patterns';
7
+ import type { Action } from '@wordpress/dataviews';
8
+
9
+ /**
10
+ * Internal dependencies
11
+ */
12
+ import { unlock } from '../../lock-unlock';
13
+ import type { Pattern } from '../../types';
14
+
15
+ // Patterns.
16
+ const { CreatePatternModalContents, useDuplicatePatternProps } =
17
+ unlock( patternsPrivateApis );
18
+
19
+ const duplicatePattern: Action< Pattern > = {
20
+ id: 'duplicate-pattern',
21
+ label: _x( 'Duplicate', 'action label' ),
22
+ isEligible: ( item ) => item.type !== 'wp_template_part',
23
+ modalHeader: _x( 'Duplicate pattern', 'action label' ),
24
+ RenderModal: ( { items, closeModal } ) => {
25
+ const [ item ] = items;
26
+ const duplicatedProps = useDuplicatePatternProps( {
27
+ pattern: item,
28
+ onSuccess: () => closeModal?.(),
29
+ } );
30
+ return (
31
+ <CreatePatternModalContents
32
+ onClose={ closeModal }
33
+ confirmLabel={ _x( 'Duplicate', 'action label' ) }
34
+ { ...duplicatedProps }
35
+ />
36
+ );
37
+ },
38
+ };
39
+
40
+ export default duplicatePattern;
@@ -0,0 +1,3 @@
1
+ const exportPattern = undefined;
2
+
3
+ export default exportPattern;