From 9ae9ec35ff68f3426d3a75e3c543d80c1f16c3e2 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Mon, 9 Dec 2024 16:39:08 +0100 Subject: [PATCH] DataViews: Fix filters lost when switching layouts (#67740) Co-authored-by: youknowriad Co-authored-by: ntsekouras --- .../src/components/post-list/index.js | 90 ++++++++++--------- test/e2e/specs/site-editor/page-list.spec.js | 56 ++++++++++++ 2 files changed, 104 insertions(+), 42 deletions(-) create mode 100644 test/e2e/specs/site-editor/page-list.spec.js diff --git a/packages/edit-site/src/components/post-list/index.js b/packages/edit-site/src/components/post-list/index.js index 145a5e8243ac54..a67a505795b3c8 100644 --- a/packages/edit-site/src/components/post-list/index.js +++ b/packages/edit-site/src/components/post-list/index.js @@ -13,7 +13,7 @@ import { DataViews, filterSortAndPaginate } from '@wordpress/dataviews'; import { privateApis as editorPrivateApis } from '@wordpress/editor'; import { __ } from '@wordpress/i18n'; import { drawerRight } from '@wordpress/icons'; -import { usePrevious } from '@wordpress/compose'; +import { useEvent, usePrevious } from '@wordpress/compose'; import { addQueryArgs } from '@wordpress/url'; /** @@ -112,53 +112,50 @@ function useView( postType ) { }; } ); - const setViewWithUrlUpdate = useCallback( - ( newView ) => { - if ( newView.type === LAYOUT_LIST && ! layout ) { - // Skip updating the layout URL param if - // it is not present and the newView.type is LAYOUT_LIST. - } else if ( newView.type !== layout ) { - history.navigate( - addQueryArgs( path, { - layout: newView.type, - } ) - ); - } + const setViewWithUrlUpdate = useEvent( ( newView ) => { + setView( newView ); - setView( newView ); + if ( isCustom === 'true' && editedEntityRecord?.id ) { + editEntityRecord( + 'postType', + 'wp_dataviews', + editedEntityRecord?.id, + { + content: JSON.stringify( newView ), + } + ); + } - if ( isCustom === 'true' && editedEntityRecord?.id ) { - editEntityRecord( - 'postType', - 'wp_dataviews', - editedEntityRecord?.id, - { - content: JSON.stringify( newView ), - } - ); - } - }, - [ - history, - isCustom, - editEntityRecord, - editedEntityRecord?.id, - layout, - path, - ] - ); + const currentUrlLayout = layout ?? LAYOUT_LIST; + if ( newView.type !== currentUrlLayout ) { + history.navigate( + addQueryArgs( path, { + layout: newView.type, + } ) + ); + } + } ); // When layout URL param changes, update the view type // without affecting any other config. + const onUrlLayoutChange = useEvent( () => { + setView( ( prevView ) => { + const layoutToApply = layout ?? LAYOUT_LIST; + if ( layoutToApply === prevView.type ) { + return prevView; + } + return { + ...prevView, + type: layout ?? LAYOUT_LIST, + }; + } ); + } ); useEffect( () => { - setView( ( prevView ) => ( { - ...prevView, - type: layout ?? LAYOUT_LIST, - } ) ); - }, [ layout ] ); + onUrlLayoutChange(); + }, [ onUrlLayoutChange, layout ] ); // When activeView or isCustom URL parameters change, reset the view. - useEffect( () => { + const onUrlActiveViewChange = useEvent( () => { let newView; if ( isCustom === 'true' ) { newView = getCustomView( editedEntityRecord ); @@ -173,9 +170,18 @@ function useView( postType ) { type, } ); } - }, [ activeView, isCustom, layout, defaultViews, editedEntityRecord ] ); + } ); + useEffect( () => { + onUrlActiveViewChange(); + }, [ + onUrlActiveViewChange, + activeView, + isCustom, + defaultViews, + editedEntityRecord, + ] ); - return [ view, setViewWithUrlUpdate, setViewWithUrlUpdate ]; + return [ view, setViewWithUrlUpdate ]; } const DEFAULT_STATUSES = 'draft,future,pending,private,publish'; // All but 'trash'. diff --git a/test/e2e/specs/site-editor/page-list.spec.js b/test/e2e/specs/site-editor/page-list.spec.js new file mode 100644 index 00000000000000..fa9cb86cd1d62e --- /dev/null +++ b/test/e2e/specs/site-editor/page-list.spec.js @@ -0,0 +1,56 @@ +/** + * WordPress dependencies + */ +const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); + +test.describe( 'Page List', () => { + test.beforeAll( async ( { requestUtils } ) => { + // Activate a theme with permissions to access the site editor. + await requestUtils.activateTheme( 'emptytheme' ); + await requestUtils.createPage( { + title: 'Privacy Policy', + status: 'publish', + } ); + await requestUtils.createPage( { + title: 'Sample Page', + status: 'publish', + } ); + } ); + + test.afterAll( async ( { requestUtils } ) => { + // Go back to the default theme. + await Promise.all( [ + requestUtils.activateTheme( 'twentytwentyone' ), + requestUtils.deleteAllPages(), + ] ); + } ); + + test.beforeEach( async ( { admin, page } ) => { + // Go to the pages page, as it has the list layout enabled by default. + await admin.visitSiteEditor(); + await page.getByRole( 'button', { name: 'Pages' } ).click(); + } ); + + test( 'Persists filter/search when switching layout', async ( { + page, + } ) => { + // Search pages + await page + .getByRole( 'searchbox', { name: 'Search' } ) + .fill( 'Privacy' ); + + // Switch layout + await page.getByRole( 'button', { name: 'Layout' } ).click(); + await page.getByRole( 'menuitemradio', { name: 'Table' } ).click(); + + // Confirm the table is visible + await expect( page.getByRole( 'table' ) ).toContainText( + 'Privacy Policy' + ); + + // The search should still contain the search term + await expect( + page.getByRole( 'searchbox', { name: 'Search' } ) + ).toHaveValue( 'Privacy' ); + } ); +} );