Added billing "update" CTA button

no issue

- Added billing update button to navigation menu. Ghost-Admin communicates with billing iframe and displays this button based on the plan data that iframe returns
- Ghost-Admin communicates with an iframe using same mechanism as with token exchange - throu `window.postMessage` API
This commit is contained in:
Nazar Gargol 2020-04-21 18:54:29 +12:00
parent 00b7ec2874
commit f70e1b1e29
8 changed files with 100 additions and 7 deletions

View File

@ -1,14 +1,12 @@
import Component from '@ember/component';
import {computed} from '@ember/object';
import {inject as service} from '@ember/service';
export default Component.extend({
billing: service(),
config: service(),
ghostPaths: service(),
ajax: service(),
billingEndpoint: computed.reads('config.billingUrl'),
didRender() {
let iframe = this.element.querySelector('#billing-frame');
window.addEventListener('message', (event) => {

View File

@ -0,0 +1,53 @@
import Component from '@ember/component';
import {computed} from '@ember/object';
import {inject as service} from '@ember/service';
export default Component.extend({
config: service(),
ghostPaths: service(),
ajax: service(),
billing: service(),
subscription: null,
showUpgradeButton: computed.equal('subscription.status', 'trialing'),
didRender() {
let iframe = this.element.querySelector('#billing-frame-global');
let fetchingSubscription = false;
window.addEventListener('message', (event) => {
if (event && event.data && event.data.request === 'token') {
const ghostIdentityUrl = this.get('ghostPaths.url').api('identities');
this.ajax.request(ghostIdentityUrl).then((response) => {
const token = response && response.identities && response.identities[0] && response.identities[0].token;
iframe.contentWindow.postMessage({
request: 'token',
response: token
}, '*');
});
// NOTE: the handler is placed here to avoid additional logic to check if iframe has loaded
// receiving a 'token' request is an indication that page is ready
if (!fetchingSubscription && !this.get('subscription')) {
fetchingSubscription = true;
iframe.contentWindow.postMessage({
query: 'getSubscription'
}, '*');
}
}
if (event && event.data && event.data.subscription) {
this.set('subscription', event.data.subscription);
}
});
},
actions: {
openBilling() {
this.billing.set('upgrade', true);
this.billing.toggleProperty('billingWindowOpen');
}
}
});

View File

@ -9,6 +9,7 @@ import {htmlSafe} from '@ember/string';
import {inject as service} from '@ember/service';
export default Component.extend(ShortcutsMixin, {
billing: service(),
config: service(),
customViews: service(),
feature: service(),
@ -25,8 +26,6 @@ export default Component.extend(ShortcutsMixin, {
iconStyle: '',
showSearchModal: false,
showBillingModal: false,
shortcuts: null,
isIntegrationRoute: match('router.currentRouteName', /^settings\.integration/),
@ -39,6 +38,7 @@ export default Component.extend(ShortcutsMixin, {
showMenuExtension: and('config.clientExtensions.menu', 'session.user.isOwner'),
showDropdownExtension: and('config.clientExtensions.dropdown', 'session.user.isOwner'),
showScriptExtension: and('config.clientExtensions.script', 'session.user.isOwner'),
showBillingModal: computed.reads('billing.billingWindowOpen'),
showBilling: computed.reads('config.billingUrl'),
init() {
@ -81,7 +81,8 @@ export default Component.extend(ShortcutsMixin, {
this.toggleProperty('showSearchModal');
},
toggleBillingModal() {
this.toggleProperty('showBillingModal');
this.billing.set('upgrade', false);
this.billing.toggleProperty('billingWindowOpen');
}
},

26
app/services/billing.js Normal file
View File

@ -0,0 +1,26 @@
import Service from '@ember/service';
import {computed} from '@ember/object';
import {inject as service} from '@ember/service';
export default Service.extend({
config: service(),
ghostPaths: service(),
init() {
this._super(...arguments);
this.billingWindowOpen = false;
},
billingWindowOpen: false,
upgrade: true,
endpoint: computed('config.billingUrl', 'billingWindowOpen', function () {
let url = this.config.get('billingUrl');
if (this.get('upgrade')) {
url = this.ghostPaths.url.join(url, 'plans');
}
return url;
})
});

View File

@ -35,3 +35,10 @@
transition: all 0.2s ease-in-out;
top: 25px;
}
#billing-frame-global {
visibility: hidden;
height:0;
width:0;
border:none;
}

View File

@ -1 +1 @@
<iframe id="billing-frame" class="billing-frame" src={{this.billingEndpoint}} frameborder="0" allowtransparency="true"></iframe>
<iframe id="billing-frame" class="billing-frame" src={{this.billing.endpoint}} frameborder="0" allowtransparency="true"></iframe>

View File

@ -0,0 +1,5 @@
<iframe id="billing-frame-global" src={{this.billing.endpoint}}></iframe>
{{#if this.showUpgradeButton}}
<button class="gh-btn gh-btn-green" {{action "openBilling"}}><span>Upgrade</span></button>
{{/if}}

View File

@ -101,6 +101,9 @@
{{svg-jar "house"}} View billing
</a>
</li>
<li class="relative gh-nav-pro">
<GhBillingUpdateButton />
</li>
{{/if}}
</ul>
{{/if}}