Skip to content

Commit

Permalink
Update fields to allow for array of form items
Browse files Browse the repository at this point in the history
  • Loading branch information
louwie17 committed Dec 4, 2024
1 parent 4597d3b commit 4403daf
Show file tree
Hide file tree
Showing 16 changed files with 118 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -107,16 +107,14 @@ const fields = [
id: 'sticky',
label: 'Sticky',
type: 'integer',
Edit: ( { field, onChange, data, hideLabelFromVision } ) => {
const { id, getValue } = field;
Edit: ( { field, onChange, value, hideLabelFromVision } ) => {
const { id } = field;
return (
<ToggleControl
__nextHasNoMarginBottom
label={ hideLabelFromVision ? '' : field.label }
checked={ getValue( { item: data } ) }
onChange={ () =>
onChange( { [ id ]: ! getValue( { item: data } ) } )
}
checked={ value }
onChange={ () => onChange( { [ id ]: ! value } ) }
/>
);
},
Expand Down
5 changes: 2 additions & 3 deletions packages/dataviews/src/dataform-controls/datetime.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@ import { useCallback } from '@wordpress/element';
import type { DataFormControlProps } from '../types';

export default function DateTime< Item >( {
data,
field,
onChange,
hideLabelFromVision,
value,
}: DataFormControlProps< Item > ) {
const { id, label } = field;
const value = field.getValue( { item: data } );

const onChangeControl = useCallback(
( newValue: string | null ) => onChange( { [ id ]: newValue } ),
Expand All @@ -34,7 +33,7 @@ export default function DateTime< Item >( {
<VisuallyHidden as="legend">{ label }</VisuallyHidden>
) }
<TimePicker
currentTime={ value }
currentTime={ typeof value === 'symbol' ? '' : value }
onChange={ onChangeControl }
hideLabelFromVision
/>
Expand Down
5 changes: 2 additions & 3 deletions packages/dataviews/src/dataform-controls/integer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@ import { useCallback } from '@wordpress/element';
import type { DataFormControlProps } from '../types';

export default function Integer< Item >( {
data,
field,
onChange,
hideLabelFromVision,
value,
}: DataFormControlProps< Item > ) {
const { id, label, description } = field;
const value = field.getValue( { item: data } ) ?? '';
const onChangeControl = useCallback(
( newValue: string | undefined ) =>
onChange( {
Expand All @@ -29,7 +28,7 @@ export default function Integer< Item >( {
<NumberControl
label={ label }
help={ description }
value={ value }
value={ value ?? '' }
onChange={ onChangeControl }
__next40pxDefaultSize
hideLabelFromVision={ hideLabelFromVision }
Expand Down
3 changes: 1 addition & 2 deletions packages/dataviews/src/dataform-controls/radio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@ import { useCallback } from '@wordpress/element';
import type { DataFormControlProps } from '../types';

export default function Radio< Item >( {
data,
field,
onChange,
hideLabelFromVision,
value,
}: DataFormControlProps< Item > ) {
const { id, label } = field;
const value = field.getValue( { item: data } );

const onChangeControl = useCallback(
( newValue: string ) =>
Expand Down
5 changes: 2 additions & 3 deletions packages/dataviews/src/dataform-controls/select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@ import { __ } from '@wordpress/i18n';
import type { DataFormControlProps } from '../types';

export default function Select< Item >( {
data,
field,
onChange,
hideLabelFromVision,
value,
}: DataFormControlProps< Item > ) {
const { id, label } = field;
const value = field.getValue( { item: data } ) ?? '';
const onChangeControl = useCallback(
( newValue: any ) =>
onChange( {
Expand All @@ -41,7 +40,7 @@ export default function Select< Item >( {
return (
<SelectControl
label={ label }
value={ value }
value={ value ?? '' }
options={ elements }
onChange={ onChangeControl }
__next40pxDefaultSize
Expand Down
3 changes: 1 addition & 2 deletions packages/dataviews/src/dataform-controls/text.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@ import { useCallback } from '@wordpress/element';
import type { DataFormControlProps } from '../types';

export default function Text< Item >( {
data,
field,
onChange,
hideLabelFromVision,
value,
}: DataFormControlProps< Item > ) {
const { id, label, placeholder } = field;
const value = field.getValue( { item: data } );

const onChangeControl = useCallback(
( newValue: string ) =>
Expand Down
38 changes: 35 additions & 3 deletions packages/dataviews/src/dataforms-layouts/data-form-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,43 @@ import { useContext, useMemo } from '@wordpress/element';
/**
* Internal dependencies
*/
import type { Form, FormField, SimpleFormField } from '../types';
import type {
CombinedFormField,
Form,
FormField,
NormalizedField,
SimpleFormField,
} from '../types';
import { getFormFieldLayout } from './index';
import DataFormContext from '../components/dataform-context';
import { isCombinedField } from './is-combined-field';
import normalizeFormFields from '../normalize-form-fields';

function doesCombinedFieldSupportBulkEdits< Item >(
combinedField: CombinedFormField,
fieldDefinitions: NormalizedField< Item >[]
): boolean {
return combinedField.children.some( ( child ) => {
const fieldId = typeof child === 'string' ? child : child.id;

return fieldDefinitions.find(
( fieldDefinition ) => fieldDefinition.id === fieldId
)?.supportsBulkEditing;
} );
}

export function DataFormLayout< Item >( {
data,
form,
onChange,
children,
}: {
data: Item;
data: Item | Item[];
form: Form;
onChange: ( value: any ) => void;
children?: (
FieldLayout: ( props: {
data: Item;
data: Item | Item[];
field: FormField;
onChange: ( value: any ) => void;
hideLabelFromVision?: boolean;
Expand Down Expand Up @@ -69,6 +88,19 @@ export function DataFormLayout< Item >( {
return null;
}

if (
Array.isArray( data ) &&
( ( isCombinedField( formField ) &&
! doesCombinedFieldSupportBulkEdits(
formField,
fieldDefinitions
) ) ||
( fieldDefinition &&
! fieldDefinition.supportsBulkEditing ) )
) {
return null;
}

if ( children ) {
return children( FieldLayout, formField );
}
Expand Down
29 changes: 27 additions & 2 deletions packages/dataviews/src/dataforms-layouts/panel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import type {
import DataFormContext from '../../components/dataform-context';
import { DataFormLayout } from '../data-form-layout';
import { isCombinedField } from '../is-combined-field';
import { MIXED_VALUE } from '../../constants';

function DropdownHeader( {
title,
Expand Down Expand Up @@ -70,7 +71,7 @@ function PanelDropdown< Item >( {
fieldDefinition: NormalizedField< Item >;
popoverAnchor: HTMLElement | null;
labelPosition: 'side' | 'top' | 'none';
data: Item;
data: Item | Item[];
onChange: ( value: any ) => void;
field: FormField;
} ) {
Expand Down Expand Up @@ -98,6 +99,22 @@ function PanelDropdown< Item >( {
};
}, [ field ] );

const fieldValue = useMemo( () => {
if ( Array.isArray( data ) ) {
const [ firstRecord, ...remainingRecords ] = data;
const firstValue = fieldDefinition.getValue( {
item: firstRecord,
} );
const intersects = remainingRecords.every( ( item ) => {
return fieldDefinition.getValue( { item } ) === firstValue;
} );
return intersects ? firstValue : MIXED_VALUE;
}
return fieldDefinition.getValue( {
item: data,
} );
}, [ data, fieldDefinition ] );

// Memoize popoverProps to avoid returning a new object every time.
const popoverProps = useMemo(
() => ( {
Expand All @@ -111,6 +128,8 @@ function PanelDropdown< Item >( {
[ popoverAnchor ]
);

const showMixedValue = Array.isArray( data ) && fieldValue === MIXED_VALUE;

return (
<Dropdown
contentClassName="dataforms-layouts-panel__field-dropdown"
Expand Down Expand Up @@ -138,7 +157,13 @@ function PanelDropdown< Item >( {
) }
onClick={ onToggle }
>
<fieldDefinition.render item={ data } />
{ showMixedValue ? (
__( 'Mixed' )
) : (
<fieldDefinition.render
item={ Array.isArray( data ) ? data[ 0 ] : data }
/>
) }
</Button>
) }
renderContent={ ( { onClose } ) => (
Expand Down
25 changes: 25 additions & 0 deletions packages/dataviews/src/dataforms-layouts/regular/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type { Form, FieldLayoutProps } from '../../types';
import DataFormContext from '../../components/dataform-context';
import { DataFormLayout } from '../data-form-layout';
import { isCombinedField } from '../is-combined-field';
import { MIXED_VALUE } from '../../constants';

function Header( { title }: { title: string } ) {
return (
Expand Down Expand Up @@ -59,6 +60,28 @@ export default function FormRegularField< Item >( {
};
}, [ field ] );

const fieldValue = useMemo( () => {
const fieldDefinition = fields.find(
( fieldDef ) => fieldDef.id === field.id
);
if ( ! fieldDefinition ) {
return undefined;
}
if ( Array.isArray( data ) ) {
const [ firstRecord, ...remainingRecords ] = data;
const firstValue = fieldDefinition.getValue( {
item: firstRecord,
} );
const intersects = remainingRecords.every( ( item ) => {
return fieldDefinition.getValue( { item } ) === firstValue;
} );
return intersects ? firstValue : MIXED_VALUE;
}
return fieldDefinition.getValue( {
item: data,
} );
}, [ data, fields, field.id ] );

if ( isCombinedField( field ) ) {
return (
<>
Expand Down Expand Up @@ -95,6 +118,7 @@ export default function FormRegularField< Item >( {
field={ fieldDefinition }
onChange={ onChange }
hideLabelFromVision
value={ fieldValue }
/>
</div>
</HStack>
Expand All @@ -105,6 +129,7 @@ export default function FormRegularField< Item >( {
<div className="dataforms-layouts-regular__field">
<fieldDefinition.Edit
data={ data }
value={ fieldValue }
field={ fieldDefinition }
onChange={ onChange }
hideLabelFromVision={
Expand Down
5 changes: 3 additions & 2 deletions packages/dataviews/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,11 @@ export type Fields< Item > = Field< Item >[];
export type Data< Item > = Item[];

export type DataFormControlProps< Item > = {
data: Item;
data: Item | Item[];
field: NormalizedField< Item >;
onChange: ( value: Record< string, any > ) => void;
hideLabelFromVision?: boolean;
value: any;
};

export type DataViewRenderFieldProps< Item > = {
Expand Down Expand Up @@ -576,7 +577,7 @@ export interface DataFormProps< Item > {
}

export interface FieldLayoutProps< Item > {
data: Item;
data: Item | Item[];
field: FormField;
onChange: ( value: any ) => void;
hideLabelFromVision?: boolean;
Expand Down
6 changes: 4 additions & 2 deletions packages/edit-site/src/components/post-edit/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,18 +98,20 @@ function PostEditForm( { postType, postId } ) {

const onChange = ( edits ) => {
for ( const id of ids ) {
const editedRecord =
ids.length > 1 ? records.find( ( r ) => r.id === +id ) : record;
if (
edits.status &&
edits.status !== 'future' &&
record?.status === 'future' &&
editedRecord?.status === 'future' &&
new Date( record.date ) > new Date()
) {
edits.date = null;
}
if (
edits.status &&
edits.status === 'private' &&
record.password
editedRecord.password
) {
edits.password = '';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,12 @@ import { __ } from '@wordpress/i18n';
import type { BasePost } from '../../types';

export const FeaturedImageEdit = ( {
data,
field,
onChange,
value,
}: DataFormControlProps< BasePost > ) => {
const { id } = field;

const value = field.getValue( { item: data } );

const media = useSelect(
( select ) => {
const { getEntityRecord } = select( coreStore );
Expand Down
1 change: 1 addition & 0 deletions packages/fields/src/fields/parent/parent-edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ export const ParentEdit = ( {
onChange,
}: DataFormControlProps< BasePost > ) => {
const { id } = field;
data = Array.isArray( data ) ? data[ 0 ] : data;

const homeUrl = useSelect( ( select ) => {
// @ts-expect-error getEntityRecord is not typed with unstableBase as argument.
Expand Down
Loading

0 comments on commit 4403daf

Please sign in to comment.