@wordpress/core-data 4.12.0 → 4.13.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.
- package/CHANGELOG.md +2 -0
- package/README.md +51 -0
- package/build/batch/create-batch.js +3 -15
- package/build/batch/create-batch.js.map +1 -1
- package/build/hooks/use-entity-record.js +82 -2
- package/build/hooks/use-entity-record.js.map +1 -1
- package/build-module/batch/create-batch.js +3 -14
- package/build-module/batch/create-batch.js.map +1 -1
- package/build-module/hooks/use-entity-record.js +80 -2
- package/build-module/hooks/use-entity-record.js.map +1 -1
- package/package.json +11 -11
- package/src/batch/create-batch.js +3 -12
- package/src/hooks/test/use-entity-record.js +9 -1
- package/src/hooks/use-entity-record.ts +97 -2
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -764,6 +764,57 @@ In the above example, when `PageTitleDisplay` is rendered into an
|
|
|
764
764
|
application, the page and the resolution details will be retrieved from
|
|
765
765
|
the store state using `getEntityRecord()`, or resolved if missing.
|
|
766
766
|
|
|
767
|
+
```js
|
|
768
|
+
import { useState } from '@wordpress/data';
|
|
769
|
+
import { useDispatch } from '@wordpress/data';
|
|
770
|
+
import { __ } from '@wordpress/i18n';
|
|
771
|
+
import { TextControl } from '@wordpress/components';
|
|
772
|
+
import { store as noticeStore } from '@wordpress/notices';
|
|
773
|
+
import { useEntityRecord } from '@wordpress/core-data';
|
|
774
|
+
|
|
775
|
+
function PageRenameForm( { id } ) {
|
|
776
|
+
const page = useEntityRecord( 'postType', 'page', id );
|
|
777
|
+
const [ title, setTitle ] = useState( () => page.record.title.rendered );
|
|
778
|
+
const { createSuccessNotice, createErrorNotice } =
|
|
779
|
+
useDispatch( noticeStore );
|
|
780
|
+
|
|
781
|
+
if ( page.isResolving ) {
|
|
782
|
+
return 'Loading...';
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
async function onRename( event ) {
|
|
786
|
+
event.preventDefault();
|
|
787
|
+
page.edit( { title } );
|
|
788
|
+
try {
|
|
789
|
+
await page.save();
|
|
790
|
+
createSuccessNotice( __( 'Page renamed.' ), {
|
|
791
|
+
type: 'snackbar',
|
|
792
|
+
} );
|
|
793
|
+
} catch ( error ) {
|
|
794
|
+
createErrorNotice( error.message, { type: 'snackbar' } );
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
return (
|
|
799
|
+
<form onSubmit={ onRename }>
|
|
800
|
+
<TextControl
|
|
801
|
+
label={ __( 'Name' ) }
|
|
802
|
+
value={ title }
|
|
803
|
+
onChange={ setTitle }
|
|
804
|
+
/>
|
|
805
|
+
<button type="submit">{ __( 'Save' ) }</button>
|
|
806
|
+
</form>
|
|
807
|
+
);
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
// Rendered in the application:
|
|
811
|
+
// <PageRenameForm id={ 1 } />
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
In the above example, updating and saving the page title is handled
|
|
815
|
+
via the `edit()` and `save()` mutation helpers provided by
|
|
816
|
+
`useEntityRecord()`;
|
|
817
|
+
|
|
767
818
|
_Parameters_
|
|
768
819
|
|
|
769
820
|
- _kind_ `string`: Kind of the entity, e.g. `root` or a `postType`. See rootEntitiesConfig in ../entities.ts for a list of available kinds.
|
|
@@ -7,14 +7,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
7
7
|
});
|
|
8
8
|
exports.default = createBatch;
|
|
9
9
|
|
|
10
|
-
var _lodash = require("lodash");
|
|
11
|
-
|
|
12
10
|
var _defaultProcessor = _interopRequireDefault(require("./default-processor"));
|
|
13
11
|
|
|
14
|
-
/**
|
|
15
|
-
* External dependencies
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
12
|
/**
|
|
19
13
|
* Internal dependencies
|
|
20
14
|
*/
|
|
@@ -151,13 +145,8 @@ function createBatch() {
|
|
|
151
145
|
}
|
|
152
146
|
|
|
153
147
|
let isSuccess = true;
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
/** @type {{error?: unknown, output?: unknown}} */
|
|
157
|
-
const result = pair[0];
|
|
158
|
-
/** @type {{resolve: (value: any) => void; reject: (error: any) => void} | undefined} */
|
|
159
|
-
|
|
160
|
-
const queueItem = pair[1];
|
|
148
|
+
results.forEach((result, key) => {
|
|
149
|
+
const queueItem = queue[key];
|
|
161
150
|
|
|
162
151
|
if (result !== null && result !== void 0 && result.error) {
|
|
163
152
|
queueItem === null || queueItem === void 0 ? void 0 : queueItem.reject(result.error);
|
|
@@ -167,8 +156,7 @@ function createBatch() {
|
|
|
167
156
|
|
|
168
157
|
queueItem === null || queueItem === void 0 ? void 0 : queueItem.resolve((_result$output = result === null || result === void 0 ? void 0 : result.output) !== null && _result$output !== void 0 ? _result$output : result);
|
|
169
158
|
}
|
|
170
|
-
}
|
|
171
|
-
|
|
159
|
+
});
|
|
172
160
|
queue = [];
|
|
173
161
|
return isSuccess;
|
|
174
162
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["@wordpress/core-data/src/batch/create-batch.js"],"names":["createBatch","processor","defaultProcessor","lastId","queue","pending","ObservableSet","add","inputOrThunk","id","input","Promise","resolve","reject","push","delete","finally","run","size","unsubscribe","subscribe","undefined","results","map","length","Error","error","isSuccess","
|
|
1
|
+
{"version":3,"sources":["@wordpress/core-data/src/batch/create-batch.js"],"names":["createBatch","processor","defaultProcessor","lastId","queue","pending","ObservableSet","add","inputOrThunk","id","input","Promise","resolve","reject","push","delete","finally","run","size","unsubscribe","subscribe","undefined","results","map","length","Error","error","isSuccess","forEach","result","key","queueItem","output","constructor","args","set","Set","subscribers","value","subscriber"],"mappings":"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","sourcesContent":["/**\n * Internal dependencies\n */\nimport defaultProcessor from './default-processor';\n\n/**\n * Creates a batch, which can be used to combine multiple API requests into one\n * API request using the WordPress batch processing API (/v1/batch).\n *\n * ```\n * const batch = createBatch();\n * const dunePromise = batch.add( {\n * path: '/v1/books',\n * method: 'POST',\n * data: { title: 'Dune' }\n * } );\n * const lotrPromise = batch.add( {\n * path: '/v1/books',\n * method: 'POST',\n * data: { title: 'Lord of the Rings' }\n * } );\n * const isSuccess = await batch.run(); // Sends one POST to /v1/batch.\n * if ( isSuccess ) {\n * console.log(\n * 'Saved two books:',\n * await dunePromise,\n * await lotrPromise\n * );\n * }\n * ```\n *\n * @param {Function} [processor] Processor function. Can be used to replace the\n * default functionality which is to send an API\n * request to /v1/batch. Is given an array of\n * inputs and must return a promise that\n * resolves to an array of objects containing\n * either `output` or `error`.\n */\nexport default function createBatch( processor = defaultProcessor ) {\n\tlet lastId = 0;\n\t/** @type {Array<{ input: any; resolve: ( value: any ) => void; reject: ( error: any ) => void }>} */\n\tlet queue = [];\n\tconst pending = new ObservableSet();\n\n\treturn {\n\t\t/**\n\t\t * Adds an input to the batch and returns a promise that is resolved or\n\t\t * rejected when the input is processed by `batch.run()`.\n\t\t *\n\t\t * You may also pass a thunk which allows inputs to be added\n\t\t * asychronously.\n\t\t *\n\t\t * ```\n\t\t * // Both are allowed:\n\t\t * batch.add( { path: '/v1/books', ... } );\n\t\t * batch.add( ( add ) => add( { path: '/v1/books', ... } ) );\n\t\t * ```\n\t\t *\n\t\t * If a thunk is passed, `batch.run()` will pause until either:\n\t\t *\n\t\t * - The thunk calls its `add` argument, or;\n\t\t * - The thunk returns a promise and that promise resolves, or;\n\t\t * - The thunk returns a non-promise.\n\t\t *\n\t\t * @param {any|Function} inputOrThunk Input to add or thunk to execute.\n\t\t *\n\t\t * @return {Promise|any} If given an input, returns a promise that\n\t\t * is resolved or rejected when the batch is\n\t\t * processed. If given a thunk, returns the return\n\t\t * value of that thunk.\n\t\t */\n\t\tadd( inputOrThunk ) {\n\t\t\tconst id = ++lastId;\n\t\t\tpending.add( id );\n\n\t\t\tconst add = ( input ) =>\n\t\t\t\tnew Promise( ( resolve, reject ) => {\n\t\t\t\t\tqueue.push( {\n\t\t\t\t\t\tinput,\n\t\t\t\t\t\tresolve,\n\t\t\t\t\t\treject,\n\t\t\t\t\t} );\n\t\t\t\t\tpending.delete( id );\n\t\t\t\t} );\n\n\t\t\tif ( typeof inputOrThunk === 'function' ) {\n\t\t\t\treturn Promise.resolve( inputOrThunk( add ) ).finally( () => {\n\t\t\t\t\tpending.delete( id );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn add( inputOrThunk );\n\t\t},\n\n\t\t/**\n\t\t * Runs the batch. This calls `batchProcessor` and resolves or rejects\n\t\t * all promises returned by `add()`.\n\t\t *\n\t\t * @return {Promise<boolean>} A promise that resolves to a boolean that is true\n\t\t * if the processor returned no errors.\n\t\t */\n\t\tasync run() {\n\t\t\tif ( pending.size ) {\n\t\t\t\tawait new Promise( ( resolve ) => {\n\t\t\t\t\tconst unsubscribe = pending.subscribe( () => {\n\t\t\t\t\t\tif ( ! pending.size ) {\n\t\t\t\t\t\t\tunsubscribe();\n\t\t\t\t\t\t\tresolve( undefined );\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tlet results;\n\n\t\t\ttry {\n\t\t\t\tresults = await processor(\n\t\t\t\t\tqueue.map( ( { input } ) => input )\n\t\t\t\t);\n\n\t\t\t\tif ( results.length !== queue.length ) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t'run: Array returned by processor must be same size as input array.'\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch ( error ) {\n\t\t\t\tfor ( const { reject } of queue ) {\n\t\t\t\t\treject( error );\n\t\t\t\t}\n\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tlet isSuccess = true;\n\n\t\t\tresults.forEach( ( result, key ) => {\n\t\t\t\tconst queueItem = queue[ key ];\n\n\t\t\t\tif ( result?.error ) {\n\t\t\t\t\tqueueItem?.reject( result.error );\n\t\t\t\t\tisSuccess = false;\n\t\t\t\t} else {\n\t\t\t\t\tqueueItem?.resolve( result?.output ?? result );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tqueue = [];\n\n\t\t\treturn isSuccess;\n\t\t},\n\t};\n}\n\nclass ObservableSet {\n\tconstructor( ...args ) {\n\t\tthis.set = new Set( ...args );\n\t\tthis.subscribers = new Set();\n\t}\n\n\tget size() {\n\t\treturn this.set.size;\n\t}\n\n\tadd( value ) {\n\t\tthis.set.add( value );\n\t\tthis.subscribers.forEach( ( subscriber ) => subscriber() );\n\t\treturn this;\n\t}\n\n\tdelete( value ) {\n\t\tconst isSuccess = this.set.delete( value );\n\t\tthis.subscribers.forEach( ( subscriber ) => subscriber() );\n\t\treturn isSuccess;\n\t}\n\n\tsubscribe( subscriber ) {\n\t\tthis.subscribers.add( subscriber );\n\t\treturn () => {\n\t\t\tthis.subscribers.delete( subscriber );\n\t\t};\n\t}\n}\n"]}
|
|
@@ -8,8 +8,12 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
8
8
|
exports.__experimentalUseEntityRecord = __experimentalUseEntityRecord;
|
|
9
9
|
exports.default = useEntityRecord;
|
|
10
10
|
|
|
11
|
+
var _data = require("@wordpress/data");
|
|
12
|
+
|
|
11
13
|
var _deprecated = _interopRequireDefault(require("@wordpress/deprecated"));
|
|
12
14
|
|
|
15
|
+
var _element = require("@wordpress/element");
|
|
16
|
+
|
|
13
17
|
var _useQuerySelect = _interopRequireDefault(require("./use-query-select"));
|
|
14
18
|
|
|
15
19
|
var _ = require("../");
|
|
@@ -51,6 +55,58 @@ var _ = require("../");
|
|
|
51
55
|
* application, the page and the resolution details will be retrieved from
|
|
52
56
|
* the store state using `getEntityRecord()`, or resolved if missing.
|
|
53
57
|
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```js
|
|
60
|
+
* import { useState } from '@wordpress/data';
|
|
61
|
+
* import { useDispatch } from '@wordpress/data';
|
|
62
|
+
* import { __ } from '@wordpress/i18n';
|
|
63
|
+
* import { TextControl } from '@wordpress/components';
|
|
64
|
+
* import { store as noticeStore } from '@wordpress/notices';
|
|
65
|
+
* import { useEntityRecord } from '@wordpress/core-data';
|
|
66
|
+
*
|
|
67
|
+
* function PageRenameForm( { id } ) {
|
|
68
|
+
* const page = useEntityRecord( 'postType', 'page', id );
|
|
69
|
+
* const [ title, setTitle ] = useState( () => page.record.title.rendered );
|
|
70
|
+
* const { createSuccessNotice, createErrorNotice } =
|
|
71
|
+
* useDispatch( noticeStore );
|
|
72
|
+
*
|
|
73
|
+
* if ( page.isResolving ) {
|
|
74
|
+
* return 'Loading...';
|
|
75
|
+
* }
|
|
76
|
+
*
|
|
77
|
+
* async function onRename( event ) {
|
|
78
|
+
* event.preventDefault();
|
|
79
|
+
* page.edit( { title } );
|
|
80
|
+
* try {
|
|
81
|
+
* await page.save();
|
|
82
|
+
* createSuccessNotice( __( 'Page renamed.' ), {
|
|
83
|
+
* type: 'snackbar',
|
|
84
|
+
* } );
|
|
85
|
+
* } catch ( error ) {
|
|
86
|
+
* createErrorNotice( error.message, { type: 'snackbar' } );
|
|
87
|
+
* }
|
|
88
|
+
* }
|
|
89
|
+
*
|
|
90
|
+
* return (
|
|
91
|
+
* <form onSubmit={ onRename }>
|
|
92
|
+
* <TextControl
|
|
93
|
+
* label={ __( 'Name' ) }
|
|
94
|
+
* value={ title }
|
|
95
|
+
* onChange={ setTitle }
|
|
96
|
+
* />
|
|
97
|
+
* <button type="submit">{ __( 'Save' ) }</button>
|
|
98
|
+
* </form>
|
|
99
|
+
* );
|
|
100
|
+
* }
|
|
101
|
+
*
|
|
102
|
+
* // Rendered in the application:
|
|
103
|
+
* // <PageRenameForm id={ 1 } />
|
|
104
|
+
* ```
|
|
105
|
+
*
|
|
106
|
+
* In the above example, updating and saving the page title is handled
|
|
107
|
+
* via the `edit()` and `save()` mutation helpers provided by
|
|
108
|
+
* `useEntityRecord()`;
|
|
109
|
+
*
|
|
54
110
|
* @return Entity record data.
|
|
55
111
|
* @template RecordType
|
|
56
112
|
*/
|
|
@@ -58,9 +114,30 @@ function useEntityRecord(kind, name, recordId) {
|
|
|
58
114
|
let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {
|
|
59
115
|
enabled: true
|
|
60
116
|
};
|
|
117
|
+
const {
|
|
118
|
+
editEntityRecord,
|
|
119
|
+
saveEditedEntityRecord
|
|
120
|
+
} = (0, _data.useDispatch)(_.store);
|
|
121
|
+
const mutations = (0, _element.useMemo)(() => ({
|
|
122
|
+
edit: record => editEntityRecord(kind, name, recordId, record),
|
|
123
|
+
save: function () {
|
|
124
|
+
let saveOptions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
125
|
+
return saveEditedEntityRecord(kind, name, recordId, {
|
|
126
|
+
throwOnError: true,
|
|
127
|
+
...saveOptions
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}), [recordId]);
|
|
131
|
+
const {
|
|
132
|
+
editedRecord,
|
|
133
|
+
hasEdits
|
|
134
|
+
} = (0, _data.useSelect)(select => ({
|
|
135
|
+
editedRecord: select(_.store).getEditedEntityRecord(),
|
|
136
|
+
hasEdits: select(_.store).hasEditsForEntityRecord()
|
|
137
|
+
}), [kind, name, recordId]);
|
|
61
138
|
const {
|
|
62
139
|
data: record,
|
|
63
|
-
...
|
|
140
|
+
...querySelectRest
|
|
64
141
|
} = (0, _useQuerySelect.default)(query => {
|
|
65
142
|
if (!options.enabled) {
|
|
66
143
|
return null;
|
|
@@ -70,7 +147,10 @@ function useEntityRecord(kind, name, recordId) {
|
|
|
70
147
|
}, [kind, name, recordId, options.enabled]);
|
|
71
148
|
return {
|
|
72
149
|
record,
|
|
73
|
-
|
|
150
|
+
editedRecord,
|
|
151
|
+
hasEdits,
|
|
152
|
+
...querySelectRest,
|
|
153
|
+
...mutations
|
|
74
154
|
};
|
|
75
155
|
}
|
|
76
156
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["@wordpress/core-data/src/hooks/use-entity-record.ts"],"names":["useEntityRecord","kind","name","recordId","options","enabled","
|
|
1
|
+
{"version":3,"sources":["@wordpress/core-data/src/hooks/use-entity-record.ts"],"names":["useEntityRecord","kind","name","recordId","options","enabled","editEntityRecord","saveEditedEntityRecord","coreStore","mutations","edit","record","save","saveOptions","throwOnError","editedRecord","hasEdits","select","getEditedEntityRecord","hasEditsForEntityRecord","data","querySelectRest","query","getEntityRecord","__experimentalUseEntityRecord","alternative","since"],"mappings":";;;;;;;;;;AAGA;;AACA;;AACA;;AAKA;;AACA;;AAXA;AACA;AACA;;AAKA;AACA;AACA;;AA8CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACe,SAASA,eAAT,CACdC,IADc,EAEdC,IAFc,EAGdC,QAHc,EAKyB;AAAA,MADvCC,OACuC,uEADpB;AAAEC,IAAAA,OAAO,EAAE;AAAX,GACoB;AACvC,QAAM;AAAEC,IAAAA,gBAAF;AAAoBC,IAAAA;AAApB,MACL,uBAAaC,OAAb,CADD;AAGA,QAAMC,SAAS,GAAG,sBACjB,OAAQ;AACPC,IAAAA,IAAI,EAAIC,MAAF,IACLL,gBAAgB,CAAEL,IAAF,EAAQC,IAAR,EAAcC,QAAd,EAAwBQ,MAAxB,CAFV;AAGPC,IAAAA,IAAI,EAAE;AAAA,UAAEC,WAAF,uEAAqB,EAArB;AAAA,aACLN,sBAAsB,CAAEN,IAAF,EAAQC,IAAR,EAAcC,QAAd,EAAwB;AAC7CW,QAAAA,YAAY,EAAE,IAD+B;AAE7C,WAAGD;AAF0C,OAAxB,CADjB;AAAA;AAHC,GAAR,CADiB,EAUjB,CAAEV,QAAF,CAViB,CAAlB;AAaA,QAAM;AAAEY,IAAAA,YAAF;AAAgBC,IAAAA;AAAhB,MAA6B,qBAChCC,MAAF,KAAgB;AACfF,IAAAA,YAAY,EAAEE,MAAM,CAAET,OAAF,CAAN,CAAoBU,qBAApB,EADC;AAEfF,IAAAA,QAAQ,EAAEC,MAAM,CAAET,OAAF,CAAN,CAAoBW,uBAApB;AAFK,GAAhB,CADkC,EAKlC,CAAElB,IAAF,EAAQC,IAAR,EAAcC,QAAd,CALkC,CAAnC;AAQA,QAAM;AAAEiB,IAAAA,IAAI,EAAET,MAAR;AAAgB,OAAGU;AAAnB,MAAuC,6BAC1CC,KAAF,IAAa;AACZ,QAAK,CAAElB,OAAO,CAACC,OAAf,EAAyB;AACxB,aAAO,IAAP;AACA;;AACD,WAAOiB,KAAK,CAAEd,OAAF,CAAL,CAAmBe,eAAnB,CAAoCtB,IAApC,EAA0CC,IAA1C,EAAgDC,QAAhD,CAAP;AACA,GAN2C,EAO5C,CAAEF,IAAF,EAAQC,IAAR,EAAcC,QAAd,EAAwBC,OAAO,CAACC,OAAhC,CAP4C,CAA7C;AAUA,SAAO;AACNM,IAAAA,MADM;AAENI,IAAAA,YAFM;AAGNC,IAAAA,QAHM;AAIN,OAAGK,eAJG;AAKN,OAAGZ;AALG,GAAP;AAOA;;AAEM,SAASe,6BAAT,CACNvB,IADM,EAENC,IAFM,EAGNC,QAHM,EAINC,OAJM,EAKL;AACD,2BAAa,uCAAb,EAAqD;AACpDqB,IAAAA,WAAW,EAAE,yBADuC;AAEpDC,IAAAA,KAAK,EAAE;AAF6C,GAArD;AAIA,SAAO1B,eAAe,CAAEC,IAAF,EAAQC,IAAR,EAAcC,QAAd,EAAwBC,OAAxB,CAAtB;AACA","sourcesContent":["/**\n * WordPress dependencies\n */\nimport { useDispatch, useSelect } from '@wordpress/data';\nimport deprecated from '@wordpress/deprecated';\nimport { useMemo } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport useQuerySelect from './use-query-select';\nimport { store as coreStore } from '../';\nimport type { Status } from './constants';\n\nexport interface EntityRecordResolution< RecordType > {\n\t/** The requested entity record */\n\trecord: RecordType | null;\n\n\t/** The edited entity record */\n\teditedRecord: Partial< RecordType >;\n\n\t/** Apply local (in-browser) edits to the edited entity record */\n\tedit: ( diff: Partial< RecordType > ) => void;\n\n\t/** Persist the edits to the server */\n\tsave: () => Promise< void >;\n\n\t/**\n\t * Is the record still being resolved?\n\t */\n\tisResolving: boolean;\n\n\t/**\n\t * Does the record have any local edits?\n\t */\n\thasEdits: boolean;\n\n\t/**\n\t * Is the record resolved by now?\n\t */\n\thasResolved: boolean;\n\n\t/** Resolution status */\n\tstatus: Status;\n}\n\nexport interface Options {\n\t/**\n\t * Whether to run the query or short-circuit and return null.\n\t *\n\t * @default true\n\t */\n\tenabled: boolean;\n}\n\n/**\n * Resolves the specified entity record.\n *\n * @param kind Kind of the entity, e.g. `root` or a `postType`. See rootEntitiesConfig in ../entities.ts for a list of available kinds.\n * @param name Name of the entity, e.g. `plugin` or a `post`. See rootEntitiesConfig in ../entities.ts for a list of available names.\n * @param recordId ID of the requested entity record.\n * @param options Optional hook options.\n * @example\n * ```js\n * import { useEntityRecord } from '@wordpress/core-data';\n *\n * function PageTitleDisplay( { id } ) {\n * const { record, isResolving } = useEntityRecord( 'postType', 'page', id );\n *\n * if ( isResolving ) {\n * return 'Loading...';\n * }\n *\n * return record.title;\n * }\n *\n * // Rendered in the application:\n * // <PageTitleDisplay id={ 1 } />\n * ```\n *\n * In the above example, when `PageTitleDisplay` is rendered into an\n * application, the page and the resolution details will be retrieved from\n * the store state using `getEntityRecord()`, or resolved if missing.\n *\n * @example\n * ```js\n * import { useState } from '@wordpress/data';\n * import { useDispatch } from '@wordpress/data';\n * import { __ } from '@wordpress/i18n';\n * import { TextControl } from '@wordpress/components';\n * import { store as noticeStore } from '@wordpress/notices';\n * import { useEntityRecord } from '@wordpress/core-data';\n *\n * function PageRenameForm( { id } ) {\n * \tconst page = useEntityRecord( 'postType', 'page', id );\n * \tconst [ title, setTitle ] = useState( () => page.record.title.rendered );\n * \tconst { createSuccessNotice, createErrorNotice } =\n * \t\tuseDispatch( noticeStore );\n *\n * \tif ( page.isResolving ) {\n * \t\treturn 'Loading...';\n * \t}\n *\n * \tasync function onRename( event ) {\n * \t\tevent.preventDefault();\n * \t\tpage.edit( { title } );\n * \t\ttry {\n * \t\t\tawait page.save();\n * \t\t\tcreateSuccessNotice( __( 'Page renamed.' ), {\n * \t\t\t\ttype: 'snackbar',\n * \t\t\t} );\n * \t\t} catch ( error ) {\n * \t\t\tcreateErrorNotice( error.message, { type: 'snackbar' } );\n * \t\t}\n * \t}\n *\n * \treturn (\n * \t\t<form onSubmit={ onRename }>\n * \t\t\t<TextControl\n * \t\t\t\tlabel={ __( 'Name' ) }\n * \t\t\t\tvalue={ title }\n * \t\t\t\tonChange={ setTitle }\n * \t\t\t/>\n * \t\t\t<button type=\"submit\">{ __( 'Save' ) }</button>\n * \t\t</form>\n * \t);\n * }\n *\n * // Rendered in the application:\n * // <PageRenameForm id={ 1 } />\n * ```\n *\n * In the above example, updating and saving the page title is handled\n * via the `edit()` and `save()` mutation helpers provided by\n * `useEntityRecord()`;\n *\n * @return Entity record data.\n * @template RecordType\n */\nexport default function useEntityRecord< RecordType >(\n\tkind: string,\n\tname: string,\n\trecordId: string | number,\n\toptions: Options = { enabled: true }\n): EntityRecordResolution< RecordType > {\n\tconst { editEntityRecord, saveEditedEntityRecord } =\n\t\tuseDispatch( coreStore );\n\n\tconst mutations = useMemo(\n\t\t() => ( {\n\t\t\tedit: ( record ) =>\n\t\t\t\teditEntityRecord( kind, name, recordId, record ),\n\t\t\tsave: ( saveOptions: any = {} ) =>\n\t\t\t\tsaveEditedEntityRecord( kind, name, recordId, {\n\t\t\t\t\tthrowOnError: true,\n\t\t\t\t\t...saveOptions,\n\t\t\t\t} ),\n\t\t} ),\n\t\t[ recordId ]\n\t);\n\n\tconst { editedRecord, hasEdits } = useSelect(\n\t\t( select ) => ( {\n\t\t\teditedRecord: select( coreStore ).getEditedEntityRecord(),\n\t\t\thasEdits: select( coreStore ).hasEditsForEntityRecord(),\n\t\t} ),\n\t\t[ kind, name, recordId ]\n\t);\n\n\tconst { data: record, ...querySelectRest } = useQuerySelect(\n\t\t( query ) => {\n\t\t\tif ( ! options.enabled ) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn query( coreStore ).getEntityRecord( kind, name, recordId );\n\t\t},\n\t\t[ kind, name, recordId, options.enabled ]\n\t);\n\n\treturn {\n\t\trecord,\n\t\teditedRecord,\n\t\thasEdits,\n\t\t...querySelectRest,\n\t\t...mutations,\n\t};\n}\n\nexport function __experimentalUseEntityRecord(\n\tkind: string,\n\tname: string,\n\trecordId: any,\n\toptions: any\n) {\n\tdeprecated( `wp.data.__experimentalUseEntityRecord`, {\n\t\talternative: 'wp.data.useEntityRecord',\n\t\tsince: '6.1',\n\t} );\n\treturn useEntityRecord( kind, name, recordId, options );\n}\n"]}
|
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* External dependencies
|
|
3
|
-
*/
|
|
4
|
-
import { zip } from 'lodash';
|
|
5
1
|
/**
|
|
6
2
|
* Internal dependencies
|
|
7
3
|
*/
|
|
8
|
-
|
|
9
4
|
import defaultProcessor from './default-processor';
|
|
10
5
|
/**
|
|
11
6
|
* Creates a batch, which can be used to combine multiple API requests into one
|
|
@@ -140,13 +135,8 @@ export default function createBatch() {
|
|
|
140
135
|
}
|
|
141
136
|
|
|
142
137
|
let isSuccess = true;
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
/** @type {{error?: unknown, output?: unknown}} */
|
|
146
|
-
const result = pair[0];
|
|
147
|
-
/** @type {{resolve: (value: any) => void; reject: (error: any) => void} | undefined} */
|
|
148
|
-
|
|
149
|
-
const queueItem = pair[1];
|
|
138
|
+
results.forEach((result, key) => {
|
|
139
|
+
const queueItem = queue[key];
|
|
150
140
|
|
|
151
141
|
if (result !== null && result !== void 0 && result.error) {
|
|
152
142
|
queueItem === null || queueItem === void 0 ? void 0 : queueItem.reject(result.error);
|
|
@@ -156,8 +146,7 @@ export default function createBatch() {
|
|
|
156
146
|
|
|
157
147
|
queueItem === null || queueItem === void 0 ? void 0 : queueItem.resolve((_result$output = result === null || result === void 0 ? void 0 : result.output) !== null && _result$output !== void 0 ? _result$output : result);
|
|
158
148
|
}
|
|
159
|
-
}
|
|
160
|
-
|
|
149
|
+
});
|
|
161
150
|
queue = [];
|
|
162
151
|
return isSuccess;
|
|
163
152
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["@wordpress/core-data/src/batch/create-batch.js"],"names":["
|
|
1
|
+
{"version":3,"sources":["@wordpress/core-data/src/batch/create-batch.js"],"names":["defaultProcessor","createBatch","processor","lastId","queue","pending","ObservableSet","add","inputOrThunk","id","input","Promise","resolve","reject","push","delete","finally","run","size","unsubscribe","subscribe","undefined","results","map","length","Error","error","isSuccess","forEach","result","key","queueItem","output","constructor","args","set","Set","subscribers","value","subscriber"],"mappings":"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","sourcesContent":["/**\n * Internal dependencies\n */\nimport defaultProcessor from './default-processor';\n\n/**\n * Creates a batch, which can be used to combine multiple API requests into one\n * API request using the WordPress batch processing API (/v1/batch).\n *\n * ```\n * const batch = createBatch();\n * const dunePromise = batch.add( {\n * path: '/v1/books',\n * method: 'POST',\n * data: { title: 'Dune' }\n * } );\n * const lotrPromise = batch.add( {\n * path: '/v1/books',\n * method: 'POST',\n * data: { title: 'Lord of the Rings' }\n * } );\n * const isSuccess = await batch.run(); // Sends one POST to /v1/batch.\n * if ( isSuccess ) {\n * console.log(\n * 'Saved two books:',\n * await dunePromise,\n * await lotrPromise\n * );\n * }\n * ```\n *\n * @param {Function} [processor] Processor function. Can be used to replace the\n * default functionality which is to send an API\n * request to /v1/batch. Is given an array of\n * inputs and must return a promise that\n * resolves to an array of objects containing\n * either `output` or `error`.\n */\nexport default function createBatch( processor = defaultProcessor ) {\n\tlet lastId = 0;\n\t/** @type {Array<{ input: any; resolve: ( value: any ) => void; reject: ( error: any ) => void }>} */\n\tlet queue = [];\n\tconst pending = new ObservableSet();\n\n\treturn {\n\t\t/**\n\t\t * Adds an input to the batch and returns a promise that is resolved or\n\t\t * rejected when the input is processed by `batch.run()`.\n\t\t *\n\t\t * You may also pass a thunk which allows inputs to be added\n\t\t * asychronously.\n\t\t *\n\t\t * ```\n\t\t * // Both are allowed:\n\t\t * batch.add( { path: '/v1/books', ... } );\n\t\t * batch.add( ( add ) => add( { path: '/v1/books', ... } ) );\n\t\t * ```\n\t\t *\n\t\t * If a thunk is passed, `batch.run()` will pause until either:\n\t\t *\n\t\t * - The thunk calls its `add` argument, or;\n\t\t * - The thunk returns a promise and that promise resolves, or;\n\t\t * - The thunk returns a non-promise.\n\t\t *\n\t\t * @param {any|Function} inputOrThunk Input to add or thunk to execute.\n\t\t *\n\t\t * @return {Promise|any} If given an input, returns a promise that\n\t\t * is resolved or rejected when the batch is\n\t\t * processed. If given a thunk, returns the return\n\t\t * value of that thunk.\n\t\t */\n\t\tadd( inputOrThunk ) {\n\t\t\tconst id = ++lastId;\n\t\t\tpending.add( id );\n\n\t\t\tconst add = ( input ) =>\n\t\t\t\tnew Promise( ( resolve, reject ) => {\n\t\t\t\t\tqueue.push( {\n\t\t\t\t\t\tinput,\n\t\t\t\t\t\tresolve,\n\t\t\t\t\t\treject,\n\t\t\t\t\t} );\n\t\t\t\t\tpending.delete( id );\n\t\t\t\t} );\n\n\t\t\tif ( typeof inputOrThunk === 'function' ) {\n\t\t\t\treturn Promise.resolve( inputOrThunk( add ) ).finally( () => {\n\t\t\t\t\tpending.delete( id );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn add( inputOrThunk );\n\t\t},\n\n\t\t/**\n\t\t * Runs the batch. This calls `batchProcessor` and resolves or rejects\n\t\t * all promises returned by `add()`.\n\t\t *\n\t\t * @return {Promise<boolean>} A promise that resolves to a boolean that is true\n\t\t * if the processor returned no errors.\n\t\t */\n\t\tasync run() {\n\t\t\tif ( pending.size ) {\n\t\t\t\tawait new Promise( ( resolve ) => {\n\t\t\t\t\tconst unsubscribe = pending.subscribe( () => {\n\t\t\t\t\t\tif ( ! pending.size ) {\n\t\t\t\t\t\t\tunsubscribe();\n\t\t\t\t\t\t\tresolve( undefined );\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tlet results;\n\n\t\t\ttry {\n\t\t\t\tresults = await processor(\n\t\t\t\t\tqueue.map( ( { input } ) => input )\n\t\t\t\t);\n\n\t\t\t\tif ( results.length !== queue.length ) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t'run: Array returned by processor must be same size as input array.'\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch ( error ) {\n\t\t\t\tfor ( const { reject } of queue ) {\n\t\t\t\t\treject( error );\n\t\t\t\t}\n\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tlet isSuccess = true;\n\n\t\t\tresults.forEach( ( result, key ) => {\n\t\t\t\tconst queueItem = queue[ key ];\n\n\t\t\t\tif ( result?.error ) {\n\t\t\t\t\tqueueItem?.reject( result.error );\n\t\t\t\t\tisSuccess = false;\n\t\t\t\t} else {\n\t\t\t\t\tqueueItem?.resolve( result?.output ?? result );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tqueue = [];\n\n\t\t\treturn isSuccess;\n\t\t},\n\t};\n}\n\nclass ObservableSet {\n\tconstructor( ...args ) {\n\t\tthis.set = new Set( ...args );\n\t\tthis.subscribers = new Set();\n\t}\n\n\tget size() {\n\t\treturn this.set.size;\n\t}\n\n\tadd( value ) {\n\t\tthis.set.add( value );\n\t\tthis.subscribers.forEach( ( subscriber ) => subscriber() );\n\t\treturn this;\n\t}\n\n\tdelete( value ) {\n\t\tconst isSuccess = this.set.delete( value );\n\t\tthis.subscribers.forEach( ( subscriber ) => subscriber() );\n\t\treturn isSuccess;\n\t}\n\n\tsubscribe( subscriber ) {\n\t\tthis.subscribers.add( subscriber );\n\t\treturn () => {\n\t\t\tthis.subscribers.delete( subscriber );\n\t\t};\n\t}\n}\n"]}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
|
+
import { useDispatch, useSelect } from '@wordpress/data';
|
|
4
5
|
import deprecated from '@wordpress/deprecated';
|
|
6
|
+
import { useMemo } from '@wordpress/element';
|
|
5
7
|
/**
|
|
6
8
|
* Internal dependencies
|
|
7
9
|
*/
|
|
@@ -38,6 +40,58 @@ import { store as coreStore } from '../';
|
|
|
38
40
|
* application, the page and the resolution details will be retrieved from
|
|
39
41
|
* the store state using `getEntityRecord()`, or resolved if missing.
|
|
40
42
|
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```js
|
|
45
|
+
* import { useState } from '@wordpress/data';
|
|
46
|
+
* import { useDispatch } from '@wordpress/data';
|
|
47
|
+
* import { __ } from '@wordpress/i18n';
|
|
48
|
+
* import { TextControl } from '@wordpress/components';
|
|
49
|
+
* import { store as noticeStore } from '@wordpress/notices';
|
|
50
|
+
* import { useEntityRecord } from '@wordpress/core-data';
|
|
51
|
+
*
|
|
52
|
+
* function PageRenameForm( { id } ) {
|
|
53
|
+
* const page = useEntityRecord( 'postType', 'page', id );
|
|
54
|
+
* const [ title, setTitle ] = useState( () => page.record.title.rendered );
|
|
55
|
+
* const { createSuccessNotice, createErrorNotice } =
|
|
56
|
+
* useDispatch( noticeStore );
|
|
57
|
+
*
|
|
58
|
+
* if ( page.isResolving ) {
|
|
59
|
+
* return 'Loading...';
|
|
60
|
+
* }
|
|
61
|
+
*
|
|
62
|
+
* async function onRename( event ) {
|
|
63
|
+
* event.preventDefault();
|
|
64
|
+
* page.edit( { title } );
|
|
65
|
+
* try {
|
|
66
|
+
* await page.save();
|
|
67
|
+
* createSuccessNotice( __( 'Page renamed.' ), {
|
|
68
|
+
* type: 'snackbar',
|
|
69
|
+
* } );
|
|
70
|
+
* } catch ( error ) {
|
|
71
|
+
* createErrorNotice( error.message, { type: 'snackbar' } );
|
|
72
|
+
* }
|
|
73
|
+
* }
|
|
74
|
+
*
|
|
75
|
+
* return (
|
|
76
|
+
* <form onSubmit={ onRename }>
|
|
77
|
+
* <TextControl
|
|
78
|
+
* label={ __( 'Name' ) }
|
|
79
|
+
* value={ title }
|
|
80
|
+
* onChange={ setTitle }
|
|
81
|
+
* />
|
|
82
|
+
* <button type="submit">{ __( 'Save' ) }</button>
|
|
83
|
+
* </form>
|
|
84
|
+
* );
|
|
85
|
+
* }
|
|
86
|
+
*
|
|
87
|
+
* // Rendered in the application:
|
|
88
|
+
* // <PageRenameForm id={ 1 } />
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* In the above example, updating and saving the page title is handled
|
|
92
|
+
* via the `edit()` and `save()` mutation helpers provided by
|
|
93
|
+
* `useEntityRecord()`;
|
|
94
|
+
*
|
|
41
95
|
* @return Entity record data.
|
|
42
96
|
* @template RecordType
|
|
43
97
|
*/
|
|
@@ -45,9 +99,30 @@ export default function useEntityRecord(kind, name, recordId) {
|
|
|
45
99
|
let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {
|
|
46
100
|
enabled: true
|
|
47
101
|
};
|
|
102
|
+
const {
|
|
103
|
+
editEntityRecord,
|
|
104
|
+
saveEditedEntityRecord
|
|
105
|
+
} = useDispatch(coreStore);
|
|
106
|
+
const mutations = useMemo(() => ({
|
|
107
|
+
edit: record => editEntityRecord(kind, name, recordId, record),
|
|
108
|
+
save: function () {
|
|
109
|
+
let saveOptions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
110
|
+
return saveEditedEntityRecord(kind, name, recordId, {
|
|
111
|
+
throwOnError: true,
|
|
112
|
+
...saveOptions
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}), [recordId]);
|
|
116
|
+
const {
|
|
117
|
+
editedRecord,
|
|
118
|
+
hasEdits
|
|
119
|
+
} = useSelect(select => ({
|
|
120
|
+
editedRecord: select(coreStore).getEditedEntityRecord(),
|
|
121
|
+
hasEdits: select(coreStore).hasEditsForEntityRecord()
|
|
122
|
+
}), [kind, name, recordId]);
|
|
48
123
|
const {
|
|
49
124
|
data: record,
|
|
50
|
-
...
|
|
125
|
+
...querySelectRest
|
|
51
126
|
} = useQuerySelect(query => {
|
|
52
127
|
if (!options.enabled) {
|
|
53
128
|
return null;
|
|
@@ -57,7 +132,10 @@ export default function useEntityRecord(kind, name, recordId) {
|
|
|
57
132
|
}, [kind, name, recordId, options.enabled]);
|
|
58
133
|
return {
|
|
59
134
|
record,
|
|
60
|
-
|
|
135
|
+
editedRecord,
|
|
136
|
+
hasEdits,
|
|
137
|
+
...querySelectRest,
|
|
138
|
+
...mutations
|
|
61
139
|
};
|
|
62
140
|
}
|
|
63
141
|
export function __experimentalUseEntityRecord(kind, name, recordId, options) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["@wordpress/core-data/src/hooks/use-entity-record.ts"],"names":["deprecated","useQuerySelect","store","coreStore","useEntityRecord","kind","name","recordId","options","enabled","
|
|
1
|
+
{"version":3,"sources":["@wordpress/core-data/src/hooks/use-entity-record.ts"],"names":["useDispatch","useSelect","deprecated","useMemo","useQuerySelect","store","coreStore","useEntityRecord","kind","name","recordId","options","enabled","editEntityRecord","saveEditedEntityRecord","mutations","edit","record","save","saveOptions","throwOnError","editedRecord","hasEdits","select","getEditedEntityRecord","hasEditsForEntityRecord","data","querySelectRest","query","getEntityRecord","__experimentalUseEntityRecord","alternative","since"],"mappings":"AAAA;AACA;AACA;AACA,SAASA,WAAT,EAAsBC,SAAtB,QAAuC,iBAAvC;AACA,OAAOC,UAAP,MAAuB,uBAAvB;AACA,SAASC,OAAT,QAAwB,oBAAxB;AAEA;AACA;AACA;;AACA,OAAOC,cAAP,MAA2B,oBAA3B;AACA,SAASC,KAAK,IAAIC,SAAlB,QAAmC,KAAnC;;AA4CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,SAASC,eAAT,CACdC,IADc,EAEdC,IAFc,EAGdC,QAHc,EAKyB;AAAA,MADvCC,OACuC,uEADpB;AAAEC,IAAAA,OAAO,EAAE;AAAX,GACoB;AACvC,QAAM;AAAEC,IAAAA,gBAAF;AAAoBC,IAAAA;AAApB,MACLd,WAAW,CAAEM,SAAF,CADZ;AAGA,QAAMS,SAAS,GAAGZ,OAAO,CACxB,OAAQ;AACPa,IAAAA,IAAI,EAAIC,MAAF,IACLJ,gBAAgB,CAAEL,IAAF,EAAQC,IAAR,EAAcC,QAAd,EAAwBO,MAAxB,CAFV;AAGPC,IAAAA,IAAI,EAAE;AAAA,UAAEC,WAAF,uEAAqB,EAArB;AAAA,aACLL,sBAAsB,CAAEN,IAAF,EAAQC,IAAR,EAAcC,QAAd,EAAwB;AAC7CU,QAAAA,YAAY,EAAE,IAD+B;AAE7C,WAAGD;AAF0C,OAAxB,CADjB;AAAA;AAHC,GAAR,CADwB,EAUxB,CAAET,QAAF,CAVwB,CAAzB;AAaA,QAAM;AAAEW,IAAAA,YAAF;AAAgBC,IAAAA;AAAhB,MAA6BrB,SAAS,CACzCsB,MAAF,KAAgB;AACfF,IAAAA,YAAY,EAAEE,MAAM,CAAEjB,SAAF,CAAN,CAAoBkB,qBAApB,EADC;AAEfF,IAAAA,QAAQ,EAAEC,MAAM,CAAEjB,SAAF,CAAN,CAAoBmB,uBAApB;AAFK,GAAhB,CAD2C,EAK3C,CAAEjB,IAAF,EAAQC,IAAR,EAAcC,QAAd,CAL2C,CAA5C;AAQA,QAAM;AAAEgB,IAAAA,IAAI,EAAET,MAAR;AAAgB,OAAGU;AAAnB,MAAuCvB,cAAc,CACxDwB,KAAF,IAAa;AACZ,QAAK,CAAEjB,OAAO,CAACC,OAAf,EAAyB;AACxB,aAAO,IAAP;AACA;;AACD,WAAOgB,KAAK,CAAEtB,SAAF,CAAL,CAAmBuB,eAAnB,CAAoCrB,IAApC,EAA0CC,IAA1C,EAAgDC,QAAhD,CAAP;AACA,GANyD,EAO1D,CAAEF,IAAF,EAAQC,IAAR,EAAcC,QAAd,EAAwBC,OAAO,CAACC,OAAhC,CAP0D,CAA3D;AAUA,SAAO;AACNK,IAAAA,MADM;AAENI,IAAAA,YAFM;AAGNC,IAAAA,QAHM;AAIN,OAAGK,eAJG;AAKN,OAAGZ;AALG,GAAP;AAOA;AAED,OAAO,SAASe,6BAAT,CACNtB,IADM,EAENC,IAFM,EAGNC,QAHM,EAINC,OAJM,EAKL;AACDT,EAAAA,UAAU,CAAG,uCAAH,EAA2C;AACpD6B,IAAAA,WAAW,EAAE,yBADuC;AAEpDC,IAAAA,KAAK,EAAE;AAF6C,GAA3C,CAAV;AAIA,SAAOzB,eAAe,CAAEC,IAAF,EAAQC,IAAR,EAAcC,QAAd,EAAwBC,OAAxB,CAAtB;AACA","sourcesContent":["/**\n * WordPress dependencies\n */\nimport { useDispatch, useSelect } from '@wordpress/data';\nimport deprecated from '@wordpress/deprecated';\nimport { useMemo } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport useQuerySelect from './use-query-select';\nimport { store as coreStore } from '../';\nimport type { Status } from './constants';\n\nexport interface EntityRecordResolution< RecordType > {\n\t/** The requested entity record */\n\trecord: RecordType | null;\n\n\t/** The edited entity record */\n\teditedRecord: Partial< RecordType >;\n\n\t/** Apply local (in-browser) edits to the edited entity record */\n\tedit: ( diff: Partial< RecordType > ) => void;\n\n\t/** Persist the edits to the server */\n\tsave: () => Promise< void >;\n\n\t/**\n\t * Is the record still being resolved?\n\t */\n\tisResolving: boolean;\n\n\t/**\n\t * Does the record have any local edits?\n\t */\n\thasEdits: boolean;\n\n\t/**\n\t * Is the record resolved by now?\n\t */\n\thasResolved: boolean;\n\n\t/** Resolution status */\n\tstatus: Status;\n}\n\nexport interface Options {\n\t/**\n\t * Whether to run the query or short-circuit and return null.\n\t *\n\t * @default true\n\t */\n\tenabled: boolean;\n}\n\n/**\n * Resolves the specified entity record.\n *\n * @param kind Kind of the entity, e.g. `root` or a `postType`. See rootEntitiesConfig in ../entities.ts for a list of available kinds.\n * @param name Name of the entity, e.g. `plugin` or a `post`. See rootEntitiesConfig in ../entities.ts for a list of available names.\n * @param recordId ID of the requested entity record.\n * @param options Optional hook options.\n * @example\n * ```js\n * import { useEntityRecord } from '@wordpress/core-data';\n *\n * function PageTitleDisplay( { id } ) {\n * const { record, isResolving } = useEntityRecord( 'postType', 'page', id );\n *\n * if ( isResolving ) {\n * return 'Loading...';\n * }\n *\n * return record.title;\n * }\n *\n * // Rendered in the application:\n * // <PageTitleDisplay id={ 1 } />\n * ```\n *\n * In the above example, when `PageTitleDisplay` is rendered into an\n * application, the page and the resolution details will be retrieved from\n * the store state using `getEntityRecord()`, or resolved if missing.\n *\n * @example\n * ```js\n * import { useState } from '@wordpress/data';\n * import { useDispatch } from '@wordpress/data';\n * import { __ } from '@wordpress/i18n';\n * import { TextControl } from '@wordpress/components';\n * import { store as noticeStore } from '@wordpress/notices';\n * import { useEntityRecord } from '@wordpress/core-data';\n *\n * function PageRenameForm( { id } ) {\n * \tconst page = useEntityRecord( 'postType', 'page', id );\n * \tconst [ title, setTitle ] = useState( () => page.record.title.rendered );\n * \tconst { createSuccessNotice, createErrorNotice } =\n * \t\tuseDispatch( noticeStore );\n *\n * \tif ( page.isResolving ) {\n * \t\treturn 'Loading...';\n * \t}\n *\n * \tasync function onRename( event ) {\n * \t\tevent.preventDefault();\n * \t\tpage.edit( { title } );\n * \t\ttry {\n * \t\t\tawait page.save();\n * \t\t\tcreateSuccessNotice( __( 'Page renamed.' ), {\n * \t\t\t\ttype: 'snackbar',\n * \t\t\t} );\n * \t\t} catch ( error ) {\n * \t\t\tcreateErrorNotice( error.message, { type: 'snackbar' } );\n * \t\t}\n * \t}\n *\n * \treturn (\n * \t\t<form onSubmit={ onRename }>\n * \t\t\t<TextControl\n * \t\t\t\tlabel={ __( 'Name' ) }\n * \t\t\t\tvalue={ title }\n * \t\t\t\tonChange={ setTitle }\n * \t\t\t/>\n * \t\t\t<button type=\"submit\">{ __( 'Save' ) }</button>\n * \t\t</form>\n * \t);\n * }\n *\n * // Rendered in the application:\n * // <PageRenameForm id={ 1 } />\n * ```\n *\n * In the above example, updating and saving the page title is handled\n * via the `edit()` and `save()` mutation helpers provided by\n * `useEntityRecord()`;\n *\n * @return Entity record data.\n * @template RecordType\n */\nexport default function useEntityRecord< RecordType >(\n\tkind: string,\n\tname: string,\n\trecordId: string | number,\n\toptions: Options = { enabled: true }\n): EntityRecordResolution< RecordType > {\n\tconst { editEntityRecord, saveEditedEntityRecord } =\n\t\tuseDispatch( coreStore );\n\n\tconst mutations = useMemo(\n\t\t() => ( {\n\t\t\tedit: ( record ) =>\n\t\t\t\teditEntityRecord( kind, name, recordId, record ),\n\t\t\tsave: ( saveOptions: any = {} ) =>\n\t\t\t\tsaveEditedEntityRecord( kind, name, recordId, {\n\t\t\t\t\tthrowOnError: true,\n\t\t\t\t\t...saveOptions,\n\t\t\t\t} ),\n\t\t} ),\n\t\t[ recordId ]\n\t);\n\n\tconst { editedRecord, hasEdits } = useSelect(\n\t\t( select ) => ( {\n\t\t\teditedRecord: select( coreStore ).getEditedEntityRecord(),\n\t\t\thasEdits: select( coreStore ).hasEditsForEntityRecord(),\n\t\t} ),\n\t\t[ kind, name, recordId ]\n\t);\n\n\tconst { data: record, ...querySelectRest } = useQuerySelect(\n\t\t( query ) => {\n\t\t\tif ( ! options.enabled ) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn query( coreStore ).getEntityRecord( kind, name, recordId );\n\t\t},\n\t\t[ kind, name, recordId, options.enabled ]\n\t);\n\n\treturn {\n\t\trecord,\n\t\teditedRecord,\n\t\thasEdits,\n\t\t...querySelectRest,\n\t\t...mutations,\n\t};\n}\n\nexport function __experimentalUseEntityRecord(\n\tkind: string,\n\tname: string,\n\trecordId: any,\n\toptions: any\n) {\n\tdeprecated( `wp.data.__experimentalUseEntityRecord`, {\n\t\talternative: 'wp.data.useEntityRecord',\n\t\tsince: '6.1',\n\t} );\n\treturn useEntityRecord( kind, name, recordId, options );\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/core-data",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.13.0",
|
|
4
4
|
"description": "Access to and manipulation of core WordPress entities.",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -30,15 +30,15 @@
|
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@babel/runtime": "^7.16.0",
|
|
33
|
-
"@wordpress/api-fetch": "^6.
|
|
34
|
-
"@wordpress/blocks": "^11.
|
|
35
|
-
"@wordpress/data": "^6.
|
|
36
|
-
"@wordpress/deprecated": "^3.
|
|
37
|
-
"@wordpress/element": "^4.
|
|
38
|
-
"@wordpress/html-entities": "^3.
|
|
39
|
-
"@wordpress/i18n": "^4.
|
|
40
|
-
"@wordpress/is-shallow-equal": "^4.
|
|
41
|
-
"@wordpress/url": "^3.
|
|
33
|
+
"@wordpress/api-fetch": "^6.12.0",
|
|
34
|
+
"@wordpress/blocks": "^11.14.0",
|
|
35
|
+
"@wordpress/data": "^6.15.0",
|
|
36
|
+
"@wordpress/deprecated": "^3.15.0",
|
|
37
|
+
"@wordpress/element": "^4.13.0",
|
|
38
|
+
"@wordpress/html-entities": "^3.15.0",
|
|
39
|
+
"@wordpress/i18n": "^4.15.0",
|
|
40
|
+
"@wordpress/is-shallow-equal": "^4.15.0",
|
|
41
|
+
"@wordpress/url": "^3.16.0",
|
|
42
42
|
"equivalent-key-map": "^0.2.2",
|
|
43
43
|
"lodash": "^4.17.21",
|
|
44
44
|
"memize": "^1.1.0",
|
|
@@ -51,5 +51,5 @@
|
|
|
51
51
|
"publishConfig": {
|
|
52
52
|
"access": "public"
|
|
53
53
|
},
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "08358f53b627a15148c3a3e433cdf58cf8714aa4"
|
|
55
55
|
}
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* External dependencies
|
|
3
|
-
*/
|
|
4
|
-
import { zip } from 'lodash';
|
|
5
|
-
|
|
6
1
|
/**
|
|
7
2
|
* Internal dependencies
|
|
8
3
|
*/
|
|
@@ -138,12 +133,8 @@ export default function createBatch( processor = defaultProcessor ) {
|
|
|
138
133
|
|
|
139
134
|
let isSuccess = true;
|
|
140
135
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const result = pair[ 0 ];
|
|
144
|
-
|
|
145
|
-
/** @type {{resolve: (value: any) => void; reject: (error: any) => void} | undefined} */
|
|
146
|
-
const queueItem = pair[ 1 ];
|
|
136
|
+
results.forEach( ( result, key ) => {
|
|
137
|
+
const queueItem = queue[ key ];
|
|
147
138
|
|
|
148
139
|
if ( result?.error ) {
|
|
149
140
|
queueItem?.reject( result.error );
|
|
@@ -151,7 +142,7 @@ export default function createBatch( processor = defaultProcessor ) {
|
|
|
151
142
|
} else {
|
|
152
143
|
queueItem?.resolve( result?.output ?? result );
|
|
153
144
|
}
|
|
154
|
-
}
|
|
145
|
+
} );
|
|
155
146
|
|
|
156
147
|
queue = [];
|
|
157
148
|
|
|
@@ -50,7 +50,11 @@ describe( 'useEntityRecord', () => {
|
|
|
50
50
|
);
|
|
51
51
|
|
|
52
52
|
expect( data ).toEqual( {
|
|
53
|
-
|
|
53
|
+
edit: expect.any( Function ),
|
|
54
|
+
editedRecord: {},
|
|
55
|
+
hasEdits: false,
|
|
56
|
+
record: undefined,
|
|
57
|
+
save: expect.any( Function ),
|
|
54
58
|
hasResolved: false,
|
|
55
59
|
isResolving: false,
|
|
56
60
|
status: 'IDLE',
|
|
@@ -66,7 +70,11 @@ describe( 'useEntityRecord', () => {
|
|
|
66
70
|
} );
|
|
67
71
|
|
|
68
72
|
expect( data ).toEqual( {
|
|
73
|
+
edit: expect.any( Function ),
|
|
74
|
+
editedRecord: {},
|
|
75
|
+
hasEdits: false,
|
|
69
76
|
record: { hello: 'world', id: 1 },
|
|
77
|
+
save: expect.any( Function ),
|
|
70
78
|
hasResolved: true,
|
|
71
79
|
isResolving: false,
|
|
72
80
|
status: 'SUCCESS',
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
|
+
import { useDispatch, useSelect } from '@wordpress/data';
|
|
4
5
|
import deprecated from '@wordpress/deprecated';
|
|
6
|
+
import { useMemo } from '@wordpress/element';
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* Internal dependencies
|
|
@@ -14,11 +16,25 @@ export interface EntityRecordResolution< RecordType > {
|
|
|
14
16
|
/** The requested entity record */
|
|
15
17
|
record: RecordType | null;
|
|
16
18
|
|
|
19
|
+
/** The edited entity record */
|
|
20
|
+
editedRecord: Partial< RecordType >;
|
|
21
|
+
|
|
22
|
+
/** Apply local (in-browser) edits to the edited entity record */
|
|
23
|
+
edit: ( diff: Partial< RecordType > ) => void;
|
|
24
|
+
|
|
25
|
+
/** Persist the edits to the server */
|
|
26
|
+
save: () => Promise< void >;
|
|
27
|
+
|
|
17
28
|
/**
|
|
18
29
|
* Is the record still being resolved?
|
|
19
30
|
*/
|
|
20
31
|
isResolving: boolean;
|
|
21
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Does the record have any local edits?
|
|
35
|
+
*/
|
|
36
|
+
hasEdits: boolean;
|
|
37
|
+
|
|
22
38
|
/**
|
|
23
39
|
* Is the record resolved by now?
|
|
24
40
|
*/
|
|
@@ -66,6 +82,58 @@ export interface Options {
|
|
|
66
82
|
* application, the page and the resolution details will be retrieved from
|
|
67
83
|
* the store state using `getEntityRecord()`, or resolved if missing.
|
|
68
84
|
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```js
|
|
87
|
+
* import { useState } from '@wordpress/data';
|
|
88
|
+
* import { useDispatch } from '@wordpress/data';
|
|
89
|
+
* import { __ } from '@wordpress/i18n';
|
|
90
|
+
* import { TextControl } from '@wordpress/components';
|
|
91
|
+
* import { store as noticeStore } from '@wordpress/notices';
|
|
92
|
+
* import { useEntityRecord } from '@wordpress/core-data';
|
|
93
|
+
*
|
|
94
|
+
* function PageRenameForm( { id } ) {
|
|
95
|
+
* const page = useEntityRecord( 'postType', 'page', id );
|
|
96
|
+
* const [ title, setTitle ] = useState( () => page.record.title.rendered );
|
|
97
|
+
* const { createSuccessNotice, createErrorNotice } =
|
|
98
|
+
* useDispatch( noticeStore );
|
|
99
|
+
*
|
|
100
|
+
* if ( page.isResolving ) {
|
|
101
|
+
* return 'Loading...';
|
|
102
|
+
* }
|
|
103
|
+
*
|
|
104
|
+
* async function onRename( event ) {
|
|
105
|
+
* event.preventDefault();
|
|
106
|
+
* page.edit( { title } );
|
|
107
|
+
* try {
|
|
108
|
+
* await page.save();
|
|
109
|
+
* createSuccessNotice( __( 'Page renamed.' ), {
|
|
110
|
+
* type: 'snackbar',
|
|
111
|
+
* } );
|
|
112
|
+
* } catch ( error ) {
|
|
113
|
+
* createErrorNotice( error.message, { type: 'snackbar' } );
|
|
114
|
+
* }
|
|
115
|
+
* }
|
|
116
|
+
*
|
|
117
|
+
* return (
|
|
118
|
+
* <form onSubmit={ onRename }>
|
|
119
|
+
* <TextControl
|
|
120
|
+
* label={ __( 'Name' ) }
|
|
121
|
+
* value={ title }
|
|
122
|
+
* onChange={ setTitle }
|
|
123
|
+
* />
|
|
124
|
+
* <button type="submit">{ __( 'Save' ) }</button>
|
|
125
|
+
* </form>
|
|
126
|
+
* );
|
|
127
|
+
* }
|
|
128
|
+
*
|
|
129
|
+
* // Rendered in the application:
|
|
130
|
+
* // <PageRenameForm id={ 1 } />
|
|
131
|
+
* ```
|
|
132
|
+
*
|
|
133
|
+
* In the above example, updating and saving the page title is handled
|
|
134
|
+
* via the `edit()` and `save()` mutation helpers provided by
|
|
135
|
+
* `useEntityRecord()`;
|
|
136
|
+
*
|
|
69
137
|
* @return Entity record data.
|
|
70
138
|
* @template RecordType
|
|
71
139
|
*/
|
|
@@ -75,7 +143,31 @@ export default function useEntityRecord< RecordType >(
|
|
|
75
143
|
recordId: string | number,
|
|
76
144
|
options: Options = { enabled: true }
|
|
77
145
|
): EntityRecordResolution< RecordType > {
|
|
78
|
-
const {
|
|
146
|
+
const { editEntityRecord, saveEditedEntityRecord } =
|
|
147
|
+
useDispatch( coreStore );
|
|
148
|
+
|
|
149
|
+
const mutations = useMemo(
|
|
150
|
+
() => ( {
|
|
151
|
+
edit: ( record ) =>
|
|
152
|
+
editEntityRecord( kind, name, recordId, record ),
|
|
153
|
+
save: ( saveOptions: any = {} ) =>
|
|
154
|
+
saveEditedEntityRecord( kind, name, recordId, {
|
|
155
|
+
throwOnError: true,
|
|
156
|
+
...saveOptions,
|
|
157
|
+
} ),
|
|
158
|
+
} ),
|
|
159
|
+
[ recordId ]
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
const { editedRecord, hasEdits } = useSelect(
|
|
163
|
+
( select ) => ( {
|
|
164
|
+
editedRecord: select( coreStore ).getEditedEntityRecord(),
|
|
165
|
+
hasEdits: select( coreStore ).hasEditsForEntityRecord(),
|
|
166
|
+
} ),
|
|
167
|
+
[ kind, name, recordId ]
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
const { data: record, ...querySelectRest } = useQuerySelect(
|
|
79
171
|
( query ) => {
|
|
80
172
|
if ( ! options.enabled ) {
|
|
81
173
|
return null;
|
|
@@ -87,7 +179,10 @@ export default function useEntityRecord< RecordType >(
|
|
|
87
179
|
|
|
88
180
|
return {
|
|
89
181
|
record,
|
|
90
|
-
|
|
182
|
+
editedRecord,
|
|
183
|
+
hasEdits,
|
|
184
|
+
...querySelectRest,
|
|
185
|
+
...mutations,
|
|
91
186
|
};
|
|
92
187
|
}
|
|
93
188
|
|