Address errors

This commit is contained in:
Lourens Schep 2024-09-04 14:46:06 +02:00
parent de0ce09f93
commit ab33e45a13
1 changed files with 74 additions and 50 deletions

View File

@ -2,15 +2,16 @@
* External dependencies * External dependencies
*/ */
import { DataForm, isItemValid } from '@wordpress/dataviews'; import { DataForm, isItemValid } from '@wordpress/dataviews';
import type { Form } from '@wordpress/dataviews'; import type { Field, Form } from '@wordpress/dataviews';
import { import {
createElement, createElement,
useState, useState,
useMemo, useMemo,
useEffect, useEffect,
Fragment,
} from '@wordpress/element'; } from '@wordpress/element';
import { __ } from '@wordpress/i18n'; import { __, sprintf } from '@wordpress/i18n';
import { getBlockType } from '@wordpress/blocks'; import { BlockEditProps, Template, getBlockType } from '@wordpress/blocks';
import { Product } from '@woocommerce/data'; import { Product } from '@woocommerce/data';
import { useSelect } from '@wordpress/data'; import { useSelect } from '@wordpress/data';
import { useLayoutTemplate } from '@woocommerce/block-templates'; import { useLayoutTemplate } from '@woocommerce/block-templates';
@ -40,7 +41,6 @@ import { EntityProvider } from '@wordpress/core-data';
* Internal dependencies * Internal dependencies
*/ */
import { unlock } from '../../lock-unlock'; import { unlock } from '../../lock-unlock';
import { productFields } from '../product-list/fields';
import { initBlocks } from '../../components/editor/init-blocks'; import { initBlocks } from '../../components/editor/init-blocks';
import { useProductTemplate } from '../../hooks/use-product-template'; import { useProductTemplate } from '../../hooks/use-product-template';
import { productApiFetchMiddleware } from '../../utils/product-apifetch-middleware'; import { productApiFetchMiddleware } from '../../utils/product-apifetch-middleware';
@ -116,16 +116,18 @@ export default function ProductEditWithOldForm( {
// @ts-ignore // @ts-ignore
const { getEntityRecordNonTransientEdits } = select( 'core' ); const { getEntityRecordNonTransientEdits } = select( 'core' );
const _edits: Product | null =
pr &&
getEntityRecordNonTransientEdits(
'postType',
pr.type,
ids[ 0 ]
);
if ( ! pr ) { if ( ! pr ) {
return { itemWithEdits: null }; return { itemWithEdits: null };
} }
const _edits = getEntityRecordNonTransientEdits(
'postType',
pr.type,
ids[ 0 ]
);
return { return {
itemWithEdits: _edits, itemWithEdits: _edits,
}; };
@ -149,15 +151,15 @@ export default function ProductEditWithOldForm( {
const { layoutTemplate } = useLayoutTemplate( const { layoutTemplate } = useLayoutTemplate(
initialEdits ? getLayoutTemplateId( productTemplate, postType ) : null initialEdits ? getLayoutTemplateId( productTemplate, postType ) : null
); );
let flattendedLayoutTemplate = useMemo( () => { const flattendedLayoutTemplate: Template[] = useMemo( () => {
if ( ! layoutTemplate ) { if ( ! layoutTemplate ) {
return []; return [];
} }
return layoutTemplate.blockTemplates.flatMap( ( item ) => { return layoutTemplate.blockTemplates.flatMap( ( item: Template ) => {
if ( item[ 0 ] === 'woocommerce/product-tab' ) { if ( item[ 0 ] === 'woocommerce/product-tab' && item[ 2 ] ) {
return item[ 2 ].flatMap( ( tabItems ) => { return item[ 2 ].flatMap( ( tabItems ) => {
if ( tabItems[ 0 ] === 'woocommerce/product-section' ) { if ( tabItems[ 0 ] === 'woocommerce/product-section' ) {
return tabItems[ 2 ]; return tabItems[ 2 ] || [];
} }
return []; return [];
} ); } );
@ -165,78 +167,100 @@ export default function ProductEditWithOldForm( {
return []; return [];
} ); } );
}, [ layoutTemplate ] ); }, [ layoutTemplate ] );
const productRenderedFields = useMemo( () => { const productRenderedFields: Field< Product >[] = useMemo( () => {
return flattendedLayoutTemplate function isField(
.map( ( item ) => { item: Field< Product > | null
const Block = getBlockType( item[ 0 ] ); ): item is Field< Product > {
return !! item;
}
const mappedItems: Array< Field< Product > | null > =
flattendedLayoutTemplate.map( ( block ) => {
const Block = getBlockType( block[ 0 ] );
if ( if (
! Block || ! Block ||
Block.name.includes( 'column' ) || Block.name.includes( 'column' ) ||
Block.name.includes( 'section-description' ) Block.name.includes( 'section-description' ) ||
! block[ 1 ] ||
! Block.edit
) { ) {
return null; return null;
} }
let id = item[ 1 ]._templateBlockId; let id = block[ 1 ]._templateBlockId;
if ( item[ 1 ].property ) { if ( block[ 1 ].property ) {
id = item[ 1 ].property; id = block[ 1 ].property;
} }
return { return {
id, id,
label: item[ 1 ].label || Block.title, label: block[ 1 ].label || Block.title,
render: ( { item: product }: { item: Product } ) => { render: ( { item: product }: { item: Product } ) => {
if ( item[ 1 ].property ) { if ( block[ 1 ] && block[ 1 ].property ) {
return JSON.stringify( return (
product[ item[ 1 ].property ] <>
{ JSON.stringify(
product[ block[ 1 ].property ]
) }
</>
); );
} }
return ''; return null;
}, },
Edit: () => { Edit: () => {
const BlockEdit = Block.edit as
| React.ComponentType<
Partial<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
BlockEditProps< Record< string, any > >
> & {
context?: string;
}
>
| undefined;
return ( return (
<ErrorBoundary <ErrorBoundary
errorMessage={ __( errorMessage={ sprintf(
`The ${ Block.name } failed to render.`, /* translators: %1$s: rating, %2$s: total number of stars */
'woocommerce' __(
'The %s failed to render.',
'woocommerce'
),
Block.name
) } ) }
> >
<Block.edit { BlockEdit && (
attributes={ item[ 1 ] } <BlockEdit
context={ postType } attributes={ block[ 1 ] || {} }
/> context={ postType }
/>
) }
</ErrorBoundary> </ErrorBoundary>
); );
}, },
}; };
} ) } );
.filter( ( item ) => !! item ); return mappedItems.filter( isField );
}, [ flattendedLayoutTemplate ] ); }, [ flattendedLayoutTemplate ] );
const updatedForm = useMemo( () => { const updatedForm = useMemo( () => {
return { return {
...form, ...form,
fields: flattendedLayoutTemplate.map( ( field ) => { fields: flattendedLayoutTemplate.map( ( field ) => {
if ( field[ 1 ].property ) { if ( field[ 1 ] && field[ 1 ].property ) {
return field[ 1 ].property; return field[ 1 ].property;
} }
return field[ 1 ]._templateBlockId; return field[ 1 ] ? field[ 1 ]._templateBlockId : null;
} ), } ),
}; };
}, [ flattendedLayoutTemplate ] ); }, [ flattendedLayoutTemplate ] );
const [ edits, setEdits ] = useState( {} ); const [ , setEdits ] = useState( {} );
const isUpdateDisabled = ! isItemValid( const isUpdateDisabled =
itemWithEdits, itemWithEdits &&
productFields, isItemValid( itemWithEdits, productRenderedFields, form );
form
);
const onSubmit = async ( event: Event ) => { const onSubmit = async ( event: Event ) => {
event.preventDefault(); event.preventDefault();
if ( ! isItemValid( itemWithEdits, productFields, form ) ) {
return;
}
// Empty save. // Empty save.
setEdits( {} ); setEdits( {} );
@ -282,12 +306,12 @@ export default function ProductEditWithOldForm( {
{ ! postId && ( { ! postId && (
<p>{ __( 'Select a product to edit', 'woocommerce' ) }</p> <p>{ __( 'Select a product to edit', 'woocommerce' ) }</p>
) } ) }
{ postId && ( { postId && itemWithEdits && (
<VStack spacing={ 4 } as="form" onSubmit={ onSubmit }> <VStack spacing={ 4 } as="form" onSubmit={ onSubmit }>
<EntityProvider <EntityProvider
kind="postType" kind="postType"
type={ postType } type={ postType }
id={ itemWithEdits.id } id={ parseInt( postId, 10 ) }
> >
<DataForm <DataForm
data={ itemWithEdits } data={ itemWithEdits }
@ -301,7 +325,7 @@ export default function ProductEditWithOldForm( {
type="submit" type="submit"
// @ts-expect-error missing type. // @ts-expect-error missing type.
accessibleWhenDisabled accessibleWhenDisabled
disabled={ isUpdateDisabled } disabled={ !! isUpdateDisabled }
__next40pxDefaultSize __next40pxDefaultSize
> >
{ __( 'Update', 'woocommerce' ) } { __( 'Update', 'woocommerce' ) }