0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-24 23:48:13 -05:00

Use Ember.Comparable mixin to sort posts

closes https://github.com/TryGhost/Ghost/issues/7002
- move sorting logic out of the controller and into the Post model

This is a quick attempt at implementing the refactoring referenced in https://github.com/TryGhost/Ghost/issues/7002. The client-side sorting is working but we still have the problem of scheduled posts not appearing in the list until you scroll to the very first published post because the server is returning posts in the wrong order.
This commit is contained in:
Kevin Ansfield 2016-06-17 11:18:17 +01:00
parent f1c68e48c8
commit a109c1c3db
2 changed files with 100 additions and 100 deletions

View file

@ -8,101 +8,6 @@ const {
} = Ember;
const {equal} = computed;
// a custom sort function is needed in order to sort the posts list the same way the server would:
// status: scheduled, draft, published
// publishedAtUTC: DESC
// updatedAtUTC: DESC
// id: DESC
function comparator(item1, item2) {
let updated1 = item1.get('updatedAtUTC');
let updated2 = item2.get('updatedAtUTC');
let idResult,
publishedAtResult,
statusResult,
updatedAtResult;
// when `updatedAt` is undefined, the model is still
// being written to with the results from the server
if (item1.get('isNew') || !updated1) {
return -1;
}
if (item2.get('isNew') || !updated2) {
return 1;
}
idResult = compare(parseInt(item1.get('id')), parseInt(item2.get('id')));
statusResult = statusCompare(item1, item2);
updatedAtResult = compare(updated1.valueOf(), updated2.valueOf());
publishedAtResult = publishedAtCompare(item1, item2);
if (statusResult === 0) {
if (publishedAtResult === 0) {
if (updatedAtResult === 0) {
// This should be DESC
return idResult * -1;
}
// This should be DESC
return updatedAtResult * -1;
}
// This should be DESC
return publishedAtResult * -1;
}
return statusResult;
}
function statusCompare(item1, item2) {
let status1 = item1.get('status');
let status2 = item2.get('status');
// if any of those is empty
if (!status1 && !status2) {
return 0;
}
if (!status1 && status2) {
return -1;
}
if (!status2 && status1) {
return 1;
}
// We have to make sure, that scheduled posts will be listed first
// after that, draft and published will be sorted alphabetically and don't need
// any manual comparison.
if (status1 === 'scheduled' && (status2 === 'draft' || status2 === 'published')) {
return -1;
}
if (status2 === 'scheduled' && (status1 === 'draft' || status1 === 'published')) {
return 1;
}
return compare(status1.valueOf(), status2.valueOf());
}
function publishedAtCompare(item1, item2) {
let published1 = item1.get('publishedAtUTC');
let published2 = item2.get('publishedAtUTC');
if (!published1 && !published2) {
return 0;
}
if (!published1 && published2) {
return -1;
}
if (!published2 && published1) {
return 1;
}
return compare(published1.valueOf(), published2.valueOf());
}
export default Controller.extend({
feature: service(),
@ -112,10 +17,8 @@ export default Controller.extend({
postListFocused: equal('keyboardFocus', 'postList'),
postContentFocused: equal('keyboardFocus', 'postContent'),
sortedPosts: computed('model.@each.status', 'model.@each.publishedAtUTC', 'model.@each.isNew', 'model.@each.updatedAtUTC', function () {
let postsArray = this.get('model').toArray();
return postsArray.sort(comparator);
sortedPosts: computed('model.@each.{status,publishedAtUTC,isNew,updatedAtUTC}', function () {
return this.get('model').toArray().sort(compare);
}),
actions: {

View file

@ -6,12 +6,65 @@ import { belongsTo, hasMany } from 'ember-data/relationships';
import ValidationEngine from 'ghost-admin/mixins/validation-engine';
const {
Comparable,
compare,
computed,
inject: {service}
} = Ember;
const {equal, filterBy} = computed;
export default Model.extend(ValidationEngine, {
function statusCompare(postA, postB) {
let status1 = postA.get('status');
let status2 = postB.get('status');
// if any of those is empty
if (!status1 && !status2) {
return 0;
}
if (!status1 && status2) {
return -1;
}
if (!status2 && status1) {
return 1;
}
// We have to make sure, that scheduled posts will be listed first
// after that, draft and published will be sorted alphabetically and don't need
// any manual comparison.
if (status1 === 'scheduled' && (status2 === 'draft' || status2 === 'published')) {
return -1;
}
if (status2 === 'scheduled' && (status1 === 'draft' || status1 === 'published')) {
return 1;
}
return compare(status1.valueOf(), status2.valueOf());
}
function publishedAtCompare(postA, postB) {
let published1 = postA.get('publishedAtUTC');
let published2 = postB.get('publishedAtUTC');
if (!published1 && !published2) {
return 0;
}
if (!published1 && published2) {
return -1;
}
if (!published2 && published1) {
return 1;
}
return compare(published1.valueOf(), published2.valueOf());
}
export default Model.extend(Comparable, ValidationEngine, {
validationType: 'post',
uuid: attr('string'),
@ -95,5 +148,49 @@ export default Model.extend(ValidationEngine, {
isAuthoredByUser(user) {
return parseInt(user.get('id'), 10) === parseInt(this.get('authorId'), 10);
},
// a custom sort function is needed in order to sort the posts list the same way the server would:
// status: scheduled, draft, published
// publishedAt: DESC
// updatedAt: DESC
// id: DESC
compare(postA, postB) {
let updated1 = postA.get('updatedAtUTC');
let updated2 = postB.get('updatedAtUTC');
let idResult,
publishedAtResult,
statusResult,
updatedAtResult;
// when `updatedAt` is undefined, the model is still
// being written to with the results from the server
if (postA.get('isNew') || !updated1) {
return -1;
}
if (postB.get('isNew') || !updated2) {
return 1;
}
idResult = compare(parseInt(postA.get('id')), parseInt(postB.get('id')));
statusResult = statusCompare(postA, postB);
updatedAtResult = compare(updated1.valueOf(), updated2.valueOf());
publishedAtResult = publishedAtCompare(postA, postB);
if (statusResult === 0) {
if (publishedAtResult === 0) {
if (updatedAtResult === 0) {
// This should be DESC
return idResult * -1;
}
// This should be DESC
return updatedAtResult * -1;
}
// This should be DESC
return publishedAtResult * -1;
}
return statusResult;
}
});