diff --git a/packages/edit-site/src/components/dataviews/dataviews.js b/packages/edit-site/src/components/dataviews/dataviews.js index a0973a82a291ca..755ce8a2ea348d 100644 --- a/packages/edit-site/src/components/dataviews/dataviews.js +++ b/packages/edit-site/src/components/dataviews/dataviews.js @@ -1,211 +1,54 @@ -/** - * External dependencies - */ -import { - getCoreRowModel, - getFilteredRowModel, - getSortedRowModel, - getPaginationRowModel, - useReactTable, -} from '@tanstack/react-table'; - /** * WordPress dependencies */ import { __experimentalVStack as VStack, __experimentalHStack as HStack, - VisuallyHidden, - DropdownMenu, - MenuGroup, - MenuItem, } from '@wordpress/components'; -import { useMemo } from '@wordpress/element'; -import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import ListView from './list-view'; -import { Pagination } from './pagination'; +import ViewList from './view-list'; +import Pagination from './pagination'; import ViewActions from './view-actions'; import TextFilter from './text-filter'; -import { moreVertical } from '@wordpress/icons'; - -const EMPTY_OBJECT = {}; +import { ViewGrid } from './view-grid'; export default function DataViews( { - actions, - data, - fields, view, onChangeView, - isLoading, + fields, + actions, + data, + isLoading = false, paginationInfo, - options: { pageCount }, } ) { - const columns = useMemo( () => { - const _columns = [ ...fields ]; - 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 } - - ) ) } - - ) } - - ); - }, - enableHiding: false, - } ); - } - - return _columns; - }, [ fields, actions ] ); - - const columnVisibility = useMemo( () => { - if ( ! view.hiddenFields?.length ) { - return; - } - return view.hiddenFields.reduce( - ( accumulator, fieldId ) => ( { - ...accumulator, - [ fieldId ]: false, - } ), - {} - ); - }, [ view.hiddenFields ] ); - - const dataView = useReactTable( { - data, - columns, - manualSorting: true, - manualFiltering: true, - manualPagination: true, - enableRowSelection: true, - state: { - sorting: view.sort - ? [ - { - id: view.sort.field, - desc: view.sort.direction === 'desc', - }, - ] - : [], - globalFilter: view.search, - pagination: { - pageIndex: view.page, - pageSize: view.perPage, - }, - columnVisibility: columnVisibility ?? EMPTY_OBJECT, - }, - onSortingChange: ( sortingUpdater ) => { - onChangeView( ( currentView ) => { - const sort = - typeof sortingUpdater === 'function' - ? sortingUpdater( - currentView.sort - ? [ - { - id: currentView.sort.field, - desc: - currentView.sort - .direction === 'desc', - }, - ] - : [] - ) - : sortingUpdater; - if ( ! sort.length ) { - return { - ...currentView, - sort: {}, - }; - } - const [ { id, desc } ] = sort; - return { - ...currentView, - sort: { field: id, direction: desc ? 'desc' : 'asc' }, - }; - } ); - }, - onColumnVisibilityChange: ( columnVisibilityUpdater ) => { - onChangeView( ( currentView ) => { - const hiddenFields = Object.entries( - columnVisibilityUpdater() - ).reduce( - ( accumulator, [ fieldId, value ] ) => { - if ( value ) { - return accumulator.filter( - ( id ) => id !== fieldId - ); - } - return [ ...accumulator, fieldId ]; - }, - [ ...( currentView.hiddenFields || [] ) ] - ); - return { - ...currentView, - hiddenFields, - }; - } ); - }, - onGlobalFilterChange: ( value ) => { - onChangeView( { ...view, search: value, page: 0 } ); - }, - onPaginationChange: ( paginationUpdater ) => { - onChangeView( ( currentView ) => { - const { pageIndex, pageSize } = paginationUpdater( { - pageIndex: currentView.page, - pageSize: currentView.perPage, - } ); - return { ...view, page: pageIndex, perPage: pageSize }; - } ); - }, - getCoreRowModel: getCoreRowModel(), - getFilteredRowModel: getFilteredRowModel(), - getSortedRowModel: getSortedRowModel(), - getPaginationRowModel: getPaginationRowModel(), - pageCount, - } ); + const ViewComponent = view.type === 'list' ? ViewList : ViewGrid; return (
- + - { /* This component will be selected based on viewConfigs. Now we only have the list view. */ } - +
diff --git a/packages/edit-site/src/components/dataviews/index.js b/packages/edit-site/src/components/dataviews/index.js index 3fea6fd63714b7..422d128b1461d0 100644 --- a/packages/edit-site/src/components/dataviews/index.js +++ b/packages/edit-site/src/components/dataviews/index.js @@ -1,2 +1 @@ export { default as DataViews } from './dataviews'; -export { PAGE_SIZE_VALUES } from './view-actions'; diff --git a/packages/edit-site/src/components/dataviews/pagination.js b/packages/edit-site/src/components/dataviews/pagination.js index 3adecd2bb80851..bd6cb503653b07 100644 --- a/packages/edit-site/src/components/dataviews/pagination.js +++ b/packages/edit-site/src/components/dataviews/pagination.js @@ -6,26 +6,54 @@ import { __experimentalHStack as HStack, __experimentalText as Text, __experimentalNumberControl as NumberControl, + __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper, + SelectControl, } from '@wordpress/components'; import { createInterpolateElement } from '@wordpress/element'; import { sprintf, __, _x, _n } from '@wordpress/i18n'; -/** - * Internal dependencies - */ -import { PageSizeControl } from './view-actions'; +const PAGE_SIZE_VALUES = [ 5, 20, 50 ]; +function PageSizeControl( { view, onChangeView } ) { + const label = __( 'Rows per page:' ); + return ( + + { label } + + } + value={ view.perPage } + options={ PAGE_SIZE_VALUES.map( ( pageSize ) => ( { + value: pageSize, + label: pageSize, + } ) ) } + onChange={ ( value ) => + onChangeView( { ...view, perPage: value } ) + } + /> + ); +} // For now this is copied from the patterns list Pagination component, because // the datatable pagination starts from index zero(`0`). Eventually all lists will be // using this one. -export function Pagination( { - dataView, - // If passed, use it, as it's for controlled pagination. - totalItems = 0, +function Pagination( { + view, + onChangeView, + paginationInfo: { totalItems = 0, totalPages }, } ) { - const currentPage = dataView.getState().pagination.pageIndex + 1; - const numPages = dataView.getPageCount(); - const _totalItems = totalItems || dataView.getCoreRowModel().rows.length; + const currentPage = view.page + 1; + if ( ! totalItems || ! totalPages ) { + return null; + } return ( - { !! _totalItems && ( + { !! totalItems && ( ) } - + ); } + +export default Pagination; diff --git a/packages/edit-site/src/components/dataviews/text-filter.js b/packages/edit-site/src/components/dataviews/text-filter.js index 76a06c14486170..0b5f7b3cf6790e 100644 --- a/packages/edit-site/src/components/dataviews/text-filter.js +++ b/packages/edit-site/src/components/dataviews/text-filter.js @@ -1,8 +1,3 @@ -/** - * External dependencies - */ -import classnames from 'classnames'; - /** * WordPress dependencies */ @@ -15,18 +10,19 @@ import { SearchControl } from '@wordpress/components'; */ import useDebouncedInput from '../../utils/use-debounced-input'; -export default function TextFilter( { - className, - searchLabel = __( 'Filter list' ), - onChange, -} ) { - const [ search, setSearch, debouncedSearch ] = useDebouncedInput(); +export default function TextFilter( { view, onChangeView } ) { + const [ search, setSearch, debouncedSearch ] = useDebouncedInput( + view.search + ); useEffect( () => { - onChange( debouncedSearch ); - }, [ debouncedSearch, onChange ] ); + onChangeView( ( currentView ) => ( { + ...currentView, + search: debouncedSearch, + } ) ); + }, [ debouncedSearch, onChangeView ] ); + const searchLabel = __( 'Filter list' ); return ( view.type === v.id ); return ( - + { activeView.label } + + + } > - { label } - + { __( 'Layout' ) } + } - value={ dataView.getState().pagination.pageSize } - options={ PAGE_SIZE_VALUES.map( ( pageSize ) => ( { - value: pageSize, - label: pageSize, - } ) ) } - onChange={ ( value ) => dataView.setPageSize( +value ) } - /> + > + { availableViews.map( ( availableView ) => { + return ( + + ) + } + onSelect={ ( event ) => { + // We need to handle this on DropDown component probably.. + event.preventDefault(); + onChangeView( { ...view, type: availableView.id } ); + } } + // TODO: check about role and a11y. + role="menuitemcheckbox" + > + { availableView.label } + + ); + } ) } + ); } +const PAGE_SIZE_VALUES = [ 5, 20, 50 ]; function PageSizeMenu( { view, onChangeView } ) { return ( + ); } -function ListView( { dataView, className, isLoading = false }, ref ) { +function ViewList( { + view, + onChangeView, + fields, + actions, + data, + isLoading = false, + paginationInfo, +} ) { + const columns = useMemo( () => { + const _columns = [ ...fields ]; + 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 } + + ) ) } + + ) } + + ); + }, + enableHiding: false, + } ); + } + + return _columns; + }, [ fields, actions ] ); + + const columnVisibility = useMemo( () => { + if ( ! view.hiddenFields?.length ) { + return; + } + return view.hiddenFields.reduce( + ( accumulator, fieldId ) => ( { + ...accumulator, + [ fieldId ]: false, + } ), + {} + ); + }, [ view.hiddenFields ] ); + + const dataView = useReactTable( { + data, + columns, + manualSorting: true, + manualFiltering: true, + manualPagination: true, + enableRowSelection: true, + state: { + sorting: view.sort + ? [ + { + id: view.sort.field, + desc: view.sort.direction === 'desc', + }, + ] + : [], + globalFilter: view.search, + pagination: { + pageIndex: view.page, + pageSize: view.perPage, + }, + columnVisibility: columnVisibility ?? EMPTY_OBJECT, + }, + onSortingChange: ( sortingUpdater ) => { + onChangeView( ( currentView ) => { + const sort = + typeof sortingUpdater === 'function' + ? sortingUpdater( + currentView.sort + ? [ + { + id: currentView.sort.field, + desc: + currentView.sort + .direction === 'desc', + }, + ] + : [] + ) + : sortingUpdater; + if ( ! sort.length ) { + return { + ...currentView, + sort: {}, + }; + } + const [ { id, desc } ] = sort; + return { + ...currentView, + sort: { field: id, direction: desc ? 'desc' : 'asc' }, + }; + } ); + }, + onColumnVisibilityChange: ( columnVisibilityUpdater ) => { + onChangeView( ( currentView ) => { + const hiddenFields = Object.entries( + columnVisibilityUpdater() + ).reduce( + ( accumulator, [ fieldId, value ] ) => { + if ( value ) { + return accumulator.filter( + ( id ) => id !== fieldId + ); + } + return [ ...accumulator, fieldId ]; + }, + [ ...( currentView.hiddenFields || [] ) ] + ); + return { + ...currentView, + hiddenFields, + }; + } ); + }, + onGlobalFilterChange: ( value ) => { + onChangeView( { ...view, search: value, page: 0 } ); + }, + onPaginationChange: ( paginationUpdater ) => { + onChangeView( ( currentView ) => { + const { pageIndex, pageSize } = paginationUpdater( { + pageIndex: currentView.page, + pageSize: currentView.perPage, + } ); + return { ...view, page: pageIndex, perPage: pageSize }; + } ); + }, + getCoreRowModel: getCoreRowModel(), + getFilteredRowModel: getFilteredRowModel(), + getSortedRowModel: getSortedRowModel(), + getPaginationRowModel: getPaginationRowModel(), + pageCount: paginationInfo.totalPages, + } ); + const { rows } = dataView.getRowModel(); const hasRows = !! rows?.length; if ( isLoading ) { @@ -123,10 +290,7 @@ function ListView( { dataView, className, isLoading = false }, ref ) { return (
{ hasRows && ( - +
{ dataView.getHeaderGroups().map( ( headerGroup ) => ( @@ -183,4 +347,4 @@ function ListView( { dataView, className, isLoading = false }, ref ) { ); } -export default forwardRef( ListView ); +export default ViewList; diff --git a/packages/edit-site/src/components/page-pages/index.js b/packages/edit-site/src/components/page-pages/index.js index a616ea617feb91..728f7c2c716fe6 100644 --- a/packages/edit-site/src/components/page-pages/index.js +++ b/packages/edit-site/src/components/page-pages/index.js @@ -167,9 +167,6 @@ export default function PagePages() { isLoading={ isLoadingPages } view={ view } onChangeView={ setView } - options={ { - pageCount: totalPages, - } } /> );