From acbb3b816279b4467d929229d09206e275d1e48d Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Tue, 23 Jan 2024 18:31:13 +0000 Subject: [PATCH 1/6] Add: Selection and bulk actions to grid view. --- packages/dataviews/src/dataviews.js | 5 +- packages/dataviews/src/style.scss | 4 + packages/dataviews/src/view-grid.js | 136 ++++++++++++++++++---------- 3 files changed, 94 insertions(+), 51 deletions(-) diff --git a/packages/dataviews/src/dataviews.js b/packages/dataviews/src/dataviews.js index 64a70d46c7d12..272676e649155 100644 --- a/packages/dataviews/src/dataviews.js +++ b/packages/dataviews/src/dataviews.js @@ -14,7 +14,7 @@ import Pagination from './pagination'; import ViewActions from './view-actions'; import Filters from './filters'; import Search from './search'; -import { VIEW_LAYOUTS, LAYOUT_TABLE } from './constants'; +import { VIEW_LAYOUTS, LAYOUT_TABLE, LAYOUT_GRID } from './constants'; import BulkActions from './bulk-actions'; const defaultGetItemId = ( item ) => item.id; @@ -93,7 +93,8 @@ export default function DataViews( { onChangeView={ onChangeView } /> - { view.type === LAYOUT_TABLE && ( + { ( view.type === LAYOUT_TABLE || + view.type === LAYOUT_GRID ) && ( field.id === view.layout.mediaField @@ -44,59 +51,90 @@ export default function ViewGrid( { alignment="top" className="dataviews-view-grid" > - { usedData.map( ( item ) => ( - -
- { mediaField?.render( { item } ) } -
- - - { primaryField?.render( { item } ) } - - - + { usedData.map( ( item ) => { + const id = getItemId( item ); + const isSelected = selection.includes( getItemId( item ) ); + return ( - { visibleFields.map( ( field ) => { - const renderedValue = field.render( { - item, - } ); - if ( ! renderedValue ) { - return null; + spacing={ 0 } + key={ id } + className={ classnames( 'dataviews-view-grid__card', { + 'is-selected': isSelected, + } ) } + onClick={ ( event ) => { + if ( event.ctrlKey || event.metaKey ) { + if ( ! isSelected ) { + onSelectionChange( + data.filter( ( _item ) => { + const itemId = getItemId?.( _item ); + return ( + itemId === id || + selection.includes( itemId ) + ); + } ) + ); + } else { + onSelectionChange( + data.filter( ( _item ) => { + const itemId = getItemId?.( _item ); + return ( + itemId !== id && + selection.includes( itemId ) + ); + } ) + ); + } } - return ( - - +
+ { mediaField?.render( { item } ) } +
+ + + { primaryField?.render( { item } ) } + + + + + { visibleFields.map( ( field ) => { + const renderedValue = field.render( { + item, + } ); + if ( ! renderedValue ) { + return null; + } + return ( + -
- { renderedValue } -
-
-
- ); - } ) } + +
+ { renderedValue } +
+
+
+ ); + } ) } +
- - ) ) } + ); + } ) } ); } From c5434185076f592365ca7d84ceeb157218003ea7 Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Tue, 30 Jan 2024 19:41:46 +0000 Subject: [PATCH 2/6] updates --- .../src/single-selection-checkbox.js | 59 ++++++ packages/dataviews/src/style.scss | 12 +- packages/dataviews/src/view-grid.js | 196 +++++++++++------- 3 files changed, 183 insertions(+), 84 deletions(-) create mode 100644 packages/dataviews/src/single-selection-checkbox.js diff --git a/packages/dataviews/src/single-selection-checkbox.js b/packages/dataviews/src/single-selection-checkbox.js new file mode 100644 index 0000000000000..0aa27824c4f9b --- /dev/null +++ b/packages/dataviews/src/single-selection-checkbox.js @@ -0,0 +1,59 @@ +/** + * WordPress dependencies + */ +import { __, sprintf } from '@wordpress/i18n'; +import { CheckboxControl } from '@wordpress/components'; + +export default function SingleSelectionCheckbox( { + selection, + onSelectionChange, + item, + data, + getItemId, + primaryField, +} ) { + const id = getItemId( item ); + const isSelected = selection.includes( id ); + let selectionLabel; + if ( primaryField?.getValue && item ) { + // eslint-disable-next-line @wordpress/valid-sprintf + selectionLabel = sprintf( + /* translators: %s: item title. */ + isSelected ? __( 'Deselect item: %s' ) : __( 'Select item: %s' ), + primaryField.getValue( { item } ) + ); + } else { + selectionLabel = isSelected + ? __( 'Select a new item' ) + : __( 'Deselect item' ); + } + return ( + { + if ( ! isSelected ) { + onSelectionChange( + data.filter( ( _item ) => { + const itemId = getItemId?.( _item ); + return ( + itemId === id || selection.includes( itemId ) + ); + } ) + ); + } else { + onSelectionChange( + data.filter( ( _item ) => { + const itemId = getItemId?.( _item ); + return ( + itemId !== id && selection.includes( itemId ) + ); + } ) + ); + } + } } + /> + ); +} diff --git a/packages/dataviews/src/style.scss b/packages/dataviews/src/style.scss index a28c38976a723..483a194400647 100644 --- a/packages/dataviews/src/style.scss +++ b/packages/dataviews/src/style.scss @@ -301,10 +301,6 @@ } } - .dataviews-view-grid__primary-field { - padding: $grid-unit-10; - } - .dataviews-view-grid__fields { position: relative; font-size: 12px; @@ -499,3 +495,11 @@ .dataviews-bulk-edit-button.components-button { flex-shrink: 0; } + +.dataviews-view-grid__title-actions .dataviews-view-table-selection-checkbox { + margin-left: $grid-unit-10; +} + +.dataviews-view-grid__card.has-no-pointer-events * { + pointer-events: none; +} \ No newline at end of file diff --git a/packages/dataviews/src/view-grid.js b/packages/dataviews/src/view-grid.js index e8a14382562da..14024163878d1 100644 --- a/packages/dataviews/src/view-grid.js +++ b/packages/dataviews/src/view-grid.js @@ -13,11 +13,115 @@ import { Tooltip, } from '@wordpress/components'; import { useAsyncList } from '@wordpress/compose'; +import { useState } from '@wordpress/element'; /** * Internal dependencies */ import ItemActions from './item-actions'; +import SingleSelectionCheckbox from './single-selection-checkbox'; + +function GridItem( { + selection, + data, + onSelectionChange, + getItemId, + item, + actions, + mediaField, + primaryField, + visibleFields, +} ) { + const [ hasNoPointerEvents, setHasNoPointerEvents ] = useState( false ); + const id = getItemId( item ); + const isSelected = selection.includes( id ); + return ( + { + if ( event.ctrlKey || event.metaKey ) { + setHasNoPointerEvents( true ); + if ( ! isSelected ) { + onSelectionChange( + data.filter( ( _item ) => { + const itemId = getItemId?.( _item ); + return ( + itemId === id || + selection.includes( itemId ) + ); + } ) + ); + } else { + onSelectionChange( + data.filter( ( _item ) => { + const itemId = getItemId?.( _item ); + return ( + itemId !== id && + selection.includes( itemId ) + ); + } ) + ); + } + } + } } + onClick={ () => { + if ( hasNoPointerEvents ) { + setHasNoPointerEvents( false ); + } + } } + > +
+ { mediaField?.render( { item } ) } +
+ + + + { primaryField?.render( { item } ) } + + + + + { visibleFields.map( ( field ) => { + const renderedValue = field.render( { + item, + } ); + if ( ! renderedValue ) { + return null; + } + return ( + + +
+ { renderedValue } +
+
+
+ ); + } ) } +
+
+ ); +} export default function ViewGrid( { data, @@ -52,87 +156,19 @@ export default function ViewGrid( { className="dataviews-view-grid" > { usedData.map( ( item ) => { - const id = getItemId( item ); - const isSelected = selection.includes( getItemId( item ) ); return ( - { - if ( event.ctrlKey || event.metaKey ) { - if ( ! isSelected ) { - onSelectionChange( - data.filter( ( _item ) => { - const itemId = getItemId?.( _item ); - return ( - itemId === id || - selection.includes( itemId ) - ); - } ) - ); - } else { - onSelectionChange( - data.filter( ( _item ) => { - const itemId = getItemId?.( _item ); - return ( - itemId !== id && - selection.includes( itemId ) - ); - } ) - ); - } - } - } } - > -
- { mediaField?.render( { item } ) } -
- - - { primaryField?.render( { item } ) } - - - - - { visibleFields.map( ( field ) => { - const renderedValue = field.render( { - item, - } ); - if ( ! renderedValue ) { - return null; - } - return ( - - -
- { renderedValue } -
-
-
- ); - } ) } -
-
+ ); } ) } From ffc183ef45523a6ccf28f94c7a3374603304759b Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Tue, 30 Jan 2024 19:55:08 +0000 Subject: [PATCH 3/6] remove duplicate code --- packages/dataviews/src/view-table.js | 57 +--------------------------- 1 file changed, 2 insertions(+), 55 deletions(-) diff --git a/packages/dataviews/src/view-table.js b/packages/dataviews/src/view-table.js index 264662c19369d..b424a30747053 100644 --- a/packages/dataviews/src/view-table.js +++ b/packages/dataviews/src/view-table.js @@ -6,7 +6,7 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { __, sprintf } from '@wordpress/i18n'; +import { __ } from '@wordpress/i18n'; import { useAsyncList } from '@wordpress/compose'; import { unseen, funnel } from '@wordpress/icons'; import { @@ -32,6 +32,7 @@ import { unlock } from './lock-unlock'; import ItemActions from './item-actions'; import { ENUMERATION_TYPE, OPERATORS, SORTING_DIRECTIONS } from './constants'; import { DropdownMenuRadioItemCustom } from './dropdown-menu-helper'; +import SingleSelectionCheckbox from './single-selection-checkbox'; const { DropdownMenuV2: DropdownMenu, @@ -327,60 +328,6 @@ function BulkSelectionCheckbox( { selection, onSelectionChange, data } ) { ); } -function SingleSelectionCheckbox( { - selection, - onSelectionChange, - item, - data, - getItemId, - primaryField, -} ) { - const id = getItemId( item ); - const isSelected = selection.includes( id ); - let selectionLabel; - if ( primaryField?.getValue && item ) { - // eslint-disable-next-line @wordpress/valid-sprintf - selectionLabel = sprintf( - /* translators: %s: item title. */ - isSelected ? __( 'Deselect item: %s' ) : __( 'Select item: %s' ), - primaryField.getValue( { item } ) - ); - } else { - selectionLabel = isSelected - ? __( 'Select a new item' ) - : __( 'Deselect item' ); - } - return ( - { - if ( ! isSelected ) { - onSelectionChange( - data.filter( ( _item ) => { - const itemId = getItemId?.( _item ); - return ( - itemId === id || selection.includes( itemId ) - ); - } ) - ); - } else { - onSelectionChange( - data.filter( ( _item ) => { - const itemId = getItemId?.( _item ); - return ( - itemId !== id && selection.includes( itemId ) - ); - } ) - ); - } - } } - /> - ); -} - function ViewTable( { view, onChangeView, From 130ff212d1ba2dd709b0b87ff7ec15f4f595d494 Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Wed, 31 Jan 2024 11:13:36 +0000 Subject: [PATCH 4/6] fix lint issue --- packages/dataviews/src/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dataviews/src/style.scss b/packages/dataviews/src/style.scss index 483a194400647..c98b6386995c7 100644 --- a/packages/dataviews/src/style.scss +++ b/packages/dataviews/src/style.scss @@ -502,4 +502,4 @@ .dataviews-view-grid__card.has-no-pointer-events * { pointer-events: none; -} \ No newline at end of file +} From cdef00684c110d18036fca7f4c6d1961f54ecf87 Mon Sep 17 00:00:00 2001 From: James Koster Date: Wed, 31 Jan 2024 16:38:05 +0000 Subject: [PATCH 5/6] Selected item styles --- packages/dataviews/src/style.scss | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/dataviews/src/style.scss b/packages/dataviews/src/style.scss index c98b6386995c7..81e2d8833d2da 100644 --- a/packages/dataviews/src/style.scss +++ b/packages/dataviews/src/style.scss @@ -281,8 +281,12 @@ min-height: $grid-unit-50; } &.is-selected { - box-shadow: 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); - background-color: #aecae1; + border-color: var(--wp-admin-theme-color); + background-color: rgba(var(--wp-admin-theme-color--rgb), 0.04); + + .dataviews-view-grid__fields .dataviews-view-grid__field .dataviews-view-grid__field-value { + color: $gray-900; + } } } From f04f7ace4c445863b4ac0755a75a90e5e34bc753 Mon Sep 17 00:00:00 2001 From: James Koster Date: Wed, 31 Jan 2024 16:44:37 +0000 Subject: [PATCH 6/6] card actions padding --- packages/dataviews/src/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dataviews/src/style.scss b/packages/dataviews/src/style.scss index 81e2d8833d2da..0d804da18e6b0 100644 --- a/packages/dataviews/src/style.scss +++ b/packages/dataviews/src/style.scss @@ -274,7 +274,7 @@ justify-content: flex-start; .dataviews-view-grid__title-actions { - padding: 0 $grid-unit-05; + padding: $grid-unit-05 $grid-unit 0 $grid-unit-05; } .dataviews-view-grid__primary-field {