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

Disable selection checkbox if no bulk actions are eligible #58950

10 changes: 10 additions & 0 deletions packages/base-styles/_mixins.scss
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Loading
Loading