@wordpress/core-data 6.22.0 → 6.24.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 +5 -0
- package/README.md +77 -2
- package/build/actions.js +55 -0
- package/build/actions.js.map +1 -1
- package/build/entities.js +18 -3
- package/build/entities.js.map +1 -1
- package/build/entity-provider.js +7 -1
- package/build/entity-provider.js.map +1 -1
- package/build/entity-types/global-styles-revision.js +6 -0
- package/build/entity-types/global-styles-revision.js.map +1 -0
- package/build/entity-types/index.js.map +1 -1
- package/build/entity-types/post-revision.js +6 -0
- package/build/entity-types/post-revision.js.map +1 -0
- package/build/hooks/use-entity-record.js +16 -5
- package/build/hooks/use-entity-record.js.map +1 -1
- package/build/queried-data/reducer.js +3 -1
- package/build/queried-data/reducer.js.map +1 -1
- package/build/queried-data/selectors.js +3 -1
- package/build/queried-data/selectors.js.map +1 -1
- package/build/reducer.js +52 -4
- package/build/reducer.js.map +1 -1
- package/build/resolvers.js +131 -3
- package/build/resolvers.js.map +1 -1
- package/build/selectors.js +92 -1
- package/build/selectors.js.map +1 -1
- package/build-module/actions.js +52 -0
- package/build-module/actions.js.map +1 -1
- package/build-module/entities.js +18 -3
- package/build-module/entities.js.map +1 -1
- package/build-module/entity-provider.js +7 -1
- package/build-module/entity-provider.js.map +1 -1
- package/build-module/entity-types/global-styles-revision.js +2 -0
- package/build-module/entity-types/global-styles-revision.js.map +1 -0
- package/build-module/entity-types/index.js.map +1 -1
- package/build-module/entity-types/post-revision.js +2 -0
- package/build-module/entity-types/post-revision.js.map +1 -0
- package/build-module/hooks/use-entity-record.js +16 -5
- package/build-module/hooks/use-entity-record.js.map +1 -1
- package/build-module/queried-data/reducer.js +3 -1
- package/build-module/queried-data/reducer.js.map +1 -1
- package/build-module/queried-data/selectors.js +3 -1
- package/build-module/queried-data/selectors.js.map +1 -1
- package/build-module/reducer.js +51 -4
- package/build-module/reducer.js.map +1 -1
- package/build-module/resolvers.js +127 -2
- package/build-module/resolvers.js.map +1 -1
- package/build-module/selectors.js +88 -1
- package/build-module/selectors.js.map +1 -1
- package/build-types/actions.d.ts +14 -0
- package/build-types/actions.d.ts.map +1 -1
- package/build-types/entities.d.ts +23 -1
- package/build-types/entities.d.ts.map +1 -1
- package/build-types/entity-provider.d.ts.map +1 -1
- package/build-types/entity-types/global-styles-revision.d.ts +43 -0
- package/build-types/entity-types/global-styles-revision.d.ts.map +1 -0
- package/build-types/entity-types/index.d.ts +4 -2
- package/build-types/entity-types/index.d.ts.map +1 -1
- package/build-types/entity-types/post-revision.d.ts +76 -0
- package/build-types/entity-types/post-revision.d.ts.map +1 -0
- package/build-types/hooks/use-entity-record.d.ts.map +1 -1
- package/build-types/index.d.ts +19 -4
- package/build-types/index.d.ts.map +1 -1
- package/build-types/queried-data/selectors.d.ts.map +1 -1
- package/build-types/reducer.d.ts +10 -0
- package/build-types/reducer.d.ts.map +1 -1
- package/build-types/resolvers.d.ts +12 -0
- package/build-types/resolvers.d.ts.map +1 -1
- package/build-types/selectors.d.ts +54 -3
- package/build-types/selectors.d.ts.map +1 -1
- package/package.json +17 -17
- package/src/actions.js +61 -0
- package/src/entities.js +33 -1
- package/src/entity-provider.js +8 -1
- package/src/entity-types/global-styles-revision.ts +47 -0
- package/src/entity-types/index.ts +6 -0
- package/src/entity-types/post-revision.ts +93 -0
- package/src/hooks/test/use-entity-record.js +41 -0
- package/src/hooks/use-entity-record.ts +30 -18
- package/src/queried-data/reducer.js +3 -3
- package/src/queried-data/selectors.js +3 -1
- package/src/queried-data/test/reducer.js +11 -0
- package/src/reducer.js +68 -2
- package/src/resolvers.js +176 -2
- package/src/selectors.ts +141 -1
- package/src/test/entities.js +9 -0
- package/src/test/reducer.js +235 -0
- package/src/test/selectors.js +96 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal dependencies
|
|
3
|
+
*/
|
|
4
|
+
import type { Context, ContextualField, OmitNevers } from './helpers';
|
|
5
|
+
|
|
6
|
+
import type { BaseEntityRecords as _BaseEntityRecords } from './base-entity-records';
|
|
7
|
+
|
|
8
|
+
declare module './base-entity-records' {
|
|
9
|
+
export namespace BaseEntityRecords {
|
|
10
|
+
export interface GlobalStylesRevision< C extends Context > {
|
|
11
|
+
/**
|
|
12
|
+
* The ID for the author of the global styles revision.
|
|
13
|
+
*/
|
|
14
|
+
author: number;
|
|
15
|
+
/**
|
|
16
|
+
* The date the post global styles revision published, in the site's timezone.
|
|
17
|
+
*/
|
|
18
|
+
date: string | null;
|
|
19
|
+
/**
|
|
20
|
+
* The date the global styles revision was published, as GMT.
|
|
21
|
+
*/
|
|
22
|
+
date_gmt: ContextualField< string | null, 'view' | 'edit', C >;
|
|
23
|
+
/**
|
|
24
|
+
* Unique identifier for the revision.
|
|
25
|
+
*/
|
|
26
|
+
id: number;
|
|
27
|
+
/**
|
|
28
|
+
* The date the global styles revision was last modified, in the site's timezone.
|
|
29
|
+
*/
|
|
30
|
+
modified: ContextualField< string, 'view' | 'edit', C >;
|
|
31
|
+
/**
|
|
32
|
+
* The date the global styles revision was last modified, as GMT.
|
|
33
|
+
*/
|
|
34
|
+
modified_gmt: ContextualField< string, 'view' | 'edit', C >;
|
|
35
|
+
/**
|
|
36
|
+
* Identifier for the parent of the revision.
|
|
37
|
+
*/
|
|
38
|
+
parent: number;
|
|
39
|
+
styles: Record< string, Object >;
|
|
40
|
+
settings: Record< string, Object >;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type GlobalStylesRevision< C extends Context = 'view' > = OmitNevers<
|
|
46
|
+
_BaseEntityRecords.GlobalStylesRevision< C >
|
|
47
|
+
>;
|
|
@@ -4,12 +4,14 @@
|
|
|
4
4
|
import type { Context, Updatable } from './helpers';
|
|
5
5
|
import type { Attachment } from './attachment';
|
|
6
6
|
import type { Comment } from './comment';
|
|
7
|
+
import type { GlobalStylesRevision } from './global-styles-revision';
|
|
7
8
|
import type { MenuLocation } from './menu-location';
|
|
8
9
|
import type { NavMenu } from './nav-menu';
|
|
9
10
|
import type { NavMenuItem } from './nav-menu-item';
|
|
10
11
|
import type { Page } from './page';
|
|
11
12
|
import type { Plugin } from './plugin';
|
|
12
13
|
import type { Post } from './post';
|
|
14
|
+
import type { PostRevision } from './post-revision';
|
|
13
15
|
import type { Settings } from './settings';
|
|
14
16
|
import type { Sidebar } from './sidebar';
|
|
15
17
|
import type { Taxonomy } from './taxonomy';
|
|
@@ -27,12 +29,14 @@ export type {
|
|
|
27
29
|
Attachment,
|
|
28
30
|
Comment,
|
|
29
31
|
Context,
|
|
32
|
+
GlobalStylesRevision,
|
|
30
33
|
MenuLocation,
|
|
31
34
|
NavMenu,
|
|
32
35
|
NavMenuItem,
|
|
33
36
|
Page,
|
|
34
37
|
Plugin,
|
|
35
38
|
Post,
|
|
39
|
+
PostRevision,
|
|
36
40
|
Settings,
|
|
37
41
|
Sidebar,
|
|
38
42
|
Taxonomy,
|
|
@@ -82,12 +86,14 @@ export interface PerPackageEntityRecords< C extends Context > {
|
|
|
82
86
|
core:
|
|
83
87
|
| Attachment< C >
|
|
84
88
|
| Comment< C >
|
|
89
|
+
| GlobalStylesRevision< C >
|
|
85
90
|
| MenuLocation< C >
|
|
86
91
|
| NavMenu< C >
|
|
87
92
|
| NavMenuItem< C >
|
|
88
93
|
| Page< C >
|
|
89
94
|
| Plugin< C >
|
|
90
95
|
| Post< C >
|
|
96
|
+
| PostRevision< C >
|
|
91
97
|
| Settings< C >
|
|
92
98
|
| Sidebar< C >
|
|
93
99
|
| Taxonomy< C >
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal dependencies
|
|
3
|
+
*/
|
|
4
|
+
import type {
|
|
5
|
+
Context,
|
|
6
|
+
ContextualField,
|
|
7
|
+
RenderedText,
|
|
8
|
+
OmitNevers,
|
|
9
|
+
} from './helpers';
|
|
10
|
+
|
|
11
|
+
import type { BaseEntityRecords as _BaseEntityRecords } from './base-entity-records';
|
|
12
|
+
|
|
13
|
+
declare module './base-entity-records' {
|
|
14
|
+
export namespace BaseEntityRecords {
|
|
15
|
+
export interface PostRevision< C extends Context > {
|
|
16
|
+
/**
|
|
17
|
+
* The ID for the author of the post revision.
|
|
18
|
+
*/
|
|
19
|
+
author: number;
|
|
20
|
+
/**
|
|
21
|
+
* The content for the post.
|
|
22
|
+
*/
|
|
23
|
+
content: ContextualField<
|
|
24
|
+
RenderedText< C > & {
|
|
25
|
+
/**
|
|
26
|
+
* Whether the content is protected with a password.
|
|
27
|
+
*/
|
|
28
|
+
is_protected: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Version of the content block format used by the post.
|
|
31
|
+
*/
|
|
32
|
+
block_version: ContextualField< string, 'edit', C >;
|
|
33
|
+
},
|
|
34
|
+
'view' | 'edit',
|
|
35
|
+
C
|
|
36
|
+
>;
|
|
37
|
+
/**
|
|
38
|
+
* The date the post was published, in the site's timezone.
|
|
39
|
+
*/
|
|
40
|
+
date: string | null;
|
|
41
|
+
/**
|
|
42
|
+
* The date the post was published, as GMT.
|
|
43
|
+
*/
|
|
44
|
+
date_gmt: ContextualField< string | null, 'view' | 'edit', C >;
|
|
45
|
+
/**
|
|
46
|
+
* The excerpt for the post revision.
|
|
47
|
+
*/
|
|
48
|
+
excerpt: RenderedText< C > & {
|
|
49
|
+
protected: boolean;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* The globally unique identifier for the post.
|
|
53
|
+
*/
|
|
54
|
+
guid: ContextualField< RenderedText< C >, 'view' | 'edit', C >;
|
|
55
|
+
/**
|
|
56
|
+
* Unique identifier for the revision.
|
|
57
|
+
*/
|
|
58
|
+
id: number;
|
|
59
|
+
/**
|
|
60
|
+
* Meta fields.
|
|
61
|
+
*/
|
|
62
|
+
meta: ContextualField<
|
|
63
|
+
Record< string, string >,
|
|
64
|
+
'view' | 'edit',
|
|
65
|
+
C
|
|
66
|
+
>;
|
|
67
|
+
/**
|
|
68
|
+
* The date the post was last modified, in the site's timezone.
|
|
69
|
+
*/
|
|
70
|
+
modified: ContextualField< string, 'view' | 'edit', C >;
|
|
71
|
+
/**
|
|
72
|
+
* The date the post revision was last modified, as GMT.
|
|
73
|
+
*/
|
|
74
|
+
modified_gmt: ContextualField< string, 'view' | 'edit', C >;
|
|
75
|
+
/**
|
|
76
|
+
* Identifier for the parent of the revision.
|
|
77
|
+
*/
|
|
78
|
+
parent: number;
|
|
79
|
+
/**
|
|
80
|
+
* An alphanumeric identifier for the post unique to its type.
|
|
81
|
+
*/
|
|
82
|
+
slug: string;
|
|
83
|
+
/**
|
|
84
|
+
* The title for the post revision.
|
|
85
|
+
*/
|
|
86
|
+
title: RenderedText< C >;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export type PostRevision< C extends Context = 'view' > = OmitNevers<
|
|
92
|
+
_BaseEntityRecords.PostRevision< C >
|
|
93
|
+
>;
|
|
@@ -23,6 +23,7 @@ describe( 'useEntityRecord', () => {
|
|
|
23
23
|
beforeEach( () => {
|
|
24
24
|
registry = createRegistry();
|
|
25
25
|
registry.register( coreDataStore );
|
|
26
|
+
triggerFetch.mockReset();
|
|
26
27
|
} );
|
|
27
28
|
|
|
28
29
|
const TEST_RECORD = { id: 1, hello: 'world' };
|
|
@@ -113,4 +114,44 @@ describe( 'useEntityRecord', () => {
|
|
|
113
114
|
expect( widget.editedRecord ).toEqual( { hello: 'foo', id: 1 } );
|
|
114
115
|
expect( widget.edits ).toEqual( { hello: 'foo' } );
|
|
115
116
|
} );
|
|
117
|
+
|
|
118
|
+
it( 'does not resolve entity record when disabled via options', async () => {
|
|
119
|
+
triggerFetch.mockImplementation( () => TEST_RECORD );
|
|
120
|
+
|
|
121
|
+
let data;
|
|
122
|
+
const TestComponent = ( { enabled } ) => {
|
|
123
|
+
data = useEntityRecord( 'root', 'widget', 1, { enabled } );
|
|
124
|
+
return <div />;
|
|
125
|
+
};
|
|
126
|
+
const UI = ( { enabled } ) => (
|
|
127
|
+
<RegistryProvider value={ registry }>
|
|
128
|
+
<TestComponent enabled={ enabled } />
|
|
129
|
+
</RegistryProvider>
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
const { rerender } = render( <UI enabled={ true } /> );
|
|
133
|
+
|
|
134
|
+
// A minimum delay for a fetch request. The same delay is used again as a control.
|
|
135
|
+
await act(
|
|
136
|
+
() => new Promise( ( resolve ) => setTimeout( resolve, 0 ) )
|
|
137
|
+
);
|
|
138
|
+
expect( triggerFetch ).toHaveBeenCalledTimes( 1 );
|
|
139
|
+
|
|
140
|
+
rerender( <UI enabled={ false } /> );
|
|
141
|
+
|
|
142
|
+
expect( data ).toEqual( {
|
|
143
|
+
edit: expect.any( Function ),
|
|
144
|
+
editedRecord: {},
|
|
145
|
+
hasEdits: false,
|
|
146
|
+
edits: {},
|
|
147
|
+
record: null,
|
|
148
|
+
save: expect.any( Function ),
|
|
149
|
+
} );
|
|
150
|
+
|
|
151
|
+
// The same delay.
|
|
152
|
+
await act(
|
|
153
|
+
() => new Promise( ( resolve ) => setTimeout( resolve, 0 ) )
|
|
154
|
+
);
|
|
155
|
+
expect( triggerFetch ).toHaveBeenCalledTimes( 1 );
|
|
156
|
+
} );
|
|
116
157
|
} );
|
|
@@ -56,6 +56,8 @@ export interface Options {
|
|
|
56
56
|
enabled: boolean;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
const EMPTY_OBJECT = {};
|
|
60
|
+
|
|
59
61
|
/**
|
|
60
62
|
* Resolves the specified entity record.
|
|
61
63
|
*
|
|
@@ -167,24 +169,34 @@ export default function useEntityRecord< RecordType >(
|
|
|
167
169
|
);
|
|
168
170
|
|
|
169
171
|
const { editedRecord, hasEdits, edits } = useSelect(
|
|
170
|
-
( select ) =>
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
172
|
+
( select ) => {
|
|
173
|
+
if ( ! options.enabled ) {
|
|
174
|
+
return {
|
|
175
|
+
editedRecord: EMPTY_OBJECT,
|
|
176
|
+
hasEdits: false,
|
|
177
|
+
edits: EMPTY_OBJECT,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return {
|
|
182
|
+
editedRecord: select( coreStore ).getEditedEntityRecord(
|
|
183
|
+
kind,
|
|
184
|
+
name,
|
|
185
|
+
recordId
|
|
186
|
+
),
|
|
187
|
+
hasEdits: select( coreStore ).hasEditsForEntityRecord(
|
|
188
|
+
kind,
|
|
189
|
+
name,
|
|
190
|
+
recordId
|
|
191
|
+
),
|
|
192
|
+
edits: select( coreStore ).getEntityRecordNonTransientEdits(
|
|
193
|
+
kind,
|
|
194
|
+
name,
|
|
195
|
+
recordId
|
|
196
|
+
),
|
|
197
|
+
};
|
|
198
|
+
},
|
|
199
|
+
[ kind, name, recordId, options.enabled ]
|
|
188
200
|
);
|
|
189
201
|
|
|
190
202
|
const { data: record, ...querySelectRest } = useQuerySelect(
|
|
@@ -56,10 +56,10 @@ export function getMergedItemIds( itemIds, nextItemIds, page, perPage ) {
|
|
|
56
56
|
|
|
57
57
|
for ( let i = 0; i < size; i++ ) {
|
|
58
58
|
// Preserve existing item ID except for subset of range of next items.
|
|
59
|
+
// We need to check against the possible maximum upper boundary because
|
|
60
|
+
// a page could receive fewer than what was previously stored.
|
|
59
61
|
const isInNextItemsRange =
|
|
60
|
-
i >= nextItemIdsStartIndex &&
|
|
61
|
-
i < nextItemIdsStartIndex + nextItemIds.length;
|
|
62
|
-
|
|
62
|
+
i >= nextItemIdsStartIndex && i < nextItemIdsStartIndex + perPage;
|
|
63
63
|
mergedItemIds[ i ] = isInNextItemsRange
|
|
64
64
|
? nextItemIds[ i - nextItemIdsStartIndex ]
|
|
65
65
|
: itemIds?.[ i ];
|
|
@@ -52,7 +52,9 @@ function getQueriedItemsUncached( state, query ) {
|
|
|
52
52
|
if ( Array.isArray( include ) && ! include.includes( itemId ) ) {
|
|
53
53
|
continue;
|
|
54
54
|
}
|
|
55
|
-
|
|
55
|
+
if ( itemId === undefined ) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
56
58
|
// Having a target item ID doesn't guarantee that this object has been queried.
|
|
57
59
|
if ( ! state.items[ context ]?.hasOwnProperty( itemId ) ) {
|
|
58
60
|
return null;
|
|
@@ -64,6 +64,17 @@ describe( 'getMergedItemIds', () => {
|
|
|
64
64
|
|
|
65
65
|
expect( result ).toEqual( [ 1, 3, 4 ] );
|
|
66
66
|
} );
|
|
67
|
+
it( 'should update a page properly if less items are provided than previously stored', () => {
|
|
68
|
+
let original = deepFreeze( [ 1, 2, 3 ] );
|
|
69
|
+
let result = getMergedItemIds( original, [ 1, 2 ], 1, 3 );
|
|
70
|
+
|
|
71
|
+
expect( result ).toEqual( [ 1, 2 ] );
|
|
72
|
+
|
|
73
|
+
original = deepFreeze( [ 1, 2, 3, 4, 5, 6 ] );
|
|
74
|
+
result = getMergedItemIds( original, [ 9 ], 2, 2 );
|
|
75
|
+
|
|
76
|
+
expect( result ).toEqual( [ 1, 2, 9, undefined, 5, 6 ] );
|
|
77
|
+
} );
|
|
67
78
|
} );
|
|
68
79
|
|
|
69
80
|
describe( 'itemIsComplete', () => {
|
package/src/reducer.js
CHANGED
|
@@ -238,14 +238,13 @@ function entity( entityConfig ) {
|
|
|
238
238
|
// Inject the entity config into the action.
|
|
239
239
|
replaceAction( ( action ) => {
|
|
240
240
|
return {
|
|
241
|
-
...action,
|
|
242
241
|
key: entityConfig.key || DEFAULT_ENTITY_KEY,
|
|
242
|
+
...action,
|
|
243
243
|
};
|
|
244
244
|
} ),
|
|
245
245
|
] )(
|
|
246
246
|
combineReducers( {
|
|
247
247
|
queriedData: queriedDataReducer,
|
|
248
|
-
|
|
249
248
|
edits: ( state = {}, action ) => {
|
|
250
249
|
switch ( action.type ) {
|
|
251
250
|
case 'RECEIVE_ITEMS':
|
|
@@ -355,6 +354,52 @@ function entity( entityConfig ) {
|
|
|
355
354
|
|
|
356
355
|
return state;
|
|
357
356
|
},
|
|
357
|
+
|
|
358
|
+
// Add revisions to the state tree if the post type supports it.
|
|
359
|
+
...( entityConfig?.supports?.revisions
|
|
360
|
+
? {
|
|
361
|
+
revisions: ( state = {}, action ) => {
|
|
362
|
+
// Use the same queriedDataReducer shape for revisions.
|
|
363
|
+
if ( action.type === 'RECEIVE_ITEM_REVISIONS' ) {
|
|
364
|
+
const recordKey = action.recordKey;
|
|
365
|
+
delete action.recordKey;
|
|
366
|
+
const newState = queriedDataReducer(
|
|
367
|
+
state[ recordKey ],
|
|
368
|
+
{
|
|
369
|
+
...action,
|
|
370
|
+
type: 'RECEIVE_ITEMS',
|
|
371
|
+
}
|
|
372
|
+
);
|
|
373
|
+
return {
|
|
374
|
+
...state,
|
|
375
|
+
[ recordKey ]: newState,
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
if ( action.type === 'REMOVE_ITEMS' ) {
|
|
380
|
+
return Object.fromEntries(
|
|
381
|
+
Object.entries( state ).filter(
|
|
382
|
+
( [ id ] ) =>
|
|
383
|
+
! action.itemIds.some(
|
|
384
|
+
( itemId ) => {
|
|
385
|
+
if (
|
|
386
|
+
Number.isInteger(
|
|
387
|
+
itemId
|
|
388
|
+
)
|
|
389
|
+
) {
|
|
390
|
+
return itemId === +id;
|
|
391
|
+
}
|
|
392
|
+
return itemId === id;
|
|
393
|
+
}
|
|
394
|
+
)
|
|
395
|
+
)
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
return state;
|
|
400
|
+
},
|
|
401
|
+
}
|
|
402
|
+
: {} ),
|
|
358
403
|
} )
|
|
359
404
|
);
|
|
360
405
|
}
|
|
@@ -572,6 +617,26 @@ export function themeGlobalStyleRevisions( state = {}, action ) {
|
|
|
572
617
|
return state;
|
|
573
618
|
}
|
|
574
619
|
|
|
620
|
+
/**
|
|
621
|
+
* Reducer managing the template lookup per query.
|
|
622
|
+
*
|
|
623
|
+
* @param {Record<string, string>} state Current state.
|
|
624
|
+
* @param {Object} action Dispatched action.
|
|
625
|
+
*
|
|
626
|
+
* @return {Record<string, string>} Updated state.
|
|
627
|
+
*/
|
|
628
|
+
export function defaultTemplates( state = {}, action ) {
|
|
629
|
+
switch ( action.type ) {
|
|
630
|
+
case 'RECEIVE_DEFAULT_TEMPLATE':
|
|
631
|
+
return {
|
|
632
|
+
...state,
|
|
633
|
+
[ JSON.stringify( action.query ) ]: action.templateId,
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
return state;
|
|
638
|
+
}
|
|
639
|
+
|
|
575
640
|
export default combineReducers( {
|
|
576
641
|
terms,
|
|
577
642
|
users,
|
|
@@ -592,4 +657,5 @@ export default combineReducers( {
|
|
|
592
657
|
blockPatternCategories,
|
|
593
658
|
userPatternCategories,
|
|
594
659
|
navigationFallbackId,
|
|
660
|
+
defaultTemplates,
|
|
595
661
|
} );
|
package/src/resolvers.js
CHANGED
|
@@ -244,7 +244,7 @@ export const getEntityRecords =
|
|
|
244
244
|
|
|
245
245
|
// If we request fields but the result doesn't contain the fields,
|
|
246
246
|
// explicitly set these fields as "undefined"
|
|
247
|
-
// that way we consider the query "
|
|
247
|
+
// that way we consider the query "fulfilled".
|
|
248
248
|
if ( query._fields ) {
|
|
249
249
|
records = records.map( ( record ) => {
|
|
250
250
|
query._fields.split( ',' ).forEach( ( field ) => {
|
|
@@ -322,7 +322,7 @@ export const getCurrentTheme =
|
|
|
322
322
|
export const getThemeSupports = forwardResolver( 'getCurrentTheme' );
|
|
323
323
|
|
|
324
324
|
/**
|
|
325
|
-
* Requests a preview from the
|
|
325
|
+
* Requests a preview from the Embed API.
|
|
326
326
|
*
|
|
327
327
|
* @param {string} url URL to get the preview for.
|
|
328
328
|
*/
|
|
@@ -707,3 +707,177 @@ export const getNavigationFallbackId =
|
|
|
707
707
|
] );
|
|
708
708
|
}
|
|
709
709
|
};
|
|
710
|
+
|
|
711
|
+
export const getDefaultTemplateId =
|
|
712
|
+
( query ) =>
|
|
713
|
+
async ( { dispatch } ) => {
|
|
714
|
+
const template = await apiFetch( {
|
|
715
|
+
path: addQueryArgs( '/wp/v2/templates/lookup', query ),
|
|
716
|
+
} );
|
|
717
|
+
if ( template ) {
|
|
718
|
+
dispatch.receiveDefaultTemplateId( query, template.id );
|
|
719
|
+
}
|
|
720
|
+
};
|
|
721
|
+
|
|
722
|
+
/**
|
|
723
|
+
* Requests an entity's revisions from the REST API.
|
|
724
|
+
*
|
|
725
|
+
* @param {string} kind Entity kind.
|
|
726
|
+
* @param {string} name Entity name.
|
|
727
|
+
* @param {number|string} recordKey The key of the entity record whose revisions you want to fetch.
|
|
728
|
+
* @param {Object|undefined} query Optional object of query parameters to
|
|
729
|
+
* include with request. If requesting specific
|
|
730
|
+
* fields, fields must always include the ID.
|
|
731
|
+
*/
|
|
732
|
+
export const getRevisions =
|
|
733
|
+
( kind, name, recordKey, query = {} ) =>
|
|
734
|
+
async ( { dispatch } ) => {
|
|
735
|
+
const configs = await dispatch( getOrLoadEntitiesConfig( kind ) );
|
|
736
|
+
const entityConfig = configs.find(
|
|
737
|
+
( config ) => config.name === name && config.kind === kind
|
|
738
|
+
);
|
|
739
|
+
|
|
740
|
+
if (
|
|
741
|
+
! entityConfig ||
|
|
742
|
+
entityConfig?.__experimentalNoFetch ||
|
|
743
|
+
! entityConfig?.supports?.revisions
|
|
744
|
+
) {
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
if ( query._fields ) {
|
|
749
|
+
// If requesting specific fields, items and query association to said
|
|
750
|
+
// records are stored by ID reference. Thus, fields must always include
|
|
751
|
+
// the ID.
|
|
752
|
+
query = {
|
|
753
|
+
...query,
|
|
754
|
+
_fields: [
|
|
755
|
+
...new Set( [
|
|
756
|
+
...( getNormalizedCommaSeparable( query._fields ) ||
|
|
757
|
+
[] ),
|
|
758
|
+
entityConfig.revisionKey || DEFAULT_ENTITY_KEY,
|
|
759
|
+
] ),
|
|
760
|
+
].join(),
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
const path = addQueryArgs(
|
|
765
|
+
entityConfig.getRevisionsUrl( recordKey ),
|
|
766
|
+
query
|
|
767
|
+
);
|
|
768
|
+
|
|
769
|
+
let records, meta;
|
|
770
|
+
if ( entityConfig.supportsPagination && query.per_page !== -1 ) {
|
|
771
|
+
const response = await apiFetch( { path, parse: false } );
|
|
772
|
+
records = Object.values( await response.json() );
|
|
773
|
+
meta = {
|
|
774
|
+
totalItems: parseInt( response.headers.get( 'X-WP-Total' ) ),
|
|
775
|
+
};
|
|
776
|
+
} else {
|
|
777
|
+
records = Object.values( await apiFetch( { path } ) );
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
// If we request fields but the result doesn't contain the fields,
|
|
781
|
+
// explicitly set these fields as "undefined"
|
|
782
|
+
// that way we consider the query "fulfilled".
|
|
783
|
+
if ( query._fields ) {
|
|
784
|
+
records = records.map( ( record ) => {
|
|
785
|
+
query._fields.split( ',' ).forEach( ( field ) => {
|
|
786
|
+
if ( ! record.hasOwnProperty( field ) ) {
|
|
787
|
+
record[ field ] = undefined;
|
|
788
|
+
}
|
|
789
|
+
} );
|
|
790
|
+
|
|
791
|
+
return record;
|
|
792
|
+
} );
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
dispatch.receiveRevisions(
|
|
796
|
+
kind,
|
|
797
|
+
name,
|
|
798
|
+
recordKey,
|
|
799
|
+
records,
|
|
800
|
+
query,
|
|
801
|
+
false,
|
|
802
|
+
meta
|
|
803
|
+
);
|
|
804
|
+
|
|
805
|
+
// When requesting all fields, the list of results can be used to
|
|
806
|
+
// resolve the `getRevision` selector in addition to `getRevisions`.
|
|
807
|
+
if ( ! query?._fields && ! query.context ) {
|
|
808
|
+
const key = entityConfig.key || DEFAULT_ENTITY_KEY;
|
|
809
|
+
const resolutionsArgs = records
|
|
810
|
+
.filter( ( record ) => record[ key ] )
|
|
811
|
+
.map( ( record ) => [ kind, name, recordKey, record[ key ] ] );
|
|
812
|
+
|
|
813
|
+
dispatch( {
|
|
814
|
+
type: 'START_RESOLUTIONS',
|
|
815
|
+
selectorName: 'getRevision',
|
|
816
|
+
args: resolutionsArgs,
|
|
817
|
+
} );
|
|
818
|
+
dispatch( {
|
|
819
|
+
type: 'FINISH_RESOLUTIONS',
|
|
820
|
+
selectorName: 'getRevision',
|
|
821
|
+
args: resolutionsArgs,
|
|
822
|
+
} );
|
|
823
|
+
}
|
|
824
|
+
};
|
|
825
|
+
|
|
826
|
+
// Invalidate cache when a new revision is created.
|
|
827
|
+
getRevisions.shouldInvalidate = ( action, kind, name, recordKey ) =>
|
|
828
|
+
action.type === 'SAVE_ENTITY_RECORD_FINISH' &&
|
|
829
|
+
name === action.name &&
|
|
830
|
+
kind === action.kind &&
|
|
831
|
+
! action.error &&
|
|
832
|
+
recordKey === action.recordId;
|
|
833
|
+
|
|
834
|
+
/**
|
|
835
|
+
* Requests a specific Entity revision from the REST API.
|
|
836
|
+
*
|
|
837
|
+
* @param {string} kind Entity kind.
|
|
838
|
+
* @param {string} name Entity name.
|
|
839
|
+
* @param {number|string} recordKey The key of the entity record whose revisions you want to fetch.
|
|
840
|
+
* @param {number|string} revisionKey The revision's key.
|
|
841
|
+
* @param {Object|undefined} query Optional object of query parameters to
|
|
842
|
+
* include with request. If requesting specific
|
|
843
|
+
* fields, fields must always include the ID.
|
|
844
|
+
*/
|
|
845
|
+
export const getRevision =
|
|
846
|
+
( kind, name, recordKey, revisionKey, query ) =>
|
|
847
|
+
async ( { dispatch } ) => {
|
|
848
|
+
const configs = await dispatch( getOrLoadEntitiesConfig( kind ) );
|
|
849
|
+
const entityConfig = configs.find(
|
|
850
|
+
( config ) => config.name === name && config.kind === kind
|
|
851
|
+
);
|
|
852
|
+
|
|
853
|
+
if (
|
|
854
|
+
! entityConfig ||
|
|
855
|
+
entityConfig?.__experimentalNoFetch ||
|
|
856
|
+
! entityConfig?.supports?.revisions
|
|
857
|
+
) {
|
|
858
|
+
return;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
if ( query !== undefined && query._fields ) {
|
|
862
|
+
// If requesting specific fields, items and query association to said
|
|
863
|
+
// records are stored by ID reference. Thus, fields must always include
|
|
864
|
+
// the ID.
|
|
865
|
+
query = {
|
|
866
|
+
...query,
|
|
867
|
+
_fields: [
|
|
868
|
+
...new Set( [
|
|
869
|
+
...( getNormalizedCommaSeparable( query._fields ) ||
|
|
870
|
+
[] ),
|
|
871
|
+
entityConfig.revisionKey || DEFAULT_ENTITY_KEY,
|
|
872
|
+
] ),
|
|
873
|
+
].join(),
|
|
874
|
+
};
|
|
875
|
+
}
|
|
876
|
+
const path = addQueryArgs(
|
|
877
|
+
entityConfig.getRevisionsUrl( recordKey, revisionKey ),
|
|
878
|
+
query
|
|
879
|
+
);
|
|
880
|
+
|
|
881
|
+
const record = await apiFetch( { path } );
|
|
882
|
+
dispatch.receiveRevisions( kind, name, recordKey, record, query );
|
|
883
|
+
};
|