diff --git a/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/global-style-sidebar-notice.tsx b/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/global-style-sidebar-notice.tsx
new file mode 100644
index 00000000000000..8f984e932b74df
--- /dev/null
+++ b/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/global-style-sidebar-notice.tsx
@@ -0,0 +1,71 @@
+declare const wpcomGlobalStyles: { upgradeUrl: string; blogId: string };
+
+import { ExternalLink, Fill, Notice } from '@wordpress/components';
+import { useSelect } from '@wordpress/data';
+import { createInterpolateElement, useEffect } from '@wordpress/element';
+import { __ } from '@wordpress/i18n';
+import { recordUpgradeNoticeSidebarShow, recordUpgradeSidebarNoticeClick } from './tracks-events';
+import { useGlobalStylesConfig } from './use-global-styles-config';
+
+const GLOBAL_STYLES_SIDEBAR = 'edit-site/global-styles';
+
+type CoreInterfacePlaceholder = {
+ getActiveComplementaryArea: ( area: string ) => string;
+};
+
+export default function GlobalStylesSidebarNotice(): JSX.Element {
+ const area = useSelect(
+ ( select ) =>
+ ( select( 'core/interface' ) as CoreInterfacePlaceholder ).getActiveComplementaryArea(
+ 'core/edit-site'
+ ),
+ []
+ );
+
+ const isGlobalStylesSidebar = GLOBAL_STYLES_SIDEBAR === area;
+
+ const globalStylesInUse = useGlobalStylesConfig().globalStylesInUse;
+
+ useEffect( () => {
+ if ( globalStylesInUse && isGlobalStylesSidebar ) {
+ recordUpgradeNoticeSidebarShow();
+ }
+ }, [ globalStylesInUse, isGlobalStylesSidebar ] );
+
+ return (
+
+ { /*
+ The fragment is needed in order to avoid a forceUpdate done by the slot-fill library.
+
+ When a forceUpdate is done, the local state of the components is cleared, which means that when the nudge is displayed/removed,
+ the state of GS is cleared, disrupting the UX, since the user will be redirected to the main GS root screen.
+ */ }
+ <>
+ { /*
+ We'll need to do the condition here because if we are doing an early return, the fill will be introduced at the bottom of the page, which means some additional CSS magic needs to be done.
+ */ }
+ { globalStylesInUse && isGlobalStylesSidebar && (
+
+
+ { createInterpolateElement(
+ __(
+ 'Your changes include customized styles that will only be visible once you upgrade to a Premium plan.',
+ 'full-site-editing'
+ ),
+ {
+ a: (
+
+ ),
+ }
+ ) }
+
+
+ ) }
+ >
+
+ );
+}
diff --git a/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/index.js b/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/index.js
index 20a48f424ae572..47dffcb1de6680 100644
--- a/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/index.js
+++ b/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/index.js
@@ -3,6 +3,7 @@ import './public-path';
import domReady from '@wordpress/dom-ready';
import { registerPlugin } from '@wordpress/plugins';
+import GlobalStylesSidebarNotice from './global-style-sidebar-notice';
import GlobalStylesModal from './modal';
import GlobalStylesNotice from './notice';
import './store';
@@ -13,6 +14,7 @@ const showGlobalStylesComponents = () => {
<>
+
>
),
} );
diff --git a/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/index.php b/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/index.php
index 3e836570fc78c3..1bc0d3d3f07023 100644
--- a/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/index.php
+++ b/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/index.php
@@ -60,6 +60,26 @@ function wpcom_should_limit_global_styles( $blog_id = 0 ) {
return true;
}
+/**
+ * Get the WPCOM blog id of the current site for tracking purposes.
+ */
+function wpcom_global_styles_get_wpcom_current_blog_id() {
+ if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
+ return get_current_blog_id();
+ } elseif ( defined( 'IS_ATOMIC' ) && IS_ATOMIC ) {
+ /*
+ * Atomic sites have the WP.com blog ID stored as a Jetpack option. This code deliberately
+ * doesn't use `Jetpack_Options::get_option` so it works even when Jetpack has not been loaded.
+ */
+ $jetpack_options = get_option( 'jetpack_options' );
+ if ( is_array( $jetpack_options ) && isset( $jetpack_options['id'] ) ) {
+ return (int) $jetpack_options['id'];
+ }
+ }
+
+ return null;
+}
+
/**
* Wrapper to test a blog sticker on both Simple and Atomic sites at once.
*
@@ -131,8 +151,9 @@ function wpcom_global_styles_enqueue_block_editor_assets() {
'wpcom-global-styles-editor',
'wpcomGlobalStyles',
array(
- 'assetsUrl' => plugins_url( 'dist/', __FILE__ ),
- 'upgradeUrl' => "$calypso_domain/plans/$site_slug?plan=value_bundle&feature=advanced-design-customization",
+ 'assetsUrl' => plugins_url( 'dist/', __FILE__ ),
+ 'upgradeUrl' => "$calypso_domain/plans/$site_slug?plan=value_bundle&feature=advanced-design-customization",
+ 'wpcomBlogId' => wpcom_global_styles_get_wpcom_current_blog_id(),
)
);
wp_enqueue_style(
diff --git a/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/notice.js b/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/notice.js
index 7d4e76fd035974..2222da9a9f63b5 100644
--- a/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/notice.js
+++ b/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/notice.js
@@ -1,38 +1,14 @@
/* global wpcomGlobalStyles */
-import { recordTracksEvent } from '@automattic/calypso-analytics';
import { ExternalLink, Notice } from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { createInterpolateElement, render, useEffect, useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
-
import './notice.scss';
+import { recordUpgradePreSaveNoticeClick, recordUpgradeNoticePreSaveShow } from './tracks-events';
+import { useGlobalStylesConfig } from './use-global-styles-config';
function GlobalStylesNoticeComponent() {
- const { globalStylesConfig, siteChanges } = useSelect( ( select ) => {
- const {
- getEditedEntityRecord,
- __experimentalGetCurrentGlobalStylesId,
- __experimentalGetDirtyEntityRecords,
- } = select( 'core' );
-
- const _globalStylesId = __experimentalGetCurrentGlobalStylesId
- ? __experimentalGetCurrentGlobalStylesId()
- : null;
- const globalStylesRecord = getEditedEntityRecord( 'root', 'globalStyles', _globalStylesId );
-
- return {
- globalStylesConfig: {
- styles: globalStylesRecord?.styles ?? {},
- settings: globalStylesRecord?.settings ?? {},
- },
- siteChanges: __experimentalGetDirtyEntityRecords ? __experimentalGetDirtyEntityRecords() : [],
- };
- }, [] );
-
- // Do not show the notice if the use is trying to save the default styles.
- const isVisible =
- Object.keys( globalStylesConfig.styles ).length ||
- Object.keys( globalStylesConfig.settings ).length;
+ const { siteChanges, globalStylesInUse } = useGlobalStylesConfig();
// Closes the sidebar if there are no more changes to be saved.
useEffect( () => {
@@ -50,19 +26,21 @@ function GlobalStylesNoticeComponent() {
}, [ siteChanges ] );
useEffect( () => {
- if ( isVisible ) {
- recordTracksEvent( 'calypso_global_styles_gating_notice_show', {
- context: 'site-editor',
- } );
+ if ( globalStylesInUse ) {
+ recordUpgradeNoticePreSaveShow();
}
- }, [ isVisible ] );
+ }, [ globalStylesInUse ] );
- if ( ! isVisible ) {
+ if ( ! globalStylesInUse ) {
return null;
}
return (
-
+
{ createInterpolateElement(
__(
'Your changes include customized styles that will only be visible once you upgrade to a Premium plan.',
@@ -73,11 +51,7 @@ function GlobalStylesNoticeComponent() {
- recordTracksEvent( 'calypso_global_styles_gating_notice_upgrade_click', {
- context: 'site-editor',
- } )
- }
+ onClick={ recordUpgradePreSaveNoticeClick }
/>
),
}
diff --git a/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/notice.scss b/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/notice.scss
index 9f54b6752e5e90..137c5dd966fcef 100644
--- a/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/notice.scss
+++ b/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/notice.scss
@@ -1,5 +1,9 @@
.wpcom-global-styles-notice {
- margin: 16px 0 0;
+ margin: 0 0 0 0;
+
+ .notice-margin {
+ margin: 16px 0 0;
+ }
.components-notice__content {
margin-right: 0;
diff --git a/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/test/class-wpcom-global-styles-test.php b/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/test/class-wpcom-global-styles-test.php
index 346535d0717e61..23651d430505ee 100644
--- a/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/test/class-wpcom-global-styles-test.php
+++ b/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/test/class-wpcom-global-styles-test.php
@@ -17,24 +17,18 @@ class WPCOM_Global_Styles_Test extends TestCase {
* Tests that Global Styles are blocked in the frontend.
*/
public function test_wpcom_block_global_styles_frontend() {
- switch_theme( 'twentytwentythree' );
- $user_cpt = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( wp_get_theme(), true );
- $decoded_data = json_decode( $user_cpt['post_content'], true );
- unset( $decoded_data['isGlobalStylesUserThemeJSON'] );
- $config = $decoded_data;
-
- $config['styles']['color']['background'] = 'hotpink';
-
- $theme_json = apply_filters( 'wp_theme_json_data_user', new WP_Theme_JSON_Data( $config, 'custom' ) );
+ $theme_json_resolver = new WP_Theme_JSON_Resolver();
+ $user_data = $theme_json_resolver->get_user_data()->get_data();
+ $user_data['styles']['color']['background'] = 'hotpink';
+ // Check that the custom color is kept when Global Styles are available.
+ $theme_json = apply_filters( 'wp_theme_json_data_user', new WP_Theme_JSON_Data( $user_data, 'custom' ) );
$this->assertEquals( 'hotpink', $theme_json->get_data()['styles']['color']['background'] );
+ // Check that the custom color is blocked when Global Styles are limited.
add_filter( 'wpcom_force_limit_global_styles', '__return_true' );
-
- $theme_json = apply_filters( 'wp_theme_json_data_user', new WP_Theme_JSON_Data( $config, 'custom' ) );
-
+ $theme_json = apply_filters( 'wp_theme_json_data_user', new WP_Theme_JSON_Data( $user_data, 'custom' ) );
$this->assertEmpty( $theme_json->get_data()['styles']['color']['background'] );
-
remove_filter( 'wpcom_force_limit_global_styles', '__return_true' );
}
}
diff --git a/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/tracks-events.ts b/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/tracks-events.ts
new file mode 100644
index 00000000000000..ca64a5ae5b1fa2
--- /dev/null
+++ b/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/tracks-events.ts
@@ -0,0 +1,43 @@
+import { recordTracksEvent } from '@automattic/calypso-analytics';
+
+declare const wpcomGlobalStyles: { upgradeUrl: string; wpcomBlogId: string | null };
+
+/**
+ * Record an event when a user clicks on the notice from the pre-save panel.
+ */
+export function recordUpgradePreSaveNoticeClick(): void {
+ recordTracksEvent( 'calypso_global_styles_gating_notice_upgrade_click', {
+ context: 'site-editor',
+ blog_id: wpcomGlobalStyles.wpcomBlogId,
+ } );
+}
+
+/**
+ * Record an event when a user clicks on the notice from the Global Styles sidebar.
+ */
+export function recordUpgradeSidebarNoticeClick(): void {
+ recordTracksEvent( 'calypso_global_styles_gating_notice_sidebar_upgrade_click', {
+ context: 'site-editor',
+ blog_id: wpcomGlobalStyles.wpcomBlogId,
+ } );
+}
+
+/**
+ * Record an event when the GS upgrade notice is shown in the pre-save screen.
+ */
+export function recordUpgradeNoticePreSaveShow(): void {
+ recordTracksEvent( 'calypso_global_styles_gating_notice_show', {
+ context: 'site-editor',
+ blog_id: wpcomGlobalStyles.wpcomBlogId,
+ } );
+}
+
+/**
+ * Record an event when the GS upgrade notice is shown in the Global Styles sidebar.
+ */
+export function recordUpgradeNoticeSidebarShow(): void {
+ recordTracksEvent( 'calypso_global_styles_gating_sidebar_notice_show', {
+ context: 'site-editor',
+ blog_id: wpcomGlobalStyles.wpcomBlogId,
+ } );
+}
diff --git a/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/use-global-styles-config.js b/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/use-global-styles-config.js
new file mode 100644
index 00000000000000..f6bf492b856cff
--- /dev/null
+++ b/apps/editing-toolkit/editing-toolkit-plugin/wpcom-global-styles/use-global-styles-config.js
@@ -0,0 +1,32 @@
+import { useSelect } from '@wordpress/data';
+
+export function useGlobalStylesConfig() {
+ return useSelect( ( select ) => {
+ const {
+ getEditedEntityRecord,
+ __experimentalGetCurrentGlobalStylesId,
+ __experimentalGetDirtyEntityRecords,
+ } = select( 'core' );
+
+ const _globalStylesId = __experimentalGetCurrentGlobalStylesId
+ ? __experimentalGetCurrentGlobalStylesId()
+ : null;
+ const globalStylesRecord = getEditedEntityRecord( 'root', 'globalStyles', _globalStylesId );
+
+ const globalStylesConfig = {
+ styles: globalStylesRecord?.styles ?? {},
+ settings: globalStylesRecord?.settings ?? {},
+ };
+
+ // Determine if the global Styles are in use on the current site.
+ const globalStylesInUse = !! (
+ Object.keys( globalStylesConfig.styles ).length ||
+ Object.keys( globalStylesConfig.settings ).length
+ );
+
+ return {
+ globalStylesInUse,
+ siteChanges: __experimentalGetDirtyEntityRecords ? __experimentalGetDirtyEntityRecords() : [],
+ };
+ }, [] );
+}