diff --git a/lib/compat/wordpress-6.3/class-gutenberg-rest-global-styles-controller-6-3.php b/lib/compat/wordpress-6.3/class-gutenberg-rest-global-styles-controller-6-3.php index 6a6fad620b80c1..1999cc748cb520 100644 --- a/lib/compat/wordpress-6.3/class-gutenberg-rest-global-styles-controller-6-3.php +++ b/lib/compat/wordpress-6.3/class-gutenberg-rest-global-styles-controller-6-3.php @@ -34,79 +34,11 @@ public function register_routes() { ), ), ), - 'schema' => array( $this, 'get_public_item_schema' ), ) ); parent::register_routes(); } - /** - * Retrieves the global styles type' schema, conforming to JSON Schema. - * - * @since 5.9.0 - * @since 6.3 Adds `revisions` schema. - * - * @return array Item schema data. - */ - public function get_item_schema() { - if ( $this->schema ) { - return $this->add_additional_fields_schema( $this->schema ); - } - - $schema = array( - '$schema' => 'http://json-schema.org/draft-04/schema#', - 'title' => $this->post_type, - 'type' => 'object', - 'properties' => array( - 'id' => array( - 'description' => __( 'ID of global styles config.', 'gutenberg' ), - 'type' => 'string', - 'context' => array( 'embed', 'view', 'edit' ), - 'readonly' => true, - ), - 'styles' => array( - 'description' => __( 'Global styles.', 'gutenberg' ), - 'type' => array( 'object' ), - 'context' => array( 'view', 'edit' ), - ), - 'settings' => array( - 'description' => __( 'Global settings.', 'gutenberg' ), - 'type' => array( 'object' ), - 'context' => array( 'view', 'edit' ), - ), - 'title' => array( - 'description' => __( 'Title of the global styles variation.', 'gutenberg' ), - 'type' => array( 'object', 'string' ), - 'default' => '', - 'context' => array( 'embed', 'view', 'edit' ), - 'properties' => array( - 'raw' => array( - 'description' => __( 'Title for the global styles variation, as it exists in the database.', 'gutenberg' ), - 'type' => 'string', - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'rendered' => array( - 'description' => __( 'HTML title for the post, transformed for display.', 'gutenberg' ), - 'type' => 'string', - 'context' => array( 'view', 'edit', 'embed' ), - 'readonly' => true, - ), - ), - ), - 'revisions' => array( - 'description' => __( 'Global styles revisions.', 'gutenberg' ), - 'type' => array( 'object' ), - 'context' => array( 'view', 'edit' ), - 'readonly' => true, - ), - ), - ); - - $this->schema = $schema; - - return $this->add_additional_fields_schema( $this->schema ); - } - /** * Returns revisions of the given global styles config custom post type. * @@ -129,7 +61,6 @@ public function get_item_revisions( $request ) { $user_theme_revisions = wp_get_post_revisions( $post->ID, array( - 'author' => $post->post_author, 'posts_per_page' => 100, ) ); @@ -148,13 +79,22 @@ public function get_item_revisions( $request ) { $revisions[] = array( 'styles' => ! empty( $config['styles'] ) ? $config['styles'] : new stdClass(), 'settings' => ! empty( $config['settings'] ) ? $config['settings'] : new stdClass(), - 'title' => array( + 'date' => array( 'raw' => $revision->post_modified, /* translators: 1: Human-readable time difference, 2: short date combined to show rendered revision date. */ 'rendered' => sprintf( __( '%1$s (%2$s)', 'gutenberg' ), $time_ago, $date_short ), ), 'id' => $id, 'is_latest' => array_key_first( $user_theme_revisions ) === $id, + 'author' => array( + 'display_name' => get_the_author_meta( 'display_name', $post->post_author ), + 'avatar_url' => get_avatar_url( + $post->post_author, + array( + 'size' => 24, + ) + ), + ), ); } } diff --git a/packages/core-data/src/resolvers.js b/packages/core-data/src/resolvers.js index 4a51b51c2d84a3..824a1f2455773d 100644 --- a/packages/core-data/src/resolvers.js +++ b/packages/core-data/src/resolvers.js @@ -508,17 +508,9 @@ export const __experimentalGetCurrentThemeGlobalStylesRevisions = const revisionsURL = currentGlobalStyles?._links?.[ 'version-history' ]?.[ 0 ]?.href; if ( revisionsURL ) { - const restRevisions = await apiFetch( { + const revisions = await apiFetch( { url: revisionsURL, } ); - const revisions = restRevisions?.map( ( revision ) => - Object.fromEntries( - Object.entries( revision ).map( ( [ key, value ] ) => [ - camelCase( key ), - value, - ] ) - ) - ); dispatch.__experimentalReceiveThemeGlobalStyleRevisions( currentGlobalStyles?.id, revisions diff --git a/packages/edit-site/src/components/global-styles/screen-revisions.js b/packages/edit-site/src/components/global-styles/screen-revisions.js index 75b446c96869ae..4499024f3941e0 100644 --- a/packages/edit-site/src/components/global-styles/screen-revisions.js +++ b/packages/edit-site/src/components/global-styles/screen-revisions.js @@ -22,7 +22,6 @@ import { useMemo, } from '@wordpress/element'; import { - check, undo as undoIcon, redo as redoIcon, backup as backupIcon, @@ -44,11 +43,27 @@ const { GlobalStylesContext } = unlock( blockEditorPrivateApis ); function RevisionsSelect( { userRevisions, currentRevisionId, onChange } ) { const userRevisionsOptions = useMemo( () => { return ( userRevisions ?? [] ).map( ( revision ) => { + const { id, date, author, is_latest: isLatest } = revision; + const revisionTitle = decodeEntities( date?.rendered ); return { - value: revision.id, - label: revision.isLatest - ? __( 'Latest saved revision' ) - : decodeEntities( revision.title.rendered ), + value: id, + label: isLatest + ? sprintf( + /* translators: %(name)s author display name, %(date)s: human-friendly revision creation date */ + __( 'Current revision by %(name)s from %(date)s)' ), + { + name: author?.display_name, + date: revisionTitle, + } + ) + : sprintf( + /* translators: %(name)s author display name, %(date)s: human-friendly revision creation date */ + __( 'Revision by %(name)s from %(date)s' ), + { + name: author?.display_name, + date: revisionTitle, + } + ), }; } ); }, [ userRevisions ] ); @@ -72,16 +87,18 @@ function RevisionsSelect( { userRevisions, currentRevisionId, onChange } ) { function RevisionsButtons( { userRevisions, currentRevisionId, onChange } ) { return ( <> -
    +
      { userRevisions.map( ( revision ) => { - revision.is_latest = undefined; - const isActive = revision?.id === currentRevisionId; - const revisionTitle = decodeEntities( - revision.title.rendered - ); + const { id, date, author, is_latest: isLatest } = revision; + const isActive = id === currentRevisionId; + const revisionTitle = decodeEntities( date?.rendered ); return ( -
    1. +
    2. @@ -174,7 +222,7 @@ function ScreenRevisions() { canRestoreCachedConfig && ! isGlobalStyleConfigEqual( cachedUserConfig, - userRevisions.find( ( revision ) => revision.isLatest === true ) + userRevisions.find( ( revision ) => revision.is_latest === true ) ); return ( @@ -187,7 +235,7 @@ function ScreenRevisions() { />
      - { __( 'REVISIONS' ) } + { __( 'Revisions' ) } { + const { canEditCSS, revisionsCount } = useSelect( ( select ) => { const { getEntityRecord, __experimentalGetCurrentGlobalStyles } = select( coreStore ); const currentGlobalStyles = __experimentalGetCurrentGlobalStyles(); const globalStyles = currentGlobalStyles?.id ? getEntityRecord( 'root', 'globalStyles', currentGlobalStyles?.id ) : undefined; - const revisionsCount = - globalStyles?._links?.[ 'version-history' ]?.[ 0 ]?.count; return { canEditCSS: !! globalStyles?._links?.[ 'wp:action-edit-css' ] ?? false, - hasRevisions: revisionsCount && revisionsCount > 1, + revisionsCount: + ( globalStyles?._links?.[ 'version-history' ]?.[ 0 ]?.count ?? + 0 ) + 1, }; }, [] ); const { useGlobalStylesReset } = unlock( blockEditorPrivateApis ); @@ -71,6 +71,7 @@ function GlobalStylesActionMenu() { const { goTo } = useNavigator(); const loadCustomCSS = () => goTo( '/css' ); const loadRevisions = () => goTo( '/revisions' ); + const hasRevisions = revisionsCount >= 2; return ( { // There are not enough revisions to show the revisions UI yet, so let's create some. if ( currentRevisions.length < 1 ) { - await expect( - page.getByRole( 'button', { - name: 'Styles revisions', - } ) - ).not.toBeVisible(); // Change a style and save it. await page .getByRole( 'button', { name: 'Typography styles' } ) @@ -74,36 +69,25 @@ test.describe( 'Global styles revisions', () => { await page .getByRole( 'button', { name: 'Typography Text styles' } ) .click(); - await page.getByRole( 'button', { name: 'Appearance' } ).click(); - await page.getByRole( 'option', { name: 'Thin Italic' } ).click(); + await page.click( + 'role=radiogroup[name="Font size"i] >> role=radio[name="Large"i]' + ); await editor.saveSiteEditorEntities(); // Change a style and save it again just for good luck. // We need more than 2 revisions to show the UI. - await page.getByRole( 'button', { name: 'Appearance' } ).click(); - await page.getByRole( 'option', { name: 'Light' } ).click(); - await editor.saveSiteEditorEntities(); - - // Back to styles pane. await page.click( - 'role=button[name="Navigate to the previous view"i]' - ); - await page.click( - 'role=button[name="Navigate to the previous view"i]' + 'role=radiogroup[name="Font size"i] >> role=radio[name="Medium"i]' ); + await editor.saveSiteEditorEntities(); // Now there should be enough revisions to show the revisions UI. - await expect( - page.getByRole( 'button', { - name: 'Styles actions', - } ) - ).toBeVisible(); await page .getByRole( 'button', { name: 'Styles actions' } ) .click(); await page.getByRole( 'menuitem', { name: 'Revisions' } ).click(); const revisionButtons = page.locator( - 'role=button[name=/^Restore revision/]' + 'role=group[name="Global styles revisions"i] >> role=button[name=/^Revision by /]' ); await expect( revisionButtons ).toHaveCount( @@ -111,17 +95,12 @@ test.describe( 'Global styles revisions', () => { ); } else { // There are some revisions. Let's check that the UI looks how we expect it to. - await expect( - page.getByRole( 'button', { - name: 'Styles actions', - } ) - ).toBeVisible(); await page .getByRole( 'button', { name: 'Styles actions' } ) .click(); await page.getByRole( 'menuitem', { name: 'Revisions' } ).click(); const revisionButtons = page.locator( - 'role=button[name=/^Restore revision/]' + 'role=group[name="Global styles revisions"i] >> role=button[name=/^Revision by /]' ); await expect( revisionButtons ).toHaveCount(