From a1d941e23033efc3a8a5147a67451bdbb03f188b Mon Sep 17 00:00:00 2001
From: Andrew Serong <14988353+andrewserong@users.noreply.github.com>
Date: Tue, 6 Jun 2023 14:06:40 +1000
Subject: [PATCH] Styles Screen: Add link to global styles revisions (#51149)

* Styles Screen: Add link to global styles revisions

* Add button label

* Update packages/edit-site/src/components/global-styles/ui.js

Co-authored-by: Ramon <ramonjd@users.noreply.github.com>

* Small code quality improvements

* Try sticking the navigation screen footer to the bottom of the screen at all times

* Add as span to the HStack

* Update border radius and left padding so that the button lines up

* Remove classnames call

* Add redirect for style book, too

* Only redirect to root when opening the style book on the revisions screen

* Use truthy check for editor canvas container when redirecting from the revisions screen.

Co-authored-by: ramon <ramonjd@gmail.com>

---------

Co-authored-by: Ramon <ramonjd@users.noreply.github.com>
Co-authored-by: ramon <ramonjd@gmail.com>
---
 .../src/components/global-styles/ui.js        |  28 ++++
 .../index.js                                  | 100 ++++++++++++--
 .../style.scss                                |  15 ++
 .../sidebar-navigation-screen-page/index.js   |   2 +-
 .../sidebar-navigation-screen-page/style.scss |   6 +
 .../sidebar-navigation-screen/index.js        | 128 +++++++++---------
 .../sidebar-navigation-screen/style.scss      |  13 ++
 .../src/components/sidebar/style.scss         |   3 +
 packages/edit-site/src/style.scss             |   1 +
 9 files changed, 222 insertions(+), 74 deletions(-)
 create mode 100644 packages/edit-site/src/components/sidebar-navigation-screen-global-styles/style.scss

diff --git a/packages/edit-site/src/components/global-styles/ui.js b/packages/edit-site/src/components/global-styles/ui.js
index f15fcff11aa560..953904e314928c 100644
--- a/packages/edit-site/src/components/global-styles/ui.js
+++ b/packages/edit-site/src/components/global-styles/ui.js
@@ -237,6 +237,33 @@ function GlobalStylesBlockLink() {
 	}, [ selectedBlockClientId, selectedBlockName, blockHasGlobalStyles ] );
 }
 
+function GlobalStylesEditorCanvasContainerLink() {
+	const { goTo, location } = useNavigator();
+	const editorCanvasContainerView = useSelect(
+		( select ) =>
+			unlock( select( editSiteStore ) ).getEditorCanvasContainerView(),
+		[]
+	);
+
+	// If the user switches the editor canvas container view, redirect
+	// to the appropriate screen. This effectively allows deep linking to the
+	// desired screens from outside the global styles navigation provider.
+	useEffect( () => {
+		if ( editorCanvasContainerView === 'global-styles-revisions' ) {
+			// Switching to the revisions container view should
+			// redirect to the revisions screen.
+			goTo( '/revisions' );
+		} else if (
+			!! editorCanvasContainerView &&
+			location?.path === '/revisions'
+		) {
+			// Switching to any container other than revisions should
+			// redirect from the revisions screen to the root global styles screen.
+			goTo( '/' );
+		}
+	}, [ editorCanvasContainerView, location?.path, goTo ] );
+}
+
 function GlobalStylesUI() {
 	const blocks = getBlockTypes();
 	const editorCanvasContainerView = useSelect(
@@ -326,6 +353,7 @@ function GlobalStylesUI() {
 
 			<GlobalStylesActionMenu />
 			<GlobalStylesBlockLink />
+			<GlobalStylesEditorCanvasContainerLink />
 		</NavigatorProvider>
 	);
 }
diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js
index 8e6f080e74a80a..926f8b8611af0d 100644
--- a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js
+++ b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js
@@ -2,12 +2,19 @@
  * WordPress dependencies
  */
 import { __ } from '@wordpress/i18n';
-import { edit, seen } from '@wordpress/icons';
+import { backup, edit, seen } from '@wordpress/icons';
 import { useSelect, useDispatch } from '@wordpress/data';
 import { store as coreStore } from '@wordpress/core-data';
-import { __experimentalNavigatorButton as NavigatorButton } from '@wordpress/components';
+import {
+	Icon,
+	__experimentalNavigatorButton as NavigatorButton,
+	__experimentalVStack as HStack,
+	__experimentalVStack as VStack,
+} from '@wordpress/components';
 import { useViewportMatch } from '@wordpress/compose';
 import { BlockEditorProvider } from '@wordpress/block-editor';
+import { humanTimeDiff } from '@wordpress/date';
+import { useCallback } from '@wordpress/element';
 
 /**
  * Internal dependencies
@@ -19,6 +26,7 @@ import { store as editSiteStore } from '../../store';
 import SidebarButton from '../sidebar-button';
 import SidebarNavigationItem from '../sidebar-navigation-item';
 import StyleBook from '../style-book';
+import useGlobalStylesRevisions from '../global-styles/screen-revisions/use-global-styles-revisions';
 
 const noop = () => {};
 
@@ -74,13 +82,64 @@ function SidebarNavigationScreenGlobalStylesContent() {
 			onChange={ noop }
 			onInput={ noop }
 		>
-			<div className="edit-site-sidebar-navigation-screen-global-styles__content">
-				<StyleVariationsContainer />
-			</div>
+			<StyleVariationsContainer />
 		</BlockEditorProvider>
 	);
 }
 
+function SidebarNavigationScreenGlobalStylesFooter( { onClickRevisions } ) {
+	const { revisions, isLoading } = useGlobalStylesRevisions();
+	const { revisionsCount } = useSelect( ( select ) => {
+		const { getEntityRecord, __experimentalGetCurrentGlobalStylesId } =
+			select( coreStore );
+
+		const globalStylesId = __experimentalGetCurrentGlobalStylesId();
+		const globalStyles = globalStylesId
+			? getEntityRecord( 'root', 'globalStyles', globalStylesId )
+			: undefined;
+
+		return {
+			revisionsCount:
+				globalStyles?._links?.[ 'version-history' ]?.[ 0 ]?.count ?? 0,
+		};
+	}, [] );
+
+	const hasRevisions = revisionsCount >= 2;
+	const modified = revisions?.[ 0 ]?.modified;
+
+	if ( ! hasRevisions || isLoading || ! modified ) {
+		return null;
+	}
+
+	return (
+		<VStack className="edit-site-sidebar-navigation-screen-global-styles__footer">
+			<SidebarNavigationItem
+				className="edit-site-sidebar-navigation-screen-global-styles__revisions"
+				label={ __( 'Revisions' ) }
+				onClick={ onClickRevisions }
+			>
+				<HStack
+					as="span"
+					alignment="center"
+					spacing={ 5 }
+					direction="row"
+					justify="space-between"
+				>
+					<span className="edit-site-sidebar-navigation-screen-global-styles__revisions__label">
+						{ __( 'Last modified' ) }
+					</span>
+					<span>
+						<time dateTime={ modified }>
+							{ humanTimeDiff( modified ) }
+						</time>
+					</span>
+					<Icon icon={ backup } style={ { fill: 'currentcolor' } } />
+				</HStack>
+			</SidebarNavigationItem>
+		</VStack>
+	);
+}
+
 export default function SidebarNavigationScreenGlobalStyles() {
 	const { openGeneralSidebar } = useDispatch( editSiteStore );
 	const isMobileViewport = useViewportMatch( 'medium', '<' );
@@ -95,19 +154,31 @@ export default function SidebarNavigationScreenGlobalStyles() {
 		[]
 	);
 
-	const openGlobalStyles = async () =>
-		Promise.all( [
-			setCanvasMode( 'edit' ),
-			openGeneralSidebar( 'edit-site/global-styles' ),
-		] );
+	const openGlobalStyles = useCallback(
+		async () =>
+			Promise.all( [
+				setCanvasMode( 'edit' ),
+				openGeneralSidebar( 'edit-site/global-styles' ),
+			] ),
+		[ setCanvasMode, openGeneralSidebar ]
+	);
 
-	const openStyleBook = async () => {
+	const openStyleBook = useCallback( async () => {
 		await openGlobalStyles();
 		// Open the Style Book once the canvas mode is set to edit,
 		// and the global styles sidebar is open. This ensures that
 		// the Style Book is not prematurely closed.
 		setEditorCanvasContainerView( 'style-book' );
-	};
+	}, [ openGlobalStyles, setEditorCanvasContainerView ] );
+
+	const openRevisions = useCallback( async () => {
+		await openGlobalStyles();
+		// Open the global styles revisions once the canvas mode is set to edit,
+		// and the global styles sidebar is open. The global styles UI is responsible
+		// for redirecting to the revisions screen once the editor canvas container
+		// has been set to 'global-styles-revisions'.
+		setEditorCanvasContainerView( 'global-styles-revisions' );
+	}, [ openGlobalStyles, setEditorCanvasContainerView ] );
 
 	return (
 		<>
@@ -117,6 +188,11 @@ export default function SidebarNavigationScreenGlobalStyles() {
 					'Choose a different style combination for the theme styles.'
 				) }
 				content={ <SidebarNavigationScreenGlobalStylesContent /> }
+				footer={
+					<SidebarNavigationScreenGlobalStylesFooter
+						onClickRevisions={ openRevisions }
+					/>
+				}
 				actions={
 					<>
 						{ ! isMobileViewport && (
diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/style.scss
new file mode 100644
index 00000000000000..26ac157cb24bef
--- /dev/null
+++ b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/style.scss
@@ -0,0 +1,15 @@
+.edit-site-sidebar-navigation-screen-global-styles__footer {
+	padding-left: $grid-unit-15;
+}
+
+.edit-site-sidebar-navigation-screen-global-styles__revisions {
+	border-radius: $radius-block-ui;
+
+	&:not(:hover) {
+		color: $gray-200;
+
+		.edit-site-sidebar-navigation-screen-global-styles__revisions__label {
+			color: $gray-600;
+		}
+	}
+}
diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-page/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-page/index.js
index 5e0c113b3544ad..176470b3576b84 100644
--- a/packages/edit-site/src/components/sidebar-navigation-screen-page/index.js
+++ b/packages/edit-site/src/components/sidebar-navigation-screen-page/index.js
@@ -147,7 +147,7 @@ export default function SidebarNavigationScreenPage() {
 					<HStack
 						spacing={ 5 }
 						alignment="left"
-						className="edit-site-sidebar-navigation-screen-page__details"
+						className="edit-site-sidebar-navigation-screen-page__details edit-site-sidebar-navigation-screen-page__footer"
 					>
 						<Text className="edit-site-sidebar-navigation-screen-page__details-label">
 							{ __( 'Last modified' ) }
diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-page/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen-page/style.scss
index 6ec9e565f9e8ff..c58e9f09392465 100644
--- a/packages/edit-site/src/components/sidebar-navigation-screen-page/style.scss
+++ b/packages/edit-site/src/components/sidebar-navigation-screen-page/style.scss
@@ -61,6 +61,12 @@
 	}
 }
 
+.edit-site-sidebar-navigation-screen-page__footer {
+	padding-top: $grid-unit-10;
+	padding-bottom: $grid-unit-10;
+	padding-left: $grid-unit-20;
+}
+
 .edit-site-sidebar-navigation-screen-page__details {
 	.edit-site-sidebar-navigation-screen-page__details-label {
 		color: $gray-600;
diff --git a/packages/edit-site/src/components/sidebar-navigation-screen/index.js b/packages/edit-site/src/components/sidebar-navigation-screen/index.js
index 67e22721e78f0b..026cbaba8e860f 100644
--- a/packages/edit-site/src/components/sidebar-navigation-screen/index.js
+++ b/packages/edit-site/src/components/sidebar-navigation-screen/index.js
@@ -42,74 +42,80 @@ export default function SidebarNavigationScreen( {
 	const theme = getTheme( currentlyPreviewingTheme() );
 
 	return (
-		<VStack spacing={ 0 }>
-			<HStack
-				spacing={ 4 }
-				alignment="flex-start"
-				className="edit-site-sidebar-navigation-screen__title-icon"
+		<>
+			<VStack
+				className="edit-site-sidebar-navigation-screen__main"
+				spacing={ 0 }
+				justify="flex-start"
 			>
-				{ ! isRoot ? (
-					<NavigatorToParentButton
-						as={ SidebarButton }
-						icon={ isRTL() ? chevronRight : chevronLeft }
-						label={ __( 'Back' ) }
-					/>
-				) : (
-					<SidebarButton
-						icon={ isRTL() ? chevronRight : chevronLeft }
-						label={
-							! isPreviewingTheme()
-								? __( 'Go back to the Dashboard' )
-								: __( 'Go back to the theme showcase' )
-						}
-						href={
-							! isPreviewingTheme()
-								? dashboardLink || 'index.php'
-								: 'themes.php'
-						}
-					/>
-				) }
-				<Heading
-					className="edit-site-sidebar-navigation-screen__title"
-					color={ 'white' }
-					level={ 2 }
-					size={ 20 }
+				<HStack
+					spacing={ 4 }
+					alignment="flex-start"
+					className="edit-site-sidebar-navigation-screen__title-icon"
 				>
-					{ ! isPreviewingTheme()
-						? title
-						: sprintf(
-								'Previewing %1$s: %2$s',
-								theme?.name?.rendered,
-								title
-						  ) }
-				</Heading>
-				{ actions && (
-					<div className="edit-site-sidebar-navigation-screen__actions">
-						{ actions }
-					</div>
+					{ ! isRoot ? (
+						<NavigatorToParentButton
+							as={ SidebarButton }
+							icon={ isRTL() ? chevronRight : chevronLeft }
+							label={ __( 'Back' ) }
+						/>
+					) : (
+						<SidebarButton
+							icon={ isRTL() ? chevronRight : chevronLeft }
+							label={
+								! isPreviewingTheme()
+									? __( 'Go back to the Dashboard' )
+									: __( 'Go back to the theme showcase' )
+							}
+							href={
+								! isPreviewingTheme()
+									? dashboardLink || 'index.php'
+									: 'themes.php'
+							}
+						/>
+					) }
+					<Heading
+						className="edit-site-sidebar-navigation-screen__title"
+						color={ 'white' }
+						level={ 2 }
+						size={ 20 }
+					>
+						{ ! isPreviewingTheme()
+							? title
+							: sprintf(
+									'Previewing %1$s: %2$s',
+									theme?.name?.rendered,
+									title
+							  ) }
+					</Heading>
+					{ actions && (
+						<div className="edit-site-sidebar-navigation-screen__actions">
+							{ actions }
+						</div>
+					) }
+				</HStack>
+				{ meta && (
+					<>
+						<div className="edit-site-sidebar-navigation-screen__meta">
+							{ meta }
+						</div>
+					</>
 				) }
-			</HStack>
-			{ meta && (
-				<>
-					<div className="edit-site-sidebar-navigation-screen__meta">
-						{ meta }
-					</div>
-				</>
-			) }
 
-			<nav className="edit-site-sidebar-navigation-screen__content">
-				{ description && (
-					<p className="edit-site-sidebar-navigation-screen__description">
-						{ description }
-					</p>
-				) }
-				{ content }
-			</nav>
+				<nav className="edit-site-sidebar-navigation-screen__content">
+					{ description && (
+						<p className="edit-site-sidebar-navigation-screen__description">
+							{ description }
+						</p>
+					) }
+					{ content }
+				</nav>
+			</VStack>
 			{ footer && (
-				<footer className="edit-site-sidebar-navigation-screen__sticky-section">
+				<footer className="edit-site-sidebar-navigation-screen__footer">
 					{ footer }
 				</footer>
 			) }
-		</VStack>
+		</>
 	);
 }
diff --git a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss
index 111b2650e41256..713a3ca1449e65 100644
--- a/packages/edit-site/src/components/sidebar-navigation-screen/style.scss
+++ b/packages/edit-site/src/components/sidebar-navigation-screen/style.scss
@@ -5,6 +5,12 @@
 	position: relative;
 }
 
+.edit-site-sidebar-navigation-screen__main {
+	// Ensure the sidebar is always at least as tall as the viewport.
+	// This allows the footer section to be sticky at the bottom of the viewport.
+	flex-grow: 1;
+}
+
 .edit-site-sidebar-navigation-screen__content {
 	margin: 0 0 $grid-unit-20 0;
 	color: $gray-400;
@@ -86,3 +92,10 @@
 	margin: $grid-unit-40 $grid-unit-20;
 	border-top: 1px solid $gray-800;
 }
+
+.edit-site-sidebar-navigation-screen__footer {
+	position: sticky;
+	bottom: 0;
+	background-color: $gray-900;
+	padding: $grid-unit-20 0;
+}
diff --git a/packages/edit-site/src/components/sidebar/style.scss b/packages/edit-site/src/components/sidebar/style.scss
index 03d4410941167e..9a3644cc830d56 100644
--- a/packages/edit-site/src/components/sidebar/style.scss
+++ b/packages/edit-site/src/components/sidebar/style.scss
@@ -5,6 +5,9 @@
 	.components-navigator-screen {
 		@include custom-scrollbars-on-hover(transparent, $gray-700);
 		scrollbar-gutter: stable;
+		display: flex;
+		flex-direction: column;
+		height: 100%;
 	}
 }
 
diff --git a/packages/edit-site/src/style.scss b/packages/edit-site/src/style.scss
index e31978cf0f45df..1004684c17cc2c 100644
--- a/packages/edit-site/src/style.scss
+++ b/packages/edit-site/src/style.scss
@@ -27,6 +27,7 @@
 @import "./components/sidebar-button/style.scss";
 @import "./components/sidebar-navigation-item/style.scss";
 @import "./components/sidebar-navigation-screen/style.scss";
+@import "./components/sidebar-navigation-screen-global-styles/style.scss";
 @import "./components/sidebar-navigation-screen-page/style.scss";
 @import "./components/sidebar-navigation-screen-template/style.scss";
 @import "./components/sidebar-navigation-screen-templates/style.scss";