From d2f7264facd1675c27f5054a671939398939b007 Mon Sep 17 00:00:00 2001 From: ramon Date: Fri, 5 May 2023 13:50:21 +1000 Subject: [PATCH] This commit: - refactors useGlobalOutput by splitting out the build logic into a separate hook so that we can pass a custom config - uses wp.date.getSettings().formats.datetimeAbbreviated for formatted date in the revisions buttons - removes unnecessary role on the ordered list - updated copy - replacing modal component with the confirm dialog component - minor code optimizations - making the revisions store methods stable - updating tests - removing shouldShowClose button prop on the editor-canvas-container update e2e --- docs/reference-guides/data/data-core.md | 12 ++++ .../src/components/global-styles/index.js | 7 ++- .../components/global-styles/test/utils.js | 15 ++--- .../global-styles/use-global-styles-output.js | 27 +++++++-- .../src/components/global-styles/utils.js | 8 +-- packages/core-data/README.md | 12 ++++ packages/core-data/src/actions.js | 5 +- packages/core-data/src/resolvers.js | 11 ++-- packages/core-data/src/selectors.ts | 2 +- .../editor-canvas-container/index.js | 13 ++--- .../global-styles/screen-revisions/index.js | 47 ++++++++++++---- .../restore-global-styles-revision-modal.js | 55 ------------------- .../screen-revisions/revisions-buttons.js | 14 ++--- ...ions.js => use-global-styles-revisions.js} | 16 ++---- ...ions.js => use-global-styles-revisions.js} | 30 +++++----- .../style-variations-container.js | 4 +- .../src/components/revisions/index.js | 10 ++-- .../keep-styles-on-block-transforms.spec.js | 2 +- .../user-global-styles-revisions.spec.js | 28 +++++----- 19 files changed, 157 insertions(+), 161 deletions(-) delete mode 100644 packages/edit-site/src/components/global-styles/screen-revisions/restore-global-styles-revision-modal.js rename packages/edit-site/src/components/global-styles/screen-revisions/test/{use-get-global-styles-revisions.js => use-global-styles-revisions.js} (80%) rename packages/edit-site/src/components/global-styles/screen-revisions/{use-get-global-styles-revisions.js => use-global-styles-revisions.js} (79%) diff --git a/docs/reference-guides/data/data-core.md b/docs/reference-guides/data/data-core.md index e8daf6e34e978..1ee04e09550e2 100644 --- a/docs/reference-guides/data/data-core.md +++ b/docs/reference-guides/data/data-core.md @@ -126,6 +126,18 @@ _Returns_ - `any`: The current theme. +### getCurrentThemeGlobalStylesRevisions + +Returns the revisions of the current global styles theme. + +_Parameters_ + +- _state_ `State`: Data state. + +_Returns_ + +- `Object | null`: The current global styles. + ### getCurrentUser Returns the current user. diff --git a/packages/block-editor/src/components/global-styles/index.js b/packages/block-editor/src/components/global-styles/index.js index 45c2b3b11ef2d..2eb6a0f3287e5 100644 --- a/packages/block-editor/src/components/global-styles/index.js +++ b/packages/block-editor/src/components/global-styles/index.js @@ -5,7 +5,10 @@ export { useSettingsForBlockElement, } from './hooks'; export { getBlockCSSSelector } from './get-block-css-selector'; -export { useGlobalStylesOutput } from './use-global-styles-output'; +export { + useGlobalStylesOutput, + useGlobalStylesOutputWithConfig, +} from './use-global-styles-output'; export { GlobalStylesContext } from './context'; export { default as TypographyPanel, @@ -20,4 +23,4 @@ export { default as ColorPanel, useHasColorPanel } from './color-panel'; export { default as EffectsPanel, useHasEffectsPanel } from './effects-panel'; export { default as FiltersPanel, useHasFiltersPanel } from './filters-panel'; export { default as AdvancedPanel } from './advanced-panel'; -export { isGlobalStyleConfigEqual } from './utils'; +export { areGlobalStyleConfigsEqual } from './utils'; diff --git a/packages/block-editor/src/components/global-styles/test/utils.js b/packages/block-editor/src/components/global-styles/test/utils.js index 1b1cc4e12703c..0bca8da6f7da9 100644 --- a/packages/block-editor/src/components/global-styles/test/utils.js +++ b/packages/block-editor/src/components/global-styles/test/utils.js @@ -2,7 +2,7 @@ * Internal dependencies */ import { - isGlobalStyleConfigEqual, + areGlobalStyleConfigsEqual, getPresetVariableFromValue, getValueFromVariable, } from '../utils'; @@ -208,9 +208,10 @@ describe( 'editor utils', () => { } ); } ); - describe( 'isGlobalStyleConfigEqual', () => { + describe( 'areGlobalStyleConfigsEqual', () => { test.each( [ - { original: null, variation: null, expected: false }, + { original: null, variation: null, expected: true }, + { original: {}, variation: {}, expected: true }, { original: {}, variation: undefined, expected: false }, { original: { @@ -250,11 +251,11 @@ describe( 'editor utils', () => { expected: true, }, ] )( - '.isGlobalStyleConfigEqual( $original, $variation )', + '.areGlobalStyleConfigsEqual( $original, $variation )', ( { original, variation, expected } ) => { - expect( isGlobalStyleConfigEqual( original, variation ) ).toBe( - expected - ); + expect( + areGlobalStyleConfigsEqual( original, variation ) + ).toBe( expected ); } ); } ); diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index 172a06a093c64..55dbab06de152 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -1106,12 +1106,17 @@ const processCSSNesting = ( css, blockSelector ) => { return processedCSS; }; -export function useGlobalStylesOutput( customMergedConfig = null ) { - let { merged: mergedConfig } = useContext( GlobalStylesContext ); - if ( !! customMergedConfig ) { - mergedConfig = customMergedConfig; - } - +/** + * Returns the global styles output using a global styles configuration. + * If wishing to generate global styles and settings based on the + * global styles config loaded in the editor context, use `useGlobalStylesOutput()`. + * The use case for a custom config is to generate bespoke styles + * and settings for previews, or other out-of-editor experiences. + * + * @param {Object} mergedConfig Global styles configuration. + * @return {Array} Array of stylesheets and settings. + */ +export function useGlobalStylesOutputWithConfig( mergedConfig = {} ) { const [ blockGap ] = useGlobalSetting( 'spacing.blockGap' ); const hasBlockGapSupport = blockGap !== null; const hasFallbackGapSupport = ! hasBlockGapSupport; // This setting isn't useful yet: it exists as a placeholder for a future explicit fallback styles support. @@ -1193,3 +1198,13 @@ export function useGlobalStylesOutput( customMergedConfig = null ) { disableLayoutStyles, ] ); } + +/** + * Returns the global styles output based on the current state of global styles config loaded in the editor context. + * + * @return {Array} Array of stylesheets and settings. + */ +export function useGlobalStylesOutput() { + const { merged: mergedConfig } = useContext( GlobalStylesContext ); + return useGlobalStylesOutputWithConfig( mergedConfig ); +} diff --git a/packages/block-editor/src/components/global-styles/utils.js b/packages/block-editor/src/components/global-styles/utils.js index 3610b4f82b5a3..0207110ae5223 100644 --- a/packages/block-editor/src/components/global-styles/utils.js +++ b/packages/block-editor/src/components/global-styles/utils.js @@ -385,7 +385,7 @@ export function scopeSelector( scope, selector ) { * ```js * const globalStyles = { styles: { typography: { fontSize: '10px' } }, settings: {} }; * const variation = { styles: { typography: { fontSize: '10000px' } }, settings: {} }; - * const isEqual = isGlobalStyleConfigEqual( globalStyles, variation ); + * const isEqual = areGlobalStyleConfigsEqual( globalStyles, variation ); * // false * ``` * @@ -394,9 +394,9 @@ export function scopeSelector( scope, selector ) { * * @return {boolean} Whether `original` and `variation` match. */ -export function isGlobalStyleConfigEqual( original, variation ) { - if ( ! original || ! variation ) { - return false; +export function areGlobalStyleConfigsEqual( original, variation ) { + if ( typeof original !== 'object' || typeof variation !== 'object' ) { + return original === variation; } return ( fastDeepEqual( original?.styles, variation?.styles ) && diff --git a/packages/core-data/README.md b/packages/core-data/README.md index 93001a45334bf..dddc3550e03b2 100644 --- a/packages/core-data/README.md +++ b/packages/core-data/README.md @@ -303,6 +303,18 @@ _Returns_ - `any`: The current theme. +### getCurrentThemeGlobalStylesRevisions + +Returns the revisions of the current global styles theme. + +_Parameters_ + +- _state_ `State`: Data state. + +_Returns_ + +- `Object | null`: The current global styles. + ### getCurrentUser Returns the current user. diff --git a/packages/core-data/src/actions.js b/packages/core-data/src/actions.js index 3ffba340c5fbd..ffae417a83cd1 100644 --- a/packages/core-data/src/actions.js +++ b/packages/core-data/src/actions.js @@ -221,10 +221,7 @@ export function receiveThemeSupports() { * * @return {Object} Action object. */ -export function __experimentalReceiveThemeGlobalStyleRevisions( - currentId, - revisions -) { +export function receiveThemeGlobalStyleRevisions( currentId, revisions ) { return { type: 'RECEIVE_THEME_GLOBAL_STYLE_REVISIONS', currentId, diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 8bf38d437a4ca..6437b75997690 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -500,7 +500,10 @@ export const __experimentalGetCurrentThemeGlobalStylesVariations = ); }; -export const __experimentalGetCurrentThemeGlobalStylesRevisions = +/** + * Fetches and returns the revisions of the current global styles theme. + */ +export const getCurrentThemeGlobalStylesRevisions = () => async ( { resolveSelect, dispatch } ) => { const globalStylesId = @@ -526,16 +529,14 @@ export const __experimentalGetCurrentThemeGlobalStylesRevisions = ] ) ) ); - dispatch.__experimentalReceiveThemeGlobalStyleRevisions( + dispatch.receiveThemeGlobalStyleRevisions( globalStylesId, revisions ); } }; -__experimentalGetCurrentThemeGlobalStylesRevisions.shouldInvalidate = ( - action -) => { +getCurrentThemeGlobalStylesRevisions.shouldInvalidate = ( action ) => { return ( action.type === 'SAVE_ENTITY_RECORD_FINISH' && action.kind === 'root' && diff --git a/packages/core-data/src/selectors.ts b/packages/core-data/src/selectors.ts index d2a00244e2f34..7513d91810967 100644 --- a/packages/core-data/src/selectors.ts +++ b/packages/core-data/src/selectors.ts @@ -1256,7 +1256,7 @@ export function getNavigationFallbackId( * * @return The current global styles. */ -export function __experimentalGetCurrentThemeGlobalStylesRevisions( +export function getCurrentThemeGlobalStylesRevisions( state: State ): Object | null { const currentGlobalStylesId = diff --git a/packages/edit-site/src/components/editor-canvas-container/index.js b/packages/edit-site/src/components/editor-canvas-container/index.js index 5cac4d33434aa..091c5b9ec60f6 100644 --- a/packages/edit-site/src/components/editor-canvas-container/index.js +++ b/packages/edit-site/src/components/editor-canvas-container/index.js @@ -46,12 +46,7 @@ const { Fill: EditorCanvasContainerFill, } = createPrivateSlotFill( SLOT_FILL_NAME ); -function EditorCanvasContainer( { - children, - showCloseButton = false, - closeButtonLabel, - onClose = () => {}, -} ) { +function EditorCanvasContainer( { children, closeButtonLabel, onClose } ) { const editorCanvasContainerView = useSelect( ( select ) => unlock( select( editSiteStore ) ).getEditorCanvasContainerView(), @@ -68,7 +63,9 @@ function EditorCanvasContainer( { [ editorCanvasContainerView ] ); function onCloseContainer() { - onClose(); + if ( typeof onClose === 'function' ) { + onClose(); + } setEditorCanvasContainerView( undefined ); setIsClosed( true ); } @@ -96,7 +93,7 @@ function EditorCanvasContainer( { return null; } - const shouldShowCloseButton = showCloseButton || !! closeButtonLabel; + const shouldShowCloseButton = onClose || closeButtonLabel; return ( diff --git a/packages/edit-site/src/components/global-styles/screen-revisions/index.js b/packages/edit-site/src/components/global-styles/screen-revisions/index.js index d6f4b663993db..a0c7085b5f49f 100644 --- a/packages/edit-site/src/components/global-styles/screen-revisions/index.js +++ b/packages/edit-site/src/components/global-styles/screen-revisions/index.js @@ -5,6 +5,7 @@ import { __ } from '@wordpress/i18n'; import { Button, __experimentalUseNavigator as useNavigator, + __experimentalConfirmDialog as ConfirmDialog, Spinner, } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; @@ -22,11 +23,10 @@ import { unlock } from '../../../private-apis'; import Revisions from '../../revisions'; import SidebarFixedBottom from '../../sidebar-edit-mode/sidebar-fixed-bottom'; import { store as editSiteStore } from '../../../store'; -import useGetGlobalStylesRevisions from './use-get-global-styles-revisions'; -import RestoreGlobalStylesRevisionModal from './restore-global-styles-revision-modal'; +import useGlobalStylesRevisions from './use-global-styles-revisions'; import RevisionsButtons from './revisions-buttons'; -const { GlobalStylesContext, isGlobalStyleConfigEqual } = unlock( +const { GlobalStylesContext, areGlobalStyleConfigsEqual } = unlock( blockEditorPrivateApis ); @@ -44,11 +44,16 @@ function ScreenRevisions() { }, [] ); const { revisions, isLoading, hasUnsavedChanges } = - useGetGlobalStylesRevisions(); - const [ globalStylesRevision, setGlobalStylesRevision ] = useState( {} ); + useGlobalStylesRevisions(); + const [ globalStylesRevision, setGlobalStylesRevision ] = + useState( userConfig ); const [ currentRevisionId, setCurrentRevisionId ] = useState( - revisions?.[ 0 ]?.id + /* + * We need this for the first render, + * otherwise the unsaved changes haven't been merged into the revisions array yet. + */ + hasUnsavedChanges ? 'unsaved' : revisions?.[ 0 ]?.id ); const [ isLoadingRevisionWithUnsavedChanges, @@ -89,7 +94,7 @@ function ScreenRevisions() { const isLoadButtonEnabled = !! globalStylesRevision?.id && - ! isGlobalStyleConfigEqual( globalStylesRevision, userConfig ); + ! areGlobalStyleConfigsEqual( globalStylesRevision, userConfig ); return ( <> @@ -135,18 +140,36 @@ function ScreenRevisions() { } } } > - { __( 'Load revision' ) } + { __( 'Apply' ) } ) } { isLoadingRevisionWithUnsavedChanges && ( - + restoreRevision( globalStylesRevision ) } + onCancel={ () => setIsLoadingRevisionWithUnsavedChanges( false ) } - onSubmit={ () => restoreRevision( globalStylesRevision ) } - /> + > + <> +

+ { __( + 'Loading this revision will discard all unsaved changes.' + ) } +

+

+ { __( + 'Do you want to replace your unsaved changes in the editor?' + ) } +

+ +
) } ); diff --git a/packages/edit-site/src/components/global-styles/screen-revisions/restore-global-styles-revision-modal.js b/packages/edit-site/src/components/global-styles/screen-revisions/restore-global-styles-revision-modal.js deleted file mode 100644 index 95e42fa8c3e8a..0000000000000 --- a/packages/edit-site/src/components/global-styles/screen-revisions/restore-global-styles-revision-modal.js +++ /dev/null @@ -1,55 +0,0 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import { - Button, - Modal, - __experimentalVStack as VStack, - __experimentalHStack as HStack, - __experimentalText as Text, -} from '@wordpress/components'; - -/** - * Returns a modal to confirm the user wants to load a revision in the presence of unsaved changes. - * - * @typedef {Object} props - * @property {Function} onClose Callback fired when the modal is closed or action cancelled. - * @property {Function} onSubmit Callback fired when the modal is submitted. - * - * @param {props} Component props. - * @return {JSX.Element} The modal component. - */ -function RestoreGlobalStylesRevisionModal( { onClose, onSubmit } ) { - return ( - -
- - - { __( - 'Loading a revision will replace any unsaved changes. Would you like continue?' - ) } - - - - - - - -
-
- ); -} - -export default RestoreGlobalStylesRevisionModal; diff --git a/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js b/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js index 7e6088d35cac3..950aeb1a780f7 100644 --- a/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js +++ b/packages/edit-site/src/components/global-styles/screen-revisions/revisions-buttons.js @@ -6,9 +6,9 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { __, _x, sprintf } from '@wordpress/i18n'; +import { __, sprintf } from '@wordpress/i18n'; import { Button } from '@wordpress/components'; -import { dateI18n, getDate, humanTimeDiff } from '@wordpress/date'; +import { dateI18n, getDate, humanTimeDiff, getSettings } from '@wordpress/date'; /** * Returns a button label for the revision. @@ -29,11 +29,9 @@ function getRevisionLabel( revision ) { } ); } - const date = getDate( revision?.modified ); const formattedDate = dateI18n( - // translators: a compact version of the revision's modified date. - _x( 'j M @ H:i', 'formatted version of revision last modified date' ), - date + getSettings().formats.datetimeAbbreviated, + getDate( revision?.modified ) ); return revision?.isLatest @@ -92,7 +90,7 @@ function RevisionsButtons( { userRevisions, currentRevisionId, onChange } ) { 'is-current': isActive, } ) } - key={ `user-styles-revision-${ id }` } + key={ id } >