Skip to content

Commit

Permalink
partial feedback (+7 squashed commits)
Browse files Browse the repository at this point in the history
Squashed commits:
[43c3d85] Fix rebase
[cb954b6] Fix rebase
[0a3723a] add selection label functionality
[3c48c68] Add labels
[2ae6b76] Lint fixes
[77dc74c] Feedback
[d0d1456] Add: Bulk actions API and trash action.
  • Loading branch information
jorgefilipecosta committed Dec 5, 2023
1 parent 308fc42 commit 8e0ab84
Show file tree
Hide file tree
Showing 8 changed files with 336 additions and 26 deletions.
117 changes: 117 additions & 0 deletions packages/dataviews/src/bulk-actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/**
* WordPress dependencies
*/
import {
ToolbarButton,
Toolbar,
ToolbarGroup,
Popover,
} from '@wordpress/components';
import { useMemo } from '@wordpress/element';
import { __, _n, sprintf } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import { ActionWithModal } from './item-actions';

function PrimaryActionTrigger( { action, onClick } ) {
return (
<ToolbarButton
label={ action.label }
icon={ action.icon }
isDestructive={ action.isDestructive }
size="compact"
onClick={ onClick }
/>
);
}

const EMPTY_ARRAY = [];

export default function BulkActions( {
data,
selection,
actions = EMPTY_ARRAY,
setSelection,
} ) {
const items = useMemo(
() =>
data?.filter( ( item ) => selection?.includes( item.id ) ) ??
EMPTY_ARRAY,
[ data, selection ]
);
const primaryActions = useMemo(
() =>
actions.filter( ( action ) => {
return (
action.isBulk &&
action.isPrimary &&
items.every( ( item ) => action.isEligible( item ) )
);
} ),
[ actions, items ]
);

if (
( selection && selection.length === 0 ) ||
primaryActions.length === 0
) {
return null;
}

return (
<Popover
placement="top-middle"
className="dataviews-bulk-actions-popover"
>
<Toolbar label="Bulk actions">
<div className="dataviews-bulk-actions-toolbar-wrapper">
<ToolbarGroup>
<ToolbarButton onClick={ () => {} } disabled={ true }>
{
// translators: %s: Total number of selected items.
sprintf(
// translators: %s: Total number of selected items.
_n(
'%s item selected',
'%s items selected',
selection.length
),
selection.length
)
}
</ToolbarButton>
<ToolbarButton
onClick={ () => {
setSelection( EMPTY_ARRAY );
} }
>
{ __( 'Deselect' ) }
</ToolbarButton>
</ToolbarGroup>
<ToolbarGroup>
{ primaryActions.map( ( action ) => {
if ( !! action.RenderModal ) {
return (
<ActionWithModal
key={ action.id }
action={ action }
items={ items }
ActionTrigger={ PrimaryActionTrigger }
/>
);
}
return (
<PrimaryActionTrigger
key={ action.id }
action={ action }
onClick={ () => action.callback( items ) }
/>
);
} ) }
</ToolbarGroup>
</div>
</Toolbar>
</Popover>
);
}
16 changes: 16 additions & 0 deletions packages/dataviews/src/dataviews.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import ViewActions from './view-actions';
import Filters from './filters';
import Search from './search';
import { VIEW_LAYOUTS } from './constants';
import BulkActions from './bulk-actions';

export default function DataViews( {
view,
Expand All @@ -28,6 +29,9 @@ export default function DataViews( {
isLoading = false,
paginationInfo,
supportedLayouts,
selection,
setSelection,
labels,
} ) {
const ViewComponent = VIEW_LAYOUTS.find(
( v ) => v.type === view.type
Expand Down Expand Up @@ -72,12 +76,24 @@ export default function DataViews( {
data={ data }
getItemId={ getItemId }
isLoading={ isLoading }
selection={ selection }
setSelection={ setSelection }
labels={ labels }
/>

<div>
<Pagination
view={ view }
onChangeView={ onChangeView }
paginationInfo={ paginationInfo }
/>
<BulkActions
data={ data }
actions={ actions }
selection={ selection }
setSelection={ setSelection }
/>
</div>
</VStack>
</div>
);
Expand Down
16 changes: 13 additions & 3 deletions packages/dataviews/src/item-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,18 @@ function DropdownMenuItemTrigger( { action, onClick } ) {
);
}

function ActionWithModal( { action, item, ActionTrigger } ) {
export function ActionWithModal( { action, item, items, ActionTrigger } ) {
const [ isModalOpen, setIsModalOpen ] = useState( false );
const actionTriggerProps = {
action,
onClick: () => setIsModalOpen( true ),
};
const additionalProps = {};
if ( action.isBulk ) {
additionalProps.items = items ? items : [ item ];
} else {
additionalProps.item = item;
}
const { RenderModal, hideModalHeader } = action;
return (
<>
Expand All @@ -66,7 +72,7 @@ function ActionWithModal( { action, item, ActionTrigger } ) {
overlayClassName="dataviews-action-modal"
>
<RenderModal
item={ item }
{ ...additionalProps }
closeModal={ () => setIsModalOpen( false ) }
/>
</Modal>
Expand Down Expand Up @@ -157,7 +163,11 @@ export default function ItemActions( { item, actions, isCompact } ) {
<ButtonTrigger
key={ action.id }
action={ action }
onClick={ () => action.callback( item ) }
onClick={
action.isBulk
? () => action.callback( [ item ] )
: () => action.callback( item )
}
/>
);
} ) }
Expand Down
22 changes: 22 additions & 0 deletions packages/dataviews/src/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,25 @@
.dataviews-action-modal {
z-index: z-index(".dataviews-action-modal");
}

.dataviews-bulk-actions-popover .components-popover__content {
min-width: max-content;
}

.dataviews-bulk-actions-toolbar-wrapper {
display: flex;
flex-grow: 1;
width: 100%;
}

.dataviews-table-view__selection-column label {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
87 changes: 86 additions & 1 deletion packages/dataviews/src/view-table.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
Button,
Icon,
privateApis as componentsPrivateApis,
CheckboxControl,
} from '@wordpress/components';
import { useMemo, Children, Fragment } from '@wordpress/element';

Expand Down Expand Up @@ -340,7 +341,11 @@ function ViewTable( {
getItemId,
isLoading = false,
paginationInfo,
selection,
setSelection,
labels,
} ) {
const areAllSelected = selection && selection.length === data.length;
const columns = useMemo( () => {
const _columns = fields.map( ( field ) => {
const { render, getValue, ...column } = field;
Expand All @@ -351,6 +356,70 @@ function ViewTable( {
}
return column;
} );
if ( selection !== undefined ) {
_columns.unshift( {
header: (
<CheckboxControl
__nextHasNoMarginBottom
checked={ areAllSelected }
indeterminate={ ! areAllSelected && selection.length }
onChange={ () => {
if ( areAllSelected ) {
setSelection( [] );
} else {
setSelection( data.map( ( { id } ) => id ) );
}
} }
label={
areAllSelected
? __( 'Deselect all' )
: __( 'Select all' )
}
/>
),
id: 'selection',
cell: ( props ) => {
//console.log({ props });
const item = props.row.original;
const isSelected = selection.includes( item.id );
let selectionLabel;
if ( isSelected ) {
selectionLabel = labels?.getDeselectLabel
? labels?.getDeselectLabel( item )
: __( 'Deselect item' );
} else {
selectionLabel = labels?.getSelectLabel
? labels?.getSelectLabel( item )
: __( 'Select a new item' );
}
return (
<CheckboxControl
__nextHasNoMarginBottom
checked={ isSelected }
label={ selectionLabel }
onChange={ () => {
if ( ! isSelected ) {
const newSelection = [
...selection,
item.id,
];
setSelection( newSelection );
} else {
setSelection(
selection.filter(
( id ) => id !== item.id
)
);
}
} }
/>
);
},
enableHiding: false,
width: 40,
className: 'dataviews-table-view__selection-column',
} );
}
if ( actions?.length ) {
_columns.push( {
header: __( 'Actions' ),
Expand All @@ -368,7 +437,15 @@ function ViewTable( {
}

return _columns;
}, [ fields, actions, view ] );
}, [
areAllSelected,
fields,
actions,
view,
selection,
setSelection,
data,
] );

const columnVisibility = useMemo( () => {
if ( ! view.hiddenFields?.length ) {
Expand Down Expand Up @@ -566,6 +643,10 @@ function ViewTable( {
header.column.columnDef
.maxWidth || undefined,
} }
className={
header.column.columnDef.className ||
undefined
}
data-field-id={ header.id }
>
<HeaderMenu
Expand Down Expand Up @@ -594,6 +675,10 @@ function ViewTable( {
cell.column.columnDef
.maxWidth || undefined,
} }
className={
cell.column.columnDef.className ||
undefined
}
>
{ flexRender(
cell.column.columnDef.cell,
Expand Down
Loading

0 comments on commit 8e0ab84

Please sign in to comment.