Skip to content

Commit

Permalink
Disable selection checkbox if no bulk actions are eligible (#58950)
Browse files Browse the repository at this point in the history
Co-authored-by: jorgefilipecosta <jorgefilipecosta@git.wordpress.org>
Co-authored-by: jameskoster <jameskoster@git.wordpress.org>
Co-authored-by: getdave <get_dave@git.wordpress.org>
Co-authored-by: jeryj <jeryj@git.wordpress.org>
Co-authored-by: andrewhayward <andrewhayward@git.wordpress.org>
Co-authored-by: annezazu <annezazu@git.wordpress.org>
Co-authored-by: liviopv <liviopv@git.wordpress.org>
  • Loading branch information
8 people committed Feb 23, 2024
1 parent ca96667 commit 0b8c3ad
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 91 deletions.
10 changes: 10 additions & 0 deletions packages/base-styles/_mixins.scss
Expand Up @@ -297,6 +297,16 @@
}
}
}

&[aria-disabled="true"],
&:disabled {
background: $gray-100;
border-color: $gray-300;
cursor: default;

// Override style inherited from wp-admin. Required to avoid degraded appearance on different backgrounds.
opacity: 1;
}
}

@mixin radio-control {
Expand Down
58 changes: 54 additions & 4 deletions packages/dataviews/src/bulk-actions.js
Expand Up @@ -7,7 +7,7 @@ import {
Modal,
} from '@wordpress/components';
import { __, sprintf, _n } from '@wordpress/i18n';
import { useMemo, useState, useCallback } from '@wordpress/element';
import { useMemo, useState, useCallback, useEffect } from '@wordpress/element';

/**
* Internal dependencies
Expand All @@ -21,6 +21,24 @@ const {
DropdownMenuSeparatorV2: DropdownMenuSeparator,
} = unlock( componentsPrivateApis );

export function useHasAPossibleBulkAction( actions, item ) {
return useMemo( () => {
return actions.some( ( action ) => {
return action.supportsBulk && action.isEligible( item );
} );
}, [ actions, item ] );
}

export function useSomeItemHasAPossibleBulkAction( actions, data ) {
return useMemo( () => {
return data.some( ( item ) => {
return actions.some( ( action ) => {
return action.supportsBulk && action.isEligible( item );
} );
} );
}, [ actions, data ] );
}

function ActionWithModal( {
action,
selectedItems,
Expand Down Expand Up @@ -107,15 +125,47 @@ export default function BulkActions( {
() => actions.filter( ( action ) => action.supportsBulk ),
[ actions ]
);
const areAllSelected = selection && selection.length === data.length;
const [ isMenuOpen, onMenuOpenChange ] = useState( false );
const [ actionWithModal, setActionWithModal ] = useState();
const selectableItems = useMemo( () => {
return data.filter( ( item ) => {
return bulkActions.some( ( action ) => action.isEligible( item ) );
} );
}, [ data, bulkActions ] );

const numberSelectableItems = selectableItems.length;
const areAllSelected =
selection && selection.length === numberSelectableItems;

const selectedItems = useMemo( () => {
return data.filter( ( item ) =>
selection.includes( getItemId( item ) )
);
}, [ selection, data, getItemId ] );

const hasNonSelectableItemSelected = useMemo( () => {
return selectedItems.some( ( item ) => {
return ! selectableItems.includes( item );
} );
}, [ selectedItems, selectableItems ] );
useEffect( () => {
if ( hasNonSelectableItemSelected ) {
onSelectionChange(
selectedItems.filter( ( selectedItem ) => {
return selectableItems.some( ( item ) => {
return getItemId( selectedItem ) === getItemId( item );
} );
} )
);
}
}, [
hasNonSelectableItemSelected,
selectedItems,
selectableItems,
getItemId,
onSelectionChange,
] );

if ( bulkActions.length === 0 ) {
return null;
}
Expand Down Expand Up @@ -157,9 +207,9 @@ export default function BulkActions( {
disabled={ areAllSelected }
hideOnClick={ false }
onClick={ () => {
onSelectionChange( data );
onSelectionChange( selectableItems );
} }
suffix={ data.length }
suffix={ numberSelectableItems }
>
{ __( 'Select all' ) }
</DropdownMenuItem>
Expand Down
34 changes: 25 additions & 9 deletions packages/dataviews/src/dataviews.js
Expand Up @@ -20,6 +20,16 @@ import BulkActions from './bulk-actions';
const defaultGetItemId = ( item ) => item.id;
const defaultOnSelectionChange = () => {};

function useSomeItemHasAPossibleBulkAction( actions, data ) {
return useMemo( () => {
return data.some( ( item ) => {
return actions.some( ( action ) => {
return action.supportsBulk && action.isEligible( item );
} );
} );
}, [ actions, data ] );
}

export default function DataViews( {
view,
onChangeView,
Expand Down Expand Up @@ -75,6 +85,11 @@ export default function DataViews( {
render: field.render || field.getValue,
} ) );
}, [ fields ] );

const hasPossibleBulkAction = useSomeItemHasAPossibleBulkAction(
actions,
data
);
return (
<div className="dataviews-wrapper">
<VStack spacing={ 3 } justify="flex-start">
Expand Down Expand Up @@ -103,15 +118,16 @@ export default function DataViews( {
setOpenedFilter={ setOpenedFilter }
/>
</HStack>
{ [ LAYOUT_TABLE, LAYOUT_GRID ].includes( view.type ) && (
<BulkActions
actions={ actions }
data={ data }
onSelectionChange={ onSetSelection }
selection={ selection }
getItemId={ getItemId }
/>
) }
{ [ LAYOUT_TABLE, LAYOUT_GRID ].includes( view.type ) &&
hasPossibleBulkAction && (
<BulkActions
actions={ actions }
data={ data }
onSelectionChange={ onSetSelection }
selection={ selection }
getItemId={ getItemId }
/>
) }
<ViewActions
fields={ _fields }
view={ view }
Expand Down
2 changes: 2 additions & 0 deletions packages/dataviews/src/single-selection-checkbox.js
Expand Up @@ -11,6 +11,7 @@ export default function SingleSelectionCheckbox( {
data,
getItemId,
primaryField,
disabled,
} ) {
const id = getItemId( item );
const isSelected = selection.includes( id );
Expand All @@ -33,6 +34,7 @@ export default function SingleSelectionCheckbox( {
__nextHasNoMarginBottom
checked={ isSelected }
label={ selectionLabel }
disabled={ disabled }
onChange={ () => {
if ( ! isSelected ) {
onSelectionChange(
Expand Down
2 changes: 1 addition & 1 deletion packages/dataviews/src/style.scss
Expand Up @@ -119,7 +119,7 @@
background-color: #f8f8f8;
}

.components-checkbox-control__input {
.components-checkbox-control__input.components-checkbox-control__input {
opacity: 0;

&:checked,
Expand Down
8 changes: 6 additions & 2 deletions packages/dataviews/src/view-grid.js
Expand Up @@ -22,6 +22,8 @@ import { useState } from '@wordpress/element';
import ItemActions from './item-actions';
import SingleSelectionCheckbox from './single-selection-checkbox';

import { useHasAPossibleBulkAction } from './bulk-actions';

function GridItem( {
selection,
data,
Expand All @@ -34,18 +36,19 @@ function GridItem( {
visibleFields,
} ) {
const [ hasNoPointerEvents, setHasNoPointerEvents ] = useState( false );
const hasBulkAction = useHasAPossibleBulkAction( actions, item );
const id = getItemId( item );
const isSelected = selection.includes( id );
return (
<VStack
spacing={ 0 }
key={ id }
className={ classnames( 'dataviews-view-grid__card', {
'is-selected': isSelected,
'is-selected': hasBulkAction && isSelected,
'has-no-pointer-events': hasNoPointerEvents,
} ) }
onMouseDown={ ( event ) => {
if ( event.ctrlKey || event.metaKey ) {
if ( hasBulkAction && ( event.ctrlKey || event.metaKey ) ) {
setHasNoPointerEvents( true );
if ( ! isSelected ) {
onSelectionChange(
Expand Down Expand Up @@ -91,6 +94,7 @@ function GridItem( {
getItemId={ getItemId }
data={ data }
primaryField={ primaryField }
disabled={ ! hasBulkAction }
/>
<HStack className="dataviews-view-grid__primary-field">
{ primaryField?.render( { item } ) }
Expand Down

0 comments on commit 0b8c3ad

Please sign in to comment.