[Product Block Editor]: relocate block actions in the sections area (#43555)
* handle section actions styles from section block * rename DownloadBlockEdit * remove unneeded wrap el from linked product list * put Choose an Image button in the actions section * move attribute control to block actions section * changelog * remove unused clientId prop * tweak Image button * remove `should show subtitle and "Add new" button` test
This commit is contained in:
parent
50c7e51d86
commit
8974b86a04
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: update
|
||||
|
||||
[Product Block Editor]: tweak section actions of some blocks #43555
|
|
@ -39,6 +39,7 @@ import {
|
|||
LinkedProductListBlockEmptyState,
|
||||
} from './types';
|
||||
import getRelatedProducts from '../../../utils/get-related-products';
|
||||
import { SectionActions } from '../../../components/block-slot-fill';
|
||||
|
||||
export function EmptyStateImage( {
|
||||
image,
|
||||
|
@ -157,7 +158,7 @@ export function LinkedProductListBlockEdit( {
|
|||
|
||||
return (
|
||||
<div { ...blockProps }>
|
||||
<div className="wp-block-woocommerce-product-linked-list-field__form-group-header">
|
||||
<SectionActions>
|
||||
<Button
|
||||
variant="tertiary"
|
||||
icon={ reusableBlock }
|
||||
|
@ -165,7 +166,7 @@ export function LinkedProductListBlockEdit( {
|
|||
>
|
||||
{ __( 'Choose products for me', 'woocommerce' ) }
|
||||
</Button>
|
||||
</div>
|
||||
</SectionActions>
|
||||
|
||||
<div className="wp-block-woocommerce-product-linked-list-field__form-group-content">
|
||||
<ProductSelect
|
||||
|
|
|
@ -3,12 +3,6 @@
|
|||
flex-direction: column;
|
||||
gap: $grid-unit-30;
|
||||
|
||||
&__form-group-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: right;
|
||||
}
|
||||
|
||||
.woocommerce-advice-card {
|
||||
min-height: 233px; // min height to cover the min rows rendered in the table on its back
|
||||
|
||||
|
|
|
@ -65,7 +65,9 @@ export function SectionBlockEdit( {
|
|||
) }
|
||||
</h2>
|
||||
|
||||
<BlockSlot name="section-actions" />
|
||||
<div className="wp-block-woocommerce-product-section__actions">
|
||||
<BlockSlot name="section-actions" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<BlockSlot name="section-description" />
|
||||
|
|
|
@ -63,6 +63,12 @@
|
|||
margin: 0;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
&__actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: $grid-unit;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-tooltip > .wp-block-woocommerce-product-section__heading-tooltip {
|
||||
|
|
|
@ -16,7 +16,7 @@ import { useEntityProp, useEntityId } from '@wordpress/core-data';
|
|||
import { Attributes as AttributesContainer } from '../../../components/attributes/attributes';
|
||||
import { ProductEditorBlockEditProps } from '../../../types';
|
||||
|
||||
export function Edit( {
|
||||
export function AttributesBlockEdit( {
|
||||
attributes,
|
||||
}: ProductEditorBlockEditProps< BlockAttributes > ) {
|
||||
const [ entityAttributes, setEntityAttributes ] = useEntityProp<
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Internal dependencies
|
||||
*/
|
||||
import metadata from './block.json';
|
||||
import { Edit } from './edit';
|
||||
import { AttributesBlockEdit } from './edit';
|
||||
import { registerProductEditorBlockType } from '../../../utils';
|
||||
|
||||
const { name } = metadata;
|
||||
|
@ -11,7 +11,7 @@ export { metadata, name };
|
|||
|
||||
export const settings = {
|
||||
example: {},
|
||||
edit: Edit,
|
||||
edit: AttributesBlockEdit,
|
||||
};
|
||||
|
||||
export const init = () =>
|
||||
|
|
|
@ -32,6 +32,7 @@ import {
|
|||
} from '../../../components/manage-download-limits-modal';
|
||||
import { EditDownloadsModal } from './edit-downloads-modal';
|
||||
import { UploadImage } from './upload-image';
|
||||
import { SectionActions } from '../../../components/block-slot-fill';
|
||||
|
||||
function getFileName( url?: string ) {
|
||||
const [ name ] = url?.split( '/' ).reverse() ?? [];
|
||||
|
@ -46,7 +47,7 @@ function stringifyEntityId< ID, T extends { id?: ID } >( entity: T ): T {
|
|||
return { ...entity, id: stringifyId( entity.id ) };
|
||||
}
|
||||
|
||||
export function Edit( {
|
||||
export function DownloadBlockEdit( {
|
||||
attributes,
|
||||
context: { postType },
|
||||
}: ProductEditorBlockEditProps< UploadsBlockAttributes > ) {
|
||||
|
@ -232,7 +233,7 @@ export function Edit( {
|
|||
|
||||
return (
|
||||
<div { ...blockProps }>
|
||||
<div className="wp-block-woocommerce-product-downloads-field__header">
|
||||
<SectionActions>
|
||||
{ Boolean( downloads.length ) && (
|
||||
<Button
|
||||
variant="tertiary"
|
||||
|
@ -247,7 +248,7 @@ export function Edit( {
|
|||
onUploadSuccess={ handleFileUpload }
|
||||
onUploadError={ handleUploadError }
|
||||
/>
|
||||
</div>
|
||||
</SectionActions>
|
||||
|
||||
<div className="wp-block-woocommerce-product-downloads-field__body">
|
||||
<MediaUploader
|
||||
|
|
|
@ -6,13 +6,6 @@
|
|||
$fixed-section-height: 224px;
|
||||
|
||||
.wp-block-woocommerce-product-downloads-field {
|
||||
&__header {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-bottom: $grid-unit-30;
|
||||
gap: $grid-unit;
|
||||
}
|
||||
|
||||
&__body {
|
||||
position: relative;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Internal dependencies
|
||||
*/
|
||||
import blockConfiguration from './block.json';
|
||||
import { Edit } from './edit';
|
||||
import { DownloadBlockEdit } from './edit';
|
||||
import { registerProductEditorBlockType } from '../../../utils';
|
||||
|
||||
const { name, ...metadata } = blockConfiguration;
|
||||
|
@ -11,7 +11,7 @@ export { metadata, name };
|
|||
|
||||
export const settings = {
|
||||
example: {},
|
||||
edit: Edit,
|
||||
edit: DownloadBlockEdit,
|
||||
};
|
||||
|
||||
export function init() {
|
||||
|
|
|
@ -26,6 +26,7 @@ import { useEntityProp } from '@wordpress/core-data';
|
|||
*/
|
||||
import { ProductEditorBlockEditProps } from '../../../types';
|
||||
import { PlaceHolder } from './place-holder';
|
||||
import { SectionActions } from '../../../components/block-slot-fill';
|
||||
|
||||
type UploadImage = {
|
||||
id?: number;
|
||||
|
@ -48,7 +49,7 @@ function mapUploadImageToImage( upload: UploadImage ): Image | null {
|
|||
};
|
||||
}
|
||||
|
||||
export function Edit( {
|
||||
export function ImageBlockEdit( {
|
||||
attributes,
|
||||
context,
|
||||
}: ProductEditorBlockEditProps< BlockAttributes > ) {
|
||||
|
@ -218,27 +219,36 @@ export function Edit( {
|
|||
/>
|
||||
</div>
|
||||
) : (
|
||||
<MediaUploader
|
||||
value={
|
||||
Array.isArray( propertyValue )
|
||||
? propertyValue.map( ( { id } ) => id )
|
||||
: propertyValue?.id ?? undefined
|
||||
}
|
||||
multipleSelect={ multiple ? 'add' : false }
|
||||
onError={ () => null }
|
||||
onFileUploadChange={ uploadHandler(
|
||||
'product_images_add_via_file_upload_area'
|
||||
) }
|
||||
onMediaGalleryOpen={ () => {
|
||||
recordEvent( 'product_images_media_gallery_open' );
|
||||
} }
|
||||
onSelect={ handleSelect }
|
||||
onUpload={ uploadHandler(
|
||||
'product_images_add_via_drag_and_drop_upload'
|
||||
) }
|
||||
label={ '' }
|
||||
buttonText={ __( 'Choose an image', 'woocommerce' ) }
|
||||
/>
|
||||
<SectionActions>
|
||||
<div className="woocommerce-product-form__media-uploader">
|
||||
<MediaUploader
|
||||
value={
|
||||
Array.isArray( propertyValue )
|
||||
? propertyValue.map( ( { id } ) => id )
|
||||
: propertyValue?.id ?? undefined
|
||||
}
|
||||
multipleSelect={ multiple ? 'add' : false }
|
||||
onError={ () => null }
|
||||
onFileUploadChange={ uploadHandler(
|
||||
'product_images_add_via_file_upload_area'
|
||||
) }
|
||||
onMediaGalleryOpen={ () => {
|
||||
recordEvent(
|
||||
'product_images_media_gallery_open'
|
||||
);
|
||||
} }
|
||||
onSelect={ handleSelect }
|
||||
onUpload={ uploadHandler(
|
||||
'product_images_add_via_drag_and_drop_upload'
|
||||
) }
|
||||
label={ '' }
|
||||
buttonText={ __(
|
||||
'Choose an image',
|
||||
'woocommerce'
|
||||
) }
|
||||
/>
|
||||
</div>
|
||||
</SectionActions>
|
||||
) }
|
||||
</div>
|
||||
{ isImageGalleryVisible ? (
|
||||
|
|
|
@ -1,19 +1,6 @@
|
|||
@import "./place-holder/style.scss";
|
||||
|
||||
.wp-block-woocommerce-product-images-field {
|
||||
.woocommerce-media-uploader {
|
||||
text-align: left;
|
||||
|
||||
.components-drop-zone {
|
||||
// This height cannot be higher than this, otherwise it will invade the area from the block below.
|
||||
min-height: 84px;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-media-uploader__label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.woocommerce-sortable {
|
||||
margin-top: 0;
|
||||
padding: 0;
|
||||
|
@ -31,3 +18,16 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-product-form__media-uploader {
|
||||
.woocommerce-media-uploader {
|
||||
.components-drop-zone {
|
||||
// This height cannot be higher than this, otherwise it will invade the area from the block below.
|
||||
min-height: 84px;
|
||||
}
|
||||
|
||||
&__label {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Internal dependencies
|
||||
*/
|
||||
import metadata from './block.json';
|
||||
import { Edit } from './edit';
|
||||
import { ImageBlockEdit } from './edit';
|
||||
import { registerProductEditorBlockType } from '../../../utils';
|
||||
|
||||
const { name } = metadata;
|
||||
|
@ -11,7 +11,7 @@ export { metadata, name };
|
|||
|
||||
export const settings = {
|
||||
example: {},
|
||||
edit: Edit,
|
||||
edit: ImageBlockEdit,
|
||||
};
|
||||
|
||||
export const init = () =>
|
||||
|
|
|
@ -125,22 +125,20 @@ export function ProductListBlockEdit( {
|
|||
return (
|
||||
<div { ...blockProps }>
|
||||
<SectionActions>
|
||||
<div className="wp-block-woocommerce-product-list-field__header">
|
||||
{ ! isLoading && groupedProducts.length > 0 && (
|
||||
<Button
|
||||
onClick={ handleReorderProductsButtonClick }
|
||||
variant="tertiary"
|
||||
>
|
||||
{ __( 'Reorder', 'woocommerce' ) }
|
||||
</Button>
|
||||
) }
|
||||
{ ! isLoading && groupedProducts.length > 0 && (
|
||||
<Button
|
||||
onClick={ handleAddProductsButtonClick }
|
||||
variant="secondary"
|
||||
onClick={ handleReorderProductsButtonClick }
|
||||
variant="tertiary"
|
||||
>
|
||||
{ __( 'Add products', 'woocommerce' ) }
|
||||
{ __( 'Reorder', 'woocommerce' ) }
|
||||
</Button>
|
||||
</div>
|
||||
) }
|
||||
<Button
|
||||
onClick={ handleAddProductsButtonClick }
|
||||
variant="secondary"
|
||||
>
|
||||
{ __( 'Add products', 'woocommerce' ) }
|
||||
</Button>
|
||||
</SectionActions>
|
||||
|
||||
<div className="wp-block-woocommerce-product-list-field__body">
|
||||
|
|
|
@ -3,13 +3,6 @@
|
|||
flex-direction: column;
|
||||
gap: $grid-unit-30;
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: end;
|
||||
gap: $gap-smaller;
|
||||
}
|
||||
|
||||
&__body {
|
||||
.woocommerce-advice-card {
|
||||
padding: $grid-unit-60;
|
||||
|
|
|
@ -34,6 +34,7 @@ import { NewAttributeModal } from './new-attribute-modal';
|
|||
import { RemoveConfirmationModal } from '../remove-confirmation-modal';
|
||||
import { TRACKS_SOURCE } from '../../constants';
|
||||
import { AttributeEmptyStateSkeleton } from './attribute-empty-state-skeleton';
|
||||
import { SectionActions } from '../block-slot-fill';
|
||||
|
||||
type AttributeControlProps = {
|
||||
value: EnhancedProductAttribute[];
|
||||
|
@ -236,15 +237,17 @@ export const AttributeControl: React.FC< AttributeControlProps > = ( {
|
|||
|
||||
return (
|
||||
<div className="woocommerce-attribute-field">
|
||||
<Button
|
||||
variant="secondary"
|
||||
className="woocommerce-add-attribute-list-item__add-button"
|
||||
onClick={ () => {
|
||||
openNewModal();
|
||||
} }
|
||||
>
|
||||
{ uiStrings.newAttributeListItemLabel }
|
||||
</Button>
|
||||
<SectionActions>
|
||||
<Button
|
||||
variant="secondary"
|
||||
className="woocommerce-add-attribute-list-item__add-button"
|
||||
onClick={ () => {
|
||||
openNewModal();
|
||||
} }
|
||||
>
|
||||
{ uiStrings.newAttributeListItemLabel }
|
||||
</Button>
|
||||
</SectionActions>
|
||||
{ uiStrings.notice && (
|
||||
<Notice
|
||||
isDismissible={ true }
|
||||
|
|
|
@ -115,15 +115,6 @@ describe( 'AttributeControl', () => {
|
|||
jest.clearAllMocks();
|
||||
} );
|
||||
|
||||
describe( 'empty state', () => {
|
||||
it( 'should show subtitle and "Add new" button', () => {
|
||||
const { queryByText } = render(
|
||||
<AttributeControl value={ [] } onChange={ () => {} } />
|
||||
);
|
||||
expect( queryByText( 'Add new' ) ).toBeInTheDocument();
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'should render the list of all attributes', async () => {
|
||||
act( () => {
|
||||
render(
|
||||
|
|
Loading…
Reference in New Issue