Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 16 additions & 0 deletions assets/js/components/DashboardMainApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { Fragment, useEffect, useState } from '@wordpress/element';
/**
* Internal dependencies
*/
import { Button } from 'googlesitekit-components';
import { useSelect } from 'googlesitekit-data';
import { WELCOME_TOUR } from '@/js/feature-tours/constants';
import {
Expand Down Expand Up @@ -61,6 +62,7 @@ import {
CONTEXT_MAIN_DASHBOARD_SPEED,
CONTEXT_MAIN_DASHBOARD_TRAFFIC,
} from '@/js/googlesitekit/widgets/default-contexts';
import useActivateModuleCallback from '@/js/hooks/useActivateModuleCallback';
import { useBreakpoint } from '@/js/hooks/useBreakpoint';
import { useFeature } from '@/js/hooks/useFeature';
import useFormValue from '@/js/hooks/useFormValue';
Expand All @@ -72,6 +74,8 @@ import { AudienceSelectionPanel } from '@/js/modules/analytics-4/components/audi
import SiteGoalsIntroModalBanner from '@/js/modules/analytics-4/components/site-goals/notifications/IntroModalBanner';
import SiteGoalsSelectionPanel from '@/js/modules/analytics-4/components/site-goals/selection-panel';
import { MODULE_SLUG_ANALYTICS_4 } from '@/js/modules/analytics-4/constants';
import { MODULE_SLUG_READER_REVENUE_MANAGER } from '@/js/modules/reader-revenue-manager/constants';
import { MANAGE_SCOPE } from '@/js/modules/reader-revenue-manager/datastore/constants';
import { DAY_IN_SECONDS } from '@/js/util';
import { getNavigationalScrollTop } from '@/js/util/scroll';
import { isInitialWelcomeModalActive } from '@/js/util/welcome-modal';
Expand Down Expand Up @@ -361,6 +365,17 @@ export default function DashboardMainApp() {
isKeyMetricsActive,
} );

const onSetupActivate = useActivateModuleCallback(
MODULE_SLUG_READER_REVENUE_MANAGER,
{
redirectQueryArgs: {
expressSetup: true,
cta: 'newsletter-signup',
},
additionalScopes: [ MANAGE_SCOPE ],
}
);

return (
<Fragment>
<CoreDashboardEffects />
Expand All @@ -377,6 +392,7 @@ export default function DashboardMainApp() {
</Header>

<div className="googlesitekit-page-content">
<Button onClick={ onSetupActivate }>RRM Express Setup</Button>
{ /*
These notifications are rendered at the top of the dashboard,
but are not attached to the header. The first component renders the
Expand Down
27 changes: 23 additions & 4 deletions assets/js/googlesitekit/modules/create-info-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,23 @@ export function createInfoStore(
*
* @since 1.10.0
*
* @param {Object} options Options object.
* @param {boolean} options.reAuth The module activation status. Default is true.
* @param {Object} options Options object.
* @param {boolean} options.reAuth The module activation status. Default is true.
* @param {Object} [options.redirectQueryArgs] Optional. Additional query arguments to add to the redirect URL.
* @param {string[]} [options.additionalScopes] Optional. Additional OAuth scopes to request if not yet granted.
* @return {(string|undefined)} The admin reauthentication URL, or
* undefined if not loaded yet.
*/
getAdminReauthURL: createRegistrySelector(
( select ) =>
( state, { reAuth = true } = {} ) => {
(
state,
{
reAuth = true,
redirectQueryArgs = {},
additionalScopes = [],
} = {}
) => {
const needsReauthentication =
select( CORE_USER ).needsReauthentication();
if ( needsReauthentication === undefined ) {
Expand All @@ -137,17 +146,27 @@ export function createInfoStore(
slug,
reAuth,
...noSetupQueryArgs,
...redirectQueryArgs,
} );
if ( redirectURL === undefined ) {
return undefined;
}

if ( ! needsReauthentication ) {
const unsatisfiedAdditionalScopes = additionalScopes.filter(
( scope ) => ! select( CORE_USER ).hasScope( scope )
);

const shouldUseConnectURL =
needsReauthentication ||
unsatisfiedAdditionalScopes.length > 0;

if ( ! shouldUseConnectURL ) {
return redirectURL;
}

const connectURL = select( CORE_USER ).getConnectURL( {
redirectURL,
additionalScopes: unsatisfiedAdditionalScopes,
} );

return addQueryArgs( connectURL, { status: reAuth } );
Expand Down
26 changes: 18 additions & 8 deletions assets/js/googlesitekit/modules/datastore/modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -237,20 +237,23 @@ const baseActions = {
*
* @since 1.8.0
*
* @param {string} slug Slug of the module to activate.
* @return {Object} Object with `{response, error}`. On success, `response.moduleReauthURL`
* is set to redirect the user to the corresponding module setup or OAuth
* consent screen.
* @param {string} slug Slug of the module to activate.
* @param {Object} [options] Optional. Activation options with `redirectQueryArgs` and `additionalScopes`.
* @return {Object} Object with `{response, error}`. On success, `response.moduleReauthURL`
* is set to redirect the user to the corresponding module setup or OAuth
* consent screen.
*/
*activateModule( slug ) {
*activateModule( slug, options = {} ) {
const { redirectQueryArgs = {}, additionalScopes = [] } = options;

const { response, error } = yield baseActions.setModuleActivation( {
slug,
active: true,
} );

if ( response?.success === true ) {
const moduleReauthURL = yield {
payload: { slug },
payload: { slug, redirectQueryArgs, additionalScopes },
type: SELECT_MODULE_REAUTH_URL,
};
return {
Expand Down Expand Up @@ -613,7 +616,11 @@ export const baseControls = {
[ SELECT_MODULE_REAUTH_URL ]: createRegistryControl(
( { select, resolveSelect } ) =>
async ( { payload } ) => {
const { slug } = payload;
const {
slug,
redirectQueryArgs = {},
additionalScopes = [],
} = payload;
// Ensure the module is loaded before selecting the store name.
await resolveSelect( CORE_MODULES ).getModule( slug );

Expand All @@ -626,7 +633,10 @@ export const baseControls = {
}

if ( select( storeName )?.getAdminReauthURL ) {
return await resolveSelect( storeName ).getAdminReauthURL();
return await resolveSelect( storeName ).getAdminReauthURL( {
redirectQueryArgs,
additionalScopes,
} );
}
return select( CORE_SITE ).getAdminURL(
'googlesitekit-dashboard'
Expand Down
7 changes: 4 additions & 3 deletions assets/js/googlesitekit/modules/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,12 @@ export function createModules( { dispatch } ) {
*
* @since 1.8.0
*
* @param {string} slug Slug of the module to activate.
* @param {string} slug Slug of the module to activate.
* @param {Object} [options] Optional. Activation options.
* @return {Promise} The dispatched action.
*/
activateModule: ( slug ) => {
return dispatch( CORE_MODULES ).activateModule( slug );
activateModule: ( slug, options = {} ) => {
return dispatch( CORE_MODULES ).activateModule( slug, options );
},
/**
* Deactivates a module on the server.
Expand Down
6 changes: 4 additions & 2 deletions assets/js/hooks/useActivateModuleCallback.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ import useViewContext from './useViewContext';
* @since 1.70.0
*
* @param {string} moduleSlug Module slug.
* @param {Object} [options] Optional. Activation options.
* @return {Function|null} Callback to activate module, null if the module doesn't exist or the user can't manage options.
*/
export default function useActivateModuleCallback( moduleSlug ) {
export default function useActivateModuleCallback( moduleSlug, options = {} ) {
const viewContext = useViewContext();
const module = useSelect( ( select ) =>
select( CORE_MODULES ).getModule( moduleSlug )
Expand All @@ -59,7 +60,7 @@ export default function useActivateModuleCallback( moduleSlug ) {
const { setInternalServerError } = useDispatch( CORE_SITE );

const activateModuleCallback = useCallback( async () => {
const { error, response } = await activateModule( moduleSlug );
const { error, response } = await activateModule( moduleSlug, options );

if ( ! error ) {
await trackEvent(
Expand All @@ -80,6 +81,7 @@ export default function useActivateModuleCallback( moduleSlug ) {
}, [
activateModule,
moduleSlug,
options,
navigateTo,
setInternalServerError,
viewContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ export const ERROR_CODE_NON_HTTPS_SITE = 'non_https_site';

export const MODULES_READER_REVENUE_MANAGER = 'modules/reader-revenue-manager';

export const READONLY_SCOPE =
'https://www.googleapis.com/auth/subscribewithgoogle.publications.readonly';
export const MANAGE_SCOPE =
'https://www.googleapis.com/auth/subscribewithgoogle.publications.entitlements.manage';

export const PUBLICATION_ONBOARDING_STATES = {
ONBOARDING_COMPLETE: 'ONBOARDING_COMPLETE',
ONBOARDING_ACTION_REQUIRED: 'ONBOARDING_ACTION_REQUIRED',
Expand Down