diff --git a/ghost/admin/app/components/modal-portal-settings.hbs b/ghost/admin/app/components/modal-portal-settings.hbs
index 51ff0a157e..9c2df0b264 100644
--- a/ghost/admin/app/components/modal-portal-settings.hbs
+++ b/ghost/admin/app/components/modal-portal-settings.hbs
@@ -34,6 +34,34 @@
{{#if this.membersUtils.isStripeEnabled}}
+ {{#if (feature "multipleProducts")}}
+
+
Products available at signup
+
+ {{#each this.products as |product|}}
+
+ {{/each}}
+ {{/if}}
Prices available at signup
@@ -275,4 +303,4 @@
{{/if}}
-
\ No newline at end of file
+
diff --git a/ghost/admin/app/components/modal-portal-settings.js b/ghost/admin/app/components/modal-portal-settings.js
index e16bb6925e..b070860228 100644
--- a/ghost/admin/app/components/modal-portal-settings.js
+++ b/ghost/admin/app/components/modal-portal-settings.js
@@ -36,7 +36,7 @@ export default ModalComponent.extend({
return `data-portal`;
}),
- portalPreviewUrl: computed('page', 'membersUtils.{isFreeChecked,isMonthlyChecked,isYearlyChecked}', 'settings.{portalName,portalButton,portalButtonIcon,portalButtonSignupText,portalButtonStyle,accentColor,portalPlans.[]}', function () {
+ portalPreviewUrl: computed('page', 'membersUtils.{isFreeChecked,isMonthlyChecked,isYearlyChecked}', 'settings.{portalName,portalButton,portalButtonIcon,portalButtonSignupText,portalButtonStyle,accentColor,portalPlans.[],portalProducts.[]}', function () {
const options = this.getProperties(['page']);
return this.membersUtils.getPortalPreviewUrl(options);
}),
@@ -69,6 +69,20 @@ export default ModalComponent.extend({
const allowedPlans = this.settings.get('portalPlans') || [];
return (this.membersUtils.isStripeEnabled && allowedPlans.includes('yearly'));
}),
+ products: computed('model.products.[]', 'settings.portalProducts.[]', 'isPreloading', function () {
+ if (this.isPreloading || !this.model.products) {
+ return [];
+ }
+ const portalProducts = this.settings.get('portalProducts') || [];
+ const products = this.model.products.map((product) => {
+ return {
+ id: product.id,
+ name: product.name,
+ checked: portalProducts.includes(product.id)
+ };
+ });
+ return products;
+ }),
init() {
this._super(...arguments);
@@ -92,6 +106,9 @@ export default ModalComponent.extend({
togglePlan(plan, event) {
this.updateAllowedPlan(plan, event.target.checked);
},
+ toggleProduct(productId, event) {
+ this.updateAllowedProduct(productId, event.target.checked);
+ },
togglePortalButton(showButton) {
this.settings.set('portalButton', showButton);
},
@@ -202,6 +219,18 @@ export default ModalComponent.extend({
}
},
+ updateAllowedProduct(productId, isChecked) {
+ const portalProducts = this.settings.get('portalProducts') || [];
+ const allowedProducts = [...portalProducts];
+
+ if (!isChecked) {
+ this.settings.set('portalProducts', allowedProducts.filter(p => p !== productId));
+ } else {
+ allowedProducts.push(productId);
+ this.settings.set('portalProducts', allowedProducts);
+ }
+ },
+
_validateSignupRedirect(url, type) {
let errMessage = `Please enter a valid URL`;
this.settings.get('errors').remove(type);
diff --git a/ghost/admin/app/models/setting.js b/ghost/admin/app/models/setting.js
index 1418aa9818..f0a7d53214 100644
--- a/ghost/admin/app/models/setting.js
+++ b/ghost/admin/app/models/setting.js
@@ -45,6 +45,7 @@ export default Model.extend(ValidationEngine, {
portalButton: attr('boolean'),
portalName: attr('boolean'),
portalPlans: attr('json-string'),
+ portalProducts: attr('json-string'),
portalButtonStyle: attr('string'),
portalButtonIcon: attr('string'),
portalButtonSignupText: attr('string'),
diff --git a/ghost/admin/app/services/members-utils.js b/ghost/admin/app/services/members-utils.js
index f86d0270e3..caad697269 100644
--- a/ghost/admin/app/services/members-utils.js
+++ b/ghost/admin/app/services/members-utils.js
@@ -87,6 +87,7 @@ export default class MembersUtilsService extends Service {
monthlyPrice,
yearlyPrice,
portalPlans = this.settings.get('portalPlans'),
+ portalProducts = this.settings.get('portalProducts'),
currency,
membersSignupAccess = this.settings.get('membersSignupAccess')
} = overrides;
@@ -112,6 +113,10 @@ export default class MembersUtilsService extends Service {
settingsParam.append('portalPrices', encodeURIComponent(portalPlans));
}
+ if (portalProducts) {
+ settingsParam.append('portalProducts', encodeURIComponent(portalProducts));
+ }
+
if (this.settings.get('accentColor') === '' || this.settings.get('accentColor')) {
settingsParam.append('accentColor', encodeURIComponent(`${this.settings.get('accentColor')}`));
}
diff --git a/ghost/admin/app/templates/settings/membership.hbs b/ghost/admin/app/templates/settings/membership.hbs
index aee6364b2c..1ba8bde6f1 100644
--- a/ghost/admin/app/templates/settings/membership.hbs
+++ b/ghost/admin/app/templates/settings/membership.hbs
@@ -236,6 +236,7 @@
@model={{hash
preloadTask=this.saveSettingsTask
openStripeSettings=this.openStripeConnect
+ products=this.products
}}
@close={{this.closePortalSettings}}
@modifier="full-overlay portal-settings" />
@@ -256,4 +257,4 @@
@close={{this.closeStripeConnect}}
@modifier="action wide stripe-connect" />
{{/if}}
-
\ No newline at end of file
+