[Product Block Editor]: Handle Modal Editor visibility from UI state (#41859)

This commit is contained in:
Damián Suárez 2023-12-04 18:52:02 -03:00 committed by GitHub
commit 37e824eca8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 189 additions and 6 deletions

View File

@ -0,0 +1,4 @@
Significance: patch
Type: add
[Product Block Editor]: introduce UI state

View File

@ -2,13 +2,14 @@
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { createElement, useState } from '@wordpress/element';
import { createElement } from '@wordpress/element';
import {
BlockAttributes,
BlockInstance,
parse,
serialize,
} from '@wordpress/blocks';
import { useSelect, useDispatch } from '@wordpress/data';
import { Button } from '@wordpress/components';
import { useWooBlockProps } from '@woocommerce/block-templates';
import { recordEvent } from '@woocommerce/tracks';
@ -21,6 +22,7 @@ import { ContentPreview } from '../../../components/content-preview';
import { ModalEditor } from '../../../components/modal-editor';
import { ProductEditorBlockEditProps } from '../../../types';
import ModalEditorWelcomeGuide from '../../../components/modal-editor-welcome-guide';
import { store as productEditorUiStore } from '../../../store/product-editor-ui';
/**
* Internal dependencies
@ -50,19 +52,26 @@ export function DescriptionBlockEdit( {
attributes,
}: ProductEditorBlockEditProps< BlockAttributes > ) {
const blockProps = useWooBlockProps( attributes );
const [ isModalOpen, setIsModalOpen ] = useState( false );
const [ description, setDescription ] = useEntityProp< string >(
'postType',
'product',
'description'
);
// Check if the Modal editor is open from the store.
const isModalEditorOpen = useSelect( ( select ) => {
return select( productEditorUiStore ).isModalEditorOpen();
}, [] );
const { openModalEditor, closeModalEditor } =
useDispatch( productEditorUiStore );
return (
<div { ...blockProps }>
<Button
variant="secondary"
onClick={ () => {
setIsModalOpen( true );
openModalEditor();
recordEvent( 'product_add_description_click' );
} }
>
@ -70,7 +79,8 @@ export function DescriptionBlockEdit( {
? __( 'Edit description', 'woocommerce' )
: __( 'Add description', 'woocommerce' ) }
</Button>
{ isModalOpen && (
{ isModalEditorOpen && (
<ModalEditor
initialBlocks={ parse( description ) }
onChange={ ( blocks ) => {
@ -79,14 +89,16 @@ export function DescriptionBlockEdit( {
);
setDescription( html );
} }
onClose={ () => setIsModalOpen( false ) }
onClose={ closeModalEditor }
title={ __( 'Edit description', 'woocommerce' ) }
/>
) }
{ !! description.length && (
<ContentPreview content={ description } />
) }
{ isModalOpen && <ModalEditorWelcomeGuide /> }
{ isModalEditorOpen && <ModalEditorWelcomeGuide /> }
</div>
);
}

View File

@ -1,3 +1,8 @@
/**
* Internal dependencies
*/
import registerProductEditorUiStore from './store/product-editor-ui';
export * from './components';
export {
DETAILS_SECTION_ID,
@ -16,6 +21,11 @@ export * from './types';
*/
export * from './utils';
/*
* Store
*/
export * from './store/product-editor-ui';
/**
* Hooks
*/
@ -23,3 +33,6 @@ export * from './hooks';
export { PostTypeContext } from './contexts/post-type-context';
export { useValidation, useValidations } from './contexts/validation-context';
export * from './contexts/validation-context/types';
// Init the store
registerProductEditorUiStore();

View File

@ -0,0 +1,29 @@
# WooCommerce Product Editor UI Store
This module provides a @wordpress/data store for managing the UI state of a WooCommerce Product Editor.
## Structure
Defines action types for the UI state:
- `ACTION_MODAL_EDITOR_OPEN`
- `ACTION_MODAL_EDITOR_CLOSE`
### Actions
- `openModalEditor`
- `closeModalEditor`
### Selectors
Selector function:
- `isModalEditorOpen`
### Store
Registers the WooCommerce Product Editor UI store with the following:
- Store Name: `woo/product-editor-ui`
## Usage

View File

@ -0,0 +1,20 @@
/**
* Internal dependencies
*/
import {
ACTION_MODAL_EDITOR_CLOSE,
ACTION_MODAL_EDITOR_OPEN,
} from './constants';
const modalEditorActions = {
openModalEditor: () => ( {
type: ACTION_MODAL_EDITOR_OPEN,
} ),
closeModalEditor: () => ( {
type: ACTION_MODAL_EDITOR_CLOSE,
} ),
};
export default {
...modalEditorActions,
};

View File

@ -0,0 +1,5 @@
/**
* Full editor actions
*/
export const ACTION_MODAL_EDITOR_OPEN = 'MODAL_EDITOROPEN';
export const ACTION_MODAL_EDITOR_CLOSE = 'MODAL_EDITORCLOSE';

View File

@ -0,0 +1,26 @@
/**
* External dependencies
*/
import { createReduxStore, register } from '@wordpress/data';
/**
* Internal dependencies
*/
import actions from './actions';
import selectors from './selectors';
import reducer from './reducer';
/**
* Types
*/
export const store = 'woo/product-editor-ui';
const wooProductEditorUiStore = createReduxStore( store, {
actions,
selectors,
reducer,
} );
export default function registerProductEditorUiStore() {
register( wooProductEditorUiStore );
}

View File

@ -0,0 +1,44 @@
/**
* Internal dependencies
*/
import {
ACTION_MODAL_EDITOR_CLOSE,
ACTION_MODAL_EDITOR_OPEN,
} from './constants';
import type {
ProductEditorModalEditorAction,
ProductEditorUIStateProps,
} from './types';
/**
* Types & Constants
*/
const INITIAL_STATE: ProductEditorUIStateProps = {
modalEditor: {
isOpen: false,
},
};
export default function reducer(
state = INITIAL_STATE,
action: ProductEditorModalEditorAction
) {
switch ( action.type ) {
case ACTION_MODAL_EDITOR_OPEN:
return {
...state,
modalEditor: {
isOpen: true,
},
};
case ACTION_MODAL_EDITOR_CLOSE:
return {
...state,
modalEditor: {
isOpen: false,
},
};
}
return state;
}

View File

@ -0,0 +1,13 @@
/**
* Internal dependencies
*/
import type { ProductEditorUIStateProps } from './types';
export default {
isModalEditorOpen: function isModalEditorOpen(
state: ProductEditorUIStateProps
) {
return state.modalEditor.isOpen;
},
};

View File

@ -0,0 +1,17 @@
/**
* Internal dependencies
*/
import {
ACTION_MODAL_EDITOR_CLOSE,
ACTION_MODAL_EDITOR_OPEN,
} from './constants';
export type ProductEditorUIStateProps = {
modalEditor: {
isOpen: boolean;
};
};
export type ProductEditorModalEditorAction = {
type: typeof ACTION_MODAL_EDITOR_OPEN | typeof ACTION_MODAL_EDITOR_CLOSE;
};