From 55c6a2cb31265f42860399cf294b93d5e19e4c1f Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Mon, 11 Dec 2023 14:44:15 +0200 Subject: [PATCH] DataViews: Experiment with field types and inline editing --- package-lock.json | 2 + packages/dataviews/package.json | 1 + packages/dataviews/src/dataviews.js | 7 +- .../dataviews/src/field-types/date-field.js | 12 +++ .../src/field-types/enumeration-field.js | 42 +++++++++ packages/dataviews/src/field-types/index.js | 16 ++++ .../dataviews/src/field-types/string-field.js | 27 ++++++ packages/dataviews/src/style.scss | 12 +++ packages/dataviews/src/view-grid.js | 10 +- packages/dataviews/src/view-table.js | 94 ++++++++++++++++--- .../src/components/page-pages/index.js | 53 ++++++++--- .../sidebar-dataviews/default-views.js | 2 +- 12 files changed, 244 insertions(+), 34 deletions(-) create mode 100644 packages/dataviews/src/field-types/date-field.js create mode 100644 packages/dataviews/src/field-types/enumeration-field.js create mode 100644 packages/dataviews/src/field-types/index.js create mode 100644 packages/dataviews/src/field-types/string-field.js diff --git a/package-lock.json b/package-lock.json index ded852521693f..a5fc8fac6886d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -55032,6 +55032,7 @@ "@wordpress/a11y": "file:../a11y", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", + "@wordpress/date": "file:../date", "@wordpress/element": "file:../element", "@wordpress/i18n": "file:../i18n", "@wordpress/icons": "file:../icons", @@ -70377,6 +70378,7 @@ "@wordpress/a11y": "file:../a11y", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", + "@wordpress/date": "file:../date", "@wordpress/element": "file:../element", "@wordpress/i18n": "file:../i18n", "@wordpress/icons": "file:../icons", diff --git a/packages/dataviews/package.json b/packages/dataviews/package.json index 1872480d759c3..b1ce415618c5c 100644 --- a/packages/dataviews/package.json +++ b/packages/dataviews/package.json @@ -31,6 +31,7 @@ "@wordpress/a11y": "file:../a11y", "@wordpress/components": "file:../components", "@wordpress/compose": "file:../compose", + "@wordpress/date": "file:../date", "@wordpress/element": "file:../element", "@wordpress/i18n": "file:../i18n", "@wordpress/icons": "file:../icons", diff --git a/packages/dataviews/src/dataviews.js b/packages/dataviews/src/dataviews.js index 9e7b45d04ef87..54bd536b42dc8 100644 --- a/packages/dataviews/src/dataviews.js +++ b/packages/dataviews/src/dataviews.js @@ -15,6 +15,7 @@ import ViewActions from './view-actions'; import Filters from './filters'; import Search from './search'; import { VIEW_LAYOUTS } from './constants'; +import { FIELD_TYPES } from './field-types'; export default function DataViews( { view, @@ -44,7 +45,11 @@ export default function DataViews( { const _fields = useMemo( () => { return fields.map( ( field ) => ( { ...field, - render: field.render || field.getValue, + render: + field.render || + FIELD_TYPES[ field.fieldType ]?.render || + field.getValue, + edit: field.edit || FIELD_TYPES[ field.fieldType ]?.edit, } ) ); }, [ fields ] ); return ( diff --git a/packages/dataviews/src/field-types/date-field.js b/packages/dataviews/src/field-types/date-field.js new file mode 100644 index 0000000000000..a8592eadd5bbc --- /dev/null +++ b/packages/dataviews/src/field-types/date-field.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { dateI18n, getDate, getSettings } from '@wordpress/date'; + +export function DateField( { item, field } ) { + const formattedDate = dateI18n( + getSettings().formats.datetimeAbbreviated, + getDate( field.getValue( { item } ) ) + ); + return ; +} diff --git a/packages/dataviews/src/field-types/enumeration-field.js b/packages/dataviews/src/field-types/enumeration-field.js new file mode 100644 index 0000000000000..a3b924c785494 --- /dev/null +++ b/packages/dataviews/src/field-types/enumeration-field.js @@ -0,0 +1,42 @@ +/** + * WordPress dependencies + */ +import { Button, __experimentalVStack as VStack } from '@wordpress/components'; +import { check } from '@wordpress/icons'; + +export function EnumerationFieldEdit( { item, field } ) { + const currentValue = field.getValue( { item } ); + return ( + + { ( field.editElements || field.elements ).map( ( element ) => { + return ( + + ); + } ) } + + ); +} diff --git a/packages/dataviews/src/field-types/index.js b/packages/dataviews/src/field-types/index.js new file mode 100644 index 0000000000000..f8c126ece8b6c --- /dev/null +++ b/packages/dataviews/src/field-types/index.js @@ -0,0 +1,16 @@ +/** + * Internal dependencies + */ +import { DateField } from './date-field'; +import { StringFieldEdit } from './string-field'; +import { EnumerationFieldEdit } from './enumeration-field'; + +export const FIELD_TYPES = { + date: { + render: DateField, + }, + string: { + edit: StringFieldEdit, + }, + enumeration: { edit: EnumerationFieldEdit }, +}; diff --git a/packages/dataviews/src/field-types/string-field.js b/packages/dataviews/src/field-types/string-field.js new file mode 100644 index 0000000000000..2d2db275f9681 --- /dev/null +++ b/packages/dataviews/src/field-types/string-field.js @@ -0,0 +1,27 @@ +/** + * WordPress dependencies + */ +import { TextControl } from '@wordpress/components'; +import { useState } from '@wordpress/element'; + +export function StringFieldEdit( { item, field } ) { + const [ value, setValue ] = useState( field.getValue( { item } ) ); + return ( +
{ + event.preventDefault(); + field.setValue( { value, item } ); + } } + > + + + ); +} diff --git a/packages/dataviews/src/style.scss b/packages/dataviews/src/style.scss index ab6c052e3a898..f89249ad3a2c1 100644 --- a/packages/dataviews/src/style.scss +++ b/packages/dataviews/src/style.scss @@ -242,3 +242,15 @@ .dataviews-loading { padding: 0 $grid-unit-40; } + + +// TODO: change names/tidy +.edit-field-popover { + .components-popover__content { + // TODO: check if this the best way to do it.. + width: max-content; + } + .enumeration-field-edit-wrapper { + padding: $grid-unit-15; + } +} diff --git a/packages/dataviews/src/view-grid.js b/packages/dataviews/src/view-grid.js index e2c34ba6749fa..f2df9b04ceb06 100644 --- a/packages/dataviews/src/view-grid.js +++ b/packages/dataviews/src/view-grid.js @@ -51,14 +51,17 @@ export default function ViewGrid( { className="dataviews-view-grid__card" >
- { mediaField?.render( { item } ) } + { mediaField?.render( { item, field: mediaField } ) }
- { primaryField?.render( { item } ) } + { primaryField?.render( { + item, + field: primaryField, + } ) } { const renderedValue = field.render( { item, + field, } ); if ( ! renderedValue ) { return null; @@ -87,7 +91,7 @@ export default function ViewGrid( { { field.header }
- { field.render( { item } ) } + { renderedValue }
); diff --git a/packages/dataviews/src/view-table.js b/packages/dataviews/src/view-table.js index e34d99008657b..ca163470b8c51 100644 --- a/packages/dataviews/src/view-table.js +++ b/packages/dataviews/src/view-table.js @@ -12,13 +12,17 @@ import { arrowDown, chevronRightSmall, funnel, + edit, } from '@wordpress/icons'; import { + Popover, Button, Icon, + __experimentalHStack as HStack, privateApis as componentsPrivateApis, + FlexBlock, } from '@wordpress/components'; -import { Children, Fragment } from '@wordpress/element'; +import { useState, useRef, Children, Fragment } from '@wordpress/element'; /** * Internal dependencies @@ -396,20 +400,11 @@ function ViewTable( { { usedData.map( ( item, index ) => ( { visibleFields.map( ( field ) => ( - - { field.render( { - item, - } ) } - + field={ field } + item={ item } + /> ) ) } { !! actions?.length && ( @@ -433,4 +428,75 @@ function ViewTable( { ); } +function SingleCell( { item, field } ) { + const ref = useRef(); + const [ isHovered, setIsHovered ] = useState( false ); + const [ isViewMode, setIsViewMode ] = useState( true ); + // TODO: we probably need an `isEligible` function too.. + // TODO: we need an `edit` function and a `setValue` function.. Can we simplify/combine? + const isEditable = !! field.edit; + return ( + setIsHovered( false ) } + onMouseEnter={ () => setIsHovered( true ) } + > + <> + + + { field.render( { item, field } ) } + +