Add the summary field to the product form (#37302)

* Add summary block

* Add changelog files

* Add text alignment

* Add RTL and type definitions

* Add justify text alignment

* Fix rebasing errors
This commit is contained in:
Maikel David Pérez Gómez 2023-03-21 12:34:24 -03:00 committed by GitHub
parent f899b43d91
commit 62ca7a266b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 314 additions and 16 deletions

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Add summary block

View File

@ -14,4 +14,5 @@ export const settings = {
edit: Edit,
};
export const init = () => initBlock( { name, metadata, settings } );
export const init = () =>
initBlock( { name, metadata: metadata as never, settings } );

View File

@ -14,4 +14,9 @@ export const settings = {
edit: Edit,
};
export const init = () => initBlock( { name, metadata, settings } );
export const init = () =>
initBlock( {
name,
metadata: metadata as never,
settings,
} );

View File

@ -0,0 +1,30 @@
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 2,
"name": "woocommerce/product-summary",
"title": "Product summary",
"category": "widgets",
"description": "The product summary.",
"keywords": [ "products", "summary", "excerpt" ],
"textdomain": "default",
"attributes": {
"align": {
"type": "string"
},
"direction": {
"type": "string",
"enum": [ "ltr", "rtl" ]
},
"label": {
"type": "string"
}
},
"supports": {
"align": false,
"html": false,
"multiple": false,
"reusable": false,
"inserter": false,
"lock": false
}
}

View File

@ -0,0 +1,33 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import {
alignCenter,
alignJustify,
alignLeft,
alignRight,
} from '@wordpress/icons';
export const ALIGNMENT_CONTROLS = [
{
icon: alignLeft,
title: __( 'Align text left', 'woocommerce' ),
align: 'left',
},
{
icon: alignCenter,
title: __( 'Align text center', 'woocommerce' ),
align: 'center',
},
{
icon: alignRight,
title: __( 'Align text right', 'woocommerce' ),
align: 'right',
},
{
icon: alignJustify,
title: __( 'Align text justify', 'woocommerce' ),
align: 'justify',
},
];

View File

@ -0,0 +1,90 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { createElement } from '@wordpress/element';
import { BlockEditProps } from '@wordpress/blocks';
import { BaseControl } from '@wordpress/components';
import { useEntityProp } from '@wordpress/core-data';
import uniqueId from 'lodash/uniqueId';
import classNames from 'classnames';
import {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore No types for this exist yet.
AlignmentControl,
BlockControls,
RichText,
useBlockProps,
} from '@wordpress/block-editor';
/**
* Internal dependencies
*/
import { ParagraphRTLControl } from './paragraph-rtl-control';
import { SummaryAttributes } from './types';
import { ALIGNMENT_CONTROLS } from './constants';
export function Edit( {
attributes,
setAttributes,
}: BlockEditProps< SummaryAttributes > ) {
const { align, direction, label } = attributes;
const blockProps = useBlockProps( {
style: { direction },
} );
const id = uniqueId();
const [ summary, setSummary ] = useEntityProp< string >(
'postType',
'product',
'short_description'
);
function handleAlignmentChange( value: SummaryAttributes[ 'align' ] ) {
setAttributes( { align: value } );
}
function handleDirectionChange( value: SummaryAttributes[ 'direction' ] ) {
setAttributes( { direction: value } );
}
return (
<div { ...blockProps }>
{ /* eslint-disable-next-line @typescript-eslint/ban-ts-comment */ }
{ /* @ts-ignore No types for this exist yet. */ }
<BlockControls group="block">
<AlignmentControl
alignmentControls={ ALIGNMENT_CONTROLS }
value={ align }
onChange={ handleAlignmentChange }
/>
<ParagraphRTLControl
direction={ direction }
onChange={ handleDirectionChange }
/>
</BlockControls>
<BaseControl
id={ id }
label={ label || __( 'Summary', 'woocommerce' ) }
>
<RichText
id={ id }
identifier="content"
tagName="p"
value={ summary }
onChange={ setSummary }
placeholder={ __(
"Summarize this product in 1-2 short sentences. We'll show it at the top of the page.",
'woocommerce'
) }
data-empty={ Boolean( summary ) }
className={ classNames( 'components-summary-control', {
[ `has-text-align-${ align }` ]: align,
} ) }
dir={ direction }
/>
</BaseControl>
</div>
);
}

View File

@ -0,0 +1,30 @@
/**
* External dependencies
*/
import { BlockConfiguration } from '@wordpress/blocks';
/**
* Internal dependencies
*/
import { initBlock } from '../../utils';
import blockConfiguration from './block.json';
import { Edit } from './edit';
import { SummaryAttributes } from './types';
const { name, ...metadata } =
blockConfiguration as BlockConfiguration< SummaryAttributes >;
export { name, metadata };
export const settings = {
example: {},
edit: Edit,
};
export function init() {
return initBlock< SummaryAttributes >( {
name,
metadata,
settings,
} );
}

View File

@ -0,0 +1,2 @@
export * from './paragraph-rtl-control';
export * from './types';

View File

@ -0,0 +1,40 @@
/**
* External dependencies
*/
import { createElement, Fragment } from '@wordpress/element';
import { ToolbarButton } from '@wordpress/components';
import { _x, isRTL } from '@wordpress/i18n';
import { formatLtr } from '@wordpress/icons';
/**
* Internal dependencies
*/
import { ParagraphRTLControlProps } from './types';
export function ParagraphRTLControl( {
direction,
onChange,
}: ParagraphRTLControlProps ) {
function handleClick() {
if ( typeof onChange === 'function' ) {
onChange( direction === 'ltr' ? undefined : 'ltr' );
}
}
return (
<>
{ isRTL() && (
<ToolbarButton
icon={ formatLtr }
title={ _x(
'Left to right',
'editor button',
'woocommerce'
) }
isActive={ direction === 'ltr' }
onClick={ handleClick }
/>
) }
</>
);
}

View File

@ -0,0 +1,11 @@
/**
* Internal dependencies
*/
import { SummaryAttributes } from '../types';
export type ParagraphRTLControlProps = Pick<
SummaryAttributes,
'direction'
> & {
onChange( direction?: SummaryAttributes[ 'direction' ] ): void;
};

View File

@ -0,0 +1,6 @@
// This alignment class does not exists in
// https://github.com/WordPress/gutenberg/blob/trunk/packages/block-library/src/common.scss
.has-text-align-justify {
/*rtl:ignore*/
text-align: justify;
}

View File

@ -0,0 +1,5 @@
export type SummaryAttributes = {
align: 'left' | 'center' | 'right' | 'justify';
direction: 'ltr' | 'rtl';
label: string;
};

View File

@ -6,7 +6,7 @@ import {
EditorSettings,
EditorBlockListSettings,
} from '@wordpress/block-editor';
import { SlotFillProvider } from '@wordpress/components';
import { Popover, SlotFillProvider } from '@wordpress/components';
import { Product } from '@woocommerce/data';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore No types for this exist yet.
@ -60,6 +60,8 @@ export function Editor( { product, settings }: EditorProps ) {
/>
}
/>
<Popover.Slot />
</SlotFillProvider>
</ShortcutProvider>
</EntityProvider>

View File

@ -7,6 +7,7 @@ import { registerCoreBlocks } from '@wordpress/block-library';
* Internal dependencies
*/
import { init as initName } from '../details-name-block';
import { init as initSummary } from '../details-summary-block';
import { init as initSection } from '../section';
import { init as initTab } from '../tab';
import { init as initPricing } from '../pricing-block';
@ -15,6 +16,7 @@ import { init as initCollapsible } from '../collapsible-block';
export const initBlocks = () => {
registerCoreBlocks();
initName();
initSummary();
initSection();
initTab();
initPricing();

View File

@ -14,4 +14,9 @@ export const settings = {
edit: Edit,
};
export const init = () => initBlock( { name, metadata, settings } );
export const init = () =>
initBlock( {
name,
metadata: metadata as never,
settings,
} );

View File

@ -8,3 +8,4 @@
@import 'components/section/style.scss';
@import 'components/tab/style.scss';
@import 'components/tabs/style.scss';
@import 'components/details-summary-block/style.scss';

View File

@ -1,26 +1,31 @@
/**
* External dependencies
*/
import { BlockConfiguration, registerBlockType } from '@wordpress/blocks';
import {
Block,
BlockConfiguration,
registerBlockType,
} from '@wordpress/blocks';
interface BlockRepresentation {
name: string;
metadata: BlockConfiguration;
settings: Partial< BlockConfiguration >;
interface BlockRepresentation< T extends Record< string, object > > {
name?: string;
metadata: BlockConfiguration< T >;
settings: Partial< BlockConfiguration< T > >;
}
/**
* Function to register an individual block.
*
* @param {Object} block The block to be registered.
*
* @return {?WPBlockType} The block, if it has been successfully registered;
* otherwise `undefined`.
* @param block The block to be registered.
* @return The block, if it has been successfully registered; otherwise `undefined`.
*/
export const initBlock = ( block: BlockRepresentation ) => {
export function initBlock<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
T extends Record< string, any > = Record< string, any >
>( block: BlockRepresentation< T > ): Block< T > | undefined {
if ( ! block ) {
return;
}
const { metadata, settings, name } = block;
return registerBlockType( { name, ...metadata }, settings );
};
return registerBlockType< T >( { name, ...metadata }, settings );
}

View File

@ -19,6 +19,25 @@
}
}
.components-summary-control {
width: 100%;
min-height: calc($gap-larger * 3);
background-color: $white;
box-sizing: border-box;
border: 1px solid #757575;
border-radius: 2px;
padding: $gap-smaller;
margin: 0;
appearance: textarea;
resize: vertical;
overflow: hidden;
&:focus {
box-shadow: inset 0 0 0 1px var(--wp-admin-theme-color-darker-10, --wp-admin-theme-color);
border-color: var(--wp-admin-theme-color-darker-10, --wp-admin-theme-color);
}
}
.woocommerce-product-form {
&__custom-label-input {
display: flex;

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Add summary block

View File

@ -387,6 +387,9 @@ class WC_Post_Types {
'name' => 'Product name',
),
),
array(
'woocommerce/product-summary',
),
array(
'core/columns',
array(),