-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Templates: add postTypes
and isCustom
fields & filters
#62075
Changes from all commits
60f9774
8ead9b1
371fd48
aefaca3
bd2ba5f
005f6f1
6e00235
1a776f2
895214a
35300bb
18756b3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
https://github.com/WordPress/wordpress-develop/pull/6660 | ||
|
||
* https://github.com/WordPress/gutenberg/pull/62075 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,7 @@ import { useAddedBy } from './hooks'; | |
import { | ||
TEMPLATE_POST_TYPE, | ||
OPERATOR_IS_ANY, | ||
OPERATOR_IS, | ||
LAYOUT_GRID, | ||
LAYOUT_TABLE, | ||
LAYOUT_LIST, | ||
|
@@ -80,7 +81,7 @@ const DEFAULT_VIEW = { | |
}, | ||
// All fields are visible by default, so it's | ||
// better to keep track of the hidden ones. | ||
hiddenFields: [ 'preview' ], | ||
hiddenFields: [ 'preview', 'postTypes', 'isCustom' ], | ||
layout: defaultConfigPerViewType[ LAYOUT_GRID ], | ||
filters: [], | ||
}; | ||
|
@@ -184,6 +185,22 @@ function Preview( { item, viewType } ) { | |
); | ||
} | ||
|
||
// This maps the template slug to the post types it should be available for. | ||
// https://developer.wordpress.org/themes/basics/template-hierarchy/#visual-overview | ||
// It only addresses primary and secondary templates, but not tertiary (aka variable) templates. | ||
const TEMPLATE_TO_POST_TYPE = { | ||
// 1. Primary templates. | ||
index: [ 'post', 'page' ], | ||
singular: [ 'post', 'page' ], | ||
single: [ 'post' ], | ||
page: [ 'page' ], | ||
// 2. Secondary templates. | ||
'single-post': [ 'post' ], | ||
}; | ||
|
||
const CUSTOM_TEMPLATE = __( 'Custom' ); | ||
const NOT_CUSTOM_TEMPLATE = __( 'Not custom' ); | ||
|
||
export default function PageTemplates() { | ||
const { params } = useLocation(); | ||
const { activeView = 'all', layout } = params; | ||
|
@@ -229,6 +246,23 @@ export default function PageTemplates() { | |
per_page: -1, | ||
} | ||
); | ||
const { records: types } = useEntityRecords( 'root', 'postType', { | ||
per_page: -1, | ||
context: 'edit', | ||
} ); | ||
|
||
const registeredPostTypes = useMemo( () => { | ||
const result = | ||
types | ||
?.filter( ( type ) => type.viewable && type.supports.editor ) // supports.editor is a proxy for supporting templates. | ||
.map( ( { name, slug } ) => ( { name, slug } ) ) | ||
.reduce( ( acc, current ) => { | ||
acc[ current.slug ] = current.name; | ||
return acc; | ||
}, {} ) || {}; | ||
return result; | ||
}, [ types ] ); | ||
|
||
const history = useHistory(); | ||
const onSelectionChange = useCallback( | ||
( items ) => { | ||
|
@@ -256,6 +290,27 @@ export default function PageTemplates() { | |
} ) ); | ||
}, [ records ] ); | ||
|
||
const getPostTypesFromItem = ( item ) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be a |
||
// This logic replicates querying the REST templates endpoint with a post_type parameter. | ||
// https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-includes/block-template-utils.php#L1077 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs to be a permalink and not just relative to |
||
// | ||
// Additionaly, it also maps the the WordPress template hierarchy to known post types. | ||
// | ||
// This is how it works: | ||
// | ||
// 1. Return the list of post types defined by the item, if any. | ||
// 2. If a template is custom, add it for any CPT. | ||
// 3. Consider the template hierarchy and how it maps to post types. E.g.: single, page, etc. | ||
// 4. If none of the above, default to no post types. | ||
|
||
return ( | ||
item.post_types || | ||
( item.is_custom && Object.keys( registeredPostTypes ) ) || | ||
TEMPLATE_TO_POST_TYPE[ item.slug ] || | ||
[] | ||
); | ||
}; | ||
|
||
const fields = useMemo( | ||
() => [ | ||
{ | ||
|
@@ -315,8 +370,51 @@ export default function PageTemplates() { | |
elements: authors, | ||
width: '1%', | ||
}, | ||
{ | ||
header: __( 'Post types' ), | ||
id: 'postTypes', | ||
getValue: ( { item } ) => getPostTypesFromItem( item ), | ||
render: ( { item } ) => { | ||
const postTypes = getPostTypesFromItem( item ); | ||
if ( ! postTypes || ! postTypes.length ) { | ||
return __( 'n/a' ); | ||
} | ||
|
||
if ( | ||
postTypes.length === | ||
Object.keys( registeredPostTypes ).length | ||
) { | ||
return __( 'Any' ); | ||
} | ||
|
||
return postTypes | ||
.map( | ||
( postType ) => | ||
registeredPostTypes[ postType ] || postType | ||
) | ||
.join( ',' ); | ||
}, | ||
elements: Object.keys( registeredPostTypes ).map( ( key ) => ( { | ||
value: key, | ||
label: registeredPostTypes[ key ], | ||
} ) ), | ||
}, | ||
{ | ||
header: __( 'Type' ), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've made the following decisions about how to present the
This is a concept that requires a certain knowledge of WordPress templates, so I was unsure about how to simplify it further. Happy to hear thoughts. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah this is very tricky.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
To be honest, I'm struggling to see the value of this field/filter in isolation: having the For adding more types: is there any stablished categorization of templates I can look at? That could be useful, though I wouldn't want to introduce a new concept to templates in this PR. If this field doesn't provide much value right now, I'd rather start with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the main motivator was to provide a way to replicate the 'Custom' section in 6.5's Templates sidebar: Without this filter it wouldn't be possible to view custom templates easily which could be seen as a regression? Possibly a bad idea, but could the filter be hidden in the UI but still function as part of a 'Custom' view? I think pattern categories work a similar way. The template hierarchy resolves by page type, essentially; "Archive", "Singular", "Front Page", "Posts Page", "Search Results", "404". Grouping by "Archive", "Singular", and "Utility" seems reasonable, but I don't think it's defined in the code. Agree it seems late to be adding this complexity. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I feel this is the best solution, and I'm also wary to introduce it this close to the beta. If we agree exposing those types would be best long-term, a plan for 6.6 can be:
Thoughts? Pushed this approach at 895214a. Made the field hidden by default and not a badge as well. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How do you feel about implementing the filter with We can then use it to add a 'Custom' view, including a description about what custom templates are. This would be similar (I think) to categories in the Patterns page. This would be dependent on updating the frame titles, but there's a PR for that ready to go. |
||
id: 'isCustom', | ||
getValue: ( { item } ) => !! item.is_custom, | ||
render: ( { item } ) => | ||
!! item.is_custom ? CUSTOM_TEMPLATE : NOT_CUSTOM_TEMPLATE, | ||
elements: [ | ||
{ value: true, label: CUSTOM_TEMPLATE }, | ||
{ value: false, label: NOT_CUSTOM_TEMPLATE }, | ||
], | ||
filterBy: { | ||
operators: [ OPERATOR_IS ], | ||
}, | ||
}, | ||
], | ||
[ authors, view.type ] | ||
[ authors, view.type, registeredPostTypes, getPostTypesFromItem ] | ||
); | ||
|
||
const { data, paginationInfo } = useMemo( () => { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super minor, but this check isn't needed before
isset
.