Handled multiple products custom signup links

closes https://github.com/TryGhost/Team/issues/825

With multiple products, it's possible to link to any products from themes. The links area in Portal settings now handles signup links for multiple products. This change -

- updates portal to handle custom product monthly/yearly signup links - `signup/PRODUCT_ID/monthly` OR `signup/PRODUCT_ID/yearly`
This commit is contained in:
Rishabh 2021-07-05 17:50:29 +05:30
parent 6b1bf36cca
commit 25389193f6
2 changed files with 44 additions and 6 deletions

View File

@ -10,7 +10,7 @@ import * as Fixtures from './utils/fixtures';
import ActionHandler from './actions';
import './App.css';
import NotificationParser from './utils/notifications';
import {createPopupNotification, getCurrencySymbol, getFirstpromoterId, getQueryPrice, getSiteDomain, isComplimentaryMember, isInviteOnlySite, isSentryEventAllowed, removePortalLinkFromUrl} from './utils/helpers';
import {createPopupNotification, getCurrencySymbol, getFirstpromoterId, getProductFromId, getQueryPrice, getSiteDomain, isComplimentaryMember, isInviteOnlySite, isSentryEventAllowed, removePortalLinkFromUrl} from './utils/helpers';
const handleDataAttributes = require('./data-attributes');
const React = require('react');
@ -333,14 +333,21 @@ export default class App extends React.Component {
/** Fetch state from Portal Links */
fetchLinkData() {
const productMonthlyPriceQueryRegex = /^(?:(\w+?))?\/monthly$/;
const productYearlyPriceQueryRegex = /^(?:(\w+?))?\/monthly$/;
const [path] = window.location.hash.substr(1).split('?');
const linkRegex = /^\/portal\/?(?:\/(\w+(?:\/\w+)?))?\/?$/;
const linkRegex = /^\/portal\/?(?:\/(\w+(?:\/\w+)+))?\/?$/;
if (path && linkRegex.test(path)) {
const [,pagePath] = path.match(linkRegex);
const {page, pageQuery} = this.getPageFromLinkPath(pagePath) || {};
const lastPage = ['accountPlan', 'accountProfile'].includes(page) ? 'accountHome' : null;
const showPopup = (
['monthly', 'yearly'].includes(pageQuery) ||
productMonthlyPriceQueryRegex.test(pageQuery) ||
productYearlyPriceQueryRegex.test(pageQuery)
) ? false : true;
return {
showPopup: ['monthly', 'yearly'].includes(pageQuery) ? false : true,
showPopup,
...(page ? {page} : {}),
...(pageQuery ? {pageQuery} : {}),
...(lastPage ? {lastPage} : {})
@ -510,23 +517,49 @@ export default class App extends React.Component {
/** Handle direct signup link for a price */
handleSignupQuery({site, pageQuery}) {
const queryPrice = getQueryPrice({site: site, priceId: pageQuery});
const productMonthlyPriceQueryRegex = /^(?:(\w+?))?\/monthly$/;
const productYearlyPriceQueryRegex = /^(?:(\w+?))?\/monthly$/;
let priceId = pageQuery;
if (productMonthlyPriceQueryRegex.test(pageQuery || '')) {
const [, productId] = pageQuery.match(productMonthlyPriceQueryRegex);
const product = getProductFromId({site, productId});
priceId = product?.monthlyPrice?.id;
} else if (productYearlyPriceQueryRegex.test(pageQuery || '')) {
const [, productId] = pageQuery.match(productYearlyPriceQueryRegex);
const product = getProductFromId({site, productId});
priceId = product?.yearlyPrice?.id;
}
const queryPrice = getQueryPrice({site: site, priceId});
if (!this.state.member
&& pageQuery
&& pageQuery !== 'free'
) {
removePortalLinkFromUrl();
this.dispatchAction('signup', {plan: queryPrice?.id || pageQuery});
this.dispatchAction('signup', {plan: queryPrice?.id || priceId});
}
}
/**Get Portal page from Link/Data-attribute path*/
getPageFromLinkPath(path) {
const customPricesSignupRegex = /^signup\/?(?:\/(\w+?))?\/?$/;
const customMonthlyProductSignup = /^signup\/?(?:\/(\w+?))\/monthly\/?$/;
const customYearlyProductSignup = /^signup\/?(?:\/(\w+?))\/yearly\/?$/;
if (path === 'signup') {
return {
page: 'signup'
};
} else if (customMonthlyProductSignup.test(path)) {
const [, productId] = path.match(customMonthlyProductSignup);
return {
page: 'signup',
pageQuery: `${productId}/monthly`
};
} else if (customYearlyProductSignup.test(path)) {
const [, productId] = path.match(customYearlyProductSignup);
return {
page: 'signup',
pageQuery: `${productId}/yearly`
};
} else if (customPricesSignupRegex.test(path)) {
const [, pageQuery] = path.match(customPricesSignupRegex);
return {

View File

@ -2,7 +2,7 @@ import calculateDiscount from './discount';
export function removePortalLinkFromUrl() {
const [path] = window.location.hash.substr(1).split('?');
const linkRegex = /^\/portal\/?(?:\/(\w+(?:\/\w+)?))?\/?$/;
const linkRegex = /^\/portal\/?(?:\/(\w+(?:\/\w+)+))?\/?$/;
if (path && linkRegex.test(path)) {
window.history.pushState('', document.title, window.location.pathname + window.location.search);
}
@ -270,6 +270,11 @@ export function getProductBenefits({product, site = null}) {
}
}
export function getProductFromId({site, productId}) {
const availableProducts = getAvailableProducts({site});
return availableProducts.find(product => product.id === productId);
}
export function getPricesFromProducts({site = null, products = null}) {
if (!site && !products) {
return [];