diff --git a/core/client/adapters/application.js b/core/client/adapters/application.js index 954d6fc349..ff4a09c8c7 100644 --- a/core/client/adapters/application.js +++ b/core/client/adapters/application.js @@ -9,6 +9,17 @@ var ApplicationAdapter = DS.RESTAdapter.extend({ 'X-CSRF-Token': $('meta[name="csrf-param"]').attr('content') }, + findQuery: function (store, type, query) { + var id; + + if (query.id) { + id = query.id; + delete query.id; + } + + return this.ajax(this.buildURL(type.typeKey, id), 'GET', { data: query }); + }, + buildURL: function (type, id) { // Ensure trailing slashes var url = this._super(type, id); diff --git a/core/client/controllers/posts.js b/core/client/controllers/posts.js index a24e98712c..4ec82c5c02 100644 --- a/core/client/controllers/posts.js +++ b/core/client/controllers/posts.js @@ -1,6 +1,47 @@ import { getRequestErrorMessage } from 'ghost/utils/ajax'; var PostsController = Ember.ArrayController.extend({ + // this will cause the list to re-sort when any of these properties change on any of the models + sortProperties: ['status', 'published_at', 'updated_at'], + + // override Ember.SortableMixin + // + // this function will keep the posts list sorted when loading individual/bulk + // models from the server, even if records in between haven't been loaded. + // this can happen when reloading the page on the Editor or PostsPost routes. + // + // a custom sort function is needed in order to sort the posts list the same way the server would: + // status: ASC + // published_at: DESC + // updated_at: DESC + orderBy: function (item1, item2) { + var status1 = item1.get('status'), + status2 = item2.get('status'), + + updatedAt1, updatedAt2, + publishedAt1, publishedAt2; + + if (status1 === status2) { + if (status1 === 'draft') { + updatedAt1 = item1.get('updated_at'); + updatedAt2 = item2.get('updated_at'); + + return (new Date(updatedAt1)) < (new Date(updatedAt2)) ? 1 : -1; + } else { + publishedAt1 = item1.get('published_at'); + publishedAt2 = item2.get('published_at'); + + return (new Date(publishedAt1)) < new Date(publishedAt2) ? 1 : -1; + } + } + + if (status2 === 'draft') { + return 1; + } + + return -1; + }, + // set from PostsRoute paginationSettings: null, diff --git a/core/client/models/post.js b/core/client/models/post.js index cb6316bed6..4b84baf892 100644 --- a/core/client/models/post.js +++ b/core/client/models/post.js @@ -19,7 +19,7 @@ var Post = DS.Model.extend({ published_at: DS.attr('moment-date'), published_by: DS.belongsTo('user', { async: true }), tags: DS.hasMany('tag', { async: true }), - + //## Computed post properties isPublished: Ember.computed.equal('status', 'published'), isDraft: Ember.computed.equal('status', 'draft'), diff --git a/core/client/routes/editor/edit.js b/core/client/routes/editor/edit.js index 173c61eea3..db08f2dcbb 100644 --- a/core/client/routes/editor/edit.js +++ b/core/client/routes/editor/edit.js @@ -21,9 +21,10 @@ var EditorEditRoute = AuthenticatedRoute.extend(styleBody, { return post; } - return this.store.filter('post', { status: 'all', staticPages: 'all' }, function (post) { - //post.get('id') returns a string, so compare with params.post_id - return post.get('id') === params.post_id; + return this.store.find('post', { + id: params.post_id, + status: 'all', + staticPages: 'all' }).then(function (records) { var post = records.get('firstObject'); diff --git a/core/client/routes/posts/index.js b/core/client/routes/posts/index.js index c7d62cfa4f..532d35218d 100644 --- a/core/client/routes/posts/index.js +++ b/core/client/routes/posts/index.js @@ -2,12 +2,16 @@ import AuthenticatedRoute from 'ghost/routes/authenticated'; var PostsIndexRoute = AuthenticatedRoute.extend({ // redirect to first post subroute - redirect: function () { - var firstPost = (this.modelFor('posts') || []).get('firstObject'); + beforeModel: function () { + var self = this; - if (firstPost) { - this.transitionTo('posts.post', firstPost); - } + return this.store.find('post', { + status: 'all', + staticPages: 'all' + }).then(function (records) { + var post = records.get('firstObject'); + return self.transitionTo('posts.post', post); + }); } }); diff --git a/core/client/routes/posts/post.js b/core/client/routes/posts/post.js index df3a41263f..f02bc873b6 100644 --- a/core/client/routes/posts/post.js +++ b/core/client/routes/posts/post.js @@ -2,14 +2,36 @@ import AuthenticatedRoute from 'ghost/routes/authenticated'; var PostsPostRoute = AuthenticatedRoute.extend({ model: function (params) { - var post = this.modelFor('posts').findBy('id', params.post_id); + var self = this, + post, + postId; - if (!post) { + postId = Number(params.post_id); + + if (!Number.isInteger(postId) || !Number.isFinite(postId) || postId <= 0) { this.transitionTo('posts.index'); } - return post; - } + post = this.store.getById('post', postId); + + if (post) { + return post; + } + + return this.store.find('post', { + id: params.post_id, + status: 'all', + staticPages: 'all' + }).then(function (records) { + var post = records.get('firstObject'); + + if (post) { + return post; + } + + return self.transitionTo('posts.index'); + }); + }, }); export default PostsPostRoute;