Skip to content

Commit

Permalink
DataViews: Use items with permissions and avoid hooks to register act…
Browse files Browse the repository at this point in the history
…ions
  • Loading branch information
youknowriad committed Jul 25, 2024
1 parent 0b55895 commit bb71e27
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 110 deletions.
54 changes: 37 additions & 17 deletions packages/core-data/src/private-selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { createSelector, createRegistrySelector } from '@wordpress/data';
/**
* Internal dependencies
*/
import { canUser } from './selectors';
import type { State } from './selectors';
import { STORE_NAME } from './name';

Expand Down Expand Up @@ -55,20 +54,41 @@ export const getBlockPatternsForPostType = createRegistrySelector(
/**
* Returns the entity records permissions for the given entity record ids.
*/
export const getEntityRecordsPermissions = createSelector(
( state: State, kind: string, name: string, ids: string[] ) => {
return ids.map( ( id ) => ( {
delete: canUser( state, 'delete', {
kind,
name,
id,
} ),
update: canUser( state, 'update', {
kind,
name,
id,
} ),
} ) );
},
( state ) => [ state.userPermissions ]
export const getEntityRecordsPermissions = createRegistrySelector( ( select ) =>
createSelector(
( state: State, kind: string, name: string, ids: string[] ) => {
return ids.map( ( id ) => ( {
delete: select( STORE_NAME ).canUser( 'delete', {
kind,
name,
id,
} ),
update: select( STORE_NAME ).canUser( 'update', {
kind,
name,
id,
} ),
} ) );
},
( state ) => [ state.userPermissions ]
)
);

/**
* Returns the entity record permissions for the given entity record id.
*
* @param state Data state.
* @param kind Entity kind.
* @param name Entity name.
* @param id Entity record id.
*
* @return The entity record permissions.
*/
export function getEntityRecordPermissions(
state: State,
kind: string,
name: string,
id: string
) {
return getEntityRecordsPermissions( state, kind, name, [ id ] )[ 0 ];
}
41 changes: 38 additions & 3 deletions packages/edit-site/src/components/page-patterns/use-patterns.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { parse } from '@wordpress/blocks';
import { useSelect, createSelector } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';
import { store as editorStore } from '@wordpress/editor';
import { useMemo } from '@wordpress/element';

/**
* Internal dependencies
Expand All @@ -25,8 +26,9 @@ const EMPTY_PATTERN_LIST = [];

const selectTemplateParts = createSelector(
( select, categoryId, search = '' ) => {
const { getEntityRecords, isResolving: isResolvingSelector } =
select( coreStore );
const { getEntityRecords, isResolving: isResolvingSelector } = unlock(
select( coreStore )
);
const { __experimentalGetDefaultTemplatePartAreas } =
select( editorStore );
const query = { per_page: -1 };
Expand Down Expand Up @@ -260,7 +262,7 @@ export const usePatterns = (
categoryId,
{ search = '', syncStatus } = {}
) => {
return useSelect(
const { patterns, ...rest } = useSelect(
( select ) => {
if ( postType === TEMPLATE_PART_POST_TYPE ) {
return selectTemplateParts( select, categoryId, search );
Expand All @@ -283,6 +285,39 @@ export const usePatterns = (
},
[ categoryId, postType, search, syncStatus ]
);

const ids = useMemo(
() =>
patterns?.map(
// @ts-ignore
( record ) => record.id
) ?? [],
[ patterns ]
);

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

const patternsWithPermissions = useMemo(
() =>
patterns?.map( ( record, index ) => ( {
...record,
permissions: permissions[ index ],
} ) ) ?? [],
[ patterns, permissions ]
);

return {
...rest,
patterns: patternsWithPermissions,
};
};

export default usePatterns;
13 changes: 5 additions & 8 deletions packages/edit-site/src/components/page-templates/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import clsx from 'clsx';
import { Icon, __experimentalHStack as HStack } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { useState, useMemo, useCallback, useEffect } from '@wordpress/element';
import { useEntityRecords } from '@wordpress/core-data';
import { decodeEntities } from '@wordpress/html-entities';
import { parse } from '@wordpress/blocks';
import {
Expand All @@ -22,6 +21,7 @@ import {
privateApis as editorPrivateApis,
EditorProvider,
} from '@wordpress/editor';
import { privateApis as corePrivateApis } from '@wordpress/core-data';

/**
* Internal dependencies
Expand All @@ -44,9 +44,9 @@ import { unlock } from '../../lock-unlock';
import { useEditPostAction } from '../dataviews-actions';

const { usePostActions } = unlock( editorPrivateApis );

const { useGlobalStyle } = unlock( blockEditorPrivateApis );
const { useHistory, useLocation } = unlock( routerPrivateApis );
const { useEntityRecordsWithPermissions } = unlock( corePrivateApis );

const EMPTY_ARRAY = [];

Expand Down Expand Up @@ -248,13 +248,10 @@ export default function PageTemplates() {
} ) );
}, [ activeView ] );

const { records, isResolving: isLoadingData } = useEntityRecords(
'postType',
TEMPLATE_POST_TYPE,
{
const { records, isResolving: isLoadingData } =
useEntityRecordsWithPermissions( 'postType', TEMPLATE_POST_TYPE, {
per_page: -1,
}
);
} );
const history = useHistory();
const onChangeSelection = useCallback(
( items ) => {
Expand Down
95 changes: 20 additions & 75 deletions packages/editor/src/components/post-actions/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/
import { external, trash, backup } from '@wordpress/icons';
import { addQueryArgs } from '@wordpress/url';
import { useDispatch, useSelect, useRegistry } from '@wordpress/data';
import { useDispatch, useSelect } from '@wordpress/data';
import { decodeEntities } from '@wordpress/html-entities';
import { store as coreStore } from '@wordpress/core-data';
import { __, _n, sprintf, _x } from '@wordpress/i18n';
Expand Down Expand Up @@ -79,7 +79,10 @@ const trashPostAction = {
isPrimary: true,
icon: trash,
isEligible( item ) {
return ! [ 'auto-draft', 'trash' ].includes( item.status );
return (
! [ 'auto-draft', 'trash' ].includes( item.status ) &&
item.permissions?.delete
);
},
supportsBulk: true,
hideModalHeader: true,
Expand Down Expand Up @@ -231,40 +234,12 @@ const trashPostAction = {
},
};

function useCanUserEligibilityCheckPostType( capability, postType, action ) {
const registry = useRegistry();
return useMemo(
() => ( {
...action,
isEligible( item ) {
return (
action.isEligible( item ) &&
registry.select( coreStore ).canUser( capability, {
kind: 'postType',
name: postType,
id: item.id,
} )
);
},
} ),
[ action, registry, capability, postType ]
);
}

function useTrashPostAction( postType ) {
return useCanUserEligibilityCheckPostType(
'delete',
postType,
trashPostAction
);
}

const permanentlyDeletePostAction = {
id: 'permanently-delete',
label: __( 'Permanently delete' ),
supportsBulk: true,
isEligible( { status } ) {
return status === 'trash';
isEligible( { status, permissions } ) {
return status === 'trash' && permissions?.delete;
},
async callback( posts, { registry, onActionPerformed } ) {
const { createSuccessNotice, createErrorNotice } =
Expand Down Expand Up @@ -350,22 +325,14 @@ const permanentlyDeletePostAction = {
},
};

function usePermanentlyDeletePostAction( postType ) {
return useCanUserEligibilityCheckPostType(
'delete',
postType,
permanentlyDeletePostAction
);
}

const restorePostAction = {
id: 'restore',
label: __( 'Restore' ),
isPrimary: true,
icon: backup,
supportsBulk: true,
isEligible( { status } ) {
return status === 'trash';
isEligible( { status, permissions } ) {
return status === 'trash' && permissions?.update;
},
async callback( posts, { registry, onActionPerformed } ) {
const { createSuccessNotice, createErrorNotice } =
Expand Down Expand Up @@ -465,14 +432,6 @@ const restorePostAction = {
},
};

function useRestorePostAction( postType ) {
return useCanUserEligibilityCheckPostType(
'update',
postType,
restorePostAction
);
}

const viewPostAction = {
id: 'view-post',
label: __( 'View' ),
Expand Down Expand Up @@ -539,11 +498,15 @@ const renamePostAction = {
...Object.values( PATTERN_TYPES ),
].includes( post.type )
) {
return true;
return post.permissions?.update;
}
// In the case of templates, we can only rename custom templates.
if ( post.type === TEMPLATE_POST_TYPE ) {
return isTemplateRemovable( post ) && post.is_custom;
return (
isTemplateRemovable( post ) &&
post.is_custom &&
post.permissions?.update
);
}
// Make necessary checks for template parts and patterns.
const isTemplatePart = post.type === TEMPLATE_PART_POST_TYPE;
Expand All @@ -555,7 +518,7 @@ const renamePostAction = {
isUserPattern ||
( isTemplatePart && post.source === TEMPLATE_ORIGINS.custom );
const hasThemeFile = post?.has_theme_file;
return isCustomPattern && ! hasThemeFile;
return isCustomPattern && ! hasThemeFile && post.permissions?.update;
},
RenderModal: ( { items, closeModal, onActionPerformed } ) => {
const [ item ] = items;
Expand Down Expand Up @@ -626,14 +589,6 @@ const renamePostAction = {
},
};

function useRenamePostAction( postType ) {
return useCanUserEligibilityCheckPostType(
'update',
postType,
renamePostAction
);
}

function ReorderModal( { items, closeModal, onActionPerformed } ) {
const [ item ] = items;
const { editEntityRecord, saveEditedEntityRecord } =
Expand Down Expand Up @@ -999,11 +954,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) {
);

const duplicatePostAction = useDuplicatePostAction( postType );
const trashPostActionForPostType = useTrashPostAction( postType );
const permanentlyDeletePostActionForPostType =
usePermanentlyDeletePostAction( postType );
const renamePostActionForPostType = useRenamePostAction( postType );
const restorePostActionForPostType = useRestorePostAction( postType );
const reorderPagesAction = useReorderPagesAction( postType );
const isTemplateOrTemplatePart = [
TEMPLATE_POST_TYPE,
Expand All @@ -1030,14 +980,13 @@ export function usePostActions( { postType, onActionPerformed, context } ) {
userCanCreatePostType &&
duplicateTemplatePartAction,
isPattern && userCanCreatePostType && duplicatePatternAction,
supportsTitle && renamePostActionForPostType,
supportsTitle && renamePostAction,
reorderPagesAction,
! isTemplateOrTemplatePart && restorePostActionForPostType,
! isTemplateOrTemplatePart && ! isPattern && restorePostAction,
! isTemplateOrTemplatePart && ! isPattern && trashPostAction,
! isTemplateOrTemplatePart &&
! isPattern &&
trashPostActionForPostType,
! isTemplateOrTemplatePart &&
permanentlyDeletePostActionForPostType,
permanentlyDeletePostAction,
...defaultActions,
].filter( Boolean );
// Filter actions based on provided context. If not provided
Expand Down Expand Up @@ -1112,10 +1061,6 @@ export function usePostActions( { postType, onActionPerformed, context } ) {
postTypeObject?.viewable,
duplicatePostAction,
reorderPagesAction,
trashPostActionForPostType,
restorePostActionForPostType,
renamePostActionForPostType,
permanentlyDeletePostActionForPostType,
onActionPerformed,
isLoaded,
supportsRevisions,
Expand Down
Loading

0 comments on commit bb71e27

Please sign in to comment.