Skip to content
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

Fix warnings within useSelect of the bulk editing header #67872

Open
wants to merge 7 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 59 additions & 1 deletion packages/core-data/src/private-selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,16 @@ import { createSelector, createRegistrySelector } from '@wordpress/data';
/**
* Internal dependencies
*/
import { getDefaultTemplateId, getEntityRecord, type State } from './selectors';
import {
getDefaultTemplateId,
getEditedEntityRecord,
getEntityRecord,
type State,
type GetRecordsHttpQuery,
} from './selectors';
import { STORE_NAME } from './name';
import { unlock } from './lock-unlock';
import type * as ET from './entity-types';

type EntityRecordKey = string | number;

Expand Down Expand Up @@ -257,3 +264,54 @@ export const getTemplateId = createRegistrySelector(
} );
}
);

/**
* Returns a list of entity records, merged with their edits.
*
* @param state State tree.
* @param kind Entity kind.
* @param name Entity name.
* @param recordIds Record IDs.
*
* @return The list of entity records, merged with their edits.
*/
export const getEditedEntityRecords = createSelector(
< EntityRecord extends ET.EntityRecord< any > >(
state: State,
kind: string,
name: string,
recordIds: EntityRecordKey[]
): Array< ET.Updatable< EntityRecord > | false > => {
return recordIds.map( ( recordId ) =>
getEditedEntityRecord( state, kind, name, recordId )
);
},
(
state: State,
kind: string,
name: string,
recordIds: EntityRecordKey[],
query?: GetRecordsHttpQuery
) => {
const context = query?.context ?? 'default';
return [
state.entities.config,
...recordIds.map(
( recordId ) =>
state.entities.records?.[ kind ]?.[ name ]?.queriedData
.items[ context ]?.[ recordId ]
),
...recordIds.map(
( recordId ) =>
state.entities.records?.[ kind ]?.[ name ]?.queriedData
.itemIsComplete[ context ]?.[ recordId ]
),
...recordIds.map(
( recordId ) =>
state.entities.records?.[ kind ]?.[ name ]?.edits?.[
recordId
]
),
];
}
);
2 changes: 1 addition & 1 deletion packages/core-data/src/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ type Optional< T > = T | undefined;
/**
* HTTP Query parameters sent with the API request to fetch the entity records.
*/
type GetRecordsHttpQuery = Record< string, any >;
export type GetRecordsHttpQuery = Record< string, any >;

/**
* Arguments for EntityRecord selectors.
Expand Down
47 changes: 34 additions & 13 deletions packages/editor/src/components/post-actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,48 @@ import { usePostActions } from './actions';
const { Menu, kebabCase } = unlock( componentsPrivateApis );

function useEditedEntityRecordsWithPermissions( postType, postIds ) {
const { items, permissions } = useSelect(
const { items, entityConfig } = useSelect(
( select ) => {
const { getEditedEntityRecord, getEntityRecordPermissions } =
unlock( select( coreStore ) );
const { getEntityConfig } = select( coreStore );
const { getEditedEntityRecords } = unlock( select( coreStore ) );
const entityRecords = getEditedEntityRecords(
'postType',
postType,
postIds
);

return {
items: postIds.map( ( postId ) =>
getEditedEntityRecord( 'postType', postType, postId )
),
permissions: postIds.map( ( postId ) =>
getEntityRecordPermissions( 'postType', postType, postId )
),
items: entityRecords,
entityConfig: getEntityConfig( 'postType', postType ),
};
},
[ postIds, postType ]
);

const ids = useMemo(
() =>
items?.map( ( record ) => record[ entityConfig?.key ?? 'id' ] ) ??
[],
[ items, entityConfig?.key ]
);

const permissions = useSelect(
( select ) => {
const { getEntityRecordsPermissions } = unlock(
select( coreStore )
);
return getEntityRecordsPermissions( 'postType', postType, ids );
},
[ ids, postType ]
);

return useMemo( () => {
return items.map( ( item, index ) => ( {
...item,
permissions: permissions[ index ],
} ) );
return (
items?.map( ( item, index ) => ( {
...item,
permissions: permissions ? permissions[ index ] : undefined,
} ) ) ?? []
);
}, [ items, permissions ] );
}

Expand Down
80 changes: 42 additions & 38 deletions packages/fields/src/fields/template/template-edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,52 +39,50 @@ export const TemplateEdit = ( {
typeof data.id === 'number' ? data.id : parseInt( data.id, 10 );
const slug = data.slug;

const { availableTemplates, templates } = useSelect(
const { templates, allowSwitchingTemplate } = useSelect(
( select ) => {
const allTemplates =
select( coreStore ).getEntityRecords< WpTemplate >(
'postType',
'wp_template',
{
per_page: -1,
post_type: postType,
}
) ?? [];
const allTemplates = select(
coreStore
).getEntityRecords< WpTemplate >( 'postType', 'wp_template', {
per_page: -1,
post_type: postType,
} );
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the ?? [] and handle this outside of the useSelect.


const { getHomePage, getPostsPageId } = unlock(
select( coreStore )
);

const isPostsPage = getPostsPageId() === +postId;
const isPostsPage = getPostsPageId() === postId.toString();
const isFrontPage =
postType === 'page' && getHomePage()?.postId === +postId;

const allowSwitchingTemplate = ! isPostsPage && ! isFrontPage;
postType === 'page' &&
getHomePage()?.postId === postId.toString();

return {
templates: allTemplates,
availableTemplates: allowSwitchingTemplate
? allTemplates.filter(
( template ) =>
template.is_custom &&
template.slug !== data.template &&
!! template.content.raw // Skip empty templates.
)
: [],
allowSwitchingTemplate: ! isPostsPage && ! isFrontPage,
};
},
[ data.template, postId, postType ]
[ postId, postType ]
);

const templatesAsPatterns = useMemo(
() =>
availableTemplates.map( ( template ) => ( {
name: template.slug,
blocks: parse( template.content.raw ),
title: decodeEntities( template.title.rendered ),
id: template.id,
} ) ),
[ availableTemplates ]
allowSwitchingTemplate
? ( templates ?? [] )
.filter(
( template ) =>
template.is_custom &&
template.slug !== data.template &&
!! template.content.raw // Skip empty templates.
)
.map( ( template ) => ( {
name: template.slug,
blocks: parse( template.content.raw ),
title: decodeEntities( template.title.rendered ),
id: template.id,
} ) )
: [],
[ templates, allowSwitchingTemplate, data.template ]
);

const shownTemplates = useAsyncList( templatesAsPatterns );
Expand Down Expand Up @@ -151,6 +149,10 @@ export const TemplateEdit = ( {
variant="tertiary"
size="compact"
onClick={ onToggle }
accessibleWhenDisabled
disabled={
value === '' && ! templatesAsPatterns.length
}
>
{ currentTemplate
? getItemTitle( currentTemplate )
Expand All @@ -159,14 +161,16 @@ export const TemplateEdit = ( {
) }
renderContent={ ( { onToggle } ) => (
<MenuGroup>
<MenuItem
onClick={ () => {
setShowModal( true );
onToggle();
} }
>
{ __( 'Swap template' ) }
</MenuItem>
{ templatesAsPatterns.length > 0 && (
<MenuItem
onClick={ () => {
setShowModal( true );
onToggle();
} }
>
{ __( 'Swap template' ) }
</MenuItem>
) }
{
// The default template in a post is indicated by an empty string
value !== '' && (
Expand Down
Loading