mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-25 03:44:29 +03:00
Show notifications for overdue subscriptions and exceeded limits
no issue - Overdue subscriptions: when a subscription is in overdue state, we'd like to inform the customers so that the owner is aware and can take action - Exceeded limits: - Show a warning when the members limit is exceeded so users are aware before trying to publish a post and hitting the limit - Allow to redirect directly to a child route in the Ghost(Pro) app, so plan updates get easier
This commit is contained in:
parent
dab672c7b8
commit
3ec373e33f
@ -1,4 +1,5 @@
|
||||
import Component from '@ember/component';
|
||||
import {htmlSafe} from '@ember/template';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
||||
export default Component.extend({
|
||||
@ -6,6 +7,7 @@ export default Component.extend({
|
||||
config: service(),
|
||||
ghostPaths: service(),
|
||||
ajax: service(),
|
||||
notifications: service(),
|
||||
|
||||
didInsertElement() {
|
||||
this._super(...arguments);
|
||||
@ -47,6 +49,27 @@ export default Component.extend({
|
||||
|
||||
if (event && event.data && event.data.subscription) {
|
||||
this.billing.set('subscription', event.data.subscription);
|
||||
this.billing.set('checkoutRoute', event.data?.checkoutRoute || '/plans');
|
||||
|
||||
// Detect if the current subscription is in a grace state and render a notification
|
||||
if (event.data.subscription.status === 'past_due' || event.data.subscription.status === 'unpaid') {
|
||||
// This notification needs to be shown to every user regardless their permissions to see billing
|
||||
this.notifications.showAlert('Billing error: This site is queued for suspension. The owner of this site must update payment information.', {type: 'error', key: 'billing.overdue'});
|
||||
}
|
||||
|
||||
// Detect if the current member limits are exceeded and render a notification
|
||||
if (
|
||||
event.data?.exceededLimits
|
||||
&& event.data?.exceededLimits.length
|
||||
&& event.data?.exceededLimits.indexOf('members') >= 0
|
||||
&& event.data?.checkoutRoute
|
||||
) {
|
||||
// The action param will be picked up on a transition from the router and can
|
||||
// then send the destination route as a message to the BMA, which then handles the redirect.
|
||||
const checkoutAction = this.billing.get('billingRouteRoot') + '?action=checkout';
|
||||
|
||||
this.notifications.showAlert(htmlSafe(`Your audience has grown! To continue publishing, the site owner must confirm pricing for this number of members <a href="${checkoutAction}">here</a>`), {type: 'warn', key: 'billing.exceeded'});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import {inject as service} from '@ember/service';
|
||||
|
||||
export default ModalComponent.extend({
|
||||
router: service(),
|
||||
billing: service(),
|
||||
|
||||
headerMessage: computed('details', function () {
|
||||
let header = 'Upgrade to enable publishing';
|
||||
@ -24,7 +25,7 @@ export default ModalComponent.extend({
|
||||
|
||||
actions: {
|
||||
upgrade() {
|
||||
this.router.transitionTo('pro');
|
||||
this.router.transitionTo('pro', {queryParams: {action: 'checkout'}});
|
||||
},
|
||||
|
||||
confirm() {
|
||||
|
@ -10,6 +10,7 @@ export default Service.extend({
|
||||
billingWindowOpen: false,
|
||||
subscription: null,
|
||||
previousRoute: null,
|
||||
action: null,
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
@ -51,15 +52,34 @@ export default Service.extend({
|
||||
return url;
|
||||
},
|
||||
|
||||
// Sends a route update to a child route in the BMA, because we can't control
|
||||
// navigating to it otherwise
|
||||
sendRouteUpdate() {
|
||||
const action = this.get('action');
|
||||
|
||||
if (action) {
|
||||
if (action === 'checkout') {
|
||||
this.getBillingIframe().contentWindow.postMessage({
|
||||
query: 'routeUpdate',
|
||||
response: this.get('checkoutRoute')
|
||||
}, '*');
|
||||
}
|
||||
|
||||
this.set('action', null);
|
||||
}
|
||||
},
|
||||
|
||||
// Controls billing window modal visibility and sync of the URL visible in browser
|
||||
// and the URL opened on the iframe. It is responsible to non user triggered iframe opening,
|
||||
// for example: by entering "/pro" route in the URL or using history navigation (back and forward)
|
||||
toggleProWindow(value) {
|
||||
if (this.get('billingWindowOpen') && value) {
|
||||
if (this.get('billingWindowOpen') && value && !this.get('action')) {
|
||||
// don't attempt to open again
|
||||
return;
|
||||
}
|
||||
|
||||
this.sendRouteUpdate();
|
||||
|
||||
this.set('billingWindowOpen', value);
|
||||
},
|
||||
|
||||
@ -79,6 +99,8 @@ export default Service.extend({
|
||||
// in toggleProWindow
|
||||
window.location.hash = childRoute || '/pro';
|
||||
|
||||
this.sendRouteUpdate();
|
||||
|
||||
this.router.transitionTo(childRoute || '/pro');
|
||||
},
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user