@wordpress/edit-site 6.30.1-next.a730c9c8c.0 → 6.31.1-next.f56bd8138.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/components/add-new-template/add-custom-template-modal-content.js +3 -2
  3. package/build/components/add-new-template/add-custom-template-modal-content.js.map +1 -1
  4. package/build/components/add-new-template/index.js +1 -5
  5. package/build/components/add-new-template/index.js.map +1 -1
  6. package/build/components/add-new-template/utils.js +26 -87
  7. package/build/components/add-new-template/utils.js.map +1 -1
  8. package/build/components/dataviews-actions/index.js +51 -1
  9. package/build/components/dataviews-actions/index.js.map +1 -1
  10. package/build/components/editor/index.js +1 -1
  11. package/build/components/editor/index.js.map +1 -1
  12. package/build/components/editor/use-resolve-edited-entity.js +42 -14
  13. package/build/components/editor/use-resolve-edited-entity.js.map +1 -1
  14. package/build/components/global-styles/screen-css.js +2 -3
  15. package/build/components/global-styles/screen-css.js.map +1 -1
  16. package/build/components/global-styles/screen-root.js +3 -35
  17. package/build/components/global-styles/screen-root.js.map +1 -1
  18. package/build/components/page-templates/fields.js +65 -5
  19. package/build/components/page-templates/fields.js.map +1 -1
  20. package/build/components/page-templates/hooks.js +1 -1
  21. package/build/components/page-templates/hooks.js.map +1 -1
  22. package/build/components/page-templates/index.js +103 -29
  23. package/build/components/page-templates/index.js.map +1 -1
  24. package/build/components/sidebar-global-styles-wrapper/index.js +45 -13
  25. package/build/components/sidebar-global-styles-wrapper/index.js.map +1 -1
  26. package/build/components/sidebar-navigation-screen-templates-browse/content.js +11 -5
  27. package/build/components/sidebar-navigation-screen-templates-browse/content.js.map +1 -1
  28. package/build/components/site-editor-routes/index.js +1 -1
  29. package/build/components/site-editor-routes/index.js.map +1 -1
  30. package/build/components/site-editor-routes/template-item.js +29 -23
  31. package/build/components/site-editor-routes/template-item.js.map +1 -1
  32. package/build-module/components/add-new-template/add-custom-template-modal-content.js +3 -2
  33. package/build-module/components/add-new-template/add-custom-template-modal-content.js.map +1 -1
  34. package/build-module/components/add-new-template/index.js +2 -6
  35. package/build-module/components/add-new-template/index.js.map +1 -1
  36. package/build-module/components/add-new-template/utils.js +26 -87
  37. package/build-module/components/add-new-template/utils.js.map +1 -1
  38. package/build-module/components/dataviews-actions/index.js +49 -0
  39. package/build-module/components/dataviews-actions/index.js.map +1 -1
  40. package/build-module/components/editor/index.js +1 -1
  41. package/build-module/components/editor/index.js.map +1 -1
  42. package/build-module/components/editor/use-resolve-edited-entity.js +42 -14
  43. package/build-module/components/editor/use-resolve-edited-entity.js.map +1 -1
  44. package/build-module/components/global-styles/screen-css.js +2 -3
  45. package/build-module/components/global-styles/screen-css.js.map +1 -1
  46. package/build-module/components/global-styles/screen-root.js +4 -36
  47. package/build-module/components/global-styles/screen-root.js.map +1 -1
  48. package/build-module/components/page-templates/fields.js +65 -5
  49. package/build-module/components/page-templates/fields.js.map +1 -1
  50. package/build-module/components/page-templates/hooks.js +1 -1
  51. package/build-module/components/page-templates/hooks.js.map +1 -1
  52. package/build-module/components/page-templates/index.js +105 -31
  53. package/build-module/components/page-templates/index.js.map +1 -1
  54. package/build-module/components/sidebar-global-styles-wrapper/index.js +48 -16
  55. package/build-module/components/sidebar-global-styles-wrapper/index.js.map +1 -1
  56. package/build-module/components/sidebar-navigation-screen-templates-browse/content.js +11 -5
  57. package/build-module/components/sidebar-navigation-screen-templates-browse/content.js.map +1 -1
  58. package/build-module/components/site-editor-routes/index.js +2 -2
  59. package/build-module/components/site-editor-routes/index.js.map +1 -1
  60. package/build-module/components/site-editor-routes/template-item.js +28 -22
  61. package/build-module/components/site-editor-routes/template-item.js.map +1 -1
  62. package/package.json +41 -41
  63. package/src/components/add-new-template/add-custom-template-modal-content.js +3 -4
  64. package/src/components/add-new-template/index.js +1 -8
  65. package/src/components/add-new-template/utils.js +36 -121
  66. package/src/components/dataviews-actions/index.js +51 -0
  67. package/src/components/editor/index.js +1 -0
  68. package/src/components/editor/use-resolve-edited-entity.js +54 -7
  69. package/src/components/global-styles/screen-css.js +4 -5
  70. package/src/components/global-styles/screen-root.js +5 -51
  71. package/src/components/page-templates/fields.js +70 -4
  72. package/src/components/page-templates/hooks.js +1 -1
  73. package/src/components/page-templates/index.js +160 -57
  74. package/src/components/sidebar-global-styles-wrapper/index.js +62 -16
  75. package/src/components/sidebar-navigation-screen-templates-browse/content.js +17 -7
  76. package/src/components/site-editor-routes/index.js +2 -1
  77. package/src/components/site-editor-routes/template-item.js +34 -26
@@ -25,13 +25,12 @@ const postTypesWithoutParentTemplate = [
25
25
  TEMPLATE_PART_POST_TYPE,
26
26
  NAVIGATION_POST_TYPE,
27
27
  PATTERN_TYPES.user,
28
+ 'wp_registered_template',
28
29
  ];
29
30
 
30
31
  const authorizedPostTypes = [ 'page', 'post' ];
31
32
 
32
- export function useResolveEditedEntity() {
33
- const { name, params = {}, query } = useLocation();
34
- const { postId = query?.postId } = params; // Fallback to query param for postId for list view routes.
33
+ function getPostType( name, postId ) {
35
34
  let postType;
36
35
  if ( name === 'navigation-item' ) {
37
36
  postType = NAVIGATION_POST_TYPE;
@@ -39,19 +38,48 @@ export function useResolveEditedEntity() {
39
38
  postType = PATTERN_TYPES.user;
40
39
  } else if ( name === 'template-part-item' ) {
41
40
  postType = TEMPLATE_PART_POST_TYPE;
42
- } else if ( name === 'template-item' || name === 'templates' ) {
41
+ } else if ( name === 'templates' ) {
42
+ postType = /^\d+$/.test( postId )
43
+ ? TEMPLATE_POST_TYPE
44
+ : 'wp_registered_template';
45
+ } else if ( name === 'template-item' ) {
43
46
  postType = TEMPLATE_POST_TYPE;
47
+ } else if ( name === 'static-template-item' ) {
48
+ postType = 'wp_registered_template';
44
49
  } else if ( name === 'page-item' || name === 'pages' ) {
45
50
  postType = 'page';
46
51
  } else if ( name === 'post-item' || name === 'posts' ) {
47
52
  postType = 'post';
48
53
  }
49
54
 
55
+ return postType;
56
+ }
57
+
58
+ export function useResolveEditedEntity() {
59
+ const { name, params = {}, query } = useLocation();
60
+ const { postId: _postId = query?.postId } = params; // Fallback to query param for postId for list view routes.
61
+ const _postType = getPostType( name, _postId ) ?? query?.postType;
62
+
50
63
  const homePage = useSelect( ( select ) => {
51
64
  const { getHomePage } = unlock( select( coreDataStore ) );
52
65
  return getHomePage();
53
66
  }, [] );
54
67
 
68
+ const [ postType, postId ] = useSelect(
69
+ ( select ) => {
70
+ if ( _postType !== 'wp_registered_template' ) {
71
+ return [ _postType, _postId ];
72
+ }
73
+ return [
74
+ TEMPLATE_POST_TYPE,
75
+ unlock( select( coreDataStore ) ).getTemplateAutoDraftId(
76
+ _postId
77
+ ),
78
+ ];
79
+ },
80
+ [ _postType, _postId ]
81
+ );
82
+
55
83
  /**
56
84
  * This is a hook that recreates the logic to resolve a template for a given WordPress postID postTypeId
57
85
  * in order to match the frontend as closely as possible in the site editor.
@@ -98,6 +126,18 @@ export function useResolveEditedEntity() {
98
126
  [ homePage, postId, postType ]
99
127
  );
100
128
 
129
+ const editableResolvedTemplateId = useSelect(
130
+ ( select ) => {
131
+ if ( typeof resolvedTemplateId !== 'string' ) {
132
+ return resolvedTemplateId;
133
+ }
134
+ return unlock( select( coreDataStore ) ).getTemplateAutoDraftId(
135
+ resolvedTemplateId
136
+ );
137
+ },
138
+ [ resolvedTemplateId ]
139
+ );
140
+
101
141
  const context = useMemo( () => {
102
142
  if ( postTypesWithoutParentTemplate.includes( postType ) && postId ) {
103
143
  return {};
@@ -121,9 +161,9 @@ export function useResolveEditedEntity() {
121
161
 
122
162
  if ( !! homePage ) {
123
163
  return {
124
- isReady: resolvedTemplateId !== undefined,
164
+ isReady: editableResolvedTemplateId !== undefined,
125
165
  postType: TEMPLATE_POST_TYPE,
126
- postId: resolvedTemplateId,
166
+ postId: editableResolvedTemplateId,
127
167
  context,
128
168
  };
129
169
  }
@@ -141,7 +181,14 @@ export function useSyncDeprecatedEntityIntoState( {
141
181
 
142
182
  useEffect( () => {
143
183
  if ( isReady ) {
144
- setEditedEntity( postType, postId, context );
184
+ // setEditedEntity expects a string (because the postId used to be
185
+ // the template slug, even for edited templates). Now the postId can
186
+ // be a number (either because it's an auto-draft or edited
187
+ // template). Passing a number could break plugins doing things like
188
+ // `id.includes`. It would be way more complex to keep passing the
189
+ // template slug, while also being incorrect, so the easiest
190
+ // solution is to cast the postId to a string.
191
+ setEditedEntity( postType, String( postId ), context );
145
192
  }
146
193
  }, [ isReady, postType, postId, context, setEditedEntity ] );
147
194
  }
@@ -18,9 +18,6 @@ const { useGlobalStyle, AdvancedPanel: StylesAdvancedPanel } = unlock(
18
18
  );
19
19
 
20
20
  function ScreenCSS() {
21
- const description = __(
22
- 'Add your own CSS to customize the appearance and layout of your site.'
23
- );
24
21
  const [ style ] = useGlobalStyle( '', undefined, 'user', {
25
22
  shouldDecodeEncode: false,
26
23
  } );
@@ -35,10 +32,12 @@ function ScreenCSS() {
35
32
  return (
36
33
  <>
37
34
  <ScreenHeader
38
- title={ __( 'CSS' ) }
35
+ title={ __( 'Additional CSS' ) }
39
36
  description={
40
37
  <>
41
- { description }
38
+ { __(
39
+ 'You can add custom CSS to further customize the appearance and layout of your site.'
40
+ ) }
42
41
  <br />
43
42
  <ExternalLink
44
43
  href={ __(
@@ -26,24 +26,10 @@ import RootMenu from './root-menu';
26
26
  import PreviewStyles from './preview-styles';
27
27
 
28
28
  function ScreenRoot() {
29
- const { hasVariations, canEditCSS } = useSelect( ( select ) => {
30
- const {
31
- getEntityRecord,
32
- __experimentalGetCurrentGlobalStylesId,
33
- __experimentalGetCurrentThemeGlobalStylesVariations,
34
- } = select( coreStore );
35
-
36
- const globalStylesId = __experimentalGetCurrentGlobalStylesId();
37
- const globalStyles = globalStylesId
38
- ? getEntityRecord( 'root', 'globalStyles', globalStylesId )
39
- : undefined;
40
-
41
- return {
42
- hasVariations:
43
- !! __experimentalGetCurrentThemeGlobalStylesVariations()
44
- ?.length,
45
- canEditCSS: !! globalStyles?._links?.[ 'wp:action-edit-css' ],
46
- };
29
+ const hasVariations = useSelect( ( select ) => {
30
+ const { __experimentalGetCurrentThemeGlobalStylesVariations } =
31
+ select( coreStore );
32
+ return !! __experimentalGetCurrentThemeGlobalStylesVariations()?.length;
47
33
  }, [] );
48
34
 
49
35
  return (
@@ -92,7 +78,7 @@ function ScreenRoot() {
92
78
  * the nav button inset should be looked at before reusing further.
93
79
  */
94
80
  paddingX="13px"
95
- marginBottom={ 4 }
81
+ marginBottom={ 2 }
96
82
  >
97
83
  { __(
98
84
  'Customize the appearance of specific blocks for the whole site.'
@@ -109,38 +95,6 @@ function ScreenRoot() {
109
95
  </NavigationButtonAsItem>
110
96
  </ItemGroup>
111
97
  </CardBody>
112
-
113
- { canEditCSS && (
114
- <>
115
- <CardDivider />
116
- <CardBody>
117
- <Spacer
118
- as="p"
119
- paddingTop={ 2 }
120
- paddingX="13px"
121
- marginBottom={ 4 }
122
- >
123
- { __(
124
- 'Add your own CSS to customize the appearance and layout of your site.'
125
- ) }
126
- </Spacer>
127
- <ItemGroup>
128
- <NavigationButtonAsItem path="/css">
129
- <HStack justify="space-between">
130
- <FlexItem>
131
- { __( 'Additional CSS' ) }
132
- </FlexItem>
133
- <IconWithCurrentColor
134
- icon={
135
- isRTL() ? chevronLeft : chevronRight
136
- }
137
- />
138
- </HStack>
139
- </NavigationButtonAsItem>
140
- </ItemGroup>
141
- </CardBody>
142
- </>
143
- ) }
144
98
  </Card>
145
99
  );
146
100
  }
@@ -6,7 +6,11 @@ import clsx from 'clsx';
6
6
  /**
7
7
  * WordPress dependencies
8
8
  */
9
- import { Icon, __experimentalHStack as HStack } from '@wordpress/components';
9
+ import {
10
+ Icon,
11
+ __experimentalHStack as HStack,
12
+ privateApis as componentsPrivateApis,
13
+ } from '@wordpress/components';
10
14
  import { __ } from '@wordpress/i18n';
11
15
  import { useState, useMemo } from '@wordpress/element';
12
16
  import { decodeEntities } from '@wordpress/html-entities';
@@ -16,15 +20,40 @@ import {
16
20
  privateApis as blockEditorPrivateApis,
17
21
  } from '@wordpress/block-editor';
18
22
  import { EditorProvider } from '@wordpress/editor';
23
+ import { privateApis as corePrivateApis } from '@wordpress/core-data';
19
24
 
20
25
  /**
21
26
  * Internal dependencies
22
27
  */
23
28
  import { useAddedBy } from './hooks';
29
+ import { useDefaultTemplateTypes } from '../add-new-template/utils';
24
30
  import usePatternSettings from '../page-patterns/use-pattern-settings';
25
31
  import { unlock } from '../../lock-unlock';
26
32
 
27
33
  const { useGlobalStyle } = unlock( blockEditorPrivateApis );
34
+ const { Badge } = unlock( componentsPrivateApis );
35
+ const { useEntityRecordsWithPermissions } = unlock( corePrivateApis );
36
+
37
+ function useAllDefaultTemplateTypes() {
38
+ const defaultTemplateTypes = useDefaultTemplateTypes();
39
+ const { records: staticRecords } = useEntityRecordsWithPermissions(
40
+ 'postType',
41
+ 'wp_registered_template',
42
+ { per_page: -1 }
43
+ );
44
+ return [
45
+ ...defaultTemplateTypes,
46
+ ...staticRecords
47
+ ?.filter( ( record ) => ! record.is_custom )
48
+ .map( ( record ) => {
49
+ return {
50
+ slug: record.slug,
51
+ title: record.title.rendered,
52
+ description: record.description,
53
+ };
54
+ } ),
55
+ ];
56
+ }
28
57
 
29
58
  function PreviewField( { item } ) {
30
59
  const settings = usePatternSettings();
@@ -68,8 +97,14 @@ export const previewField = {
68
97
  export const descriptionField = {
69
98
  label: __( 'Description' ),
70
99
  id: 'description',
71
- render: ( { item } ) => {
72
- return item.description && decodeEntities( item.description );
100
+ render: function RenderDescription( { item } ) {
101
+ const defaultTemplateTypes = useAllDefaultTemplateTypes();
102
+ const defaultTemplateType = defaultTemplateTypes.find(
103
+ ( type ) => type.slug === item.slug
104
+ );
105
+ return item.description
106
+ ? decodeEntities( item.description )
107
+ : defaultTemplateType?.description;
73
108
  },
74
109
  enableSorting: false,
75
110
  enableGlobalSearch: true,
@@ -107,6 +142,37 @@ function AuthorField( { item } ) {
107
142
  export const authorField = {
108
143
  label: __( 'Author' ),
109
144
  id: 'author',
110
- getValue: ( { item } ) => item.author_text,
145
+ getValue: ( { item } ) => item.author_text ?? item.author,
111
146
  render: AuthorField,
112
147
  };
148
+
149
+ export const activeField = {
150
+ label: __( 'Status' ),
151
+ id: 'active',
152
+ getValue: ( { item } ) => item._isActive,
153
+ render: function Render( { item } ) {
154
+ const isActive = item._isActive;
155
+ return (
156
+ <Badge intent={ isActive ? 'success' : 'default' }>
157
+ { isActive ? __( 'Active' ) : __( 'Inactive' ) }
158
+ </Badge>
159
+ );
160
+ },
161
+ };
162
+
163
+ export const slugField = {
164
+ label: __( 'Template Type' ),
165
+ id: 'slug',
166
+ getValue: ( { item } ) => item.slug,
167
+ render: function Render( { item } ) {
168
+ const defaultTemplateTypes = useAllDefaultTemplateTypes();
169
+ const defaultTemplateType = defaultTemplateTypes.find(
170
+ ( type ) => type.slug === item.slug
171
+ );
172
+ return (
173
+ defaultTemplateType?.title ||
174
+ // translators: %s is the slug of a custom template.
175
+ __( 'Custom' )
176
+ );
177
+ },
178
+ };
@@ -89,7 +89,7 @@ export function useAddedBy( postType, postId ) {
89
89
  type: 'user',
90
90
  icon: authorIcon,
91
91
  imageUrl: user?.avatar_urls?.[ 48 ],
92
- text: authorText,
92
+ text: authorText ?? user?.name,
93
93
  isCustomized: false,
94
94
  };
95
95
  }
@@ -3,11 +3,16 @@
3
3
  */
4
4
  import { __ } from '@wordpress/i18n';
5
5
  import { useState, useMemo, useCallback, useEffect } from '@wordpress/element';
6
- import { privateApis as corePrivateApis } from '@wordpress/core-data';
6
+ import {
7
+ privateApis as corePrivateApis,
8
+ store as coreStore,
9
+ } from '@wordpress/core-data';
7
10
  import { DataViews, filterSortAndPaginate } from '@wordpress/dataviews';
8
11
  import { privateApis as routerPrivateApis } from '@wordpress/router';
9
12
  import { privateApis as editorPrivateApis } from '@wordpress/editor';
10
13
  import { addQueryArgs } from '@wordpress/url';
14
+ import { useSelect } from '@wordpress/data';
15
+ import { useEvent } from '@wordpress/compose';
11
16
 
12
17
  /**
13
18
  * Internal dependencies
@@ -22,16 +27,22 @@ import {
22
27
  LAYOUT_LIST,
23
28
  } from '../../utils/constants';
24
29
  import { unlock } from '../../lock-unlock';
25
- import { useEditPostAction } from '../dataviews-actions';
26
- import { authorField, descriptionField, previewField } from './fields';
27
- import { useEvent } from '@wordpress/compose';
30
+ import {
31
+ useEditPostAction,
32
+ useSetActiveTemplateAction,
33
+ } from '../dataviews-actions';
34
+ import {
35
+ authorField,
36
+ descriptionField,
37
+ previewField,
38
+ activeField,
39
+ slugField,
40
+ } from './fields';
28
41
 
29
42
  const { usePostActions, templateTitleField } = unlock( editorPrivateApis );
30
43
  const { useHistory, useLocation } = unlock( routerPrivateApis );
31
44
  const { useEntityRecordsWithPermissions } = unlock( corePrivateApis );
32
45
 
33
- const EMPTY_ARRAY = [];
34
-
35
46
  const defaultLayouts = {
36
47
  [ LAYOUT_TABLE ]: {
37
48
  showMedia: false,
@@ -56,31 +67,29 @@ const DEFAULT_VIEW = {
56
67
  titleField: 'title',
57
68
  descriptionField: 'description',
58
69
  mediaField: 'preview',
59
- fields: [ 'author' ],
70
+ fields: [ 'author', 'active', 'slug' ],
60
71
  filters: [],
61
72
  ...defaultLayouts[ LAYOUT_GRID ],
62
73
  };
63
74
 
64
75
  export default function PageTemplates() {
65
76
  const { path, query } = useLocation();
66
- const { activeView = 'all', layout, postId } = query;
77
+ const { activeView = 'active', layout, postId } = query;
67
78
  const [ selection, setSelection ] = useState( [ postId ] );
68
-
69
79
  const defaultView = useMemo( () => {
70
80
  const usedType = layout ?? DEFAULT_VIEW.type;
71
81
  return {
72
82
  ...DEFAULT_VIEW,
73
83
  type: usedType,
74
- filters:
75
- activeView !== 'all'
76
- ? [
77
- {
78
- field: 'author',
79
- operator: 'isAny',
80
- value: [ activeView ],
81
- },
82
- ]
83
- : [],
84
+ filters: ! [ 'active', 'user' ].includes( activeView )
85
+ ? [
86
+ {
87
+ field: 'author',
88
+ operator: 'isAny',
89
+ value: [ activeView ],
90
+ },
91
+ ]
92
+ : [],
84
93
  ...defaultLayouts[ usedType ],
85
94
  };
86
95
  }, [ layout, activeView ] );
@@ -98,23 +107,116 @@ export default function PageTemplates() {
98
107
  useEffect( () => {
99
108
  setView( ( currentView ) => ( {
100
109
  ...currentView,
101
- filters:
102
- activeView !== 'all'
103
- ? [
104
- {
105
- field: 'author',
106
- operator: OPERATOR_IS_ANY,
107
- value: [ activeView ],
108
- },
109
- ]
110
- : [],
110
+ filters: ! [ 'active', 'user' ].includes( activeView )
111
+ ? [
112
+ {
113
+ field: 'author',
114
+ operator: OPERATOR_IS_ANY,
115
+ value: [ activeView ],
116
+ },
117
+ ]
118
+ : [],
111
119
  } ) );
112
120
  }, [ setView, activeView ] );
113
121
 
114
- const { records, isResolving: isLoadingData } =
122
+ const activeTemplatesOption = useSelect(
123
+ ( select ) =>
124
+ select( coreStore ).getEntityRecord( 'root', 'site' )
125
+ ?.active_templates
126
+ );
127
+ // Todo: this will have to be better so that we're not fetching all the
128
+ // records all the time. Active templates query will need to move server
129
+ // side.
130
+ const { records: userRecords, isResolving: isLoadingUserRecords } =
115
131
  useEntityRecordsWithPermissions( 'postType', TEMPLATE_POST_TYPE, {
116
132
  per_page: -1,
117
133
  } );
134
+ const { records: staticRecords, isResolving: isLoadingStaticData } =
135
+ useEntityRecordsWithPermissions( 'postType', 'wp_registered_template', {
136
+ per_page: -1,
137
+ } );
138
+
139
+ const activeTemplates = useMemo( () => {
140
+ const _active = [ ...staticRecords ].filter(
141
+ ( record ) => ! record.is_custom
142
+ );
143
+ if ( activeTemplatesOption ) {
144
+ for ( const activeSlug in activeTemplatesOption ) {
145
+ const activeId = activeTemplatesOption[ activeSlug ];
146
+ if ( activeId === false ) {
147
+ // Remove the template from the array.
148
+ const index = _active.findIndex(
149
+ ( template ) => template.slug === activeSlug
150
+ );
151
+ if ( index !== -1 ) {
152
+ _active.splice( index, 1 );
153
+ }
154
+ } else {
155
+ // Replace the template in the array.
156
+ const template = userRecords.find(
157
+ ( { id } ) => id === activeId
158
+ );
159
+ if ( template ) {
160
+ const index = _active.findIndex(
161
+ ( { slug } ) => slug === template.slug
162
+ );
163
+ if ( index !== -1 ) {
164
+ _active[ index ] = template;
165
+ } else {
166
+ _active.push( template );
167
+ }
168
+ }
169
+ }
170
+ }
171
+ }
172
+ return _active;
173
+ }, [ userRecords, staticRecords, activeTemplatesOption ] );
174
+
175
+ let _records;
176
+ let isLoadingData;
177
+ if ( activeView === 'active' ) {
178
+ _records = activeTemplates;
179
+ isLoadingData = isLoadingUserRecords || isLoadingStaticData;
180
+ } else if ( activeView === 'user' ) {
181
+ _records = userRecords;
182
+ isLoadingData = isLoadingUserRecords;
183
+ } else {
184
+ _records = staticRecords;
185
+ isLoadingData = isLoadingStaticData;
186
+ }
187
+
188
+ const records = useMemo( () => {
189
+ return _records.map( ( record ) => ( {
190
+ ...record,
191
+ _isActive:
192
+ typeof record.id === 'string'
193
+ ? activeTemplatesOption[ record.slug ] === record.id ||
194
+ activeTemplatesOption[ record.slug ] === undefined
195
+ : Object.values( activeTemplatesOption ).includes(
196
+ record.id
197
+ ),
198
+ } ) );
199
+ }, [ _records, activeTemplatesOption ] );
200
+
201
+ const users = useSelect(
202
+ ( select ) => {
203
+ const { getUser } = select( coreStore );
204
+ return records.reduce( ( acc, record ) => {
205
+ if ( record.author_text ) {
206
+ if ( ! acc[ record.author_text ] ) {
207
+ acc[ record.author_text ] = record.author_text;
208
+ }
209
+ } else if ( record.author ) {
210
+ if ( ! acc[ record.author ] ) {
211
+ acc[ record.author ] = getUser( record.author );
212
+ }
213
+ }
214
+ return acc;
215
+ }, {} );
216
+ },
217
+ [ records ]
218
+ );
219
+
118
220
  const history = useHistory();
119
221
  const onChangeSelection = useCallback(
120
222
  ( items ) => {
@@ -130,32 +232,27 @@ export default function PageTemplates() {
130
232
  [ history, path, view?.type ]
131
233
  );
132
234
 
133
- const authors = useMemo( () => {
134
- if ( ! records ) {
135
- return EMPTY_ARRAY;
136
- }
137
- const authorsSet = new Set();
138
- records.forEach( ( template ) => {
139
- authorsSet.add( template.author_text );
140
- } );
141
- return Array.from( authorsSet ).map( ( author ) => ( {
142
- value: author,
143
- label: author,
144
- } ) );
145
- }, [ records ] );
146
-
147
- const fields = useMemo(
148
- () => [
235
+ const fields = useMemo( () => {
236
+ const _fields = [
149
237
  previewField,
150
238
  templateTitleField,
151
239
  descriptionField,
152
- {
153
- ...authorField,
154
- elements: authors,
155
- },
156
- ],
157
- [ authors ]
158
- );
240
+ activeField,
241
+ slugField,
242
+ ];
243
+ const elements = [];
244
+ for ( const author in users ) {
245
+ elements.push( {
246
+ value: users[ author ]?.id ?? author,
247
+ label: users[ author ]?.name ?? author,
248
+ } );
249
+ }
250
+ _fields.push( {
251
+ ...authorField,
252
+ elements,
253
+ } );
254
+ return _fields;
255
+ }, [ users ] );
159
256
 
160
257
  const { data, paginationInfo } = useMemo( () => {
161
258
  return filterSortAndPaginate( records, view, fields );
@@ -166,9 +263,13 @@ export default function PageTemplates() {
166
263
  context: 'list',
167
264
  } );
168
265
  const editAction = useEditPostAction();
266
+ const setActiveTemplateAction = useSetActiveTemplateAction();
169
267
  const actions = useMemo(
170
- () => [ editAction, ...postTypeActions ],
171
- [ postTypeActions, editAction ]
268
+ () =>
269
+ activeView === 'user'
270
+ ? [ setActiveTemplateAction, editAction, ...postTypeActions ]
271
+ : [ setActiveTemplateAction, ...postTypeActions ],
272
+ [ postTypeActions, setActiveTemplateAction, editAction, activeView ]
172
273
  );
173
274
 
174
275
  const onChangeView = useEvent( ( newView ) => {
@@ -199,8 +300,10 @@ export default function PageTemplates() {
199
300
  onChangeView={ onChangeView }
200
301
  onChangeSelection={ onChangeSelection }
201
302
  isItemClickable={ () => true }
202
- onClickItem={ ( { id } ) => {
203
- history.navigate( `/wp_template/${ id }?canvas=edit` );
303
+ onClickItem={ ( item ) => {
304
+ history.navigate(
305
+ `/${ item.type }/${ item.id }?canvas=edit`
306
+ );
204
307
  } }
205
308
  selection={ selection }
206
309
  defaultLayouts={ defaultLayouts }