Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Global Styles: Show notice in privacy settings #69242

Merged
merged 22 commits into from
Oct 26, 2022
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
585e556
We now show a notice in the privacy setting screen if the user has gl…
rcrdortiz Oct 19, 2022
54b20c8
Decouple usePremiumGlobalStyles from useLocation since it doesn't wor…
mmtr Oct 19, 2022
9dafa20
We now fetch the status of global styles from the corresponding API
rcrdortiz Oct 19, 2022
47a6fbc
We now fetch the status of global styles from the corresponding API
rcrdortiz Oct 19, 2022
f5c2065
Updated usePremiumGlobalStyles so that it uses useQuery for managing …
rcrdortiz Oct 20, 2022
80d4791
Added Global Styles Info endpoint to ETK
rcrdortiz Oct 20, 2022
c8d61ae
Fix unified-design-picker unit tests
mmtr Oct 20, 2022
304270e
Update client/my-sites/site-settings/form-general.jsx
rcrdortiz Oct 21, 2022
2dc61f7
Update client/my-sites/site-settings/form-general.jsx
rcrdortiz Oct 21, 2022
e680ded
Added an error handler for when we perform the request for getting gl…
rcrdortiz Oct 21, 2022
d579f81
Merge branch 'add/global-styles-notice-in-privacy-settings' of github…
rcrdortiz Oct 21, 2022
4317553
We now avoid requesting the GS info when the tab is focused
rcrdortiz Oct 21, 2022
f3c1e9a
Renamed the rest controller from info to status
rcrdortiz Oct 21, 2022
f0f26ea
Fixed a css issue that caused the buttons to not be displayed as expe…
rcrdortiz Oct 21, 2022
8c40b93
Merge branch 'trunk' into add/global-styles-notice-in-privacy-settings
rcrdortiz Oct 21, 2022
9050ff2
We now obtain the site url from the selected site instead of from the…
rcrdortiz Oct 21, 2022
c42a2db
Fixed use-premium-global-styles import
rcrdortiz Oct 21, 2022
3cb849c
Merge branch 'trunk' into add/global-styles-notice-in-privacy-settings
rcrdortiz Oct 25, 2022
6e666ac
We now check if we are on an onboarding flow that does not have a sit…
rcrdortiz Oct 25, 2022
3171bf5
Added protection against useQuery not returning data
rcrdortiz Oct 25, 2022
ab049fa
Refactored the code
rcrdortiz Oct 25, 2022
6e50263
Merge branch 'trunk' into add/global-styles-notice-in-privacy-settings
rcrdortiz Oct 25, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php
/**
* WPCOM Global Styles Info API.
*
* @package full-site-editing-plugin
*/

/**
* This class contains the necessary endpoints to interact with global styles outside the editor context.
*/
class Global_Styles_Info_Rest_API extends WP_REST_Controller {

/**
* Class constructor
*/
public function __construct() {
$this->namespace = 'wpcom/v2';
$this->rest_base = 'global-styles-info';
rcrdortiz marked this conversation as resolved.
Show resolved Hide resolved
$this->wpcom_is_site_specific_endpoint = true;
$this->wpcom_is_wpcom_only_endpoint = true;
rcrdortiz marked this conversation as resolved.
Show resolved Hide resolved
add_action( 'rest_api_init', array( $this, 'register_routes' ) );
}

/**
* Here we register the routes this API will expose.
*
* @return void
*/
public function register_routes() {

register_rest_route(
$this->namespace,
'/' . $this->rest_base,
array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_global_styles_info' ),
'permission_callback' => array( $this, 'permissions_check' ),
),
)
);
}

/**
* Checks if the user has the necessary permissions to get global styles information.
*
* @return bool|WP_Error
*/
public function permissions_check() {
if ( ! current_user_can( 'edit_theme_options' ) ) {
rcrdortiz marked this conversation as resolved.
Show resolved Hide resolved
return new WP_Error(
'rest_cannot_view',
__( 'Your user is not permitted to access this resource.', 'full-site-editing' ),
array( 'status' => rest_authorization_required_code() )
);
}

return true;
}

/**
* Returns if the current blog has Global Styles in use and if Global Styles should be limited.
*
* @return array
*/
public function get_global_styles_info() {
return array(
'globalStylesInUse' => wpcom_global_styles_in_use(),
'shouldLimitGlobalStyles' => wpcom_should_limit_global_styles(),
);
}
}

if ( function_exists( 'wpcom_rest_api_v2_load_plugin' ) ) {
wpcom_rest_api_v2_load_plugin( 'Global_Styles_Info_Rest_API' );
}
rcrdortiz marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -220,3 +220,8 @@ function wpcom_display_global_styles_banner( $custom_controls ) {
return $custom_controls;
}
add_filter( 'wpcom_custom_launch_bar_controls', 'wpcom_display_global_styles_banner' );

/**
* Include the Rest API that returns the global style information for a give WordPress site.
*/
require_once __DIR__ . '/api/class-global-styles-info-rest-api.php';
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import FormFieldset from 'calypso/components/forms/form-fieldset';
import FormLabel from 'calypso/components/forms/form-label';
import FormInput from 'calypso/components/forms/form-text-input';
import PremiumBadge from 'calypso/components/premium-badge';
import { usePremiumGlobalStyles } from 'calypso/landing/stepper/hooks/use-premium-global-styles';
import { tip } from 'calypso/signup/icons';
import { usePremiumGlobalStyles } from 'calypso/state/sites/hooks/use-premium-global-styles';

import './style.scss';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ jest.mock( '../../../../../hooks/use-site', () => ( {
useSite: () => MOCKED_SITE,
} ) );

jest.mock( 'calypso/state/sites/hooks/use-premium-global-styles', () => ( {
usePremiumGlobalStyles: () => ( { shouldLimitGlobalStyles: false } ),
} ) );

/**
* Mock wpcom-proxy-request so that we could use wpcom-xhr-request to call the endpoint
* and get the response from nock
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ import { useQuerySitePurchases } from 'calypso/components/data/query-site-purcha
import FormattedHeader from 'calypso/components/formatted-header';
import PremiumBadge from 'calypso/components/premium-badge';
import WebPreview from 'calypso/components/web-preview/content';
import { usePremiumGlobalStyles } from 'calypso/landing/stepper/hooks/use-premium-global-styles';
import { recordTracksEvent } from 'calypso/lib/analytics/tracks';
import { urlToSlug } from 'calypso/lib/url';
import { usePremiumGlobalStyles } from 'calypso/state/sites/hooks/use-premium-global-styles';
import { requestActiveTheme } from 'calypso/state/themes/actions';
import { getPurchasedThemes } from 'calypso/state/themes/selectors/get-purchased-themes';
import { isThemePurchased } from 'calypso/state/themes/selectors/is-theme-purchased';
Expand Down
23 changes: 0 additions & 23 deletions client/landing/stepper/hooks/use-premium-global-styles.ts

This file was deleted.

51 changes: 50 additions & 1 deletion client/my-sites/site-settings/form-general.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import isSiteWPForTeams from 'calypso/state/selectors/is-site-wpforteams';
import isUnlaunchedSite from 'calypso/state/selectors/is-unlaunched-site';
import siteHasFeature from 'calypso/state/selectors/site-has-feature';
import { getDomainsBySiteId } from 'calypso/state/sites/domains/selectors';
import { usePremiumGlobalStyles } from 'calypso/state/sites/hooks/use-premium-global-styles';
import { launchSite } from 'calypso/state/sites/launch/actions';
import {
getSiteOption,
Expand Down Expand Up @@ -260,6 +261,12 @@ export class SiteSettingsFormGeneral extends Component {
} );
};

trackAdvancedCustomizationUpgradeClick = () => {
this.props.recordTracksEvent( 'calypso_global_styles_gating_settings_notice_upgrade_click', {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll need to add this event to Tracks.

cta_name: 'settings_site_privacy',
rcrdortiz marked this conversation as resolved.
Show resolved Hide resolved
} );
};

trackFiverrLogoMakerClick = () => {
this.props.recordTracksEvent( 'calypso_site_icon_fiverr_logo_maker_cta_click', {
cta_name: 'site_icon_fiverr_logo_maker',
Expand Down Expand Up @@ -342,6 +349,7 @@ export class SiteSettingsFormGeneral extends Component {
siteIsJetpack,
siteIsAtomic,
translate,
shouldShowPremiumStylesNotice,
} = this.props;

const blogPublic = parseInt( fields.blog_public, 10 );
Expand All @@ -365,6 +373,7 @@ export class SiteSettingsFormGeneral extends Component {
! isWPForTeamsSite &&
! isAtomicAndEditingToolkitDeactivated && (
<>
{ shouldShowPremiumStylesNotice && this.advancedCustomizationNotice() }
<FormLabel className={ comingSoonFormLabelClasses }>
<FormRadio
name="blog_public"
Expand Down Expand Up @@ -698,6 +707,35 @@ export class SiteSettingsFormGeneral extends Component {
</div>
);
}

advancedCustomizationNotice() {
const { translate, siteSlug } = this.props;
const upgradeUrl = '/plans/' + siteSlug;
const siteUrl = `https://${ siteSlug }`;
rcrdortiz marked this conversation as resolved.
Show resolved Hide resolved

return (
<>
<div className="site-settings__advanced-customization-notice">
<div className="site-settings__advanced-customization-notice-cta">
<Gridicon icon="info-outline" />
<span>
{ translate( 'Your style changes wont be public until you upgrade your plan.' ) }
rcrdortiz marked this conversation as resolved.
Show resolved Hide resolved
</span>
</div>
<div className="site-settings__advanced-customization-notice-buttons">
<Button href={ siteUrl }>{ translate( 'View site' ) }</Button>
rcrdortiz marked this conversation as resolved.
Show resolved Hide resolved
<Button
className="is-primary"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick (non-blocking): The same can be accomplished by setting a primary prop.

Suggested change
className="is-primary"
primary

href={ upgradeUrl }
onClick={ this.trackAdvancedCustomizationUpgradeClick }
>
{ translate( 'Upgrade' ) }
</Button>
</div>
</div>
</>
);
}
}

const mapDispatchToProps = ( dispatch, ownProps ) => {
Expand Down Expand Up @@ -767,7 +805,18 @@ const getFormSettings = ( settings ) => {
return formSettings;
};

const SiteSettingsFormGeneralWithGlobalStylesNotice = ( props ) => {
const { globalStylesInUse, shouldLimitGlobalStyles } = usePremiumGlobalStyles();

return (
<SiteSettingsFormGeneral
{ ...props }
shouldShowPremiumStylesNotice={ globalStylesInUse && shouldLimitGlobalStyles }
/>
);
};

export default flowRight(
connectComponent,
wrapSettingsForm( getFormSettings )
)( SiteSettingsFormGeneral );
)( SiteSettingsFormGeneralWithGlobalStylesNotice );
35 changes: 35 additions & 0 deletions client/my-sites/site-settings/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -625,3 +625,38 @@ button.site-settings__general-settings-set-guessed-timezone.button.is-borderless
margin-top: -16px;
margin-bottom: 16px;
}

.site-settings__advanced-customization-notice {
display: flex;
padding: 20px;
background-color: #f4f4f4;
rcrdortiz marked this conversation as resolved.
Show resolved Hide resolved
align-items: center;
justify-content: space-between;

.site-settings__advanced-customization-notice-cta {
display: flex;
align-items: center;
}

svg.gridicon.gridicons-info-outline {
color: #d38d16;
rcrdortiz marked this conversation as resolved.
Show resolved Hide resolved
padding-right: 10px;
}

.site-settings__advanced-customization-notice-buttons {
display: flex;

.button.is-primary {
margin-left: 10px;

}
}

@media (max-width: 1100px) {
rcrdortiz marked this conversation as resolved.
Show resolved Hide resolved
flex-direction: column;

.site-settings__advanced-customization-notice-buttons {
padding-top: 10px;
}
}
}
78 changes: 78 additions & 0 deletions client/state/sites/hooks/use-premium-global-styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { isEnabled } from '@automattic/calypso-config';
import { useQuery } from 'react-query';
import { useSelector } from 'react-redux';
import wpcom from 'calypso/lib/wp';
import { getSite } from 'calypso/state/sites/selectors';
import { getSelectedSiteId } from 'calypso/state/ui/selectors';

type GlobalStylesInfo = {
shouldLimitGlobalStyles: boolean;
globalStylesInUse: boolean;
};

type Site = {
isCreated: boolean;
id: number;
};

const NEW_SITE_GLOBAL_STYLES_INFO: GlobalStylesInfo = {
// The next line should be replaced with true once the Gating global styles feature is live.
// That will make all non-created sites to limit global styles.
shouldLimitGlobalStyles: isEnabled( 'limit-global-styles' ),
globalStylesInUse: false,
};

// While we are loading the Global Styles Info we can't assume that we should limit global styles, or we would be
// showing notices for paid sites until we fetch the data from the server.
const DEFAULT_GLOBAL_STYLES_INFO: GlobalStylesInfo = {
shouldLimitGlobalStyles: false,
globalStylesInUse: false,
};

const getGSInfoEndpointForSite = ( siteId: number ) => ( {
path: `sites/${ siteId }/global-styles-info`,
apiNamespace: 'wpcom/v2/',
} );

const mapSiteIdToSite = ( siteId: number | null ) => ( {
isCreated: !! siteId,
id: siteId ?? 0,
} );

const getGlobalStylesInfoForSite = ( site: Site ) => {
if ( ! site.isCreated ) {
return NEW_SITE_GLOBAL_STYLES_INFO;
}
rcrdortiz marked this conversation as resolved.
Show resolved Hide resolved

const globalStylesInfoEndpoint = getGSInfoEndpointForSite( site.id );
return wpcom.req.get( globalStylesInfoEndpoint );
rcrdortiz marked this conversation as resolved.
Show resolved Hide resolved
rcrdortiz marked this conversation as resolved.
Show resolved Hide resolved
};

export function usePremiumGlobalStyles(): GlobalStylesInfo {
const params = new URLSearchParams( window.location.search );
const siteSlugParam = params.get( 'siteSlug' );
const siteIdParam = params.get( 'siteId' );
const selectedSiteId = useSelector( getSelectedSiteId );

// When site id is null it means that the site hasn't been created yet.
rcrdortiz marked this conversation as resolved.
Show resolved Hide resolved
const siteId = useSelector( ( state ) => {
const siteIdOrSlug = selectedSiteId ?? siteIdParam ?? siteSlugParam;
if ( ! siteIdOrSlug ) {
return null;
}
const site = getSite( state, siteIdOrSlug );
return site?.ID ?? null;
} );

const site = mapSiteIdToSite( siteId );

const { data } = useQuery(
[ 'globalStylesInfo', site ],
() => getGlobalStylesInfoForSite( site ),
{
placeholderData: DEFAULT_GLOBAL_STYLES_INFO,
rcrdortiz marked this conversation as resolved.
Show resolved Hide resolved
}
);

return data;
}