Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/dataviews/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
- DataForm: support validation in select control [#71665](https://github.com/WordPress/gutenberg/pull/71665)
- DataForm: support validation in toggleGroup control. ([#71666](https://github.com/WordPress/gutenberg/pull/71666))
- DataForm: Add object configuration support for Edit property with some options. ([#71582](https://github.com/WordPress/gutenberg/pull/71582))
- DataForm: Add summary field support for composed fields. ([#71614](https://github.com/WordPress/gutenberg/pull/71614))

### Bug Fixes

Expand Down
102 changes: 102 additions & 0 deletions packages/dataviews/src/components/dataform/stories/index.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,14 @@ type SamplePost = {
address1?: string;
address2?: string;
city?: string;
comment_status?: string;
ping_status?: boolean;
longDescription?: string;
origin?: string;
destination?: string;
flight_status?: string;
gate?: string;
seat?: string;
};

const fields: Field< SamplePost >[] = [
Expand Down Expand Up @@ -184,6 +191,71 @@ const fields: Field< SamplePost >[] = [
rows: 5,
},
},
{
id: 'comment_status',
label: 'Comment Status',
type: 'text',
Edit: 'radio',
elements: [
{ value: 'open', label: 'Allow comments' },
{ value: 'closed', label: 'Comments closed' },
],
},
{
id: 'ping_status',
label: 'Allow Pings/Trackbacks',
type: 'boolean',
},
{
id: 'discussion',
label: 'Discussion',
type: 'text',
render: ( { item } ) => {
const commentLabel =
item.comment_status === 'open'
? 'Allow comments'
: 'Comments closed';
const pingLabel = item.ping_status
? 'Pings enabled'
: 'Pings disabled';
return (
<span>
{ commentLabel }, { pingLabel }
</span>
);
},
},
{
id: 'origin',
label: 'Origin',
type: 'text',
},
{
id: 'destination',
label: 'Destination',
type: 'text',
},
{
id: 'flight_status',
label: 'Flight Status',
type: 'text',
Edit: 'radio',
elements: [
{ value: 'on-time', label: 'On Time' },
{ value: 'delayed', label: 'Delayed' },
{ value: 'cancelled', label: 'Cancelled' },
],
},
{
id: 'gate',
label: 'Gate',
type: 'text',
},
{
id: 'seat',
label: 'Seat',
type: 'text',
},
];

const LayoutRegularComponent = ( {
Expand Down Expand Up @@ -319,6 +391,13 @@ const LayoutPanelComponent = ( {
address1: '123 Main St',
address2: 'Apt 4B',
city: 'New York',
comment_status: 'open',
ping_status: true,
origin: 'New York (JFK)',
destination: 'Los Angeles (LAX)',
flight_status: 'on-time',
gate: 'A12',
seat: '14F',
} );

const form: Form = useMemo( () => {
Expand All @@ -340,11 +419,34 @@ const LayoutPanelComponent = ( {
'filesize',
'dimensions',
'tags',
{
id: 'discussion',
label: 'Discussion',
children: [ 'comment_status', 'ping_status' ],
summary: 'discussion',
},
{
id: 'address1',
label: 'Combined Address',
children: [ 'address1', 'address2', 'city' ],
},
{
id: 'flight_info',
label: 'Flight Information',
children: [
'origin',
'destination',
'flight_status',
'gate',
],
summary: [ 'origin', 'destination', 'flight_status' ],
},
{
id: 'passenger_details',
label: 'Passenger Details',
children: [ 'author', 'seat' ],
summary: [ 'author', 'seat' ],
},
],
};
}, [ labelPosition, openAs ] );
Expand Down
35 changes: 12 additions & 23 deletions packages/dataviews/src/dataforms-layouts/panel/dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
Dropdown,
Button,
} from '@wordpress/components';
import { sprintf, __, _x } from '@wordpress/i18n';
import { __ } from '@wordpress/i18n';
import { useMemo } from '@wordpress/element';
import { closeSmall } from '@wordpress/icons';

Expand All @@ -20,6 +20,7 @@ import type { Form, FormField, NormalizedField } from '../../types';
import { DataFormLayout } from '../data-form-layout';
import { isCombinedField } from '../is-combined-field';
import { DEFAULT_LAYOUT } from '../../normalize-form-fields';
import SummaryButton from './summary-button';

function DropdownHeader( {
title,
Expand Down Expand Up @@ -55,13 +56,15 @@ function DropdownHeader( {

function PanelDropdown< Item >( {
fieldDefinition,
summaryFields,
popoverAnchor,
labelPosition = 'side',
data,
onChange,
field,
}: {
fieldDefinition: NormalizedField< Item >;
summaryFields: NormalizedField< Item >[];
popoverAnchor: HTMLElement | null;
labelPosition: 'side' | 'top' | 'none';
data: Item;
Expand Down Expand Up @@ -107,29 +110,15 @@ function PanelDropdown< Item >( {
tooltipPosition: 'middle left',
} }
renderToggle={ ( { isOpen, onToggle } ) => (
<Button
className="dataforms-layouts-panel__field-control"
size="compact"
variant={
[ 'none', 'top' ].includes( labelPosition )
? 'link'
: 'tertiary'
}
aria-expanded={ isOpen }
aria-label={ sprintf(
// translators: %s: Field name.
_x( 'Edit %s', 'field' ),
fieldLabel || ''
) }
onClick={ onToggle }
<SummaryButton
summaryFields={ summaryFields }
data={ data }
labelPosition={ labelPosition }
fieldLabel={ fieldLabel }
disabled={ fieldDefinition.readOnly === true }
accessibleWhenDisabled
>
<fieldDefinition.render
item={ data }
field={ fieldDefinition }
/>
</Button>
onClick={ onToggle }
aria-expanded={ isOpen }
/>
) }
renderContent={ ( { onClose } ) => (
<>
Expand Down
55 changes: 39 additions & 16 deletions packages/dataviews/src/dataforms-layouts/panel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,28 +32,49 @@ export default function FormPanelField< Item >( {
onChange,
}: FieldLayoutProps< Item > ) {
const { fields } = useContext( DataFormContext );
const fieldDefinition = fields.find( ( _field ) => {
// Default to the first simple child if it is a combined field.
if ( isCombinedField( field ) ) {
const simpleChildren = field.children.filter(
( child ): child is string | SimpleFormField =>
typeof child === 'string' || ! isCombinedField( child )
const getSummaryFields = () => {
if ( ! isCombinedField( field ) ) {
const fieldDef = fields.find(
( _field ) => _field.id === field.id
);
return fieldDef ? [ fieldDef ] : [];
}

if ( simpleChildren.length === 0 ) {
return false;
}
// Use summary field(s) if specified for combined fields
if ( field.summary ) {
const summaryIds = Array.isArray( field.summary )
? field.summary
: [ field.summary ];
return summaryIds
.map( ( summaryId ) =>
fields.find( ( _field ) => _field.id === summaryId )
)
.filter( ( _field ) => _field !== undefined );
}

const firstChildFieldId =
typeof simpleChildren[ 0 ] === 'string'
? simpleChildren[ 0 ]
: simpleChildren[ 0 ].id;
// Default to the first simple child
const simpleChildren = field.children.filter(
( child ): child is string | SimpleFormField =>
typeof child === 'string' || ! isCombinedField( child )
);

return _field.id === firstChildFieldId;
if ( simpleChildren.length === 0 ) {
return [];
}

return _field.id === field.id;
} );
const firstChildFieldId =
typeof simpleChildren[ 0 ] === 'string'
? simpleChildren[ 0 ]
: simpleChildren[ 0 ].id;

const fieldDef = fields.find(
( _field ) => _field.id === firstChildFieldId
);
return fieldDef ? [ fieldDef ] : [];
};

const summaryFields = getSummaryFields();
const fieldDefinition = summaryFields[ 0 ]; // For backward compatibility

// Use internal state instead of a ref to make sure that the component
// re-renders when the popover's anchor updates.
Expand Down Expand Up @@ -84,6 +105,7 @@ export default function FormPanelField< Item >( {
<PanelModal
field={ field }
fieldDefinition={ fieldDefinition }
summaryFields={ summaryFields }
data={ data }
onChange={ onChange }
labelPosition={ labelPosition }
Expand All @@ -93,6 +115,7 @@ export default function FormPanelField< Item >( {
field={ field }
popoverAnchor={ popoverAnchor }
fieldDefinition={ fieldDefinition }
summaryFields={ summaryFields }
data={ data }
onChange={ onChange }
labelPosition={ labelPosition }
Expand Down
35 changes: 12 additions & 23 deletions packages/dataviews/src/dataforms-layouts/panel/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
Button,
Modal,
} from '@wordpress/components';
import { __, sprintf, _x } from '@wordpress/i18n';
import { __ } from '@wordpress/i18n';
import { useState, useMemo } from '@wordpress/element';

/**
Expand All @@ -17,6 +17,7 @@ import type { Form, FormField, NormalizedField } from '../../types';
import { DataFormLayout } from '../data-form-layout';
import { isCombinedField } from '../is-combined-field';
import { DEFAULT_LAYOUT } from '../../normalize-form-fields';
import SummaryButton from './summary-button';

function ModalContent< Item >( {
data,
Expand Down Expand Up @@ -96,12 +97,14 @@ function ModalContent< Item >( {

function PanelModal< Item >( {
fieldDefinition,
summaryFields,
labelPosition,
data,
onChange,
field,
}: {
fieldDefinition: NormalizedField< Item >;
summaryFields: NormalizedField< Item >[];
labelPosition: 'side' | 'top' | 'none';
data: Item;
onChange: ( value: any ) => void;
Expand All @@ -126,29 +129,15 @@ function PanelModal< Item >( {

return (
<>
<Button
className="dataforms-layouts-modal__field-control"
size="compact"
variant={
[ 'none', 'top' ].includes( labelPosition )
? 'link'
: 'tertiary'
}
aria-expanded={ isOpen }
aria-label={ sprintf(
// translators: %s: Field name.
_x( 'Edit %s', 'field' ),
fieldLabel || ''
) }
onClick={ () => setIsOpen( true ) }
<SummaryButton
summaryFields={ summaryFields }
data={ data }
labelPosition={ labelPosition }
fieldLabel={ fieldLabel }
disabled={ fieldDefinition.readOnly === true }
accessibleWhenDisabled
>
<fieldDefinition.render
item={ data }
field={ fieldDefinition }
/>
</Button>
onClick={ () => setIsOpen( true ) }
aria-expanded={ isOpen }
/>
{ isOpen && (
<ModalContent
data={ data }
Expand Down
Loading
Loading