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:
parent
a665ca5923
commit
bbea4f7ec5
4 changed files with 32 additions and 5 deletions
|
@ -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,
|
||||
|
|
|
@ -36,6 +36,7 @@ function closePopup({state}) {
|
|||
return {
|
||||
showPopup: false,
|
||||
lastPage: null,
|
||||
pageQuery: '',
|
||||
popupNotification: null,
|
||||
page: state.page === 'magiclink' ? '' : state.page
|
||||
};
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue