0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-17 23:44:39 -05:00

Added direct links for monthly/yearly checkout

refs https://github.com/TryGhost/Ghost/issues/12365

Currently, while its possible to open Stripe checkout directly on a monthly/yearly plan, Portal links don't allow similar feature. This change allows opening a site on a specific Portal link that can directly open Stripe checkout for monthly/yearly plan, if the plan is allowed.

- Adds handling for new portal signup link for monthly plan - `/#/portal/signup?plan=monthly`
- Adds handling for new portal signup link for yearly plan - `/#/portal/signup?plan=yearly`
This commit is contained in:
Rish 2020-11-17 19:05:58 +05:30
parent a665ca5923
commit bbea4f7ec5
4 changed files with 32 additions and 5 deletions

View file

@ -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,

View file

@ -36,6 +36,7 @@ function closePopup({state}) {
return {
showPopup: false,
lastPage: null,
pageQuery: '',
popupNotification: null,
page: state.page === 'magiclink' ? '' : state.page
};

View file

@ -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) {

View file

@ -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,