diff --git a/core/client/app/adapters/base.js b/core/client/app/adapters/base.js index 427459f05e..d1de3edea5 100644 --- a/core/client/app/adapters/base.js +++ b/core/client/app/adapters/base.js @@ -1,10 +1,15 @@ import DS from 'ember-data'; import ghostPaths from 'ghost/utils/ghost-paths'; +import Ember from 'ember'; + +const {inject} = Ember; export default DS.RESTAdapter.extend({ host: window.location.origin, namespace: ghostPaths().apiRoot.slice(1), + session: inject.service('session'), + shouldBackgroundReloadRecord: function () { return false; }, @@ -43,5 +48,15 @@ export default DS.RESTAdapter.extend({ return response.then(function () { return null; }); + }, + + handleResponse: function (status) { + if (status === 401) { + if (this.get('session.isAuthenticated')) { + this.get('session').invalidate(); + } + } + + return this._super(...arguments); } }); diff --git a/core/client/app/components/gh-selectize.js b/core/client/app/components/gh-selectize.js index fedda43960..c377797e05 100644 --- a/core/client/app/components/gh-selectize.js +++ b/core/client/app/components/gh-selectize.js @@ -17,16 +17,18 @@ export default EmberSelectizeComponent.extend({ if (!openOnFocus) { Ember.run.next(this, function () { var selectize = this._selectize; - selectize.on('dropdown_open', function () { - if (Ember.isBlank(selectize.$control_input.val())) { - selectize.close(); - } - }); - selectize.on('type', function (filter) { - if (Ember.isBlank(filter)) { - selectize.close(); - } - }); + if (selectize) { + selectize.on('dropdown_open', function () { + if (Ember.isBlank(selectize.$control_input.val())) { + selectize.close(); + } + }); + selectize.on('type', function (filter) { + if (Ember.isBlank(filter)) { + selectize.close(); + } + }); + } }); } }), diff --git a/core/client/app/controllers/modals/signin.js b/core/client/app/controllers/modals/signin.js index cc24022464..c3b2c627c3 100644 --- a/core/client/app/controllers/modals/signin.js +++ b/core/client/app/controllers/modals/signin.js @@ -24,6 +24,7 @@ export default Ember.Controller.extend(ValidationEngine, { this.get('session').authenticate(authStrategy, this.get('identification'), this.get('password')).then(function () { self.send('closeModal'); self.set('password', ''); + self.get('notifications').closeAlerts('post.save'); }).catch(function () { // if authentication fails a rejected promise will be returned. // it needs to be caught so it doesn't generate an exception in the console, diff --git a/core/client/app/controllers/settings/tags/tag.js b/core/client/app/controllers/settings/tags/tag.js index e6d29e6636..c5678ffee7 100644 --- a/core/client/app/controllers/settings/tags/tag.js +++ b/core/client/app/controllers/settings/tags/tag.js @@ -9,6 +9,7 @@ export default Ember.Controller.extend({ isMobile: alias('tagsController.isMobile'), tagsController: inject.controller('settings.tags'), + notifications: inject.service(), saveTagProperty: function (propKey, newValue) { const tag = this.get('tag'), @@ -27,10 +28,10 @@ export default Ember.Controller.extend({ tag.save().then((savedTag) => { // replace 'new' route with 'tag' route - this.replaceWith('settings.tags.tag', savedTag); + this.replaceRoute('settings.tags.tag', savedTag); }).catch((error) => { if (error) { - this.notifications.showAPIError(error, {key: 'tag.save'}); + this.get('notifications').showAPIError(error, {key: 'tag.save'}); } }); }, diff --git a/core/client/app/mirage/config.js b/core/client/app/mirage/config.js index ee31e80716..8b3b89b4cb 100644 --- a/core/client/app/mirage/config.js +++ b/core/client/app/mirage/config.js @@ -52,6 +52,23 @@ export default function () { this.get('/notifications/', 'notifications'); + /* Posts ---------------------------------------------------------------- */ + + this.post('/posts/', function (db, request) { + const [attrs] = JSON.parse(request.requestBody).posts; + let post; + + if (isBlank(attrs.slug) && !isBlank(attrs.title)) { + attrs.slug = attrs.title.dasherize(); + } + + post = db.posts.insert(attrs); + + return { + posts: [post] + }; + }); + /* Settings ------------------------------------------------------------- */ this.get('/settings/', function (db, request) { @@ -84,6 +101,16 @@ export default function () { }; }); + /* Slugs ---------------------------------------------------------------- */ + + this.get('/slugs/post/:slug/', function (db, request) { + return { + slugs: [ + {slug: request.params.slug.dasherize} + ] + }; + }); + /* Tags ----------------------------------------------------------------- */ this.post('/tags/', function (db, request) { @@ -119,7 +146,7 @@ export default function () { this.put('/tags/:id/', function (db, request) { const id = request.params.id, - [attrs] = JSON.parse(request.requestBody).contacts, + [attrs] = JSON.parse(request.requestBody).tags, record = db.tags.update(id, attrs); return { @@ -137,6 +164,8 @@ export default function () { users: [db.users.find(1)] }; }); + + this.get('/users/', 'users'); } /* diff --git a/core/client/app/mirage/factories/post.js b/core/client/app/mirage/factories/post.js new file mode 100644 index 0000000000..ef92f336ea --- /dev/null +++ b/core/client/app/mirage/factories/post.js @@ -0,0 +1,6 @@ +/* jscs:disable */ +import Mirage from 'ember-cli-mirage'; + +export default Mirage.Factory.extend({ + // TODO: fill in with actual factory data +}); diff --git a/core/client/app/routes/application.js b/core/client/app/routes/application.js index 0610cf10d2..1522f6d70e 100644 --- a/core/client/app/routes/application.js +++ b/core/client/app/routes/application.js @@ -1,9 +1,11 @@ /* global key */ import Ember from 'ember'; +import AuthConfiguration from 'ember-simple-auth/configuration'; import ApplicationRouteMixin from 'ember-simple-auth/mixins/application-route-mixin'; import ShortcutsRoute from 'ghost/mixins/shortcuts-route'; import ctrlOrCmd from 'ghost/utils/ctrl-or-cmd'; +import windowProxy from 'ghost/utils/window-proxy'; const shortcuts = {}; @@ -42,6 +44,10 @@ export default Ember.Route.extend(ApplicationRouteMixin, ShortcutsRoute, { }); }, + sessionInvalidated: function () { + this.send('authorizationFailed'); + }, + actions: { openMobileMenu: function () { this.controller.set('showMobileMenu', true); @@ -75,6 +81,10 @@ export default Ember.Route.extend(ApplicationRouteMixin, ShortcutsRoute, { }); }, + authorizationFailed: function () { + windowProxy.replaceLocation(AuthConfiguration.baseURL); + }, + openModal: function (modalName, model, type) { this.get('dropdown').closeDropdowns(); key.setScope('modal'); diff --git a/core/client/app/routes/editor/edit.js b/core/client/app/routes/editor/edit.js index bd29f217bb..0918538f00 100644 --- a/core/client/app/routes/editor/edit.js +++ b/core/client/app/routes/editor/edit.js @@ -36,7 +36,7 @@ export default AuthenticatedRoute.extend(base, { return post; } - return self.replaceWith('posts.index'); + return self.replaceRoute('posts.index'); }); }, @@ -45,7 +45,7 @@ export default AuthenticatedRoute.extend(base, { return self.get('session.user').then(function (user) { if (user.get('isAuthor') && !post.isAuthoredByUser(user)) { - return self.replaceWith('posts.index'); + return self.replaceRoute('posts.index'); } }); }, diff --git a/core/client/app/routes/posts/post.js b/core/client/app/routes/posts/post.js index 6b4f79d9dd..35e05a880f 100644 --- a/core/client/app/routes/posts/post.js +++ b/core/client/app/routes/posts/post.js @@ -32,7 +32,7 @@ export default AuthenticatedRoute.extend(ShortcutsRoute, { return post; } - return self.replaceWith('posts.index'); + return self.replaceRoute('posts.index'); }); }, @@ -41,7 +41,7 @@ export default AuthenticatedRoute.extend(ShortcutsRoute, { return self.get('session.user').then(function (user) { if (user.get('isAuthor') && !post.isAuthoredByUser(user)) { - return self.replaceWith('posts.index'); + return self.replaceRoute('posts.index'); } }); }, diff --git a/core/client/app/templates/editor/edit.hbs b/core/client/app/templates/editor/edit.hbs index 1baf984241..db5aa1a795 100644 --- a/core/client/app/templates/editor/edit.hbs +++ b/core/client/app/templates/editor/edit.hbs @@ -1,8 +1,7 @@ {{#gh-editor editorScrollInfo=editorScrollInfo as |ghEditor|}}
{{#gh-view-title classNames="gh-editor-title" openMobileMenu="openMobileMenu"}} - {{gh-trim-focus-input type="text" id="entry-title"placeholder="Your Post Title" value=model.titleScratch - tabindex="1" focus=shouldFocusTitle}} + {{gh-trim-focus-input type="text" id="entry-title" placeholder="Your Post Title" value=model.titleScratch tabindex="1" focus=shouldFocusTitle}} {{/gh-view-title}}