mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-17 23:44:39 -05:00
Handled custom prices query in links/attributes
refs https://github.com/TryGhost/Team/issues/643 Previously, Portal only worked with hardcoded `Monthly` and `Yearly` plans as those were the only possible prices available to members. With custom prices and products, Portal is now expanded to work with any number of custom prices as well as allow links/attributes for them to work via IDs. Also, to continue backwards compatibility with Monthly/Yearly, Portal will support their data attributes/links, finding the first relevant Monthly/Yearly plan by nickname, falling back on interval if needed.
This commit is contained in:
parent
811067b7a7
commit
815e00c761
3 changed files with 72 additions and 4 deletions
|
@ -9,7 +9,7 @@ import * as Fixtures from './utils/fixtures';
|
|||
import ActionHandler from './actions';
|
||||
import './App.css';
|
||||
import NotificationParser from './utils/notifications';
|
||||
import {createPopupNotification, getCurrencySymbol, getFirstpromoterId, getSiteDomain, hasPrice, isComplimentaryMember, removePortalLinkFromUrl} from './utils/helpers';
|
||||
import {createPopupNotification, getAvailablePrices, getCurrencySymbol, getFirstpromoterId, getQueryPrice, getSiteDomain, isComplimentaryMember, removePortalLinkFromUrl} from './utils/helpers';
|
||||
const React = require('react');
|
||||
|
||||
const DEV_MODE_DATA = {
|
||||
|
@ -440,10 +440,12 @@ export default class App extends React.Component {
|
|||
|
||||
/** Handle direct signup link for a price */
|
||||
handleSignupQuery({site, pageQuery}) {
|
||||
const queryPrice = hasPrice({site: site, plan: pageQuery});
|
||||
const queryPrice = getQueryPrice({site: site, priceId: pageQuery});
|
||||
const availablePrices = getAvailablePrices({site, includeFree: false});
|
||||
const isQueryPriceAvailable = availablePrices.some(d => d.id === pageQuery);
|
||||
if (!this.state.member
|
||||
&& ['monthly', 'yearly'].includes(pageQuery)
|
||||
&& queryPrice
|
||||
&& isQueryPriceAvailable
|
||||
) {
|
||||
removePortalLinkFromUrl();
|
||||
this.dispatchAction('signup', {plan: queryPrice.id});
|
||||
|
@ -452,10 +454,17 @@ export default class App extends React.Component {
|
|||
|
||||
/**Get Portal page from Link/Data-attribute path*/
|
||||
getPageFromLinkPath(path) {
|
||||
const customPricesSignupRegex = /^signup\/?(?:\/(\w+?))?\/?$/;
|
||||
if (path === 'signup') {
|
||||
return {
|
||||
page: 'signup'
|
||||
};
|
||||
} else if (customPricesSignupRegex.test(path)) {
|
||||
const [, pageQuery] = path.match(customPricesSignupRegex);
|
||||
return {
|
||||
page: 'signup',
|
||||
pageQuery: pageQuery
|
||||
};
|
||||
} else if (path === 'signup/free') {
|
||||
return {
|
||||
page: 'signup',
|
||||
|
|
|
@ -108,7 +108,7 @@ export const site = {
|
|||
description: 'The default product'
|
||||
},
|
||||
prices: prices,
|
||||
allow_self_signup: false,
|
||||
allow_self_signup: true,
|
||||
members_signup_access: 'all',
|
||||
is_stripe_configured: true,
|
||||
portal_button: true,
|
||||
|
|
|
@ -101,10 +101,26 @@ export function hasPrice({site = {}, plan}) {
|
|||
return prices && prices.length > 0 && prices.find(p => p.name === 'Monthly');
|
||||
} else if (plan === 'yearly') {
|
||||
return prices && prices.length > 0 && prices.find(p => p.name === 'Yearly');
|
||||
} else if (plan) {
|
||||
return prices && prices.length > 0 && prices.find(p => p.id === plan);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getQueryPrice({site = {}, priceId}) {
|
||||
const prices = getAvailablePrices({site});
|
||||
if (priceId === 'free') {
|
||||
return !prices || prices.length === 0 || prices.find(p => p.type === 'free');
|
||||
} else if (priceId === 'monthly') {
|
||||
return prices && prices.length > 0 && prices.find(p => p.name === 'Monthly');
|
||||
} else if (priceId === 'yearly') {
|
||||
return prices && prices.length > 0 && prices.find(p => p.name === 'Yearly');
|
||||
} else if (priceId) {
|
||||
return prices && prices.length > 0 && prices.find(p => p.id === priceId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getProductDetails({site}) {
|
||||
if (site && site.product) {
|
||||
return {
|
||||
|
@ -130,6 +146,49 @@ export function isInviteOnlySite({site = {}, pageQuery}) {
|
|||
return prices.length === 0 || (site && site.members_signup_access === 'invite');
|
||||
}
|
||||
|
||||
export function getAvailablePrices({site = {}, includeFree = true} = {}) {
|
||||
const {
|
||||
prices,
|
||||
allow_self_signup: allowSelfSignup,
|
||||
is_stripe_configured: isStripeConfigured
|
||||
} = site || {};
|
||||
|
||||
if (!prices) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const plansData = [];
|
||||
|
||||
const stripePrices = prices.map((d) => {
|
||||
return {
|
||||
...d,
|
||||
price_id: d.id,
|
||||
price: d.amount / 100,
|
||||
name: d.nickname,
|
||||
currency_symbol: getCurrencySymbol(d.currency)
|
||||
};
|
||||
}).filter((price) => {
|
||||
return price.amount !== 0 && price.type === 'recurring';
|
||||
});
|
||||
|
||||
if (allowSelfSignup && includeFree) {
|
||||
plansData.push({
|
||||
id: 'free',
|
||||
type: 'free',
|
||||
price: 0,
|
||||
currency_symbol: '$',
|
||||
name: 'Free'
|
||||
});
|
||||
}
|
||||
|
||||
if (isStripeConfigured) {
|
||||
stripePrices.forEach((price) => {
|
||||
plansData.push(price);
|
||||
});
|
||||
}
|
||||
return plansData;
|
||||
}
|
||||
|
||||
export function getSitePrices({site = {}, includeFree = true, pageQuery} = {}) {
|
||||
const {
|
||||
prices,
|
||||
|
|
Loading…
Add table
Reference in a new issue