diff --git a/ghost/admin/app/mixins/style-body.js b/ghost/admin/app/mixins/style-body.js deleted file mode 100644 index 3a977227cf..0000000000 --- a/ghost/admin/app/mixins/style-body.js +++ /dev/null @@ -1,32 +0,0 @@ -import $ from 'jquery'; -import Mixin from '@ember/object/mixin'; -import {run} from '@ember/runloop'; - -// mixin used for routes that need to set a css className on the body tag -export default Mixin.create({ - activate() { - let cssClasses = this.classNames; - - this._super(...arguments); - - if (cssClasses) { - run.schedule('afterRender', null, function () { - cssClasses.forEach((curClass) => { - $('body').addClass(curClass); - }); - }); - } - }, - - deactivate() { - let cssClasses = this.classNames; - - this._super(...arguments); - - run.schedule('afterRender', null, function () { - cssClasses.forEach((curClass) => { - $('body').removeClass(curClass); - }); - }); - } -}); diff --git a/ghost/admin/app/routes/reset.js b/ghost/admin/app/routes/reset.js index 63b050307f..f842579ea7 100644 --- a/ghost/admin/app/routes/reset.js +++ b/ghost/admin/app/routes/reset.js @@ -1,14 +1,11 @@ import Route from '@ember/routing/route'; import UnauthenticatedRouteMixin from 'ghost-admin/mixins/unauthenticated-route-mixin'; -import styleBody from 'ghost-admin/mixins/style-body'; import {inject as service} from '@ember/service'; -export default Route.extend(styleBody, UnauthenticatedRouteMixin, { +export default Route.extend(UnauthenticatedRouteMixin, { notifications: service(), session: service(), - classNames: ['ghost-reset'], - beforeModel() { if (this.get('session.isAuthenticated')) { this.notifications.showAlert('You can\'t reset your password while you\'re signed in.', {type: 'warn', delayed: true, key: 'password.reset.signed-in'}); @@ -25,5 +22,11 @@ export default Route.extend(styleBody, UnauthenticatedRouteMixin, { deactivate() { this._super(...arguments); this.controller.clearData(); + }, + + buildRouteInfoMetadata() { + return { + bodyClasses: ['unauthenticated-route'] + }; } }); diff --git a/ghost/admin/app/routes/settings/general.js b/ghost/admin/app/routes/settings/general.js index 41ddbe3be5..5b880fb45c 100644 --- a/ghost/admin/app/routes/settings/general.js +++ b/ghost/admin/app/routes/settings/general.js @@ -1,15 +1,13 @@ import AuthenticatedRoute from 'ghost-admin/routes/authenticated'; import CurrentUserSettings from 'ghost-admin/mixins/current-user-settings'; import RSVP from 'rsvp'; -import styleBody from 'ghost-admin/mixins/style-body'; import {inject as service} from '@ember/service'; -export default AuthenticatedRoute.extend(styleBody, CurrentUserSettings, { +export default AuthenticatedRoute.extend(CurrentUserSettings, { config: service(), settings: service(), titleToken: 'Settings - General', - classNames: ['settings-view-general'], beforeModel() { this._super(...arguments); diff --git a/ghost/admin/app/routes/setup.js b/ghost/admin/app/routes/setup.js index d134ac14dc..b1d6e85614 100644 --- a/ghost/admin/app/routes/setup.js +++ b/ghost/admin/app/routes/setup.js @@ -1,8 +1,7 @@ import Route from '@ember/routing/route'; -import styleBody from 'ghost-admin/mixins/style-body'; import {inject as service} from '@ember/service'; -export default Route.extend(styleBody, { +export default Route.extend({ ghostPaths: service(), session: service(), ajax: service(), @@ -10,8 +9,6 @@ export default Route.extend(styleBody, { titleToken: 'Setup', - classNames: ['ghost-setup'], - // use the beforeModel hook to check to see whether or not setup has been // previously completed. If it has, stop the transition into the setup page. beforeModel() { @@ -50,5 +47,11 @@ export default Route.extend(styleBody, { deactivate() { this._super(...arguments); this.controllerFor('setup/two').set('password', ''); + }, + + buildRouteInfoMetadata() { + return { + bodyClasses: ['unauthenticated-route'] + }; } }); diff --git a/ghost/admin/app/routes/signin.js b/ghost/admin/app/routes/signin.js index 644bb8c7d2..a670f6e65c 100644 --- a/ghost/admin/app/routes/signin.js +++ b/ghost/admin/app/routes/signin.js @@ -2,7 +2,6 @@ import DS from 'ember-data'; import EmberObject from '@ember/object'; import Route from '@ember/routing/route'; import UnauthenticatedRouteMixin from 'ghost-admin/mixins/unauthenticated-route-mixin'; -import styleBody from 'ghost-admin/mixins/style-body'; const {Errors} = DS; @@ -14,11 +13,9 @@ const defaultModel = function defaultModel() { }); }; -export default Route.extend(UnauthenticatedRouteMixin, styleBody, { +export default Route.extend(UnauthenticatedRouteMixin, { titleToken: 'Sign In', - classNames: ['ghost-login'], - model() { return defaultModel(); }, @@ -31,5 +28,11 @@ export default Route.extend(UnauthenticatedRouteMixin, styleBody, { // clear the properties that hold the credentials when we're no longer on the signin screen controller.set('signin', defaultModel()); + }, + + buildRouteInfoMetadata() { + return { + bodyClasses: ['unauthenticated-route'] + }; } }); diff --git a/ghost/admin/app/routes/signup.js b/ghost/admin/app/routes/signup.js index e23e8df100..3896141b46 100644 --- a/ghost/admin/app/routes/signup.js +++ b/ghost/admin/app/routes/signup.js @@ -4,21 +4,18 @@ import RSVP from 'rsvp'; import Route from '@ember/routing/route'; import UnauthenticatedRouteMixin from 'ghost-admin/mixins/unauthenticated-route-mixin'; import ValidationEngine from 'ghost-admin/mixins/validation-engine'; -import styleBody from 'ghost-admin/mixins/style-body'; import {inject as service} from '@ember/service'; const {Promise} = RSVP; const {Errors} = DS; -export default Route.extend(styleBody, UnauthenticatedRouteMixin, { +export default Route.extend(UnauthenticatedRouteMixin, { ghostPaths: service(), notifications: service(), session: service(), ajax: service(), config: service(), - classNames: ['ghost-signup'], - beforeModel() { if (this.get('session.isAuthenticated')) { this.notifications.showAlert('You need to sign out to register as a new user.', {type: 'warn', delayed: true, key: 'signup.create.already-authenticated'}); @@ -82,5 +79,11 @@ export default Route.extend(styleBody, UnauthenticatedRouteMixin, { // clear the properties that hold the sensitive data from the controller this.controllerFor('signup').get('signupDetails').setProperties({email: '', password: '', token: ''}); + }, + + buildRouteInfoMetadata() { + return { + bodyClasses: ['unauthenticated-route'] + }; } }); diff --git a/ghost/admin/app/services/ui.js b/ghost/admin/app/services/ui.js index 5f6cdd3f87..d23544904a 100644 --- a/ghost/admin/app/services/ui.js +++ b/ghost/admin/app/services/ui.js @@ -1,9 +1,35 @@ import Service, {inject as service} from '@ember/service'; +import {get} from '@ember/object'; import {not, or, reads} from '@ember/object/computed'; +function updateBodyClasses(transition) { + let oldClasses = []; + let newClasses = []; + let {from, to} = transition; + + while (from) { + oldClasses = oldClasses.concat(get(from, 'metadata.bodyClasses') || []); + from = from.parent; + } + + while (to) { + newClasses = newClasses.concat(get(to, 'metadata.bodyClasses') || []); + to = to.parent; + } + + let {body} = document; + oldClasses.forEach((oldClass) => { + body.classList.remove(oldClass); + }); + newClasses.forEach((newClass) => { + body.classList.add(newClass); + }); +} + export default Service.extend({ dropdown: service(), mediaQueries: service(), + router: service(), isFullScreen: false, showMobileMenu: false, @@ -13,6 +39,13 @@ export default Service.extend({ isMobile: reads('mediaQueries.isMobile'), isSideNavHidden: or('isFullScreen', 'isMobile'), + init() { + this._super(...arguments); + this.router.on('routeDidChange', (transition) => { + updateBodyClasses(transition); + }); + }, + closeMenus() { this.dropdown.closeDropdowns(); this.setProperties({ diff --git a/ghost/admin/app/styles/layouts/main.css b/ghost/admin/app/styles/layouts/main.css index d9d0815181..0c81155174 100644 --- a/ghost/admin/app/styles/layouts/main.css +++ b/ghost/admin/app/styles/layouts/main.css @@ -464,17 +464,11 @@ } /* non-authed pages shouldn't have the mobile bar */ - .ghost-setup .gh-viewport, - .ghost-reset .gh-viewport, - .ghost-signup .gh-viewport, - .ghost-login .gh-viewport { + .unauthenticated-route .gh-viewport { padding-bottom: 0; } - .ghost-setup .gh-mobile-nav-bar, - .ghost-reset .gh-mobile-nav-bar, - .ghost-signup .gh-mobile-nav-bar, - .ghost-login .gh-mobile-nav-bar { + .unauthenticated-route .gh-mobile-nav-bar { display: none; } }