From 2281876e82ee270967b3460a8194bc1659a589f4 Mon Sep 17 00:00:00 2001 From: ramon Date: Wed, 11 Sep 2024 12:42:31 +1000 Subject: [PATCH 1/7] Pulling across work from https://github.com/WordPress/gutenberg/pull/62028 and using useEntityRecords to get record counts --- .../sidebar-dataviews/default-views.js | 60 ++++++++++++++++--- .../src/components/sidebar-dataviews/index.js | 1 + 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index e5db492fce17d0..4a2f0b8b69fa69 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -13,7 +13,7 @@ import { notAllowed, } from '@wordpress/icons'; import { useSelect } from '@wordpress/data'; -import { store as coreStore } from '@wordpress/core-data'; +import { store as coreStore, useEntityRecords } from '@wordpress/core-data'; import { useMemo } from '@wordpress/element'; /** @@ -24,6 +24,7 @@ import { LAYOUT_TABLE, LAYOUT_GRID, OPERATOR_IS_ANY, + OPERATOR_IS_NONE, } from '../../utils/constants'; export const defaultLayouts = { @@ -68,21 +69,58 @@ const DEFAULT_POST_BASE = { layout: defaultLayouts[ LAYOUT_LIST ].layout, }; +function useDataViewItemCounts( { postType } ) { + const { records, totalItems } = useEntityRecords( 'postType', postType, { + status: [ 'any', 'trash' ], + } ); + return useMemo( () => { + if ( ! records ) { + return {}; + } + const counts = { + all: totalItems, + drafts: records.filter( ( record ) => record.status === 'draft' ) + .length, + future: records.filter( ( record ) => record.status === 'future' ) + .length, + pending: records.filter( ( record ) => record.status === 'pending' ) + .length, + private: records.filter( ( record ) => record.status === 'private' ) + .length, + published: records.filter( + ( record ) => record.status === 'publish' + ).length, + trash: records.filter( ( record ) => record.status === 'trash' ) + .length, + }; + return counts; + }, [ records, totalItems ] ); +} + export function useDefaultViews( { postType } ) { const labels = useSelect( - ( select ) => { - const { getPostType } = select( coreStore ); - return getPostType( postType )?.labels; - }, + ( select ) => select( coreStore ).getPostType( postType )?.labels, [ postType ] ); + const counts = useDataViewItemCounts( { postType } ); + return useMemo( () => { return [ { title: labels?.all_items || __( 'All items' ), slug: 'all', icon: pages, - view: DEFAULT_POST_BASE, + view: { + ...DEFAULT_POST_BASE, + filters: [ + { + field: 'status', + operator: OPERATOR_IS_NONE, + value: 'trash', + }, + ], + }, + count: counts?.all, }, { title: __( 'Published' ), @@ -98,6 +136,7 @@ export function useDefaultViews( { postType } ) { }, ], }, + count: counts?.published, }, { title: __( 'Scheduled' ), @@ -113,6 +152,7 @@ export function useDefaultViews( { postType } ) { }, ], }, + count: counts?.future, }, { title: __( 'Drafts' ), @@ -128,6 +168,7 @@ export function useDefaultViews( { postType } ) { }, ], }, + count: counts?.drafts, }, { title: __( 'Pending' ), @@ -143,6 +184,7 @@ export function useDefaultViews( { postType } ) { }, ], }, + count: counts?.pending, }, { title: __( 'Private' ), @@ -158,6 +200,7 @@ export function useDefaultViews( { postType } ) { }, ], }, + count: counts?.private, }, { title: __( 'Trash' ), @@ -175,7 +218,8 @@ export function useDefaultViews( { postType } ) { }, ], }, + count: counts?.trash, }, - ]; - }, [ labels ] ); + ].filter( ( { count } ) => count > 0 ); + }, [ labels, counts ] ); } diff --git a/packages/edit-site/src/components/sidebar-dataviews/index.js b/packages/edit-site/src/components/sidebar-dataviews/index.js index 86420c4eec1d1f..b4f3010e3bbef3 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/index.js +++ b/packages/edit-site/src/components/sidebar-dataviews/index.js @@ -34,6 +34,7 @@ export default function DataViewsSidebarContent() { slug={ dataview.slug } title={ dataview.title } icon={ dataview.icon } + suffix={ { dataview.count } } type={ dataview.view.type } isActive={ ! isCustomBoolean && From bdda3f2b591636fc58256700dc3b836ff983101d Mon Sep 17 00:00:00 2001 From: ramon Date: Wed, 11 Sep 2024 12:48:36 +1000 Subject: [PATCH 2/7] Display empty values by default --- .../edit-site/src/components/sidebar-dataviews/default-views.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index 4a2f0b8b69fa69..9dbe790e999237 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -220,6 +220,6 @@ export function useDefaultViews( { postType } ) { }, count: counts?.trash, }, - ].filter( ( { count } ) => count > 0 ); + ]; }, [ labels, counts ] ); } From 6ef55f6b6eac0e9c31564ebd1f119b2077483247 Mon Sep 17 00:00:00 2001 From: ramon Date: Wed, 11 Sep 2024 13:14:49 +1000 Subject: [PATCH 3/7] per_page is unfortunately required as otherwise we won't get the entire page count to filter --- .../edit-site/src/components/sidebar-dataviews/default-views.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index 9dbe790e999237..0a9debe7631e4f 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -71,6 +71,7 @@ const DEFAULT_POST_BASE = { function useDataViewItemCounts( { postType } ) { const { records, totalItems } = useEntityRecords( 'postType', postType, { + per_page: -1, status: [ 'any', 'trash' ], } ); return useMemo( () => { From b68bc0c8fda1c55cecebd29fcaf91ce6b020af60 Mon Sep 17 00:00:00 2001 From: ramon Date: Thu, 12 Sep 2024 13:25:31 +1000 Subject: [PATCH 4/7] Add a `navigationItemSuffix` prop to DataViewItem so that consumers can pass a suffix to the SidebarNavigationItem component. Refactor custom count hook to include default dataviews that it doesn't affect other components Filter out empty items Reduce RHS padding --- .../sidebar-dataviews/dataview-item.js | 2 + .../sidebar-dataviews/default-views.js | 44 ++++++++----------- .../src/components/sidebar-dataviews/index.js | 10 +++-- .../components/sidebar-dataviews/style.scss | 4 ++ 4 files changed, 32 insertions(+), 28 deletions(-) diff --git a/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js b/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js index 1e12d6706d81b5..1a96fdc0591439 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js +++ b/packages/edit-site/src/components/sidebar-dataviews/dataview-item.js @@ -27,6 +27,7 @@ export default function DataViewItem( { isActive, isCustom, suffix, + navigationItemSuffix, } ) { const { params: { postType }, @@ -55,6 +56,7 @@ export default function DataViewItem( { { title } diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index 0a9debe7631e4f..842bc14376ff36 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -24,7 +24,6 @@ import { LAYOUT_TABLE, LAYOUT_GRID, OPERATOR_IS_ANY, - OPERATOR_IS_NONE, } from '../../utils/constants'; export const defaultLayouts = { @@ -69,15 +68,18 @@ const DEFAULT_POST_BASE = { layout: defaultLayouts[ LAYOUT_LIST ].layout, }; -function useDataViewItemCounts( { postType } ) { +export function useDefaultViewsWithItemCounts( { postType } ) { + const defaultViews = useDefaultViews( { postType } ); const { records, totalItems } = useEntityRecords( 'postType', postType, { per_page: -1, status: [ 'any', 'trash' ], } ); + return useMemo( () => { - if ( ! records ) { - return {}; + if ( ! records || ! defaultViews ) { + return []; } + const counts = { all: totalItems, drafts: records.filter( ( record ) => record.status === 'draft' ) @@ -94,8 +96,17 @@ function useDataViewItemCounts( { postType } ) { trash: records.filter( ( record ) => record.status === 'trash' ) .length, }; - return counts; - }, [ records, totalItems ] ); + + // Filter out views with > 0 item counts. + return defaultViews + .map( ( _view ) => { + if ( counts?.[ _view.slug ] > 0 ) { + _view.count = counts[ _view.slug ]; + } + return _view; + } ) + .filter( ( view ) => !! view.count ); + }, [ defaultViews, records, totalItems ] ); } export function useDefaultViews( { postType } ) { @@ -103,7 +114,6 @@ export function useDefaultViews( { postType } ) { ( select ) => select( coreStore ).getPostType( postType )?.labels, [ postType ] ); - const counts = useDataViewItemCounts( { postType } ); return useMemo( () => { return [ @@ -111,17 +121,7 @@ export function useDefaultViews( { postType } ) { title: labels?.all_items || __( 'All items' ), slug: 'all', icon: pages, - view: { - ...DEFAULT_POST_BASE, - filters: [ - { - field: 'status', - operator: OPERATOR_IS_NONE, - value: 'trash', - }, - ], - }, - count: counts?.all, + view: DEFAULT_POST_BASE, }, { title: __( 'Published' ), @@ -137,7 +137,6 @@ export function useDefaultViews( { postType } ) { }, ], }, - count: counts?.published, }, { title: __( 'Scheduled' ), @@ -153,7 +152,6 @@ export function useDefaultViews( { postType } ) { }, ], }, - count: counts?.future, }, { title: __( 'Drafts' ), @@ -169,7 +167,6 @@ export function useDefaultViews( { postType } ) { }, ], }, - count: counts?.drafts, }, { title: __( 'Pending' ), @@ -185,7 +182,6 @@ export function useDefaultViews( { postType } ) { }, ], }, - count: counts?.pending, }, { title: __( 'Private' ), @@ -201,7 +197,6 @@ export function useDefaultViews( { postType } ) { }, ], }, - count: counts?.private, }, { title: __( 'Trash' ), @@ -219,8 +214,7 @@ export function useDefaultViews( { postType } ) { }, ], }, - count: counts?.trash, }, ]; - }, [ labels, counts ] ); + }, [ labels ] ); } diff --git a/packages/edit-site/src/components/sidebar-dataviews/index.js b/packages/edit-site/src/components/sidebar-dataviews/index.js index b4f3010e3bbef3..3f7f5b965fce71 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/index.js +++ b/packages/edit-site/src/components/sidebar-dataviews/index.js @@ -7,7 +7,7 @@ import { privateApis as routerPrivateApis } from '@wordpress/router'; /** * Internal dependencies */ -import { useDefaultViews } from './default-views'; +import { useDefaultViewsWithItemCounts } from './default-views'; import { unlock } from '../../lock-unlock'; import DataViewItem from './dataview-item'; import CustomDataViewsList from './custom-dataviews-list'; @@ -18,7 +18,9 @@ export default function DataViewsSidebarContent() { const { params: { postType, activeView = 'all', isCustom = 'false' }, } = useLocation(); - const defaultViews = useDefaultViews( { postType } ); + + const defaultViews = useDefaultViewsWithItemCounts( { postType } ); + if ( ! postType ) { return null; } @@ -34,7 +36,9 @@ export default function DataViewsSidebarContent() { slug={ dataview.slug } title={ dataview.title } icon={ dataview.icon } - suffix={ { dataview.count } } + navigationItemSuffix={ + { dataview.count } + } type={ dataview.view.type } isActive={ ! isCustomBoolean && diff --git a/packages/edit-site/src/components/sidebar-dataviews/style.scss b/packages/edit-site/src/components/sidebar-dataviews/style.scss index 14e6bf1d03fca8..3473c8e20e1a45 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/style.scss +++ b/packages/edit-site/src/components/sidebar-dataviews/style.scss @@ -15,6 +15,10 @@ min-width: initial; } + .edit-site-sidebar-navigation-item.with-suffix { + padding-right: $grid-unit-10; + } + &:hover, &:focus, &[aria-current] { From d0df94ad48b25ab3c0663e3d6486b75f00c409b8 Mon Sep 17 00:00:00 2001 From: ramon Date: Thu, 12 Sep 2024 13:55:25 +1000 Subject: [PATCH 5/7] Roll back code refactor. Not required. --- .../src/components/sidebar-dataviews/default-views.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index 842bc14376ff36..e739c544bd0d7b 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -111,10 +111,12 @@ export function useDefaultViewsWithItemCounts( { postType } ) { export function useDefaultViews( { postType } ) { const labels = useSelect( - ( select ) => select( coreStore ).getPostType( postType )?.labels, + ( select ) => { + const { getPostType } = select( coreStore ); + return getPostType( postType )?.labels; + }, [ postType ] ); - return useMemo( () => { return [ { From 982e752bc20fed60ef8e49eeb48c4d02fc5a5698 Mon Sep 17 00:00:00 2001 From: ramon Date: Thu, 12 Sep 2024 14:03:46 +1000 Subject: [PATCH 6/7] Don't filter and return the entire list. The counts will load once the API call is done. --- .../sidebar-dataviews/default-views.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index e739c544bd0d7b..2a8c2775179d6f 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -76,10 +76,14 @@ export function useDefaultViewsWithItemCounts( { postType } ) { } ); return useMemo( () => { - if ( ! records || ! defaultViews ) { + if ( ! defaultViews ) { return []; } + if ( ! records ) { + return defaultViews; + } + const counts = { all: totalItems, drafts: records.filter( ( record ) => record.status === 'draft' ) @@ -98,14 +102,10 @@ export function useDefaultViewsWithItemCounts( { postType } ) { }; // Filter out views with > 0 item counts. - return defaultViews - .map( ( _view ) => { - if ( counts?.[ _view.slug ] > 0 ) { - _view.count = counts[ _view.slug ]; - } - return _view; - } ) - .filter( ( view ) => !! view.count ); + return defaultViews.map( ( _view ) => { + _view.count = counts[ _view.slug ]; + return _view; + } ); }, [ defaultViews, records, totalItems ] ); } From 71517b48929e0678066efe1ca8dcd3cc793dfb8d Mon Sep 17 00:00:00 2001 From: ramon Date: Fri, 13 Sep 2024 12:38:05 +1000 Subject: [PATCH 7/7] initial commit - moving controls for background image into dedicated component. Moving styles. This is in preparation for adding colors and other background controls later. --- .../src/components/sidebar-dataviews/default-views.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/sidebar-dataviews/default-views.js b/packages/edit-site/src/components/sidebar-dataviews/default-views.js index 2a8c2775179d6f..e2c988dbddbdac 100644 --- a/packages/edit-site/src/components/sidebar-dataviews/default-views.js +++ b/packages/edit-site/src/components/sidebar-dataviews/default-views.js @@ -80,12 +80,12 @@ export function useDefaultViewsWithItemCounts( { postType } ) { return []; } + // If there are no records, return the default views with no counts. if ( ! records ) { return defaultViews; } const counts = { - all: totalItems, drafts: records.filter( ( record ) => record.status === 'draft' ) .length, future: records.filter( ( record ) => record.status === 'future' ) @@ -101,6 +101,9 @@ export function useDefaultViewsWithItemCounts( { postType } ) { .length, }; + // All items excluding trashed items as per the default "all" status query. + counts.all = totalItems ? totalItems - counts.trash : 0; + // Filter out views with > 0 item counts. return defaultViews.map( ( _view ) => { _view.count = counts[ _view.slug ];