From c5498777ffd34084ebb11b226df429f30a615f0e Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Fri, 13 Oct 2023 15:48:20 +0100 Subject: [PATCH 1/5] DataViews: Add Grid Layout --- .../src/components/dataviews/field-actions.js | 28 ++++++++ .../src/components/dataviews/text-filter.js | 10 ++- .../src/components/dataviews/view-grid.js | 72 ++++++++++++++++++- .../src/components/dataviews/view-list.js | 45 ++++-------- .../src/components/page-pages/index.js | 51 +++++++++---- .../src/components/page-pages/style.scss | 1 - 6 files changed, 157 insertions(+), 50 deletions(-) create mode 100644 packages/edit-site/src/components/dataviews/field-actions.js diff --git a/packages/edit-site/src/components/dataviews/field-actions.js b/packages/edit-site/src/components/dataviews/field-actions.js new file mode 100644 index 00000000000000..490faa1f6a126c --- /dev/null +++ b/packages/edit-site/src/components/dataviews/field-actions.js @@ -0,0 +1,28 @@ +/** + * WordPress dependencies + */ +import { DropdownMenu, MenuGroup, MenuItem } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { moreVertical } from '@wordpress/icons'; + +function FieldActions( { item, actions } ) { + return ( + + { () => ( + + { actions.map( ( action ) => ( + action.perform( item ) } + isDestructive={ action.isDesctructive } + > + { action.label } + + ) ) } + + ) } + + ); +} + +export default FieldActions; diff --git a/packages/edit-site/src/components/dataviews/text-filter.js b/packages/edit-site/src/components/dataviews/text-filter.js index 0b5f7b3cf6790e..33bcfe87e4f35f 100644 --- a/packages/edit-site/src/components/dataviews/text-filter.js +++ b/packages/edit-site/src/components/dataviews/text-filter.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { useEffect } from '@wordpress/element'; +import { useEffect, useRef } from '@wordpress/element'; import { SearchControl } from '@wordpress/components'; /** @@ -14,12 +14,16 @@ export default function TextFilter( { view, onChangeView } ) { const [ search, setSearch, debouncedSearch ] = useDebouncedInput( view.search ); + const onChangeViewRef = useRef( onChangeView ); useEffect( () => { - onChangeView( ( currentView ) => ( { + onChangeViewRef.current = onChangeView; + }, [ onChangeView ] ); + useEffect( () => { + onChangeViewRef.current( ( currentView ) => ( { ...currentView, search: debouncedSearch, } ) ); - }, [ debouncedSearch, onChangeView ] ); + }, [ debouncedSearch ] ); const searchLabel = __( 'Filter list' ); return ( field.id === view.layoutConfig.mediaField + ); + const visibleFields = fields.filter( + ( field ) => + ! view.hiddenFields.includes( field.id ) && + field.id !== view.layoutConfig.mediaField + ); + return ( + + { data.map( ( item, index ) => { + return ( + + + { ( mediaField && + mediaField.render( { item } ) ) || ( + + ) } + + + + + + + { visibleFields.map( ( field ) => ( +
+ { field.render + ? field.render( { item } ) + : field.accessorFn( item ) } +
+ ) ) } +
+
+ +
+
+
+ ); + } ) } +
+ ); } diff --git a/packages/edit-site/src/components/dataviews/view-list.js b/packages/edit-site/src/components/dataviews/view-list.js index c2080863622a45..4e43f532e8e482 100644 --- a/packages/edit-site/src/components/dataviews/view-list.js +++ b/packages/edit-site/src/components/dataviews/view-list.js @@ -21,16 +21,12 @@ import { check, arrowUp, arrowDown, - moreVertical, } from '@wordpress/icons'; import { Button, Icon, privateApis as componentsPrivateApis, VisuallyHidden, - DropdownMenu, - MenuGroup, - MenuItem, } from '@wordpress/components'; import { useMemo } from '@wordpress/element'; @@ -38,6 +34,7 @@ import { useMemo } from '@wordpress/element'; * Internal dependencies */ import { unlock } from '../../lock-unlock'; +import FieldActions from './field-actions'; const { DropdownMenuV2, @@ -135,38 +132,24 @@ function ViewList( { paginationInfo, } ) { const columns = useMemo( () => { - const _columns = [ ...fields ]; + const _columns = [ + ...fields.map( ( field ) => { + const column = { ...field }; + delete column.render; + column.cell = ( props ) => { + return field.render + ? field.render( { item: props.row.original } ) + : field.accessorFn( props.row.original ); + }; + return column; + } ), + ]; if ( actions?.length ) { _columns.push( { header: { __( 'Actions' ) }, id: 'actions', cell: ( props ) => { - return ( - - { () => ( - - { actions.map( ( action ) => ( - - action.perform( - props.row.original - ) - } - isDestructive={ - action.isDesctructive - } - > - { action.label } - - ) ) } - - ) } - - ); + return ; }, enableHiding: false, } ); diff --git a/packages/edit-site/src/components/page-pages/index.js b/packages/edit-site/src/components/page-pages/index.js index 4bdaca8cde2f6d..7b03bfd0e86666 100644 --- a/packages/edit-site/src/components/page-pages/index.js +++ b/packages/edit-site/src/components/page-pages/index.js @@ -8,7 +8,7 @@ import { import { __ } from '@wordpress/i18n'; import { useEntityRecords } from '@wordpress/core-data'; import { decodeEntities } from '@wordpress/html-entities'; -import { useState, useMemo } from '@wordpress/element'; +import { useState, useMemo, useCallback } from '@wordpress/element'; import { dateI18n, getDate, getSettings } from '@wordpress/date'; /** @@ -22,6 +22,12 @@ import Media from '../media'; const EMPTY_ARRAY = []; const EMPTY_OBJECT = {}; +const defaultConfigPerViewType = { + list: {}, + grid: { + mediaField: 'featured-image', + }, +}; export default function PagePages() { const [ view, setView ] = useState( { @@ -82,11 +88,11 @@ export default function PagePages() { id: 'featured-image', header: __( 'Featured Image' ), accessorFn: ( page ) => page.featured_media, - cell: ( props ) => - !! props.row.original.featured_media ? ( + render: ( { item } ) => + !! item.featured_media ? ( ) : null, @@ -96,8 +102,7 @@ export default function PagePages() { header: __( 'Title' ), id: 'title', accessorFn: ( page ) => page.title?.rendered || page.slug, - cell: ( props ) => { - const page = props.row.original; + render: ( { item: page } ) => { return ( @@ -108,8 +113,9 @@ export default function PagePages() { canvas: 'edit', } } > - { decodeEntities( props.getValue() ) || - __( '(no title)' ) } + { decodeEntities( + page.title?.rendered || page.slug + ) || __( '(no title)' ) } @@ -123,8 +129,8 @@ export default function PagePages() { header: __( 'Author' ), id: 'author', accessorFn: ( page ) => page._embedded?.author[ 0 ]?.name, - cell: ( props ) => { - const author = props.row.original._embedded?.author[ 0 ]; + render: ( { item } ) => { + const author = item._embedded?.author[ 0 ]; return ( { author.name } @@ -142,10 +148,10 @@ export default function PagePages() { { header: 'Date', id: 'date', - cell: ( props ) => { + render: ( { item } ) => { const formattedDate = dateI18n( getSettings().formats.datetimeAbbreviated, - getDate( props.row.original.date ) + getDate( item.date ) ); return ; }, @@ -157,6 +163,25 @@ export default function PagePages() { const trashPostAction = useTrashPostAction(); const actions = useMemo( () => [ trashPostAction ], [ trashPostAction ] ); + const onChangeView = useCallback( + ( viewUpdater ) => { + let updatedView = + typeof viewUpdater === 'function' + ? viewUpdater( view ) + : viewUpdater; + if ( updatedView.type !== view.type ) { + updatedView = { + ...updatedView, + layoutConfig: { + ...defaultConfigPerViewType[ updatedView.type ], + }, + }; + } + + setView( updatedView ); + }, + [ view ] + ); // TODO: we need to handle properly `data={ data || EMPTY_ARRAY }` for when `isLoading`. return ( @@ -168,7 +193,7 @@ export default function PagePages() { data={ pages || EMPTY_ARRAY } isLoading={ isLoadingPages } view={ view } - onChangeView={ setView } + onChangeView={ onChangeView } /> ); diff --git a/packages/edit-site/src/components/page-pages/style.scss b/packages/edit-site/src/components/page-pages/style.scss index 82e124b3ac4fe9..fde960ca1a72ca 100644 --- a/packages/edit-site/src/components/page-pages/style.scss +++ b/packages/edit-site/src/components/page-pages/style.scss @@ -1,4 +1,3 @@ .edit-site-page-pages__featured-image { border-radius: $radius-block-ui; - max-height: 60px; } From c3dcc2850606bf265319e471adeaf85da4fb7cec Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Mon, 16 Oct 2023 10:04:27 +0100 Subject: [PATCH 2/5] Avoid card components --- .../src/components/dataviews/style.scss | 11 +++++ .../src/components/dataviews/view-grid.js | 44 ++++++++----------- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/packages/edit-site/src/components/dataviews/style.scss b/packages/edit-site/src/components/dataviews/style.scss index 47e80782255a4a..2076d9a94e782c 100644 --- a/packages/edit-site/src/components/dataviews/style.scss +++ b/packages/edit-site/src/components/dataviews/style.scss @@ -34,3 +34,14 @@ color: $gray-700; text-wrap: nowrap; } + +.dataviews-view-grid__media { + width: 100%; + height: 200px; + + > * { + width: 100%; + height: 100%; + object-fit: cover; + } +} diff --git a/packages/edit-site/src/components/dataviews/view-grid.js b/packages/edit-site/src/components/dataviews/view-grid.js index ffbce6887b70be..f38d5352e45b5d 100644 --- a/packages/edit-site/src/components/dataviews/view-grid.js +++ b/packages/edit-site/src/components/dataviews/view-grid.js @@ -5,9 +5,6 @@ import { __experimentalGrid as Grid, __experimentalHStack as HStack, __experimentalVStack as VStack, - Card, - CardBody, - CardMedia, FlexBlock, Placeholder, } from '@wordpress/components'; @@ -30,8 +27,8 @@ export function ViewGrid( { data, fields, view, actions } ) { { data.map( ( item, index ) => { return ( - - + +
{ ( mediaField && mediaField.render( { item } ) ) || ( ) } - +
- - - - - { visibleFields.map( ( field ) => ( -
- { field.render - ? field.render( { item } ) - : field.accessorFn( item ) } -
- ) ) } -
-
- -
-
-
+ + + + { visibleFields.map( ( field ) => ( +
+ { field.render + ? field.render( { item } ) + : field.accessorFn( item ) } +
+ ) ) } +
+
+ +
+ ); } ) }
From b5f408f281b20f9be006ad1f10bf4aa5d0f93c36 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 17 Oct 2023 09:00:09 +0100 Subject: [PATCH 3/5] Rename layoutConfig to layout --- packages/edit-site/src/components/dataviews/view-grid.js | 4 ++-- packages/edit-site/src/components/page-pages/index.js | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/edit-site/src/components/dataviews/view-grid.js b/packages/edit-site/src/components/dataviews/view-grid.js index f38d5352e45b5d..dcf594761a46bf 100644 --- a/packages/edit-site/src/components/dataviews/view-grid.js +++ b/packages/edit-site/src/components/dataviews/view-grid.js @@ -16,12 +16,12 @@ import FieldActions from './field-actions'; export function ViewGrid( { data, fields, view, actions } ) { const mediaField = fields.find( - ( field ) => field.id === view.layoutConfig.mediaField + ( field ) => field.id === view.layout.mediaField ); const visibleFields = fields.filter( ( field ) => ! view.hiddenFields.includes( field.id ) && - field.id !== view.layoutConfig.mediaField + field.id !== view.layout.mediaField ); return ( diff --git a/packages/edit-site/src/components/page-pages/index.js b/packages/edit-site/src/components/page-pages/index.js index 7b03bfd0e86666..af1c5e521a9803 100644 --- a/packages/edit-site/src/components/page-pages/index.js +++ b/packages/edit-site/src/components/page-pages/index.js @@ -42,6 +42,7 @@ export default function PagePages() { // All fields are visible by default, so it's // better to keep track of the hidden ones. hiddenFields: [ 'date', 'featured-image' ], + layout: {}, } ); // Request post statuses to get the proper labels. const { records: statuses } = useEntityRecords( 'root', 'status' ); @@ -172,7 +173,7 @@ export default function PagePages() { if ( updatedView.type !== view.type ) { updatedView = { ...updatedView, - layoutConfig: { + layout: { ...defaultConfigPerViewType[ updatedView.type ], }, }; From 115cacd74fcbcbfc0a704a3e6d258460991e4430 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 17 Oct 2023 09:21:44 +0100 Subject: [PATCH 4/5] Improve image quality --- .../edit-site/src/components/dataviews/view-grid.js | 4 ++-- .../edit-site/src/components/dataviews/view-list.js | 2 +- packages/edit-site/src/components/media/index.js | 10 ++++------ packages/edit-site/src/components/page-pages/index.js | 8 ++++++-- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/edit-site/src/components/dataviews/view-grid.js b/packages/edit-site/src/components/dataviews/view-grid.js index dcf594761a46bf..70b36d29946f00 100644 --- a/packages/edit-site/src/components/dataviews/view-grid.js +++ b/packages/edit-site/src/components/dataviews/view-grid.js @@ -30,7 +30,7 @@ export function ViewGrid( { data, fields, view, actions } ) {
{ ( mediaField && - mediaField.render( { item } ) ) || ( + mediaField.render( { item, view } ) ) || ( (
{ field.render - ? field.render( { item } ) + ? field.render( { item, view } ) : field.accessorFn( item ) }
) ) } diff --git a/packages/edit-site/src/components/dataviews/view-list.js b/packages/edit-site/src/components/dataviews/view-list.js index 4e43f532e8e482..c8d4ee1efd063d 100644 --- a/packages/edit-site/src/components/dataviews/view-list.js +++ b/packages/edit-site/src/components/dataviews/view-list.js @@ -138,7 +138,7 @@ function ViewList( { delete column.render; column.cell = ( props ) => { return field.render - ? field.render( { item: props.row.original } ) + ? field.render( { item: props.row.original, view } ) : field.accessorFn( props.row.original ); }; return column; diff --git a/packages/edit-site/src/components/media/index.js b/packages/edit-site/src/components/media/index.js index 7120d7c7f56ce7..7df6c4f882842e 100644 --- a/packages/edit-site/src/components/media/index.js +++ b/packages/edit-site/src/components/media/index.js @@ -3,14 +3,12 @@ */ import { useEntityRecord } from '@wordpress/core-data'; -function Media( { id, size, ...props } ) { +function Media( { id, size = [ 'large', 'medium', 'thumbnail' ], ...props } ) { const { record: media } = useEntityRecord( 'root', 'media', id ); - const sizesPerPriority = [ 'large', 'thumbnail' ]; - const currentSize = - size ?? - sizesPerPriority.find( ( s ) => !! media?.media_details?.sizes[ s ] ); + const currentSize = size.find( + ( s ) => !! media?.media_details?.sizes[ s ] + ); const mediaDetails = media?.media_details?.sizes[ currentSize ]; - if ( ! mediaDetails ) { return null; } diff --git a/packages/edit-site/src/components/page-pages/index.js b/packages/edit-site/src/components/page-pages/index.js index af1c5e521a9803..6c70525b541aa9 100644 --- a/packages/edit-site/src/components/page-pages/index.js +++ b/packages/edit-site/src/components/page-pages/index.js @@ -89,12 +89,16 @@ export default function PagePages() { id: 'featured-image', header: __( 'Featured Image' ), accessorFn: ( page ) => page.featured_media, - render: ( { item } ) => + render: ( { item, view: currentView } ) => !! item.featured_media ? ( ) : null, enableSorting: false, From a14c48d2f0b16efa2daf885803c9cb7151fd53e3 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 17 Oct 2023 09:30:54 +0100 Subject: [PATCH 5/5] Avoid fixed heights --- packages/edit-site/src/components/dataviews/style.scss | 5 ++--- packages/edit-site/src/components/dataviews/view-grid.js | 2 +- packages/edit-site/src/components/page-pages/index.js | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/edit-site/src/components/dataviews/style.scss b/packages/edit-site/src/components/dataviews/style.scss index 2076d9a94e782c..1b27c0833c836c 100644 --- a/packages/edit-site/src/components/dataviews/style.scss +++ b/packages/edit-site/src/components/dataviews/style.scss @@ -37,11 +37,10 @@ .dataviews-view-grid__media { width: 100%; - height: 200px; + min-height: 200px; > * { - width: 100%; - height: 100%; + max-width: 100%; object-fit: cover; } } diff --git a/packages/edit-site/src/components/dataviews/view-grid.js b/packages/edit-site/src/components/dataviews/view-grid.js index 70b36d29946f00..f115b9c002a376 100644 --- a/packages/edit-site/src/components/dataviews/view-grid.js +++ b/packages/edit-site/src/components/dataviews/view-grid.js @@ -24,7 +24,7 @@ export function ViewGrid( { data, fields, view, actions } ) { field.id !== view.layout.mediaField ); return ( - + { data.map( ( item, index ) => { return ( diff --git a/packages/edit-site/src/components/page-pages/index.js b/packages/edit-site/src/components/page-pages/index.js index 6c70525b541aa9..eaf5d5ec24dadc 100644 --- a/packages/edit-site/src/components/page-pages/index.js +++ b/packages/edit-site/src/components/page-pages/index.js @@ -97,7 +97,7 @@ export default function PagePages() { size={ currentView.type === 'list' ? [ 'thumbnail', 'medium', 'large', 'full' ] - : [ 'large', 'medium', 'full', 'thumbnail' ] + : [ 'large', 'full', 'medium', 'thumbnail' ] } /> ) : null,