@wordpress/edit-site 4.10.0 → 4.11.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/build/components/add-new-template/add-custom-template-modal.js +22 -42
- package/build/components/add-new-template/add-custom-template-modal.js.map +1 -1
- package/build/components/add-new-template/new-template.js +17 -20
- package/build/components/add-new-template/new-template.js.map +1 -1
- package/build/components/add-new-template/utils.js +366 -239
- package/build/components/add-new-template/utils.js.map +1 -1
- package/build/components/block-editor/index.js +1 -3
- package/build/components/block-editor/index.js.map +1 -1
- package/build/components/global-styles/dimensions-panel.js +183 -13
- package/build/components/global-styles/dimensions-panel.js.map +1 -1
- package/build/components/global-styles/hooks.js +1 -1
- package/build/components/global-styles/hooks.js.map +1 -1
- package/build/components/global-styles/use-global-styles-output.js +95 -17
- package/build/components/global-styles/use-global-styles-output.js.map +1 -1
- package/build/components/global-styles/utils.js +31 -0
- package/build/components/global-styles/utils.js.map +1 -1
- package/build/components/header/index.js +7 -6
- package/build/components/header/index.js.map +1 -1
- package/build/hooks/index.js +2 -0
- package/build/hooks/index.js.map +1 -1
- package/build/hooks/template-part-edit.js +86 -0
- package/build/hooks/template-part-edit.js.map +1 -0
- package/build-module/components/add-new-template/add-custom-template-modal.js +23 -43
- package/build-module/components/add-new-template/add-custom-template-modal.js.map +1 -1
- package/build-module/components/add-new-template/new-template.js +18 -21
- package/build-module/components/add-new-template/new-template.js.map +1 -1
- package/build-module/components/add-new-template/utils.js +365 -227
- package/build-module/components/add-new-template/utils.js.map +1 -1
- package/build-module/components/block-editor/index.js +1 -2
- package/build-module/components/block-editor/index.js.map +1 -1
- package/build-module/components/global-styles/dimensions-panel.js +183 -14
- package/build-module/components/global-styles/dimensions-panel.js.map +1 -1
- package/build-module/components/global-styles/hooks.js +1 -1
- package/build-module/components/global-styles/hooks.js.map +1 -1
- package/build-module/components/global-styles/use-global-styles-output.js +94 -22
- package/build-module/components/global-styles/use-global-styles-output.js.map +1 -1
- package/build-module/components/global-styles/utils.js +29 -0
- package/build-module/components/global-styles/utils.js.map +1 -1
- package/build-module/components/header/index.js +8 -6
- package/build-module/components/header/index.js.map +1 -1
- package/build-module/hooks/index.js +1 -0
- package/build-module/hooks/index.js.map +1 -1
- package/build-module/hooks/template-part-edit.js +67 -0
- package/build-module/hooks/template-part-edit.js.map +1 -0
- package/build-style/style-rtl.css +25 -25
- package/build-style/style.css +25 -25
- package/package.json +29 -29
- package/src/components/add-new-template/add-custom-template-modal.js +27 -45
- package/src/components/add-new-template/new-template.js +27 -64
- package/src/components/add-new-template/style.scss +20 -8
- package/src/components/add-new-template/utils.js +398 -229
- package/src/components/block-editor/index.js +0 -2
- package/src/components/global-styles/dimensions-panel.js +207 -14
- package/src/components/global-styles/hooks.js +2 -0
- package/src/components/global-styles/test/use-global-styles-output.js +64 -1
- package/src/components/global-styles/use-global-styles-output.js +100 -8
- package/src/components/global-styles/utils.js +31 -0
- package/src/components/header/index.js +9 -10
- package/src/components/header/style.scss +5 -3
- package/src/components/sidebar/style.scss +4 -0
- package/src/hooks/index.js +1 -0
- package/src/hooks/template-part-edit.js +82 -0
- package/src/style.scss +0 -1
- package/build/components/edit-template-part-menu-button/index.js +0 -90
- package/build/components/edit-template-part-menu-button/index.js.map +0 -1
- package/build-module/components/edit-template-part-menu-button/index.js +0 -72
- package/build-module/components/edit-template-part-menu-button/index.js.map +0 -1
- package/src/components/edit-template-part-menu-button/index.js +0 -82
|
@@ -40,73 +40,6 @@ export const mapToIHasNameAndId = (entities, path) => {
|
|
|
40
40
|
* @property {number[]} existingEntitiesIds An array of the existing entities ids.
|
|
41
41
|
*/
|
|
42
42
|
|
|
43
|
-
/**
|
|
44
|
-
* @typedef {Object} EntityConfig
|
|
45
|
-
* @property {string} entityName The entity's name.
|
|
46
|
-
* @property {Function} getOrderBy Getter for an entity's `orderBy` query parameter, given the object
|
|
47
|
-
* {search} as argument.
|
|
48
|
-
* @property {Function} getIcon Getter function for returning an entity's icon for the menu item.
|
|
49
|
-
* @property {Function} getTitle Getter function for returning an entity's title for the menu item.
|
|
50
|
-
* @property {Function} getDescription Getter function for returning an entity's description for the menu item.
|
|
51
|
-
* @property {string} recordNamePath The path to an entity's properties to use as a `name`. If not provided
|
|
52
|
-
* is assumed that `name` property exists.
|
|
53
|
-
* @property {string} templatePrefix The template prefix to create new templates and check against existing
|
|
54
|
-
* templates. For example custom post types need a `single-` prefix to all
|
|
55
|
-
* templates(`single-post-hello`), whereas `pages` don't (`page-hello`).
|
|
56
|
-
* @property {string} templateSlug If this property is provided, it is going to be used for the creation of
|
|
57
|
-
* new templates and the check against existing templates in the place
|
|
58
|
-
* of the actual entity's `slug`. An example is `Tag` templates where the
|
|
59
|
-
* the Tag's taxonomy slug is `post_tag`, but template hierarchy is based
|
|
60
|
-
* on `tag` alias.
|
|
61
|
-
*/
|
|
62
|
-
|
|
63
|
-
const taxonomyBaseConfig = {
|
|
64
|
-
entityName: 'taxonomy',
|
|
65
|
-
getOrderBy: _ref => {
|
|
66
|
-
let {
|
|
67
|
-
search
|
|
68
|
-
} = _ref;
|
|
69
|
-
return search ? 'name' : 'count';
|
|
70
|
-
},
|
|
71
|
-
getIcon: () => blockMeta,
|
|
72
|
-
getTitle: labels => sprintf( // translators: %s: Name of the taxonomy e.g: "Cagegory".
|
|
73
|
-
__('Single taxonomy: %s'), labels.singular_name),
|
|
74
|
-
getDescription: labels => sprintf( // translators: %s: Name of the taxonomy e.g: "Product Categories".
|
|
75
|
-
__('Displays a single taxonomy: %s.'), labels.singular_name)
|
|
76
|
-
};
|
|
77
|
-
const postTypeBaseConfig = {
|
|
78
|
-
entityName: 'postType',
|
|
79
|
-
getOrderBy: _ref2 => {
|
|
80
|
-
let {
|
|
81
|
-
search
|
|
82
|
-
} = _ref2;
|
|
83
|
-
return search ? 'relevance' : 'modified';
|
|
84
|
-
},
|
|
85
|
-
recordNamePath: 'title.rendered',
|
|
86
|
-
// `icon` is the `menu_icon` property of a post type. We
|
|
87
|
-
// only handle `dashicons` for now, even if the `menu_icon`
|
|
88
|
-
// also supports urls and svg as values.
|
|
89
|
-
getIcon: _icon => _icon !== null && _icon !== void 0 && _icon.startsWith('dashicons-') ? _icon.slice(10) : post,
|
|
90
|
-
getTitle: labels => sprintf( // translators: %s: Name of the post type e.g: "Post".
|
|
91
|
-
__('Single item: %s'), labels.singular_name),
|
|
92
|
-
getDescription: labels => sprintf( // translators: %s: Name of the post type e.g: "Post".
|
|
93
|
-
__('Displays a single item: %s.'), labels.singular_name)
|
|
94
|
-
};
|
|
95
|
-
export const entitiesConfig = {
|
|
96
|
-
postType: { ...postTypeBaseConfig,
|
|
97
|
-
templatePrefix: 'single-'
|
|
98
|
-
},
|
|
99
|
-
page: { ...postTypeBaseConfig
|
|
100
|
-
},
|
|
101
|
-
taxonomy: { ...taxonomyBaseConfig,
|
|
102
|
-
templatePrefix: 'taxonomy-'
|
|
103
|
-
},
|
|
104
|
-
category: { ...taxonomyBaseConfig
|
|
105
|
-
},
|
|
106
|
-
tag: { ...taxonomyBaseConfig,
|
|
107
|
-
templateSlug: 'tag'
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
43
|
export const useExistingTemplates = () => {
|
|
111
44
|
return useSelect(select => select(coreStore).getEntityRecords('postType', 'wp_template', {
|
|
112
45
|
per_page: -1
|
|
@@ -122,40 +55,14 @@ const usePublicPostTypes = () => {
|
|
|
122
55
|
}), []);
|
|
123
56
|
return useMemo(() => {
|
|
124
57
|
const excludedPostTypes = ['attachment'];
|
|
125
|
-
return postTypes === null || postTypes === void 0 ? void 0 : postTypes.filter(
|
|
58
|
+
return postTypes === null || postTypes === void 0 ? void 0 : postTypes.filter(_ref => {
|
|
126
59
|
let {
|
|
127
60
|
viewable,
|
|
128
61
|
slug
|
|
129
|
-
} =
|
|
62
|
+
} = _ref;
|
|
130
63
|
return viewable && !excludedPostTypes.includes(slug);
|
|
131
64
|
});
|
|
132
65
|
}, [postTypes]);
|
|
133
|
-
}; // `page` post type is a special case in the template hierarchy,
|
|
134
|
-
// so we exclude it from the list of post types and we handle it
|
|
135
|
-
// separately.
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
export const usePostTypes = () => {
|
|
139
|
-
const postTypes = usePublicPostTypes();
|
|
140
|
-
return useMemo(() => {
|
|
141
|
-
return postTypes === null || postTypes === void 0 ? void 0 : postTypes.filter(_ref4 => {
|
|
142
|
-
let {
|
|
143
|
-
slug
|
|
144
|
-
} = _ref4;
|
|
145
|
-
return slug !== 'page';
|
|
146
|
-
});
|
|
147
|
-
}, [postTypes]);
|
|
148
|
-
};
|
|
149
|
-
export const usePostTypePage = () => {
|
|
150
|
-
const postTypes = usePublicPostTypes();
|
|
151
|
-
return useMemo(() => {
|
|
152
|
-
return postTypes === null || postTypes === void 0 ? void 0 : postTypes.filter(_ref5 => {
|
|
153
|
-
let {
|
|
154
|
-
slug
|
|
155
|
-
} = _ref5;
|
|
156
|
-
return slug === 'page';
|
|
157
|
-
});
|
|
158
|
-
}, [postTypes]);
|
|
159
66
|
};
|
|
160
67
|
|
|
161
68
|
const usePublicTaxonomies = () => {
|
|
@@ -163,80 +70,348 @@ const usePublicTaxonomies = () => {
|
|
|
163
70
|
per_page: -1
|
|
164
71
|
}), []);
|
|
165
72
|
return useMemo(() => {
|
|
166
|
-
return taxonomies === null || taxonomies === void 0 ? void 0 : taxonomies.filter(
|
|
73
|
+
return taxonomies === null || taxonomies === void 0 ? void 0 : taxonomies.filter(_ref2 => {
|
|
167
74
|
let {
|
|
168
75
|
visibility
|
|
169
|
-
} =
|
|
76
|
+
} = _ref2;
|
|
170
77
|
return visibility === null || visibility === void 0 ? void 0 : visibility.publicly_queryable;
|
|
171
78
|
});
|
|
172
79
|
}, [taxonomies]);
|
|
173
80
|
};
|
|
174
|
-
/**
|
|
175
|
-
* `category` and `post_tag` are handled specifically in template
|
|
176
|
-
* hierarchy so we need to differentiate them and return the rest,
|
|
177
|
-
* e.g. `category-$slug` and `taxonomy-$taxonomy-$term`.
|
|
178
|
-
*/
|
|
179
81
|
|
|
82
|
+
export const usePostTypeMenuItems = onClickMenuItem => {
|
|
83
|
+
const publicPostTypes = usePublicPostTypes();
|
|
84
|
+
const existingTemplates = useExistingTemplates();
|
|
85
|
+
const defaultTemplateTypes = useDefaultTemplateTypes(); // `page`is a special case in template hierarchy.
|
|
180
86
|
|
|
181
|
-
|
|
182
|
-
const taxonomies = usePublicTaxonomies();
|
|
183
|
-
const specialTaxonomies = ['category', 'post_tag'];
|
|
184
|
-
return useMemo(() => taxonomies === null || taxonomies === void 0 ? void 0 : taxonomies.filter(_ref7 => {
|
|
87
|
+
const templatePrefixes = useMemo(() => publicPostTypes === null || publicPostTypes === void 0 ? void 0 : publicPostTypes.reduce((accumulator, _ref3) => {
|
|
185
88
|
let {
|
|
186
89
|
slug
|
|
187
|
-
} =
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
90
|
+
} = _ref3;
|
|
91
|
+
let suffix = slug;
|
|
92
|
+
|
|
93
|
+
if (slug !== 'page') {
|
|
94
|
+
suffix = `single-${suffix}`;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
accumulator[slug] = suffix;
|
|
98
|
+
return accumulator;
|
|
99
|
+
}, {}), [publicPostTypes]); // We need to keep track of naming conflicts. If a conflict
|
|
100
|
+
// occurs, we need to add slug.
|
|
101
|
+
|
|
102
|
+
const postTypeLabels = publicPostTypes === null || publicPostTypes === void 0 ? void 0 : publicPostTypes.reduce((accumulator, _ref4) => {
|
|
103
|
+
let {
|
|
104
|
+
labels
|
|
105
|
+
} = _ref4;
|
|
106
|
+
const singularName = labels.singular_name.toLowerCase();
|
|
107
|
+
accumulator[singularName] = (accumulator[singularName] || 0) + 1;
|
|
108
|
+
return accumulator;
|
|
109
|
+
}, {});
|
|
110
|
+
|
|
111
|
+
const needsUniqueIdentifier = (labels, slug) => {
|
|
112
|
+
const singularName = labels.singular_name.toLowerCase();
|
|
113
|
+
return postTypeLabels[singularName] > 1 && singularName !== slug;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const postTypesInfo = useEntitiesInfo('postType', templatePrefixes);
|
|
117
|
+
const existingTemplateSlugs = (existingTemplates || []).map(_ref5 => {
|
|
194
118
|
let {
|
|
195
119
|
slug
|
|
196
|
-
} =
|
|
197
|
-
return slug
|
|
198
|
-
})
|
|
120
|
+
} = _ref5;
|
|
121
|
+
return slug;
|
|
122
|
+
});
|
|
123
|
+
const menuItems = (publicPostTypes || []).reduce((accumulator, postType) => {
|
|
124
|
+
var _postTypesInfo$slug;
|
|
125
|
+
|
|
126
|
+
const {
|
|
127
|
+
slug,
|
|
128
|
+
labels,
|
|
129
|
+
icon
|
|
130
|
+
} = postType; // We need to check if the general template is part of the
|
|
131
|
+
// defaultTemplateTypes. If it is, just use that info and
|
|
132
|
+
// augment it with the specific template functionality.
|
|
133
|
+
|
|
134
|
+
const generalTemplateSlug = templatePrefixes[slug];
|
|
135
|
+
const defaultTemplateType = defaultTemplateTypes === null || defaultTemplateTypes === void 0 ? void 0 : defaultTemplateTypes.find(_ref6 => {
|
|
136
|
+
let {
|
|
137
|
+
slug: _slug
|
|
138
|
+
} = _ref6;
|
|
139
|
+
return _slug === generalTemplateSlug;
|
|
140
|
+
});
|
|
141
|
+
const hasGeneralTemplate = existingTemplateSlugs === null || existingTemplateSlugs === void 0 ? void 0 : existingTemplateSlugs.includes(generalTemplateSlug);
|
|
142
|
+
|
|
143
|
+
const _needsUniqueIdentifier = needsUniqueIdentifier(labels, slug);
|
|
144
|
+
|
|
145
|
+
let menuItemTitle = sprintf( // translators: %s: Name of the post type e.g: "Post".
|
|
146
|
+
__('Single item: %s'), labels.singular_name);
|
|
147
|
+
|
|
148
|
+
if (_needsUniqueIdentifier) {
|
|
149
|
+
menuItemTitle = sprintf( // translators: %1s: Name of the post type e.g: "Post"; %2s: Slug of the post type e.g: "book".
|
|
150
|
+
__('Single item: %1$s (%2$s)'), labels.singular_name, slug);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const menuItem = defaultTemplateType ? { ...defaultTemplateType
|
|
154
|
+
} : {
|
|
155
|
+
slug: generalTemplateSlug,
|
|
156
|
+
title: menuItemTitle,
|
|
157
|
+
description: sprintf( // translators: %s: Name of the post type e.g: "Post".
|
|
158
|
+
__('Displays a single item: %s.'), labels.singular_name),
|
|
159
|
+
// `icon` is the `menu_icon` property of a post type. We
|
|
160
|
+
// only handle `dashicons` for now, even if the `menu_icon`
|
|
161
|
+
// also supports urls and svg as values.
|
|
162
|
+
icon: icon !== null && icon !== void 0 && icon.startsWith('dashicons-') ? icon.slice(10) : post
|
|
163
|
+
};
|
|
164
|
+
const hasEntities = postTypesInfo === null || postTypesInfo === void 0 ? void 0 : (_postTypesInfo$slug = postTypesInfo[slug]) === null || _postTypesInfo$slug === void 0 ? void 0 : _postTypesInfo$slug.hasEntities; // We have a different template creation flow only if they have entities.
|
|
165
|
+
|
|
166
|
+
if (hasEntities) {
|
|
167
|
+
menuItem.onClick = template => {
|
|
168
|
+
onClickMenuItem({
|
|
169
|
+
type: 'postType',
|
|
170
|
+
slug,
|
|
171
|
+
config: {
|
|
172
|
+
recordNamePath: 'title.rendered',
|
|
173
|
+
queryArgs: _ref7 => {
|
|
174
|
+
let {
|
|
175
|
+
search
|
|
176
|
+
} = _ref7;
|
|
177
|
+
return {
|
|
178
|
+
_fields: 'id,title,slug,link',
|
|
179
|
+
orderBy: search ? 'relevance' : 'modified',
|
|
180
|
+
exclude: postTypesInfo[slug].existingEntitiesIds
|
|
181
|
+
};
|
|
182
|
+
},
|
|
183
|
+
getSpecificTemplate: suggestion => {
|
|
184
|
+
let title = sprintf( // translators: Represents the title of a user's custom template in the Site Editor, where %1$s is the singular name of a post type and %2$s is the name of the post, e.g. "Page: Hello".
|
|
185
|
+
__('%1$s: %2$s'), labels.singular_name, suggestion.name);
|
|
186
|
+
const description = sprintf( // translators: Represents the description of a user's custom template in the Site Editor, e.g. "Template for Page: Hello"
|
|
187
|
+
__('Template for %1$s'), title);
|
|
188
|
+
|
|
189
|
+
if (_needsUniqueIdentifier) {
|
|
190
|
+
title = sprintf( // translators: Represents the title of a user's custom template in the Site Editor, where %1$s is the template title and %2$s is the slug of the post type, e.g. "Project: Hello (project_type)"
|
|
191
|
+
__('%1$s %2$s'), title, `(${slug})`);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return {
|
|
195
|
+
title,
|
|
196
|
+
description,
|
|
197
|
+
slug: `${templatePrefixes[slug]}-${suggestion.slug}`
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
labels,
|
|
202
|
+
hasGeneralTemplate,
|
|
203
|
+
template
|
|
204
|
+
});
|
|
205
|
+
};
|
|
206
|
+
} // We don't need to add the menu item if there are no
|
|
207
|
+
// entities and the general template exists.
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
if (!hasGeneralTemplate || hasEntities) {
|
|
211
|
+
accumulator.push(menuItem);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return accumulator;
|
|
215
|
+
}, []); // Split menu items into two groups: one for the default post types
|
|
216
|
+
// and one for the rest.
|
|
217
|
+
|
|
218
|
+
const postTypesMenuItems = useMemo(() => menuItems.reduce((accumulator, postType) => {
|
|
219
|
+
const {
|
|
220
|
+
slug
|
|
221
|
+
} = postType;
|
|
222
|
+
let key = 'postTypesMenuItems';
|
|
223
|
+
|
|
224
|
+
if (slug === 'page') {
|
|
225
|
+
key = 'defaultPostTypesMenuItems';
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
accumulator[key].push(postType);
|
|
229
|
+
return accumulator;
|
|
230
|
+
}, {
|
|
231
|
+
defaultPostTypesMenuItems: [],
|
|
232
|
+
postTypesMenuItems: []
|
|
233
|
+
}), [menuItems]);
|
|
234
|
+
return postTypesMenuItems;
|
|
199
235
|
};
|
|
200
|
-
export const
|
|
201
|
-
const
|
|
202
|
-
|
|
236
|
+
export const useTaxonomiesMenuItems = onClickMenuItem => {
|
|
237
|
+
const publicTaxonomies = usePublicTaxonomies();
|
|
238
|
+
const existingTemplates = useExistingTemplates();
|
|
239
|
+
const defaultTemplateTypes = useDefaultTemplateTypes(); // `category` and `post_tag` are special cases in template hierarchy.
|
|
240
|
+
|
|
241
|
+
const templatePrefixes = useMemo(() => publicTaxonomies === null || publicTaxonomies === void 0 ? void 0 : publicTaxonomies.reduce((accumulator, _ref8) => {
|
|
203
242
|
let {
|
|
204
243
|
slug
|
|
244
|
+
} = _ref8;
|
|
245
|
+
let suffix = slug;
|
|
246
|
+
|
|
247
|
+
if (!['category', 'post_tag'].includes(slug)) {
|
|
248
|
+
suffix = `taxonomy-${suffix}`;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (slug === 'post_tag') {
|
|
252
|
+
suffix = `tag`;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
accumulator[slug] = suffix;
|
|
256
|
+
return accumulator;
|
|
257
|
+
}, {}), [publicTaxonomies]); // We need to keep track of naming conflicts. If a conflict
|
|
258
|
+
// occurs, we need to add slug.
|
|
259
|
+
|
|
260
|
+
const taxonomyLabels = publicTaxonomies === null || publicTaxonomies === void 0 ? void 0 : publicTaxonomies.reduce((accumulator, _ref9) => {
|
|
261
|
+
let {
|
|
262
|
+
labels
|
|
205
263
|
} = _ref9;
|
|
206
|
-
|
|
207
|
-
|
|
264
|
+
const singularName = labels.singular_name.toLowerCase();
|
|
265
|
+
accumulator[singularName] = (accumulator[singularName] || 0) + 1;
|
|
266
|
+
return accumulator;
|
|
267
|
+
}, {});
|
|
268
|
+
|
|
269
|
+
const needsUniqueIdentifier = (labels, slug) => {
|
|
270
|
+
if (['category', 'post_tag'].includes(slug)) {
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const singularName = labels.singular_name.toLowerCase();
|
|
275
|
+
return taxonomyLabels[singularName] > 1 && singularName !== slug;
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
const taxonomiesInfo = useEntitiesInfo('taxonomy', templatePrefixes);
|
|
279
|
+
const existingTemplateSlugs = (existingTemplates || []).map(_ref10 => {
|
|
280
|
+
let {
|
|
281
|
+
slug
|
|
282
|
+
} = _ref10;
|
|
283
|
+
return slug;
|
|
284
|
+
});
|
|
285
|
+
const menuItems = (publicTaxonomies || []).reduce((accumulator, taxonomy) => {
|
|
286
|
+
var _taxonomiesInfo$slug;
|
|
287
|
+
|
|
288
|
+
const {
|
|
289
|
+
slug,
|
|
290
|
+
labels
|
|
291
|
+
} = taxonomy; // We need to check if the general template is part of the
|
|
292
|
+
// defaultTemplateTypes. If it is, just use that info and
|
|
293
|
+
// augment it with the specific template functionality.
|
|
294
|
+
|
|
295
|
+
const generalTemplateSlug = templatePrefixes[slug];
|
|
296
|
+
const defaultTemplateType = defaultTemplateTypes === null || defaultTemplateTypes === void 0 ? void 0 : defaultTemplateTypes.find(_ref11 => {
|
|
297
|
+
let {
|
|
298
|
+
slug: _slug
|
|
299
|
+
} = _ref11;
|
|
300
|
+
return _slug === generalTemplateSlug;
|
|
301
|
+
});
|
|
302
|
+
const hasGeneralTemplate = existingTemplateSlugs === null || existingTemplateSlugs === void 0 ? void 0 : existingTemplateSlugs.includes(generalTemplateSlug);
|
|
303
|
+
|
|
304
|
+
const _needsUniqueIdentifier = needsUniqueIdentifier(labels, slug);
|
|
305
|
+
|
|
306
|
+
let menuItemTitle = labels.singular_name;
|
|
307
|
+
|
|
308
|
+
if (_needsUniqueIdentifier) {
|
|
309
|
+
menuItemTitle = sprintf( // translators: %1s: Name of the taxonomy e.g: "Category"; %2s: Slug of the taxonomy e.g: "product_cat".
|
|
310
|
+
__('%1$s (%2$s)'), labels.singular_name, slug);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const menuItem = defaultTemplateType ? { ...defaultTemplateType
|
|
314
|
+
} : {
|
|
315
|
+
slug: generalTemplateSlug,
|
|
316
|
+
title: menuItemTitle,
|
|
317
|
+
description: sprintf( // translators: %s: Name of the taxonomy e.g: "Product Categories".
|
|
318
|
+
__('Displays taxonomy: %s.'), labels.singular_name),
|
|
319
|
+
icon: blockMeta
|
|
320
|
+
};
|
|
321
|
+
const hasEntities = taxonomiesInfo === null || taxonomiesInfo === void 0 ? void 0 : (_taxonomiesInfo$slug = taxonomiesInfo[slug]) === null || _taxonomiesInfo$slug === void 0 ? void 0 : _taxonomiesInfo$slug.hasEntities; // We have a different template creation flow only if they have entities.
|
|
322
|
+
|
|
323
|
+
if (hasEntities) {
|
|
324
|
+
menuItem.onClick = template => {
|
|
325
|
+
onClickMenuItem({
|
|
326
|
+
type: 'taxonomy',
|
|
327
|
+
slug,
|
|
328
|
+
config: {
|
|
329
|
+
queryArgs: _ref12 => {
|
|
330
|
+
let {
|
|
331
|
+
search
|
|
332
|
+
} = _ref12;
|
|
333
|
+
return {
|
|
334
|
+
_fields: 'id,name,slug,link',
|
|
335
|
+
orderBy: search ? 'name' : 'count',
|
|
336
|
+
exclude: taxonomiesInfo[slug].existingEntitiesIds
|
|
337
|
+
};
|
|
338
|
+
},
|
|
339
|
+
getSpecificTemplate: suggestion => {
|
|
340
|
+
let title = sprintf( // translators: Represents the title of a user's custom template in the Site Editor, where %1$s is the singular name of a taxonomy and %2$s is the name of the term, e.g. "Category: shoes".
|
|
341
|
+
__('%1$s: %2$s'), labels.singular_name, suggestion.name);
|
|
342
|
+
const description = sprintf( // translators: Represents the description of a user's custom template in the Site Editor, e.g. "Template for Category: shoes"
|
|
343
|
+
__('Template for %1$s'), title);
|
|
344
|
+
|
|
345
|
+
if (_needsUniqueIdentifier) {
|
|
346
|
+
title = sprintf( // translators: Represents the title of a user's custom template in the Site Editor, where %1$s is the template title and %2$s is the slug of the taxonomy, e.g. "Category: shoes (product_tag)"
|
|
347
|
+
__('%1$s %2$s'), title, `(${slug})`);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
return {
|
|
351
|
+
title,
|
|
352
|
+
description,
|
|
353
|
+
slug: `${templatePrefixes[slug]}-${suggestion.slug}`
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
},
|
|
357
|
+
labels,
|
|
358
|
+
hasGeneralTemplate,
|
|
359
|
+
template
|
|
360
|
+
});
|
|
361
|
+
};
|
|
362
|
+
} // We don't need to add the menu item if there are no
|
|
363
|
+
// entities and the general template exists.
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
if (!hasGeneralTemplate || hasEntities) {
|
|
367
|
+
accumulator.push(menuItem);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
return accumulator;
|
|
371
|
+
}, []); // Split menu items into two groups: one for the default taxonomies
|
|
372
|
+
// and one for the rest.
|
|
373
|
+
|
|
374
|
+
const taxonomiesMenuItems = useMemo(() => menuItems.reduce((accumulator, taxonomy) => {
|
|
375
|
+
const {
|
|
376
|
+
slug
|
|
377
|
+
} = taxonomy;
|
|
378
|
+
let key = 'taxonomiesMenuItems';
|
|
379
|
+
|
|
380
|
+
if (['category', 'tag'].includes(slug)) {
|
|
381
|
+
key = 'defaultTaxonomiesMenuItems';
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
accumulator[key].push(taxonomy);
|
|
385
|
+
return accumulator;
|
|
386
|
+
}, {
|
|
387
|
+
defaultTaxonomiesMenuItems: [],
|
|
388
|
+
taxonomiesMenuItems: []
|
|
389
|
+
}), [menuItems]);
|
|
390
|
+
return taxonomiesMenuItems;
|
|
208
391
|
};
|
|
209
392
|
/**
|
|
210
|
-
* Helper hook that
|
|
211
|
-
*
|
|
393
|
+
* Helper hook that filters all the existing templates by the given
|
|
394
|
+
* object with the entity's slug as key and the template prefix as value.
|
|
212
395
|
*
|
|
213
|
-
*
|
|
214
|
-
* `
|
|
396
|
+
* Example:
|
|
397
|
+
* `existingTemplates` is: [ { slug: tag-apple }, { slug: page-about }, { slug: tag } ]
|
|
398
|
+
* `templatePrefixes` is: { post_tag: 'tag' }
|
|
399
|
+
* It will return: { post_tag: [apple] }
|
|
215
400
|
*
|
|
216
|
-
*
|
|
217
|
-
* to query afterwards for any remaing record, by excluding them.
|
|
401
|
+
* Note: We append the `-` to the given template prefix in this function for our checks.
|
|
218
402
|
*
|
|
219
|
-
* @param {string
|
|
220
|
-
* @
|
|
221
|
-
* @param {EntityConfig} entityConfig The entity config.
|
|
222
|
-
* @return {Record<string,EntitiesInfo>} An object with the `entities.slug` as `keys` and EntitiesInfo as values.
|
|
403
|
+
* @param {Record<string,string>} templatePrefixes An object with the entity's slug as key and the template prefix as value.
|
|
404
|
+
* @return {Record<string,string[]>} An object with the entity's slug as key and an array with the existing template slugs as value.
|
|
223
405
|
*/
|
|
224
406
|
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
} = _ref10;
|
|
231
|
-
const slugsToExcludePerEntity = useMemo(() => {
|
|
232
|
-
return entities === null || entities === void 0 ? void 0 : entities.reduce((accumulator, entity) => {
|
|
233
|
-
let _prefix = `${templateSlug || entity.slug}-`;
|
|
234
|
-
|
|
235
|
-
if (templatePrefix) {
|
|
236
|
-
_prefix = templatePrefix + _prefix;
|
|
237
|
-
}
|
|
238
|
-
|
|
407
|
+
const useExistingTemplateSlugs = templatePrefixes => {
|
|
408
|
+
const existingTemplates = useExistingTemplates();
|
|
409
|
+
const existingSlugs = useMemo(() => {
|
|
410
|
+
return Object.entries(templatePrefixes || {}).reduce((accumulator, _ref13) => {
|
|
411
|
+
let [slug, prefix] = _ref13;
|
|
239
412
|
const slugsWithTemplates = (existingTemplates || []).reduce((_accumulator, existingTemplate) => {
|
|
413
|
+
const _prefix = `${prefix}-`;
|
|
414
|
+
|
|
240
415
|
if (existingTemplate.slug.startsWith(_prefix)) {
|
|
241
416
|
_accumulator.push(existingTemplate.slug.substring(_prefix.length));
|
|
242
417
|
}
|
|
@@ -245,43 +420,70 @@ const useEntitiesInfo = (existingTemplates, entities, _ref10) => {
|
|
|
245
420
|
}, []);
|
|
246
421
|
|
|
247
422
|
if (slugsWithTemplates.length) {
|
|
248
|
-
accumulator[
|
|
423
|
+
accumulator[slug] = slugsWithTemplates;
|
|
249
424
|
}
|
|
250
425
|
|
|
251
426
|
return accumulator;
|
|
252
427
|
}, {});
|
|
253
|
-
}, [
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
428
|
+
}, [templatePrefixes, existingTemplates]);
|
|
429
|
+
return existingSlugs;
|
|
430
|
+
};
|
|
431
|
+
/**
|
|
432
|
+
* Helper hook that finds the existing records with an associated template,
|
|
433
|
+
* as they need to be excluded from the template suggestions.
|
|
434
|
+
*
|
|
435
|
+
* @param {string} entityName The entity's name.
|
|
436
|
+
* @param {Record<string,string>} templatePrefixes An object with the entity's slug as key and the template prefix as value.
|
|
437
|
+
* @return {Record<string,EntitiesInfo>} An object with the entity's slug as key and the existing records as value.
|
|
438
|
+
*/
|
|
439
|
+
|
|
258
440
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
441
|
+
const useTemplatesToExclude = (entityName, templatePrefixes) => {
|
|
442
|
+
const slugsToExcludePerEntity = useExistingTemplateSlugs(templatePrefixes);
|
|
443
|
+
const recordsToExcludePerEntity = useSelect(select => {
|
|
444
|
+
return Object.entries(slugsToExcludePerEntity || {}).reduce((accumulator, _ref14) => {
|
|
445
|
+
let [slug, slugsWithTemplates] = _ref14;
|
|
446
|
+
const entitiesWithTemplates = select(coreStore).getEntityRecords(entityName, slug, {
|
|
262
447
|
_fields: 'id',
|
|
263
448
|
context: 'view',
|
|
264
449
|
slug: slugsWithTemplates
|
|
265
450
|
});
|
|
266
451
|
|
|
267
|
-
if (
|
|
268
|
-
accumulator[slug] =
|
|
452
|
+
if (entitiesWithTemplates !== null && entitiesWithTemplates !== void 0 && entitiesWithTemplates.length) {
|
|
453
|
+
accumulator[slug] = entitiesWithTemplates;
|
|
269
454
|
}
|
|
270
455
|
|
|
271
456
|
return accumulator;
|
|
272
457
|
}, {});
|
|
273
458
|
}, [slugsToExcludePerEntity]);
|
|
459
|
+
return recordsToExcludePerEntity;
|
|
460
|
+
};
|
|
461
|
+
/**
|
|
462
|
+
* Helper hook that returns information about an entity having
|
|
463
|
+
* records that we can create a specific template for.
|
|
464
|
+
*
|
|
465
|
+
* For example we can search for `terms` in `taxonomy` entity or
|
|
466
|
+
* `posts` in `postType` entity.
|
|
467
|
+
*
|
|
468
|
+
* First we need to find the existing records with an associated template,
|
|
469
|
+
* to query afterwards for any remaining record, by excluding them.
|
|
470
|
+
*
|
|
471
|
+
* @param {string} entityName The entity's name.
|
|
472
|
+
* @param {Record<string,string>} templatePrefixes An object with the entity's slug as key and the template prefix as value.
|
|
473
|
+
* @return {Record<string,EntitiesInfo>} An object with the entity's slug as key and the EntitiesInfo as value.
|
|
474
|
+
*/
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
const useEntitiesInfo = (entityName, templatePrefixes) => {
|
|
478
|
+
const recordsToExcludePerEntity = useTemplatesToExclude(entityName, templatePrefixes);
|
|
274
479
|
const entitiesInfo = useSelect(select => {
|
|
275
|
-
return
|
|
480
|
+
return Object.keys(templatePrefixes || {}).reduce((accumulator, slug) => {
|
|
276
481
|
var _recordsToExcludePerE, _select$getEntityReco;
|
|
277
482
|
|
|
278
|
-
|
|
279
|
-
slug
|
|
280
|
-
} = _ref12;
|
|
281
|
-
const existingEntitiesIds = (recordsToExcludePerEntity === null || recordsToExcludePerEntity === void 0 ? void 0 : (_recordsToExcludePerE = recordsToExcludePerEntity[slug]) === null || _recordsToExcludePerE === void 0 ? void 0 : _recordsToExcludePerE.map(_ref13 => {
|
|
483
|
+
const existingEntitiesIds = (recordsToExcludePerEntity === null || recordsToExcludePerEntity === void 0 ? void 0 : (_recordsToExcludePerE = recordsToExcludePerEntity[slug]) === null || _recordsToExcludePerE === void 0 ? void 0 : _recordsToExcludePerE.map(_ref15 => {
|
|
282
484
|
let {
|
|
283
485
|
id
|
|
284
|
-
} =
|
|
486
|
+
} = _ref15;
|
|
285
487
|
return id;
|
|
286
488
|
})) || [];
|
|
287
489
|
accumulator[slug] = {
|
|
@@ -295,71 +497,7 @@ const useEntitiesInfo = (existingTemplates, entities, _ref10) => {
|
|
|
295
497
|
};
|
|
296
498
|
return accumulator;
|
|
297
499
|
}, {});
|
|
298
|
-
}, [
|
|
500
|
+
}, [templatePrefixes, recordsToExcludePerEntity]);
|
|
299
501
|
return entitiesInfo;
|
|
300
502
|
};
|
|
301
|
-
|
|
302
|
-
export const useExtraTemplates = (entities, entityConfig, onClickMenuItem) => {
|
|
303
|
-
const existingTemplates = useExistingTemplates();
|
|
304
|
-
const defaultTemplateTypes = useDefaultTemplateTypes();
|
|
305
|
-
const entitiesInfo = useEntitiesInfo(existingTemplates, entities, entityConfig);
|
|
306
|
-
const existingTemplateSlugs = (existingTemplates || []).map(_ref14 => {
|
|
307
|
-
let {
|
|
308
|
-
slug
|
|
309
|
-
} = _ref14;
|
|
310
|
-
return slug;
|
|
311
|
-
});
|
|
312
|
-
const extraTemplates = (entities || []).reduce((accumulator, entity) => {
|
|
313
|
-
var _entityConfig$getIcon, _entitiesInfo$slug;
|
|
314
|
-
|
|
315
|
-
const {
|
|
316
|
-
slug,
|
|
317
|
-
labels,
|
|
318
|
-
icon
|
|
319
|
-
} = entity;
|
|
320
|
-
const slugForGeneralTemplate = entityConfig.templateSlug || slug; // We need to check if the general template is part of the
|
|
321
|
-
// defaultTemplateTypes. If it is, just use that info and
|
|
322
|
-
// augment it with the specific template functionality.
|
|
323
|
-
|
|
324
|
-
const defaultTemplateType = defaultTemplateTypes === null || defaultTemplateTypes === void 0 ? void 0 : defaultTemplateTypes.find(_ref15 => {
|
|
325
|
-
let {
|
|
326
|
-
slug: _slug
|
|
327
|
-
} = _ref15;
|
|
328
|
-
return _slug === slugForGeneralTemplate;
|
|
329
|
-
});
|
|
330
|
-
const generalTemplateSlug = (defaultTemplateType === null || defaultTemplateType === void 0 ? void 0 : defaultTemplateType.slug) || `${entityConfig.templatePrefix}${slug}`;
|
|
331
|
-
const hasGeneralTemplate = existingTemplateSlugs === null || existingTemplateSlugs === void 0 ? void 0 : existingTemplateSlugs.includes(generalTemplateSlug);
|
|
332
|
-
const menuItem = defaultTemplateType ? { ...defaultTemplateType
|
|
333
|
-
} : {
|
|
334
|
-
slug: generalTemplateSlug,
|
|
335
|
-
title: entityConfig.getTitle(labels),
|
|
336
|
-
description: entityConfig.getDescription(labels),
|
|
337
|
-
icon: (_entityConfig$getIcon = entityConfig.getIcon) === null || _entityConfig$getIcon === void 0 ? void 0 : _entityConfig$getIcon.call(entityConfig, icon)
|
|
338
|
-
};
|
|
339
|
-
const hasEntities = entitiesInfo === null || entitiesInfo === void 0 ? void 0 : (_entitiesInfo$slug = entitiesInfo[slug]) === null || _entitiesInfo$slug === void 0 ? void 0 : _entitiesInfo$slug.hasEntities; // We have a different template creation flow only if they have entities.
|
|
340
|
-
|
|
341
|
-
if (hasEntities) {
|
|
342
|
-
menuItem.onClick = template => {
|
|
343
|
-
onClickMenuItem({
|
|
344
|
-
type: entityConfig.entityName,
|
|
345
|
-
slug,
|
|
346
|
-
config: entityConfig,
|
|
347
|
-
labels,
|
|
348
|
-
hasGeneralTemplate,
|
|
349
|
-
template,
|
|
350
|
-
postsToExclude: entitiesInfo[slug].existingEntitiesIds
|
|
351
|
-
});
|
|
352
|
-
};
|
|
353
|
-
} // We don't need to add the menu item if there are no
|
|
354
|
-
// entities and the general template exists.
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
if (!hasGeneralTemplate || hasEntities) {
|
|
358
|
-
accumulator.push(menuItem);
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
return accumulator;
|
|
362
|
-
}, []);
|
|
363
|
-
return extraTemplates;
|
|
364
|
-
};
|
|
365
503
|
//# sourceMappingURL=utils.js.map
|