mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-01 22:02:11 +03:00
5d59670ac3
no issue - Opted in to use explicit `hisotry.replaceState` and setting iframe's `src` using assignment instead of tracking it through computed property. This allows for tighter control over when iframe's history is updated which was causing problems when `src` was bound to computed property - Added billing page metadata. This way browser history records appear with nicer signature - Removed "update button" iframe and rewrote "global iframe" to not use modals. This allows to have single iframe on a page, which simplifies `postMessage` communication and preserve history inside iframe to be able to navigate it after closure - Added route change handler responding to BMA app route changes. Allows to sync browser URL visible to the user with active route in BMA iframe. The sync is based on `hisory.replaceState` method that makes sure singular history records are kept in the browser history - Added nested wildcard billing route. This is meant to catch all the nested routes inside of BMA iframe
124 lines
3.9 KiB
JavaScript
124 lines
3.9 KiB
JavaScript
import Component from '@ember/component';
|
|
import ShortcutsMixin from 'ghost-admin/mixins/shortcuts';
|
|
import calculatePosition from 'ember-basic-dropdown/utils/calculate-position';
|
|
import ctrlOrCmd from 'ghost-admin/utils/ctrl-or-cmd';
|
|
import {and, equal, match} from '@ember/object/computed';
|
|
import {computed} from '@ember/object';
|
|
import {getOwner} from '@ember/application';
|
|
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(),
|
|
ghostPaths: service(),
|
|
navigation: service(),
|
|
router: service(),
|
|
session: service(),
|
|
ui: service(),
|
|
whatsNew: service(),
|
|
|
|
tagName: 'nav',
|
|
classNames: ['gh-nav'],
|
|
|
|
iconStyle: '',
|
|
|
|
showSearchModal: false,
|
|
shortcuts: null,
|
|
|
|
isIntegrationRoute: match('router.currentRouteName', /^settings\.integration/),
|
|
isSettingsRoute: match('router.currentRouteName', /^settings/),
|
|
|
|
// HACK: {{link-to}} should be doing this automatically but there appears to
|
|
// be a bug in Ember that's preventing it from working immediately after login
|
|
isOnSite: equal('router.currentRouteName', 'site'),
|
|
|
|
showMenuExtension: and('config.clientExtensions.menu', 'session.user.isOwner'),
|
|
showDropdownExtension: and('config.clientExtensions.dropdown', 'session.user.isOwner'),
|
|
showScriptExtension: and('config.clientExtensions.script', 'session.user.isOwner'),
|
|
showBilling: computed.reads('config.billingUrl'),
|
|
|
|
init() {
|
|
this._super(...arguments);
|
|
|
|
let shortcuts = {};
|
|
|
|
shortcuts[`${ctrlOrCmd}+k`] = {action: 'toggleSearchModal'};
|
|
this.shortcuts = shortcuts;
|
|
},
|
|
|
|
// the menu has a rendering issue (#8307) when the the world is reloaded
|
|
// during an import which we have worked around by not binding the icon
|
|
// style directly. However we still need to keep track of changing icons
|
|
// so that we can refresh when a new icon is uploaded
|
|
didReceiveAttrs() {
|
|
this._setIconStyle();
|
|
},
|
|
|
|
didInsertElement() {
|
|
this._super(...arguments);
|
|
this.registerShortcuts();
|
|
},
|
|
|
|
willDestroyElement() {
|
|
this.removeShortcuts();
|
|
this._super(...arguments);
|
|
},
|
|
|
|
actions: {
|
|
transitionToOrRefreshSite() {
|
|
let {currentRouteName} = this.router;
|
|
if (currentRouteName === 'site') {
|
|
getOwner(this).lookup(`route:${currentRouteName}`).refresh();
|
|
} else {
|
|
this.router.transitionTo('site');
|
|
}
|
|
},
|
|
toggleSearchModal() {
|
|
this.toggleProperty('showSearchModal');
|
|
},
|
|
toggleBillingModal() {
|
|
this.billing.openBillingWindow(this.router.currentURL);
|
|
}
|
|
},
|
|
|
|
// equivalent to "left: auto; right: -20px"
|
|
userDropdownPosition(trigger, dropdown) {
|
|
let {horizontalPosition, verticalPosition, style} = calculatePosition(...arguments);
|
|
let {width: dropdownWidth} = dropdown.firstElementChild.getBoundingClientRect();
|
|
|
|
style.right += (dropdownWidth - 20);
|
|
style['z-index'] = 1100;
|
|
|
|
return {horizontalPosition, verticalPosition, style};
|
|
},
|
|
|
|
_setIconStyle() {
|
|
let icon = this.icon;
|
|
|
|
if (icon === this._icon) {
|
|
return;
|
|
}
|
|
|
|
this._icon = icon;
|
|
|
|
if (icon && icon.match(/^https?:\/\//i)) {
|
|
this.set('iconStyle', htmlSafe(`background-image: url(${icon})`));
|
|
return;
|
|
}
|
|
|
|
let subdirRegExp = new RegExp(`^${this.get('ghostPaths.subdir')}`);
|
|
let blogIcon = icon ? icon : 'favicon.ico';
|
|
let iconUrl;
|
|
|
|
blogIcon = blogIcon.replace(subdirRegExp, '');
|
|
|
|
iconUrl = this.get('ghostPaths.url').join(this.get('config.blogUrl'), blogIcon).replace(/\/$/, '');
|
|
iconUrl += `?t=${(new Date()).valueOf()}`;
|
|
|
|
this.set('iconStyle', htmlSafe(`background-image: url(${iconUrl})`));
|
|
}
|
|
});
|