From d0745d4d282f1bc53625b490c37ac77bda7faef3 Mon Sep 17 00:00:00 2001 From: Jorge Costa Date: Thu, 1 Aug 2024 12:43:01 +0100 Subject: [PATCH 01/18] New view config UI --- .../dataviews-view-config/index.tsx | 527 +++++++++--------- .../dataviews-view-config/style.scss | 39 ++ packages/dataviews/src/constants.ts | 4 + packages/dataviews/src/style.scss | 1 + 4 files changed, 298 insertions(+), 273 deletions(-) create mode 100644 packages/dataviews/src/components/dataviews-view-config/style.scss diff --git a/packages/dataviews/src/components/dataviews-view-config/index.tsx b/packages/dataviews/src/components/dataviews-view-config/index.tsx index b89e964f6a5d0..eaa0dbca1e8b8 100644 --- a/packages/dataviews/src/components/dataviews-view-config/index.tsx +++ b/packages/dataviews/src/components/dataviews-view-config/index.tsx @@ -1,150 +1,195 @@ /** * External dependencies */ -import type { ChangeEvent } from 'react'; +import clsx from 'clsx'; /** * WordPress dependencies */ import { Button, - privateApis as componentsPrivateApis, + Popover, + __experimentalToggleGroupControl as ToggleGroupControl, + __experimentalToggleGroupControlOption as ToggleGroupControlOption, + SelectControl, + __experimentalItemGroup as ItemGroup, + __experimentalItem as Item, + __experimentalGrid as Grid, + __experimentalVStack as VStack, __experimentalHStack as HStack, } from '@wordpress/components'; import { __, _x } from '@wordpress/i18n'; -import { memo, useContext } from '@wordpress/element'; -import { cog } from '@wordpress/icons'; +import { memo, useContext, useState, useMemo } from '@wordpress/element'; +import { cog, seen } from '@wordpress/icons'; /** * Internal dependencies */ -import { unlock } from '../../lock-unlock'; -import { SORTING_DIRECTIONS, sortLabels } from '../../constants'; +import { SORTING_DIRECTIONS, sortLabelsShort } from '../../constants'; import { VIEW_LAYOUTS, getMandatoryFields } from '../../dataviews-layouts'; -import type { NormalizedField, View, SupportedLayouts } from '../../types'; +import type { SupportedLayouts } from '../../types'; import DataViewsContext from '../dataviews-context'; -const { - DropdownMenuV2: DropdownMenu, - DropdownMenuGroupV2: DropdownMenuGroup, - DropdownMenuItemV2: DropdownMenuItem, - DropdownMenuRadioItemV2: DropdownMenuRadioItem, - DropdownMenuCheckboxItemV2: DropdownMenuCheckboxItem, - DropdownMenuItemLabelV2: DropdownMenuItemLabel, -} = unlock( componentsPrivateApis ); - -interface ViewTypeMenuProps { - view: View; - onChangeView: ( view: View ) => void; +interface ViewActionsProps { defaultLayouts?: SupportedLayouts; } -interface PageSizeMenuProps { - view: View; - onChangeView: ( view: View ) => void; -} - -interface FieldsVisibilityMenuProps< Item > { - view: View; - onChangeView: ( view: View ) => void; - fields: NormalizedField< Item >[]; +function LayoutPicker( { + defaultLayouts = { list: {}, grid: {}, table: {} }, +}: ViewActionsProps ) { + const { view, onChangeView } = useContext( DataViewsContext ); + const availableLayouts = Object.keys( defaultLayouts ); + return ( + { + switch ( newLayout ) { + case 'list': + case 'grid': + case 'table': + return onChangeView( { + ...view, + type: newLayout, + ...defaultLayouts[ newLayout ], + } ); + } + throw new Error( 'Invalid dataview' ); + } } + > + { availableLayouts.map( ( layout ) => { + const config = VIEW_LAYOUTS.find( ( v ) => v.type === layout ); + if ( ! config ) { + return null; + } + return ( + + ); + } ) } + + ); } -interface SortMenuProps< Item > { - fields: NormalizedField< Item >[]; - view: View; - onChangeView: ( view: View ) => void; -} +function SortFieldControl() { + const { view, fields, onChangeView } = useContext( DataViewsContext ); + const orderOptions = useMemo( () => { + const sortableFields = fields.filter( + ( field ) => field.enableSorting !== false + ); + return sortableFields.map( ( field ) => { + return { + label: field.label, + value: field.id, + }; + } ); + }, [ fields ] ); -interface ViewActionsProps { - defaultLayouts?: SupportedLayouts; + return ( + { + onChangeView( { + ...view, + sort: { + direction: view?.sort?.direction || 'desc', + field: value, + }, + } ); + } } + /> + ); } -function ViewTypeMenu( { - view, - onChangeView, - defaultLayouts = { list: {}, grid: {}, table: {} }, -}: ViewTypeMenuProps ) { - const availableLayouts = Object.keys( defaultLayouts ); - if ( availableLayouts.length <= 1 ) { - return null; - } - return availableLayouts.map( ( layout ) => { - const config = VIEW_LAYOUTS.find( ( v ) => v.type === layout ); - if ( ! config ) { - return null; - } - return ( - ) => { - switch ( e.target.value ) { - case 'list': - case 'grid': - case 'table': - return onChangeView( { - ...view, - type: e.target.value, - ...defaultLayouts[ e.target.value ], - } ); - } - throw new Error( 'Invalid dataview' ); - } } - > - { config.label } - - ); - } ); +function SortDirectionControl() { + const { view, onChangeView } = useContext( DataViewsContext ); + return ( + { + if ( ! view?.sort?.field ) { + return; + } + if ( newDirection === 'asc' || newDirection === 'desc' ) { + onChangeView( { + ...view, + sort: { + direction: newDirection, + field: view.sort.field, + }, + } ); + return; + } + throw new Error( 'Invalid direction' ); + } } + > + { SORTING_DIRECTIONS.map( ( direction ) => { + return ( + + ); + } ) } + + ); } const PAGE_SIZE_VALUES = [ 10, 20, 50, 100 ]; -function PageSizeMenu( { view, onChangeView }: PageSizeMenuProps ) { +function ItemsPerPageControl() { + const { view, onChangeView } = useContext( DataViewsContext ); return ( - + ); } -function FieldsVisibilityMenu< Item >( { - view, - onChangeView, - fields, -}: FieldsVisibilityMenuProps< Item > ) { +function FieldControl() { + const { view, fields, onChangeView } = useContext( DataViewsContext ); const mandatoryFields = getMandatoryFields( view ); const hidableFields = fields.filter( ( field ) => @@ -156,186 +201,122 @@ function FieldsVisibilityMenu< Item >( { return null; } return ( - - - { __( 'Fields' ) } - - - } - > + { hidableFields?.map( ( field ) => { + const isVisible = viewFields.includes( field.id ); return ( - { - onChangeView( { - ...view, - fields: viewFields.includes( field.id ) - ? viewFields.filter( - ( id ) => id !== field.id - ) - : [ ...viewFields, field.id ], - } ); - } } - > - - { field.label } - - + + + { field.label } +