diff --git a/ghost/portal/src/App.js b/ghost/portal/src/App.js index 69c19704ee..e0f4312f3a 100644 --- a/ghost/portal/src/App.js +++ b/ghost/portal/src/App.js @@ -96,12 +96,13 @@ export default class App extends React.Component { async initSetup() { try { // Fetch data from API, links, preview, dev sources - const {site, member, page, showPopup, popupNotification, lastPage} = await this.fetchData(); + const {site, member, page, showPopup, popupNotification, lastPage, pageQuery} = await this.fetchData(); this.setState({ site, member, page, lastPage, + pageQuery, showPopup, popupNotification, action: 'init:success', @@ -222,7 +223,7 @@ export default class App extends React.Component { /** Fetch state from Portal Links */ fetchLinkData() { - const [path] = window.location.hash.substr(1).split('?'); + const [path, pathQuery] = window.location.hash.substr(1).split('?'); const linkRegex = /^\/portal(?:\/(\w+(?:\/\w+)?))?$/; if (path && linkRegex.test(path)) { const [,pagePath] = path.match(linkRegex); @@ -231,6 +232,7 @@ export default class App extends React.Component { return { showPopup: true, ...(page ? {page} : {}), + ...(pathQuery ? {pageQuery: pathQuery} : {}), ...(lastPage ? {lastPage} : {}) }; } @@ -375,7 +377,7 @@ export default class App extends React.Component { /**Get final App level context from data/state*/ getContextFromState() { - const {site, member, action, page, lastPage, showPopup, popupNotification} = this.state; + const {site, member, action, page, lastPage, showPopup, pageQuery, popupNotification} = this.state; const contextPage = this.getContextPage({page, member}); const contextMember = this.getContextMember({page: contextPage, member}); return { @@ -383,6 +385,7 @@ export default class App extends React.Component { action, brandColor: this.getAccentColor(), page: contextPage, + pageQuery, member: contextMember, lastPage, showPopup, diff --git a/ghost/portal/src/actions.js b/ghost/portal/src/actions.js index 1a51246f52..4b1fd4d8e4 100644 --- a/ghost/portal/src/actions.js +++ b/ghost/portal/src/actions.js @@ -36,6 +36,7 @@ function closePopup({state}) { return { showPopup: false, lastPage: null, + pageQuery: '', popupNotification: null, page: state.page === 'magiclink' ? '' : state.page }; diff --git a/ghost/portal/src/components/pages/SignupPage.js b/ghost/portal/src/components/pages/SignupPage.js index acdec74a76..249937406a 100644 --- a/ghost/portal/src/components/pages/SignupPage.js +++ b/ghost/portal/src/components/pages/SignupPage.js @@ -5,7 +5,7 @@ import PlansSection from '../common/PlansSection'; import InputForm from '../common/InputForm'; import {ValidateInputForm} from '../../utils/form'; import CalculateDiscount from '../../utils/discount'; -import {getSitePlans, hasOnlyFreePlan} from '../../utils/helpers'; +import {capitalize, getSitePlans, hasOnlyFreePlan, hasPlan} from '../../utils/helpers'; import {ReactComponent as InvitationIcon} from '../../images/icons/invitation.svg'; const React = require('react'); @@ -149,7 +149,7 @@ class SignupPage extends React.Component { } componentDidMount() { - const {member} = this.context; + const {member, site, pageQuery = ''} = this.context; if (member) { this.context.onAction('switchPage', { page: 'accountHome' @@ -158,6 +158,10 @@ class SignupPage extends React.Component { // Handle the default plan if not set const plans = this.getPlans(); + const queryPlan = pageQuery ? (new URLSearchParams(pageQuery)).get('plan') : ''; + if (['monthly', 'yearly'].includes(queryPlan) && hasPlan({site, plan: queryPlan})) { + this.context.onAction('signup', {plan: capitalize(queryPlan)}); + } const selectedPlan = this.state.plan; const defaultSelectedPlan = this.getDefaultSelectedPlan(plans, this.state.plan); if (defaultSelectedPlan !== selectedPlan) { diff --git a/ghost/portal/src/utils/helpers.js b/ghost/portal/src/utils/helpers.js index 72f315f262..e2710ee94f 100644 --- a/ghost/portal/src/utils/helpers.js +++ b/ghost/portal/src/utils/helpers.js @@ -84,6 +84,25 @@ export function hasOnlyFreePlan({site = {}}) { return !plans || plans.length === 0 || (plans.length === 1 && plans[0].type === 'free'); } +export function hasPlan({site = {}, plan}) { + const plans = getSitePlans({site}); + if (plan === 'free') { + return !plans || plans.length === 0 || plans.find(p => p.type === 'free'); + } else if (plan === 'monthly') { + return plans && plans.length > 0 && plans.find(p => p.type === 'month'); + } else if (plan === 'yearly') { + return plans && plans.length > 0 && plans.find(p => p.type === 'year'); + } + return false; +} + +export function capitalize(str) { + if (typeof str !== 'string' || !str) { + return ''; + } + return str.charAt(0).toUpperCase() + str.slice(1); +} + export function getSitePlans({site = {}, includeFree = true}) { const { plans,