diff --git a/packages/dataviews/src/index.js b/packages/dataviews/src/index.js index 01c67b34c5c99..7b0a5d35abf92 100644 --- a/packages/dataviews/src/index.js +++ b/packages/dataviews/src/index.js @@ -1,2 +1,3 @@ export { default as DataViews } from './dataviews'; +export { sortByTextFields, getPaginationResults } from './utils'; export { VIEW_LAYOUTS } from './constants'; diff --git a/packages/dataviews/src/utils.js b/packages/dataviews/src/utils.js new file mode 100644 index 0000000000000..2aa454b272c80 --- /dev/null +++ b/packages/dataviews/src/utils.js @@ -0,0 +1,51 @@ +/** + * Helper util to sort data by text fields, when sorting is done client side. + * + * @param {Object} params Function params. + * @param {Object[]} params.data Data to sort. + * @param {Object} params.view Current view object. + * @param {Object[]} params.fields Array of available fields. + * @param {string[]} params.textFields Array of the field ids to sort. + * + * @return {Object[]} Sorted data. + */ +export const sortByTextFields = ( { data, view, fields, textFields } ) => { + const sortedData = [ ...data ]; + const fieldId = view.sort.field; + if ( textFields.includes( fieldId ) ) { + const fieldToSort = fields.find( ( field ) => { + return field.id === fieldId; + } ); + sortedData.sort( ( a, b ) => { + const valueA = fieldToSort.getValue( { item: a } ) ?? ''; + const valueB = fieldToSort.getValue( { item: b } ) ?? ''; + return view.sort.direction === 'asc' + ? valueA.localeCompare( valueB ) + : valueB.localeCompare( valueA ); + } ); + } + return sortedData; +}; + +/** + * Helper util to get the paginated data and the paginateInfo needed, + * when pagination is done client side. + * + * @param {Object} params Function params. + * @param {Object[]} params.data Available data. + * @param {Object} params.view Current view object. + * + * @return {Object} Paginated data and paginationInfo. + */ +export function getPaginationResults( { data, view } ) { + const start = ( view.page - 1 ) * view.perPage; + const totalItems = data?.length || 0; + data = data?.slice( start, start + view.perPage ); + return { + data, + paginationInfo: { + totalItems, + totalPages: Math.ceil( totalItems / view.perPage ), + }, + }; +} diff --git a/packages/edit-site/src/components/page-patterns/dataviews-patterns.js b/packages/edit-site/src/components/page-patterns/dataviews-patterns.js index 380f9982d0cae..0a7c9f204091b 100644 --- a/packages/edit-site/src/components/page-patterns/dataviews-patterns.js +++ b/packages/edit-site/src/components/page-patterns/dataviews-patterns.js @@ -10,12 +10,22 @@ import { } from '@wordpress/components'; import { getQueryArgs } from '@wordpress/url'; import { __ } from '@wordpress/i18n'; -import { useState, useMemo, useCallback, useId } from '@wordpress/element'; +import { + useState, + useMemo, + useCallback, + useId, + useEffect, +} from '@wordpress/element'; import { BlockPreview, privateApis as blockEditorPrivateApis, } from '@wordpress/block-editor'; -import { DataViews } from '@wordpress/dataviews'; +import { + DataViews, + sortByTextFields, + getPaginationResults, +} from '@wordpress/dataviews'; import { Icon, header, @@ -24,6 +34,7 @@ import { symbol, lockSmall, } from '@wordpress/icons'; +import { usePrevious } from '@wordpress/compose'; /** * Internal dependencies @@ -192,6 +203,7 @@ export default function DataviewsPatterns() { const [ view, setView ] = useState( DEFAULT_VIEW ); const isUncategorizedThemePatterns = type === PATTERN_TYPES.theme && categoryId === 'uncategorized'; + const previousCategoryId = usePrevious( categoryId ); const { patterns, isResolving } = usePatterns( type, isUncategorizedThemePatterns ? '' : categoryId, @@ -229,7 +241,12 @@ export default function DataviewsPatterns() { ], [ view.type, categoryId ] ); - + // Reset the page number when the category changes. + useEffect( () => { + if ( previousCategoryId !== categoryId ) { + setView( DEFAULT_VIEW ); + } + }, [ categoryId, previousCategoryId ] ); const { data, paginationInfo } = useMemo( () => { if ( ! patterns ) { return { @@ -240,32 +257,18 @@ export default function DataviewsPatterns() { let filteredData = [ ...patterns ]; // Handle sorting. if ( view.sort ) { - const stringSortingFields = [ 'title' ]; - const fieldId = view.sort.field; - if ( stringSortingFields.includes( fieldId ) ) { - const fieldToSort = fields.find( ( field ) => { - return field.id === fieldId; - } ); - filteredData.sort( ( a, b ) => { - const valueA = fieldToSort.getValue( { item: a } ) ?? ''; - const valueB = fieldToSort.getValue( { item: b } ) ?? ''; - return view.sort.direction === 'asc' - ? valueA.localeCompare( valueB ) - : valueB.localeCompare( valueA ); - } ); - } + filteredData = sortByTextFields( { + data: filteredData, + view, + fields, + textFields: [ 'title', 'author' ], + } ); } // Handle pagination. - const start = ( view.page - 1 ) * view.perPage; - const totalItems = filteredData?.length || 0; - filteredData = filteredData?.slice( start, start + view.perPage ); - return { + return getPaginationResults( { data: filteredData, - paginationInfo: { - totalItems, - totalPages: Math.ceil( totalItems / view.perPage ), - }, - }; + view, + } ); }, [ patterns, view, fields ] ); const actions = useMemo( diff --git a/packages/edit-site/src/components/page-templates/index.js b/packages/edit-site/src/components/page-templates/index.js index d8631fd5734ed..1aaf1e153d0c5 100644 --- a/packages/edit-site/src/components/page-templates/index.js +++ b/packages/edit-site/src/components/page-templates/index.js @@ -24,7 +24,11 @@ import { BlockPreview, privateApis as blockEditorPrivateApis, } from '@wordpress/block-editor'; -import { DataViews } from '@wordpress/dataviews'; +import { + DataViews, + sortByTextFields, + getPaginationResults, +} from '@wordpress/dataviews'; import { privateApis as routerPrivateApis } from '@wordpress/router'; /** @@ -252,10 +256,10 @@ export default function DataviewsTemplates() { [ authors, view.type ] ); - const { shownTemplates, paginationInfo } = useMemo( () => { + const { data, paginationInfo } = useMemo( () => { if ( ! allTemplates ) { return { - shownTemplates: EMPTY_ARRAY, + data: EMPTY_ARRAY, paginationInfo: { totalItems: 0, totalPages: 0 }, }; } @@ -301,36 +305,18 @@ export default function DataviewsTemplates() { // Handle sorting. if ( view.sort ) { - const stringSortingFields = [ 'title', 'author' ]; - const fieldId = view.sort.field; - if ( stringSortingFields.includes( fieldId ) ) { - const fieldToSort = fields.find( ( field ) => { - return field.id === fieldId; - } ); - filteredTemplates.sort( ( a, b ) => { - const valueA = fieldToSort.getValue( { item: a } ) ?? ''; - const valueB = fieldToSort.getValue( { item: b } ) ?? ''; - return view.sort.direction === 'asc' - ? valueA.localeCompare( valueB ) - : valueB.localeCompare( valueA ); - } ); - } + filteredTemplates = sortByTextFields( { + data: filteredTemplates, + view, + fields, + textFields: [ 'title' ], + } ); } - // Handle pagination. - const start = ( view.page - 1 ) * view.perPage; - const totalItems = filteredTemplates?.length || 0; - filteredTemplates = filteredTemplates?.slice( - start, - start + view.perPage - ); - return { - shownTemplates: filteredTemplates, - paginationInfo: { - totalItems, - totalPages: Math.ceil( totalItems / view.perPage ), - }, - }; + return getPaginationResults( { + data: filteredTemplates, + view, + } ); }, [ allTemplates, view, fields ] ); const resetTemplateAction = useResetTemplateAction(); @@ -381,7 +367,7 @@ export default function DataviewsTemplates() { paginationInfo={ paginationInfo } fields={ fields } actions={ actions } - data={ shownTemplates } + data={ data } isLoading={ isLoadingData } view={ view } onChangeView={ onChangeView }