Convert `Composer` to use Store
- Uses store for `PostStream`, `TopicList` too
This commit is contained in:
parent
a83a19f6ce
commit
d4a05825da
|
@ -0,0 +1,39 @@
|
||||||
|
import RestAdapter from 'discourse/adapters/rest';
|
||||||
|
|
||||||
|
function finderFor(filter, params) {
|
||||||
|
return function() {
|
||||||
|
let url = Discourse.getURL("/") + filter + ".json";
|
||||||
|
|
||||||
|
if (params) {
|
||||||
|
const keys = Object.keys(params),
|
||||||
|
encoded = [];
|
||||||
|
|
||||||
|
keys.forEach(function(p) {
|
||||||
|
const value = params[p];
|
||||||
|
if (typeof value !== 'undefined') {
|
||||||
|
encoded.push(p + "=" + value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (encoded.length > 0) {
|
||||||
|
url += "?" + encoded.join('&');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Discourse.ajax(url);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RestAdapter.extend({
|
||||||
|
|
||||||
|
find(store, type, findArgs) {
|
||||||
|
const filter = findArgs.filter;
|
||||||
|
const params = findArgs.params;
|
||||||
|
|
||||||
|
return PreloadStore.getAndRemove("topic_list_" + filter, finderFor(filter, params)).then(function(result) {
|
||||||
|
result.filter = filter;
|
||||||
|
result.params = params;
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
|
@ -413,7 +413,7 @@ export default DiscourseController.extend({
|
||||||
composerModel.set('topic', opts.topic);
|
composerModel.set('topic', opts.topic);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
composerModel = composerModel || Discourse.Composer.create({ store: this.store });
|
composerModel = composerModel || this.store.createRecord('composer');
|
||||||
composerModel.open(opts);
|
composerModel.open(opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,8 @@ var controllerOpts = {
|
||||||
// router and ember throws an error due to missing `handlerInfos`.
|
// router and ember throws an error due to missing `handlerInfos`.
|
||||||
// Lesson learned: Don't call `loading` yourself.
|
// Lesson learned: Don't call `loading` yourself.
|
||||||
this.set('controllers.discovery.loading', true);
|
this.set('controllers.discovery.loading', true);
|
||||||
Discourse.TopicList.find(filter).then(function(list) {
|
|
||||||
|
this.store.findFiltered('topicList', {filter}).then(function(list) {
|
||||||
Discourse.TopicList.hideUniformCategory(list, self.get('category'));
|
Discourse.TopicList.hideUniformCategory(list, self.get('category'));
|
||||||
|
|
||||||
self.setProperties({ model: list });
|
self.setProperties({ model: list });
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
import RestModel from 'discourse/models/rest';
|
||||||
|
import Post from 'discourse/models/post';
|
||||||
|
import Topic from 'discourse/models/topic';
|
||||||
|
|
||||||
const CLOSED = 'closed',
|
const CLOSED = 'closed',
|
||||||
SAVING = 'saving',
|
SAVING = 'saving',
|
||||||
OPEN = 'open',
|
OPEN = 'open',
|
||||||
|
@ -26,7 +30,7 @@ const CLOSED = 'closed',
|
||||||
categoryId: 'topic.category.id'
|
categoryId: 'topic.category.id'
|
||||||
};
|
};
|
||||||
|
|
||||||
const Composer = Discourse.Model.extend({
|
const Composer = RestModel.extend({
|
||||||
|
|
||||||
archetypes: function() {
|
archetypes: function() {
|
||||||
return this.site.get('archetypes');
|
return this.site.get('archetypes');
|
||||||
|
@ -420,7 +424,8 @@ const Composer = Discourse.Model.extend({
|
||||||
post.get('post_number') === 1 &&
|
post.get('post_number') === 1 &&
|
||||||
this.get('topic.details.can_edit')) {
|
this.get('topic.details.can_edit')) {
|
||||||
const topicProps = this.getProperties(Object.keys(_edit_topic_serializer));
|
const topicProps = this.getProperties(Object.keys(_edit_topic_serializer));
|
||||||
promise = Discourse.Topic.update(this.get('topic'), topicProps);
|
|
||||||
|
promise = Topic.update(this.get('topic'), topicProps);
|
||||||
} else {
|
} else {
|
||||||
promise = Ember.RSVP.resolve();
|
promise = Ember.RSVP.resolve();
|
||||||
}
|
}
|
||||||
|
@ -468,7 +473,7 @@ const Composer = Discourse.Model.extend({
|
||||||
let addedToStream = false;
|
let addedToStream = false;
|
||||||
|
|
||||||
// Build the post object
|
// Build the post object
|
||||||
const createdPost = Discourse.Post.create({
|
const createdPost = Post.create({
|
||||||
imageSizes: opts.imageSizes,
|
imageSizes: opts.imageSizes,
|
||||||
cooked: this.getCookedHtml(),
|
cooked: this.getCookedHtml(),
|
||||||
reply_count: 0,
|
reply_count: 0,
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
const PostStream = Ember.Object.extend({
|
import RestModel from 'discourse/models/rest';
|
||||||
|
|
||||||
|
const PostStream = RestModel.extend({
|
||||||
loading: Em.computed.or('loadingAbove', 'loadingBelow', 'loadingFilter', 'stagingPost'),
|
loading: Em.computed.or('loadingAbove', 'loadingBelow', 'loadingFilter', 'stagingPost'),
|
||||||
notLoading: Em.computed.not('loading'),
|
notLoading: Em.computed.not('loading'),
|
||||||
filteredPostsCount: Em.computed.alias("stream.length"),
|
filteredPostsCount: Em.computed.alias("stream.length"),
|
||||||
|
@ -420,8 +422,9 @@ const PostStream = Ember.Object.extend({
|
||||||
} else {
|
} else {
|
||||||
// need to insert into stream
|
// need to insert into stream
|
||||||
const url = "/posts/" + postId;
|
const url = "/posts/" + postId;
|
||||||
|
const store = this.store;
|
||||||
Discourse.ajax(url).then(function(p){
|
Discourse.ajax(url).then(function(p){
|
||||||
const post = Discourse.Post.create(p);
|
const post = store.createRecord('post', p);
|
||||||
const stream = self.get("stream");
|
const stream = self.get("stream");
|
||||||
const posts = self.get("posts");
|
const posts = self.get("posts");
|
||||||
self.storePost(post);
|
self.storePost(post);
|
||||||
|
@ -461,9 +464,10 @@ const PostStream = Ember.Object.extend({
|
||||||
|
|
||||||
if(existing){
|
if(existing){
|
||||||
const url = "/posts/" + postId;
|
const url = "/posts/" + postId;
|
||||||
|
const store = this.store;
|
||||||
Discourse.ajax(url).then(
|
Discourse.ajax(url).then(
|
||||||
function(p){
|
function(p){
|
||||||
self.storePost(Discourse.Post.create(p));
|
self.storePost(store.createRecord('post', p));
|
||||||
},
|
},
|
||||||
function(){
|
function(){
|
||||||
self.removePosts([existing]);
|
self.removePosts([existing]);
|
||||||
|
@ -480,8 +484,9 @@ const PostStream = Ember.Object.extend({
|
||||||
|
|
||||||
if (existing && existing.updated_at !== updatedAt) {
|
if (existing && existing.updated_at !== updatedAt) {
|
||||||
const url = "/posts/" + postId;
|
const url = "/posts/" + postId;
|
||||||
|
const store = this.store;
|
||||||
Discourse.ajax(url).then(function(p){
|
Discourse.ajax(url).then(function(p){
|
||||||
self.storePost(Discourse.Post.create(p));
|
self.storePost(store.createRecord('post', p));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -491,9 +496,10 @@ const PostStream = Ember.Object.extend({
|
||||||
const postStream = this,
|
const postStream = this,
|
||||||
url = "/posts/" + post.get('id') + "/reply-history.json?max_replies=" + Discourse.SiteSettings.max_reply_history;
|
url = "/posts/" + post.get('id') + "/reply-history.json?max_replies=" + Discourse.SiteSettings.max_reply_history;
|
||||||
|
|
||||||
|
const store = this.store;
|
||||||
return Discourse.ajax(url).then(function(result) {
|
return Discourse.ajax(url).then(function(result) {
|
||||||
return result.map(function (p) {
|
return result.map(function (p) {
|
||||||
return postStream.storePost(Discourse.Post.create(p));
|
return postStream.storePost(store.createRecord('post', p));
|
||||||
});
|
});
|
||||||
}).then(function (replyHistory) {
|
}).then(function (replyHistory) {
|
||||||
post.set('replyHistory', replyHistory);
|
post.set('replyHistory', replyHistory);
|
||||||
|
@ -594,8 +600,9 @@ const PostStream = Ember.Object.extend({
|
||||||
this.set('gaps', null);
|
this.set('gaps', null);
|
||||||
if (postStreamData) {
|
if (postStreamData) {
|
||||||
// Load posts if present
|
// Load posts if present
|
||||||
|
const store = this.store;
|
||||||
postStreamData.posts.forEach(function(p) {
|
postStreamData.posts.forEach(function(p) {
|
||||||
postStream.appendPost(Discourse.Post.create(p));
|
postStream.appendPost(store.createRecord('post', p));
|
||||||
});
|
});
|
||||||
delete postStreamData.posts;
|
delete postStreamData.posts;
|
||||||
|
|
||||||
|
@ -671,11 +678,12 @@ const PostStream = Ember.Object.extend({
|
||||||
data = { post_ids: postIds },
|
data = { post_ids: postIds },
|
||||||
postStream = this;
|
postStream = this;
|
||||||
|
|
||||||
|
const store = this.store;
|
||||||
return Discourse.ajax(url, {data: data}).then(function(result) {
|
return Discourse.ajax(url, {data: data}).then(function(result) {
|
||||||
const posts = Em.get(result, "post_stream.posts");
|
const posts = Em.get(result, "post_stream.posts");
|
||||||
if (posts) {
|
if (posts) {
|
||||||
posts.forEach(function (p) {
|
posts.forEach(function (p) {
|
||||||
postStream.storePost(Discourse.Post.create(p));
|
postStream.storePost(store.createRecord('post', p));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -751,6 +759,8 @@ PostStream.reopenClass({
|
||||||
url += "/" + opts.nearPost;
|
url += "/" + opts.nearPost;
|
||||||
}
|
}
|
||||||
delete opts.nearPost;
|
delete opts.nearPost;
|
||||||
|
delete opts.__type;
|
||||||
|
delete opts.store;
|
||||||
|
|
||||||
return PreloadStore.getAndRemove("topic_" + topicId, function() {
|
return PreloadStore.getAndRemove("topic_" + topicId, function() {
|
||||||
return Discourse.ajax(url + ".json", {data: opts});
|
return Discourse.ajax(url + ".json", {data: opts});
|
||||||
|
|
|
@ -394,32 +394,29 @@ const Post = RestModel.extend({
|
||||||
throw e;
|
throw e;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Post.reopenClass({
|
Post.reopenClass({
|
||||||
|
|
||||||
createActionSummary(result) {
|
munge(json) {
|
||||||
if (result.actions_summary) {
|
if (json.actions_summary) {
|
||||||
const lookup = Em.Object.create();
|
const lookup = Em.Object.create();
|
||||||
// this area should be optimized, it is creating way too many objects per post
|
// this area should be optimized, it is creating way too many objects per post
|
||||||
result.actions_summary = result.actions_summary.map(function(a) {
|
json.actions_summary = json.actions_summary.map(function(a) {
|
||||||
a.post = result;
|
a.post = json;
|
||||||
a.actionType = Discourse.Site.current().postActionTypeById(a.id);
|
a.actionType = Discourse.Site.current().postActionTypeById(a.id);
|
||||||
const actionSummary = Discourse.ActionSummary.create(a);
|
const actionSummary = Discourse.ActionSummary.create(a);
|
||||||
lookup[a.actionType.name_key] = actionSummary;
|
lookup[a.actionType.name_key] = actionSummary;
|
||||||
return actionSummary;
|
return actionSummary;
|
||||||
});
|
});
|
||||||
result.set('actionByName', lookup);
|
json.actionByName = lookup;
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
create(obj) {
|
if (json && json.reply_to_user) {
|
||||||
const result = this._super.apply(this, arguments);
|
json.reply_to_user = Discourse.User.create(json.reply_to_user);
|
||||||
this.createActionSummary(result);
|
|
||||||
if (obj && obj.reply_to_user) {
|
|
||||||
result.set('reply_to_user', Discourse.User.create(obj.reply_to_user));
|
|
||||||
}
|
}
|
||||||
return result;
|
return json;
|
||||||
},
|
},
|
||||||
|
|
||||||
updateBookmark(postId, bookmarked) {
|
updateBookmark(postId, bookmarked) {
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
import Presence from 'discourse/mixins/presence';
|
import Presence from 'discourse/mixins/presence';
|
||||||
|
|
||||||
export default Ember.Object.extend(Presence, {
|
const RestModel = Ember.Object.extend(Presence, {
|
||||||
update(attrs) {
|
update(attrs) {
|
||||||
const self = this,
|
const self = this,
|
||||||
type = this.get('__type');
|
type = this.get('__type');
|
||||||
|
|
||||||
|
const munge = this.__munge;
|
||||||
return this.store.update(type, this.get('id'), attrs).then(function(result) {
|
return this.store.update(type, this.get('id'), attrs).then(function(result) {
|
||||||
if (result && result[type]) {
|
if (result && result[type]) {
|
||||||
Object.keys(result).forEach(function(k) {
|
Object.keys(result).forEach(function(k) {
|
||||||
attrs[k] = result[k];
|
attrs[k] = result[k];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
self.setProperties(attrs);
|
self.setProperties(munge(attrs));
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -20,3 +22,25 @@ export default Ember.Object.extend(Presence, {
|
||||||
return this.store.destroyRecord(type, this);
|
return this.store.destroyRecord(type, this);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
RestModel.reopenClass({
|
||||||
|
|
||||||
|
// Overwrite and JSON will be passed through here before `create` and `update`
|
||||||
|
munge(json) {
|
||||||
|
return json;
|
||||||
|
},
|
||||||
|
|
||||||
|
create(args) {
|
||||||
|
args = args || {};
|
||||||
|
if (!args.store) {
|
||||||
|
const container = Discourse.__container__;
|
||||||
|
Ember.warn('Use `store.createRecord` to create records instead of `.create()`');
|
||||||
|
args.store = container.lookup('store:main');
|
||||||
|
}
|
||||||
|
|
||||||
|
args.__munge = this.munge;
|
||||||
|
return this._super(this.munge(args, args.store));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default RestModel;
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
import RestModel from 'discourse/models/rest';
|
import RestModel from 'discourse/models/rest';
|
||||||
import ResultSet from 'discourse/models/result-set';
|
import ResultSet from 'discourse/models/result-set';
|
||||||
|
|
||||||
const _identityMap = {};
|
let _identityMap;
|
||||||
|
|
||||||
|
// You should only call this if you're a test scaffold
|
||||||
|
function flushMap() {
|
||||||
|
_identityMap = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
flushMap();
|
||||||
|
|
||||||
export default Ember.Object.extend({
|
export default Ember.Object.extend({
|
||||||
pluralize(thing) {
|
pluralize(thing) {
|
||||||
|
@ -16,6 +23,15 @@ export default Ember.Object.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Mostly for legacy, things like TopicList without ResultSets
|
||||||
|
findFiltered(type, findArgs) {
|
||||||
|
const adapter = this.container.lookup('adapter:' + type) || this.container.lookup('adapter:rest');
|
||||||
|
const self = this;
|
||||||
|
return adapter.find(this, type, findArgs).then(function(result) {
|
||||||
|
return self._build(type, result);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
find(type, findArgs) {
|
find(type, findArgs) {
|
||||||
const adapter = this.container.lookup('adapter:' + type) || this.container.lookup('adapter:rest');
|
const adapter = this.container.lookup('adapter:' + type) || this.container.lookup('adapter:rest');
|
||||||
const self = this;
|
const self = this;
|
||||||
|
@ -60,7 +76,8 @@ export default Ember.Object.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
createRecord(type, attrs) {
|
createRecord(type, attrs) {
|
||||||
return this._hydrate(type, attrs);
|
attrs = attrs || {};
|
||||||
|
return !!attrs.id ? this._hydrate(type, attrs) : this._build(type, attrs);
|
||||||
},
|
},
|
||||||
|
|
||||||
destroyRecord(type, record) {
|
destroyRecord(type, record) {
|
||||||
|
@ -81,6 +98,19 @@ export default Ember.Object.extend({
|
||||||
return ResultSet.create({ content, totalRows, loadMoreUrl, store: this, __type: type });
|
return ResultSet.create({ content, totalRows, loadMoreUrl, store: this, __type: type });
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_build(type, obj) {
|
||||||
|
obj.store = this;
|
||||||
|
obj.__type = type;
|
||||||
|
|
||||||
|
const klass = this.container.lookupFactory('model:' + type) || RestModel;
|
||||||
|
const model = klass.create(obj);
|
||||||
|
|
||||||
|
if (obj.id) {
|
||||||
|
_identityMap[type][obj.id] = model;
|
||||||
|
}
|
||||||
|
return model;
|
||||||
|
},
|
||||||
|
|
||||||
_hydrate(type, obj) {
|
_hydrate(type, obj) {
|
||||||
if (!obj) { throw "Can't hydrate " + type + " of `null`"; }
|
if (!obj) { throw "Can't hydrate " + type + " of `null`"; }
|
||||||
if (!obj.id) { throw "Can't hydrate " + type + " without an `id`"; }
|
if (!obj.id) { throw "Can't hydrate " + type + " without an `id`"; }
|
||||||
|
@ -88,18 +118,17 @@ export default Ember.Object.extend({
|
||||||
_identityMap[type] = _identityMap[type] || {};
|
_identityMap[type] = _identityMap[type] || {};
|
||||||
|
|
||||||
const existing = _identityMap[type][obj.id];
|
const existing = _identityMap[type][obj.id];
|
||||||
|
if (existing === obj) { return existing; }
|
||||||
|
|
||||||
if (existing) {
|
if (existing) {
|
||||||
delete obj.id;
|
delete obj.id;
|
||||||
existing.setProperties(obj);
|
const klass = this.container.lookupFactory('model:' + type) || RestModel;
|
||||||
|
existing.setProperties(klass.munge(obj));
|
||||||
return existing;
|
return existing;
|
||||||
}
|
}
|
||||||
|
|
||||||
obj.store = this;
|
return this._build(type, obj);
|
||||||
obj.__type = type;
|
|
||||||
|
|
||||||
const klass = this.container.lookupFactory('model:' + type) || RestModel;
|
|
||||||
const model = klass.create(obj);
|
|
||||||
_identityMap[type][obj.id] = model;
|
|
||||||
return model;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export { flushMap };
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
A model representing a Topic's details that aren't always present, such as a list of participants.
|
A model representing a Topic's details that aren't always present, such as a list of participants.
|
||||||
When showing topics in lists and such this information should not be required.
|
When showing topics in lists and such this information should not be required.
|
||||||
**/
|
**/
|
||||||
const TopicDetails = Discourse.Model.extend({
|
import RestModel from 'discourse/models/rest';
|
||||||
|
|
||||||
|
const TopicDetails = RestModel.extend({
|
||||||
loaded: false,
|
loaded: false,
|
||||||
|
|
||||||
updateFromJson(details) {
|
updateFromJson(details) {
|
||||||
|
@ -15,8 +17,9 @@ const TopicDetails = Discourse.Model.extend({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (details.suggested_topics) {
|
if (details.suggested_topics) {
|
||||||
|
const store = this.store;
|
||||||
details.suggested_topics = details.suggested_topics.map(function (st) {
|
details.suggested_topics = details.suggested_topics.map(function (st) {
|
||||||
return Discourse.Topic.create(st);
|
return store.createRecord('topic', st);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,163 @@
|
||||||
|
import RestModel from 'discourse/models/rest';
|
||||||
|
import Model from 'discourse/models/model';
|
||||||
|
|
||||||
|
|
||||||
|
function topicsFrom(result, store) {
|
||||||
|
if (!result) { return; }
|
||||||
|
|
||||||
|
// Stitch together our side loaded data
|
||||||
|
const categories = Discourse.Category.list(),
|
||||||
|
users = Model.extractByKey(result.users, Discourse.User);
|
||||||
|
|
||||||
|
return result.topic_list.topics.map(function (t) {
|
||||||
|
t.category = categories.findBy('id', t.category_id);
|
||||||
|
t.posters.forEach(function(p) {
|
||||||
|
p.user = users[p.user_id];
|
||||||
|
});
|
||||||
|
if (t.participants) {
|
||||||
|
t.participants.forEach(function(p) {
|
||||||
|
p.user = users[p.user_id];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return store.createRecord('topic', t);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const TopicList = RestModel.extend({
|
||||||
|
canLoadMore: Em.computed.notEmpty("more_topics_url"),
|
||||||
|
|
||||||
|
forEachNew: function(topics, callback) {
|
||||||
|
const topicIds = [];
|
||||||
|
_.each(this.get('topics'),function(topic) {
|
||||||
|
topicIds[topic.get('id')] = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
_.each(topics,function(topic) {
|
||||||
|
if(!topicIds[topic.id]) {
|
||||||
|
callback(topic);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
refreshSort: function(order, ascending) {
|
||||||
|
const self = this,
|
||||||
|
params = this.get('params');
|
||||||
|
|
||||||
|
params.order = order || params.order;
|
||||||
|
|
||||||
|
if (ascending === undefined) {
|
||||||
|
params.ascending = ascending;
|
||||||
|
} else {
|
||||||
|
params.ascending = ascending;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.set('loaded', false);
|
||||||
|
const store = this.store;
|
||||||
|
store.findFiltered('topicList', {filter: this.get('filter'), params}).then(function(tl) {
|
||||||
|
const newTopics = tl.get('topics'),
|
||||||
|
topics = self.get('topics');
|
||||||
|
|
||||||
|
topics.clear();
|
||||||
|
topics.pushObjects(newTopics);
|
||||||
|
self.setProperties({ loaded: true, more_topics_url: newTopics.get('more_topics_url') });
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
loadMore: function() {
|
||||||
|
if (this.get('loadingMore')) { return Ember.RSVP.resolve(); }
|
||||||
|
|
||||||
|
const moreUrl = this.get('more_topics_url');
|
||||||
|
if (moreUrl) {
|
||||||
|
const self = this;
|
||||||
|
this.set('loadingMore', true);
|
||||||
|
|
||||||
|
const store = this.store;
|
||||||
|
return Discourse.ajax({url: moreUrl}).then(function (result) {
|
||||||
|
let topicsAdded = 0;
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
// the new topics loaded from the server
|
||||||
|
const newTopics = topicsFrom(result, store),
|
||||||
|
topics = self.get("topics");
|
||||||
|
|
||||||
|
self.forEachNew(newTopics, function(t) {
|
||||||
|
t.set('highlight', topicsAdded++ === 0);
|
||||||
|
topics.pushObject(t);
|
||||||
|
});
|
||||||
|
|
||||||
|
self.setProperties({
|
||||||
|
loadingMore: false,
|
||||||
|
more_topics_url: result.topic_list.more_topics_url
|
||||||
|
});
|
||||||
|
|
||||||
|
Discourse.Session.currentProp('topicList', self);
|
||||||
|
return self.get('more_topics_url');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Return a promise indicating no more results
|
||||||
|
return Ember.RSVP.resolve();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// loads topics with these ids "before" the current topics
|
||||||
|
loadBefore: function(topic_ids){
|
||||||
|
const topicList = this,
|
||||||
|
topics = this.get('topics');
|
||||||
|
|
||||||
|
// refresh dupes
|
||||||
|
topics.removeObjects(topics.filter(function(topic){
|
||||||
|
return topic_ids.indexOf(topic.get('id')) >= 0;
|
||||||
|
}));
|
||||||
|
|
||||||
|
const url = Discourse.getURL("/") + this.get('filter') + "?topic_ids=" + topic_ids.join(",");
|
||||||
|
|
||||||
|
const store = this.store;
|
||||||
|
return Discourse.ajax({ url }).then(function(result) {
|
||||||
|
let i = 0;
|
||||||
|
topicList.forEachNew(topicsFrom(result, store), function(t) {
|
||||||
|
// highlight the first of the new topics so we can get a visual feedback
|
||||||
|
t.set('highlight', true);
|
||||||
|
topics.insertAt(i,t);
|
||||||
|
i++;
|
||||||
|
});
|
||||||
|
Discourse.Session.currentProp('topicList', topicList);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
TopicList.reopenClass({
|
||||||
|
|
||||||
|
munge(json, store) {
|
||||||
|
json.inserted = json.inserted || [];
|
||||||
|
json.can_create_topic = json.topic_list.can_create_topic;
|
||||||
|
json.more_topics_url = json.topic_list.more_topics_url;
|
||||||
|
json.draft_key = json.topic_list.draft_key;
|
||||||
|
json.draft_sequence = json.topic_list.draft_sequence;
|
||||||
|
json.draft = json.topic_list.draft;
|
||||||
|
json.for_period = json.topic_list.for_period;
|
||||||
|
json.loaded = true;
|
||||||
|
json.per_page = json.topic_list.per_page;
|
||||||
|
json.topics = topicsFrom(json, store);
|
||||||
|
|
||||||
|
if (json.topic_list.filtered_category) {
|
||||||
|
json.category = Discourse.Category.create(json.topic_list.filtered_category);
|
||||||
|
}
|
||||||
|
return json;
|
||||||
|
},
|
||||||
|
|
||||||
|
find(filter, params) {
|
||||||
|
const store = Discourse.__container__.lookup('store:main');
|
||||||
|
return store.findFiltered('topicList', {filter, params});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Sets `hideCategory` if all topics in the last have a particular category
|
||||||
|
hideUniformCategory(list, category) {
|
||||||
|
const hideCategory = !list.get('topics').any(function (t) { return t.get('category') !== category; });
|
||||||
|
list.set('hideCategory', hideCategory);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
export default TopicList;
|
|
@ -1,7 +1,6 @@
|
||||||
import TopicDetails from 'discourse/models/topic-details';
|
import RestModel from 'discourse/models/rest';
|
||||||
import PostStream from 'discourse/models/post-stream';
|
|
||||||
|
|
||||||
const Topic = Discourse.Model.extend({
|
const Topic = RestModel.extend({
|
||||||
|
|
||||||
// returns createdAt if there's no bumped date
|
// returns createdAt if there's no bumped date
|
||||||
bumpedAt: function() {
|
bumpedAt: function() {
|
||||||
|
@ -23,7 +22,7 @@ const Topic = Discourse.Model.extend({
|
||||||
}.property('created_at'),
|
}.property('created_at'),
|
||||||
|
|
||||||
postStream: function() {
|
postStream: function() {
|
||||||
return PostStream.create({topic: this});
|
return this.store.createRecord('postStream', {id: this.get('id'), topic: this});
|
||||||
}.property(),
|
}.property(),
|
||||||
|
|
||||||
replyCount: function() {
|
replyCount: function() {
|
||||||
|
@ -31,7 +30,7 @@ const Topic = Discourse.Model.extend({
|
||||||
}.property('posts_count'),
|
}.property('posts_count'),
|
||||||
|
|
||||||
details: function() {
|
details: function() {
|
||||||
return TopicDetails.create({topic: this});
|
return this.store.createRecord('topicDetails', {id: this.get('id'), topic: this});
|
||||||
}.property(),
|
}.property(),
|
||||||
|
|
||||||
invisible: Em.computed.not('visible'),
|
invisible: Em.computed.not('visible'),
|
||||||
|
|
|
@ -1,272 +0,0 @@
|
||||||
function finderFor(filter, params) {
|
|
||||||
return function() {
|
|
||||||
var url = Discourse.getURL("/") + filter + ".json";
|
|
||||||
|
|
||||||
if (params) {
|
|
||||||
var keys = Object.keys(params),
|
|
||||||
encoded = [];
|
|
||||||
|
|
||||||
keys.forEach(function(p) {
|
|
||||||
var value = params[p];
|
|
||||||
if (typeof value !== 'undefined') {
|
|
||||||
encoded.push(p + "=" + value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (encoded.length > 0) {
|
|
||||||
url += "?" + encoded.join('&');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Discourse.ajax(url);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
Discourse.TopicList = Discourse.Model.extend({
|
|
||||||
canLoadMore: Em.computed.notEmpty("more_topics_url"),
|
|
||||||
|
|
||||||
forEachNew: function(topics, callback) {
|
|
||||||
var topicIds = [];
|
|
||||||
_.each(this.get('topics'),function(topic) {
|
|
||||||
topicIds[topic.get('id')] = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
_.each(topics,function(topic) {
|
|
||||||
if(!topicIds[topic.id]) {
|
|
||||||
callback(topic);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
refreshSort: function(order, ascending) {
|
|
||||||
var self = this,
|
|
||||||
params = this.get('params');
|
|
||||||
|
|
||||||
params.order = order || params.order;
|
|
||||||
|
|
||||||
if (ascending === undefined) {
|
|
||||||
params.ascending = ascending;
|
|
||||||
} else {
|
|
||||||
params.ascending = ascending;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.set('loaded', false);
|
|
||||||
var finder = finderFor(this.get('filter'), params);
|
|
||||||
finder().then(function (result) {
|
|
||||||
var newTopics = Discourse.TopicList.topicsFrom(result),
|
|
||||||
topics = self.get('topics');
|
|
||||||
|
|
||||||
topics.clear();
|
|
||||||
topics.pushObjects(newTopics);
|
|
||||||
self.setProperties({ loaded: true, more_topics_url: result.topic_list.more_topics_url });
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
loadMore: function() {
|
|
||||||
if (this.get('loadingMore')) { return Ember.RSVP.resolve(); }
|
|
||||||
|
|
||||||
var moreUrl = this.get('more_topics_url');
|
|
||||||
if (moreUrl) {
|
|
||||||
var self = this;
|
|
||||||
this.set('loadingMore', true);
|
|
||||||
|
|
||||||
return Discourse.ajax({url: moreUrl}).then(function (result) {
|
|
||||||
var topicsAdded = 0;
|
|
||||||
if (result) {
|
|
||||||
// the new topics loaded from the server
|
|
||||||
var newTopics = Discourse.TopicList.topicsFrom(result),
|
|
||||||
topics = self.get("topics");
|
|
||||||
|
|
||||||
self.forEachNew(newTopics, function(t) {
|
|
||||||
t.set('highlight', topicsAdded++ === 0);
|
|
||||||
topics.pushObject(t);
|
|
||||||
});
|
|
||||||
|
|
||||||
self.setProperties({
|
|
||||||
loadingMore: false,
|
|
||||||
more_topics_url: result.topic_list.more_topics_url
|
|
||||||
});
|
|
||||||
|
|
||||||
Discourse.Session.currentProp('topicList', self);
|
|
||||||
return self.get('more_topics_url');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Return a promise indicating no more results
|
|
||||||
return Ember.RSVP.resolve();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
// loads topics with these ids "before" the current topics
|
|
||||||
loadBefore: function(topic_ids){
|
|
||||||
var topicList = this,
|
|
||||||
topics = this.get('topics');
|
|
||||||
|
|
||||||
// refresh dupes
|
|
||||||
topics.removeObjects(topics.filter(function(topic){
|
|
||||||
return topic_ids.indexOf(topic.get('id')) >= 0;
|
|
||||||
}));
|
|
||||||
|
|
||||||
Discourse.TopicList.loadTopics(topic_ids, this.get('filter'))
|
|
||||||
.then(function(newTopics){
|
|
||||||
var i = 0;
|
|
||||||
topicList.forEachNew(newTopics, function(t) {
|
|
||||||
// highlight the first of the new topics so we can get a visual feedback
|
|
||||||
t.set('highlight', true);
|
|
||||||
topics.insertAt(i,t);
|
|
||||||
i++;
|
|
||||||
});
|
|
||||||
Discourse.Session.currentProp('topicList', topicList);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Discourse.TopicList.reopenClass({
|
|
||||||
|
|
||||||
loadTopics: function(topic_ids, filter) {
|
|
||||||
return new Ember.RSVP.Promise(function(resolve, reject) {
|
|
||||||
var url = Discourse.getURL("/") + filter + "?topic_ids=" + topic_ids.join(",");
|
|
||||||
|
|
||||||
Discourse.ajax({url: url}).then(function (result) {
|
|
||||||
if (result) {
|
|
||||||
// the new topics loaded from the server
|
|
||||||
var newTopics = Discourse.TopicList.topicsFrom(result);
|
|
||||||
resolve(newTopics);
|
|
||||||
} else {
|
|
||||||
reject();
|
|
||||||
}
|
|
||||||
}).catch(reject);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
Stitch together side loaded topic data
|
|
||||||
|
|
||||||
@method topicsFrom
|
|
||||||
@param {Object} result JSON object with topic data
|
|
||||||
@returns {Array} the list of topics
|
|
||||||
**/
|
|
||||||
topicsFrom: function(result) {
|
|
||||||
// Stitch together our side loaded data
|
|
||||||
var categories = Discourse.Category.list(),
|
|
||||||
users = this.extractByKey(result.users, Discourse.User);
|
|
||||||
|
|
||||||
return result.topic_list.topics.map(function (t) {
|
|
||||||
t.category = categories.findBy('id', t.category_id);
|
|
||||||
t.posters.forEach(function(p) {
|
|
||||||
p.user = users[p.user_id];
|
|
||||||
});
|
|
||||||
if (t.participants) {
|
|
||||||
t.participants.forEach(function(p) {
|
|
||||||
p.user = users[p.user_id];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return Discourse.Topic.create(t);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
from: function(result, filter, params) {
|
|
||||||
var topicList = Discourse.TopicList.create({
|
|
||||||
inserted: [],
|
|
||||||
filter: filter,
|
|
||||||
params: params || {},
|
|
||||||
topics: Discourse.TopicList.topicsFrom(result),
|
|
||||||
can_create_topic: result.topic_list.can_create_topic,
|
|
||||||
more_topics_url: result.topic_list.more_topics_url,
|
|
||||||
draft_key: result.topic_list.draft_key,
|
|
||||||
draft_sequence: result.topic_list.draft_sequence,
|
|
||||||
draft: result.topic_list.draft,
|
|
||||||
for_period: result.topic_list.for_period,
|
|
||||||
loaded: true,
|
|
||||||
per_page: result.topic_list.per_page
|
|
||||||
});
|
|
||||||
|
|
||||||
if (result.topic_list.filtered_category) {
|
|
||||||
topicList.set('category', Discourse.Category.create(result.topic_list.filtered_category));
|
|
||||||
}
|
|
||||||
|
|
||||||
return topicList;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
Lists topics on a given menu item
|
|
||||||
|
|
||||||
@method list
|
|
||||||
@param {Object} filter The menu item to filter to
|
|
||||||
@param {Object} params Any additional params to pass to TopicList.find()
|
|
||||||
@param {Object} extras Additional finding options, such as caching
|
|
||||||
@returns {Promise} a promise that resolves to the list of topics
|
|
||||||
**/
|
|
||||||
list: function(filter, filterParams, extras) {
|
|
||||||
var tracking = Discourse.TopicTrackingState.current();
|
|
||||||
|
|
||||||
extras = extras || {};
|
|
||||||
return new Ember.RSVP.Promise(function(resolve) {
|
|
||||||
var session = Discourse.Session.current();
|
|
||||||
|
|
||||||
if (extras.cached) {
|
|
||||||
var cachedList = session.get('topicList');
|
|
||||||
|
|
||||||
// Try to use the cached version if it exists and is greater than the topics per page
|
|
||||||
if (cachedList && (cachedList.get('filter') === filter) &&
|
|
||||||
(cachedList.get('topics.length') || 0) > cachedList.get('per_page') &&
|
|
||||||
_.isEqual(cachedList.get('listParams'), filterParams)) {
|
|
||||||
cachedList.set('loaded', true);
|
|
||||||
|
|
||||||
if (tracking) {
|
|
||||||
tracking.updateTopics(cachedList.get('topics'));
|
|
||||||
}
|
|
||||||
return resolve(cachedList);
|
|
||||||
}
|
|
||||||
session.set('topicList', null);
|
|
||||||
} else {
|
|
||||||
// Clear the cache
|
|
||||||
session.setProperties({topicList: null, topicListScrollPosition: null});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Clean up any string parameters that might slip through
|
|
||||||
filterParams = filterParams || {};
|
|
||||||
Ember.keys(filterParams).forEach(function(k) {
|
|
||||||
var val = filterParams[k];
|
|
||||||
if (val === "undefined" || val === "null" || val === 'false') {
|
|
||||||
filterParams[k] = undefined;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var findParams = {};
|
|
||||||
Discourse.SiteSettings.top_menu.split('|').forEach(function (i) {
|
|
||||||
if (i.indexOf(filter) === 0) {
|
|
||||||
var exclude = i.split("-");
|
|
||||||
if (exclude && exclude.length === 2) {
|
|
||||||
findParams.exclude_category = exclude[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return resolve(Discourse.TopicList.find(filter, _.extend(findParams, filterParams || {})));
|
|
||||||
|
|
||||||
}).then(function(list) {
|
|
||||||
list.set('listParams', filterParams);
|
|
||||||
if (tracking) {
|
|
||||||
tracking.sync(list, list.filter);
|
|
||||||
tracking.trackIncoming(list.filter);
|
|
||||||
}
|
|
||||||
Discourse.Session.currentProp('topicList', list);
|
|
||||||
return list;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
find: function(filter, params) {
|
|
||||||
return PreloadStore.getAndRemove("topic_list_" + filter, finderFor(filter, params)).then(function(result) {
|
|
||||||
return Discourse.TopicList.from(result, filter, params);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// Sets `hideCategory` if all topics in the last have a particular category
|
|
||||||
hideUniformCategory: function(list, category) {
|
|
||||||
var hideCategory = !list.get('topics').any(function (t) { return t.get('category') !== category; });
|
|
||||||
list.set('hideCategory', hideCategory);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { queryParams, filterQueryParams } from 'discourse/routes/build-topic-route';
|
import { queryParams, filterQueryParams, findTopicList } from 'discourse/routes/build-topic-route';
|
||||||
|
|
||||||
// A helper function to create a category route with parameters
|
// A helper function to create a category route with parameters
|
||||||
export default function(filter, params) {
|
export default function(filter, params) {
|
||||||
|
@ -52,7 +52,7 @@ export default function(filter, params) {
|
||||||
var findOpts = filterQueryParams(transition.queryParams, params),
|
var findOpts = filterQueryParams(transition.queryParams, params),
|
||||||
extras = { cached: this.isPoppedState(transition) };
|
extras = { cached: this.isPoppedState(transition) };
|
||||||
|
|
||||||
return Discourse.TopicList.list(listFilter, findOpts, extras).then(function(list) {
|
return findTopicList(this.store, listFilter, findOpts, extras).then(function(list) {
|
||||||
Discourse.TopicList.hideUniformCategory(list, model);
|
Discourse.TopicList.hideUniformCategory(list, model);
|
||||||
self.set('topics', list);
|
self.set('topics', list);
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,6 +11,65 @@ function filterQueryParams(params, defaultParams) {
|
||||||
return findOpts;
|
return findOpts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function findTopicList(store, filter, filterParams, extras) {
|
||||||
|
const tracking = Discourse.TopicTrackingState.current();
|
||||||
|
|
||||||
|
extras = extras || {};
|
||||||
|
return new Ember.RSVP.Promise(function(resolve) {
|
||||||
|
const session = Discourse.Session.current();
|
||||||
|
|
||||||
|
if (extras.cached) {
|
||||||
|
const cachedList = session.get('topicList');
|
||||||
|
|
||||||
|
// Try to use the cached version if it exists and is greater than the topics per page
|
||||||
|
if (cachedList && (cachedList.get('filter') === filter) &&
|
||||||
|
(cachedList.get('topics.length') || 0) > cachedList.get('per_page') &&
|
||||||
|
_.isEqual(cachedList.get('listParams'), filterParams)) {
|
||||||
|
cachedList.set('loaded', true);
|
||||||
|
|
||||||
|
if (tracking) {
|
||||||
|
tracking.updateTopics(cachedList.get('topics'));
|
||||||
|
}
|
||||||
|
return resolve(cachedList);
|
||||||
|
}
|
||||||
|
session.set('topicList', null);
|
||||||
|
} else {
|
||||||
|
// Clear the cache
|
||||||
|
session.setProperties({topicList: null, topicListScrollPosition: null});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Clean up any string parameters that might slip through
|
||||||
|
filterParams = filterParams || {};
|
||||||
|
Ember.keys(filterParams).forEach(function(k) {
|
||||||
|
const val = filterParams[k];
|
||||||
|
if (val === "undefined" || val === "null" || val === 'false') {
|
||||||
|
filterParams[k] = undefined;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const findParams = {};
|
||||||
|
Discourse.SiteSettings.top_menu.split('|').forEach(function (i) {
|
||||||
|
if (i.indexOf(filter) === 0) {
|
||||||
|
const exclude = i.split("-");
|
||||||
|
if (exclude && exclude.length === 2) {
|
||||||
|
findParams.exclude_category = exclude[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return resolve(store.findFiltered('topicList', { filter, params:_.extend(findParams, filterParams || {})}));
|
||||||
|
|
||||||
|
}).then(function(list) {
|
||||||
|
list.set('listParams', filterParams);
|
||||||
|
if (tracking) {
|
||||||
|
tracking.sync(list, list.filter);
|
||||||
|
tracking.trackIncoming(list.filter);
|
||||||
|
}
|
||||||
|
Discourse.Session.currentProp('topicList', list);
|
||||||
|
return list;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export default function(filter, extras) {
|
export default function(filter, extras) {
|
||||||
extras = extras || {};
|
extras = extras || {};
|
||||||
return Discourse.Route.extend({
|
return Discourse.Route.extend({
|
||||||
|
@ -28,7 +87,7 @@ export default function(filter, extras) {
|
||||||
const findOpts = filterQueryParams(transition.queryParams),
|
const findOpts = filterQueryParams(transition.queryParams),
|
||||||
extras = { cached: this.isPoppedState(transition) };
|
extras = { cached: this.isPoppedState(transition) };
|
||||||
|
|
||||||
return Discourse.TopicList.list(filter, findOpts, extras);
|
return findTopicList(this.store, filter, findOpts, extras);
|
||||||
},
|
},
|
||||||
|
|
||||||
titleToken() {
|
titleToken() {
|
||||||
|
@ -72,4 +131,4 @@ export default function(filter, extras) {
|
||||||
}, extras);
|
}, extras);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { filterQueryParams };
|
export { filterQueryParams, findTopicList };
|
||||||
|
|
|
@ -14,7 +14,7 @@ export default function (viewName, path) {
|
||||||
},
|
},
|
||||||
|
|
||||||
model: function() {
|
model: function() {
|
||||||
return Discourse.TopicList.find('topics/' + path + '/' + this.modelFor('user').get('username_lower'));
|
return this.store.findFiltered('topicList', {filter: 'topics/' + path + '/' + this.modelFor('user').get('username_lower')});
|
||||||
},
|
},
|
||||||
|
|
||||||
setupController: function() {
|
setupController: function() {
|
||||||
|
|
|
@ -5,7 +5,6 @@ let isTransitioning = false,
|
||||||
const SCROLL_DELAY = 500;
|
const SCROLL_DELAY = 500;
|
||||||
|
|
||||||
import ShowFooter from "discourse/mixins/show-footer";
|
import ShowFooter from "discourse/mixins/show-footer";
|
||||||
import Topic from 'discourse/models/topic';
|
|
||||||
import showModal from 'discourse/lib/show-modal';
|
import showModal from 'discourse/lib/show-modal';
|
||||||
|
|
||||||
const TopicRoute = Discourse.Route.extend(ShowFooter, {
|
const TopicRoute = Discourse.Route.extend(ShowFooter, {
|
||||||
|
@ -153,7 +152,7 @@ const TopicRoute = Discourse.Route.extend(ShowFooter, {
|
||||||
model(params, transition) {
|
model(params, transition) {
|
||||||
const queryParams = transition.queryParams;
|
const queryParams = transition.queryParams;
|
||||||
|
|
||||||
const topic = this.modelFor('topic');
|
let topic = this.modelFor('topic');
|
||||||
if (topic && (topic.get('id') === parseInt(params.id, 10))) {
|
if (topic && (topic.get('id') === parseInt(params.id, 10))) {
|
||||||
this.setupParams(topic, queryParams);
|
this.setupParams(topic, queryParams);
|
||||||
// If we have the existing model, refresh it
|
// If we have the existing model, refresh it
|
||||||
|
@ -161,7 +160,8 @@ const TopicRoute = Discourse.Route.extend(ShowFooter, {
|
||||||
return topic;
|
return topic;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return this.setupParams(Topic.create(_.omit(params, 'username_filters', 'filter')), queryParams);
|
topic = this.store.createRecord('topic', _.omit(params, 'username_filters', 'filter'));
|
||||||
|
return this.setupParams(topic, queryParams);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,6 @@ export default UserTopicListRoute.extend({
|
||||||
userActionType: Discourse.UserAction.TYPES.topics,
|
userActionType: Discourse.UserAction.TYPES.topics,
|
||||||
|
|
||||||
model: function() {
|
model: function() {
|
||||||
return Discourse.TopicList.find('topics/created-by/' + this.modelFor('user').get('username_lower'));
|
return this.store.findFiltered('topicList', {filter: 'topics/created-by/' + this.modelFor('user').get('username_lower') });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -27,11 +27,11 @@
|
||||||
//= require ./discourse/models/rest
|
//= require ./discourse/models/rest
|
||||||
//= require ./discourse/models/model
|
//= require ./discourse/models/model
|
||||||
//= require ./discourse/models/post
|
//= require ./discourse/models/post
|
||||||
//= require ./discourse/models/user_action
|
|
||||||
//= require ./discourse/models/composer
|
|
||||||
//= require ./discourse/models/post-stream
|
//= require ./discourse/models/post-stream
|
||||||
//= require ./discourse/models/topic-details
|
//= require ./discourse/models/topic-details
|
||||||
//= require ./discourse/models/topic
|
//= require ./discourse/models/topic
|
||||||
|
//= require ./discourse/models/user_action
|
||||||
|
//= require ./discourse/models/composer
|
||||||
//= require ./discourse/controllers/controller
|
//= require ./discourse/controllers/controller
|
||||||
//= require ./discourse/controllers/discovery-sortable
|
//= require ./discourse/controllers/discovery-sortable
|
||||||
//= require ./discourse/controllers/object
|
//= require ./discourse/controllers/object
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import Store from "discourse/models/store";
|
import Store from "discourse/models/store";
|
||||||
import RestAdapter from 'discourse/adapters/rest';
|
import RestAdapter from 'discourse/adapters/rest';
|
||||||
|
import Resolver from 'discourse/ember/resolver';
|
||||||
|
|
||||||
let _restAdapter;
|
let _restAdapter;
|
||||||
export default function() {
|
export default function() {
|
||||||
|
const resolver = Resolver.create();
|
||||||
return Store.create({
|
return Store.create({
|
||||||
container: {
|
container: {
|
||||||
lookup(type) {
|
lookup(type) {
|
||||||
|
@ -12,7 +14,10 @@ export default function() {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
lookupFactory: function() { }
|
lookupFactory(type) {
|
||||||
|
const split = type.split(':');
|
||||||
|
return resolver.customResolve({type: split[0], fullNameWithoutType: split[1]});
|
||||||
|
},
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,32 +1,34 @@
|
||||||
module("model:post-stream");
|
module("model:post-stream");
|
||||||
|
|
||||||
import PostStream from 'discourse/models/post-stream';
|
import createStore from 'helpers/create-store';
|
||||||
import Topic from 'discourse/models/topic';
|
|
||||||
|
|
||||||
var buildStream = function(id, stream) {
|
const buildStream = function(id, stream) {
|
||||||
var topic = Topic.create({id: id, chunk_size: 5});
|
const store = createStore();
|
||||||
var ps = topic.get('postStream');
|
const topic = store.createRecord('topic', {id, chunk_size: 5});
|
||||||
|
const ps = topic.get('postStream');
|
||||||
if (stream) {
|
if (stream) {
|
||||||
ps.set('stream', stream);
|
ps.set('stream', stream);
|
||||||
}
|
}
|
||||||
return ps;
|
return ps;
|
||||||
};
|
};
|
||||||
|
|
||||||
var participant = {username: 'eviltrout'};
|
const participant = {username: 'eviltrout'};
|
||||||
|
|
||||||
test('create', function() {
|
test('create', function() {
|
||||||
ok(PostStream.create(), 'it can be created with no parameters');
|
const store = createStore();
|
||||||
|
ok(store.createRecord('postStream'), 'it can be created with no parameters');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('defaults', function() {
|
test('defaults', function() {
|
||||||
var postStream = buildStream(1234);
|
const postStream = buildStream(1234);
|
||||||
blank(postStream.get('posts'), "there are no posts in a stream by default");
|
blank(postStream.get('posts'), "there are no posts in a stream by default");
|
||||||
ok(!postStream.get('loaded'), "it has never loaded");
|
ok(!postStream.get('loaded'), "it has never loaded");
|
||||||
present(postStream.get('topic'));
|
present(postStream.get('topic'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('appending posts', function() {
|
test('appending posts', function() {
|
||||||
var postStream = buildStream(4567, [1, 3, 4]);
|
const postStream = buildStream(4567, [1, 3, 4]);
|
||||||
|
const store = postStream.store;
|
||||||
|
|
||||||
equal(postStream.get('lastPostId'), 4, "the last post id is 4");
|
equal(postStream.get('lastPostId'), 4, "the last post id is 4");
|
||||||
|
|
||||||
|
@ -35,25 +37,24 @@ test('appending posts', function() {
|
||||||
ok(!postStream.get('loadedAllPosts'), "the last post is not loaded");
|
ok(!postStream.get('loadedAllPosts'), "the last post is not loaded");
|
||||||
equal(postStream.get('posts.length'), 0, "it has no posts initially");
|
equal(postStream.get('posts.length'), 0, "it has no posts initially");
|
||||||
|
|
||||||
postStream.appendPost(Discourse.Post.create({id: 2, post_number: 2}));
|
postStream.appendPost(store.createRecord('post', {id: 2, post_number: 2}));
|
||||||
ok(!postStream.get('firstPostPresent'), "the first post is still not loaded");
|
ok(!postStream.get('firstPostPresent'), "the first post is still not loaded");
|
||||||
equal(postStream.get('posts.length'), 1, "it has one post in the stream");
|
equal(postStream.get('posts.length'), 1, "it has one post in the stream");
|
||||||
|
|
||||||
postStream.appendPost(Discourse.Post.create({id: 4, post_number: 4}));
|
postStream.appendPost(store.createRecord('post', {id: 4, post_number: 4}));
|
||||||
ok(!postStream.get('firstPostPresent'), "the first post is still loaded");
|
ok(!postStream.get('firstPostPresent'), "the first post is still loaded");
|
||||||
ok(postStream.get('loadedAllPosts'), "the last post is now loaded");
|
ok(postStream.get('loadedAllPosts'), "the last post is now loaded");
|
||||||
equal(postStream.get('posts.length'), 2, "it has two posts in the stream");
|
equal(postStream.get('posts.length'), 2, "it has two posts in the stream");
|
||||||
|
|
||||||
postStream.appendPost(Discourse.Post.create({id: 4, post_number: 4}));
|
postStream.appendPost(store.createRecord('post', {id: 4, post_number: 4}));
|
||||||
equal(postStream.get('posts.length'), 2, "it will not add the same post with id twice");
|
equal(postStream.get('posts.length'), 2, "it will not add the same post with id twice");
|
||||||
|
|
||||||
var stagedPost = Discourse.Post.create({raw: 'incomplete post'});
|
const stagedPost = store.createRecord('post', {raw: 'incomplete post'});
|
||||||
postStream.appendPost(stagedPost);
|
postStream.appendPost(stagedPost);
|
||||||
equal(postStream.get('posts.length'), 3, "it can handle posts without ids");
|
equal(postStream.get('posts.length'), 3, "it can handle posts without ids");
|
||||||
postStream.appendPost(stagedPost);
|
postStream.appendPost(stagedPost);
|
||||||
equal(postStream.get('posts.length'), 3, "it won't add the same post without an id twice");
|
equal(postStream.get('posts.length'), 3, "it won't add the same post without an id twice");
|
||||||
|
|
||||||
|
|
||||||
// change the stream
|
// change the stream
|
||||||
postStream.set('stream', [1, 2, 4]);
|
postStream.set('stream', [1, 2, 4]);
|
||||||
ok(!postStream.get('firstPostPresent'), "the first post no longer loaded since the stream changed.");
|
ok(!postStream.get('firstPostPresent'), "the first post no longer loaded since the stream changed.");
|
||||||
|
@ -61,12 +62,13 @@ test('appending posts', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('closestPostNumberFor', function() {
|
test('closestPostNumberFor', function() {
|
||||||
var postStream = buildStream(1231);
|
const postStream = buildStream(1231);
|
||||||
|
const store = postStream.store;
|
||||||
|
|
||||||
blank(postStream.closestPostNumberFor(1), "there is no closest post when nothing is loaded");
|
blank(postStream.closestPostNumberFor(1), "there is no closest post when nothing is loaded");
|
||||||
|
|
||||||
postStream.appendPost(Discourse.Post.create({id: 1, post_number: 2}));
|
postStream.appendPost(store.createRecord('post', {id: 1, post_number: 2}));
|
||||||
postStream.appendPost(Discourse.Post.create({id: 2, post_number: 3}));
|
postStream.appendPost(store.createRecord('post', {id: 2, post_number: 3}));
|
||||||
|
|
||||||
equal(postStream.closestPostNumberFor(2), 2, "If a post is in the stream it returns its post number");
|
equal(postStream.closestPostNumberFor(2), 2, "If a post is in the stream it returns its post number");
|
||||||
equal(postStream.closestPostNumberFor(3), 3, "If a post is in the stream it returns its post number");
|
equal(postStream.closestPostNumberFor(3), 3, "If a post is in the stream it returns its post number");
|
||||||
|
@ -75,7 +77,7 @@ test('closestPostNumberFor', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('updateFromJson', function() {
|
test('updateFromJson', function() {
|
||||||
var postStream = buildStream(1231);
|
const postStream = buildStream(1231);
|
||||||
|
|
||||||
postStream.updateFromJson({
|
postStream.updateFromJson({
|
||||||
posts: [{id: 1}],
|
posts: [{id: 1}],
|
||||||
|
@ -90,11 +92,12 @@ test('updateFromJson', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("removePosts", function() {
|
test("removePosts", function() {
|
||||||
var postStream = buildStream(10000001, [1,2,3]);
|
const postStream = buildStream(10000001, [1,2,3]);
|
||||||
|
const store = postStream.store;
|
||||||
|
|
||||||
var p1 = Discourse.Post.create({id: 1, post_number: 2}),
|
const p1 = store.createRecord('post', {id: 1, post_number: 2}),
|
||||||
p2 = Discourse.Post.create({id: 2, post_number: 3}),
|
p2 = store.createRecord('post', {id: 2, post_number: 3}),
|
||||||
p3 = Discourse.Post.create({id: 3, post_number: 4});
|
p3 = store.createRecord('post', {id: 3, post_number: 4});
|
||||||
|
|
||||||
postStream.appendPost(p1);
|
postStream.appendPost(p1);
|
||||||
postStream.appendPost(p2);
|
postStream.appendPost(p2);
|
||||||
|
@ -111,7 +114,7 @@ test("removePosts", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("cancelFilter", function() {
|
test("cancelFilter", function() {
|
||||||
var postStream = buildStream(1235);
|
const postStream = buildStream(1235);
|
||||||
|
|
||||||
sandbox.stub(postStream, "refresh");
|
sandbox.stub(postStream, "refresh");
|
||||||
|
|
||||||
|
@ -125,7 +128,7 @@ test("cancelFilter", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("findPostIdForPostNumber", function() {
|
test("findPostIdForPostNumber", function() {
|
||||||
var postStream = buildStream(1234, [10, 20, 30, 40, 50, 60, 70]);
|
const postStream = buildStream(1234, [10, 20, 30, 40, 50, 60, 70]);
|
||||||
postStream.set('gaps', { before: { 60: [55, 58] } });
|
postStream.set('gaps', { before: { 60: [55, 58] } });
|
||||||
|
|
||||||
equal(postStream.findPostIdForPostNumber(500), null, 'it returns null when the post cannot be found');
|
equal(postStream.findPostIdForPostNumber(500), null, 'it returns null when the post cannot be found');
|
||||||
|
@ -136,7 +139,7 @@ test("findPostIdForPostNumber", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("toggleParticipant", function() {
|
test("toggleParticipant", function() {
|
||||||
var postStream = buildStream(1236);
|
const postStream = buildStream(1236);
|
||||||
sandbox.stub(postStream, "refresh");
|
sandbox.stub(postStream, "refresh");
|
||||||
|
|
||||||
equal(postStream.get('userFilters.length'), 0, "by default no participants are toggled");
|
equal(postStream.get('userFilters.length'), 0, "by default no participants are toggled");
|
||||||
|
@ -149,7 +152,7 @@ test("toggleParticipant", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("streamFilters", function() {
|
test("streamFilters", function() {
|
||||||
var postStream = buildStream(1237);
|
const postStream = buildStream(1237);
|
||||||
sandbox.stub(postStream, "refresh");
|
sandbox.stub(postStream, "refresh");
|
||||||
|
|
||||||
deepEqual(postStream.get('streamFilters'), {}, "there are no postFilters by default");
|
deepEqual(postStream.get('streamFilters'), {}, "there are no postFilters by default");
|
||||||
|
@ -179,7 +182,7 @@ test("streamFilters", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("loading", function() {
|
test("loading", function() {
|
||||||
var postStream = buildStream(1234);
|
let postStream = buildStream(1234);
|
||||||
ok(!postStream.get('loading'), "we're not loading by default");
|
ok(!postStream.get('loading'), "we're not loading by default");
|
||||||
|
|
||||||
postStream.set('loadingAbove', true);
|
postStream.set('loadingAbove', true);
|
||||||
|
@ -195,7 +198,7 @@ test("loading", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("nextWindow", function() {
|
test("nextWindow", function() {
|
||||||
var postStream = buildStream(1234, [1,2,3,5,8,9,10,11,13,14,15,16]);
|
const postStream = buildStream(1234, [1,2,3,5,8,9,10,11,13,14,15,16]);
|
||||||
|
|
||||||
blank(postStream.get('nextWindow'), 'With no posts loaded, the window is blank');
|
blank(postStream.get('nextWindow'), 'With no posts loaded, the window is blank');
|
||||||
|
|
||||||
|
@ -211,7 +214,7 @@ test("nextWindow", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("previousWindow", function() {
|
test("previousWindow", function() {
|
||||||
var postStream = buildStream(1234, [1,2,3,5,8,9,10,11,13,14,15,16]);
|
const postStream = buildStream(1234, [1,2,3,5,8,9,10,11,13,14,15,16]);
|
||||||
|
|
||||||
blank(postStream.get('previousWindow'), 'With no posts loaded, the window is blank');
|
blank(postStream.get('previousWindow'), 'With no posts loaded, the window is blank');
|
||||||
|
|
||||||
|
@ -227,21 +230,22 @@ test("previousWindow", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("storePost", function() {
|
test("storePost", function() {
|
||||||
var postStream = buildStream(1234),
|
const postStream = buildStream(1234),
|
||||||
post = Discourse.Post.create({id: 1, post_number: 100, raw: 'initial value'});
|
store = postStream.store,
|
||||||
|
post = store.createRecord('post', {id: 1, post_number: 100, raw: 'initial value'});
|
||||||
|
|
||||||
blank(postStream.get('topic.highest_post_number'), "it has no highest post number yet");
|
blank(postStream.get('topic.highest_post_number'), "it has no highest post number yet");
|
||||||
var stored = postStream.storePost(post);
|
let stored = postStream.storePost(post);
|
||||||
equal(post, stored, "it returns the post it stored");
|
equal(post, stored, "it returns the post it stored");
|
||||||
equal(post.get('topic'), postStream.get('topic'), "it creates the topic reference properly");
|
equal(post.get('topic'), postStream.get('topic'), "it creates the topic reference properly");
|
||||||
equal(postStream.get('topic.highest_post_number'), 100, "it set the highest post number");
|
equal(postStream.get('topic.highest_post_number'), 100, "it set the highest post number");
|
||||||
|
|
||||||
var dupePost = Discourse.Post.create({id: 1, post_number: 100, raw: 'updated value'});
|
const dupePost = store.createRecord('post', {id: 1, post_number: 100, raw: 'updated value'});
|
||||||
var storedDupe = postStream.storePost(dupePost);
|
const storedDupe = postStream.storePost(dupePost);
|
||||||
equal(storedDupe, post, "it returns the previously stored post instead to avoid dupes");
|
equal(storedDupe, post, "it returns the previously stored post instead to avoid dupes");
|
||||||
equal(storedDupe.get('raw'), 'updated value', 'it updates the previously stored post');
|
equal(storedDupe.get('raw'), 'updated value', 'it updates the previously stored post');
|
||||||
|
|
||||||
var postWithoutId = Discourse.Post.create({raw: 'hello world'});
|
const postWithoutId = store.createRecord('post', {raw: 'hello world'});
|
||||||
stored = postStream.storePost(postWithoutId);
|
stored = postStream.storePost(postWithoutId);
|
||||||
equal(stored, postWithoutId, "it returns the same post back");
|
equal(stored, postWithoutId, "it returns the same post back");
|
||||||
equal(postStream.get('postIdentityMap.size'), 1, "it does not add a new entry into the identity map");
|
equal(postStream.get('postIdentityMap.size'), 1, "it does not add a new entry into the identity map");
|
||||||
|
@ -249,9 +253,11 @@ test("storePost", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("identity map", function() {
|
test("identity map", function() {
|
||||||
var postStream = buildStream(1234);
|
const postStream = buildStream(1234),
|
||||||
var p1 = postStream.appendPost(Discourse.Post.create({id: 1, post_number: 1}));
|
store = postStream.store;
|
||||||
postStream.appendPost(Discourse.Post.create({id: 3, post_number: 4}));
|
|
||||||
|
const p1 = postStream.appendPost(store.createRecord('post', {id: 1, post_number: 1}));
|
||||||
|
postStream.appendPost(store.createRecord('post', {id: 3, post_number: 4}));
|
||||||
|
|
||||||
equal(postStream.findLoadedPost(1), p1, "it can return cached posts by id");
|
equal(postStream.findLoadedPost(1), p1, "it can return cached posts by id");
|
||||||
blank(postStream.findLoadedPost(4), "it can't find uncached posts");
|
blank(postStream.findLoadedPost(4), "it can't find uncached posts");
|
||||||
|
@ -262,7 +268,7 @@ test("identity map", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTestDiscourse("loadIntoIdentityMap with no data", function() {
|
asyncTestDiscourse("loadIntoIdentityMap with no data", function() {
|
||||||
var postStream = buildStream(1234);
|
const postStream = buildStream(1234);
|
||||||
expect(1);
|
expect(1);
|
||||||
|
|
||||||
sandbox.stub(Discourse, "ajax");
|
sandbox.stub(Discourse, "ajax");
|
||||||
|
@ -273,7 +279,7 @@ asyncTestDiscourse("loadIntoIdentityMap with no data", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTestDiscourse("loadIntoIdentityMap with post ids", function() {
|
asyncTestDiscourse("loadIntoIdentityMap with post ids", function() {
|
||||||
var postStream = buildStream(1234);
|
const postStream = buildStream(1234);
|
||||||
expect(1);
|
expect(1);
|
||||||
|
|
||||||
sandbox.stub(Discourse, "ajax").returns(Ember.RSVP.resolve({
|
sandbox.stub(Discourse, "ajax").returns(Ember.RSVP.resolve({
|
||||||
|
@ -289,12 +295,12 @@ asyncTestDiscourse("loadIntoIdentityMap with post ids", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTestDiscourse("loading a post's history", function() {
|
asyncTestDiscourse("loading a post's history", function() {
|
||||||
var postStream = buildStream(1234);
|
const postStream = buildStream(1234);
|
||||||
|
const store = postStream.store;
|
||||||
expect(3);
|
expect(3);
|
||||||
|
|
||||||
var post = Discourse.Post.create({id: 4321});
|
const post = store.createRecord('post', {id: 4321});
|
||||||
|
const secondPost = store.createRecord('post', {id: 2222});
|
||||||
var secondPost = Discourse.Post.create({id: 2222});
|
|
||||||
|
|
||||||
sandbox.stub(Discourse, "ajax").returns(Ember.RSVP.resolve([secondPost]));
|
sandbox.stub(Discourse, "ajax").returns(Ember.RSVP.resolve([secondPost]));
|
||||||
postStream.findReplyHistory(post).then(function() {
|
postStream.findReplyHistory(post).then(function() {
|
||||||
|
@ -306,20 +312,22 @@ asyncTestDiscourse("loading a post's history", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("staging and undoing a new post", function() {
|
test("staging and undoing a new post", function() {
|
||||||
var postStream = buildStream(10101, [1]);
|
const postStream = buildStream(10101, [1]);
|
||||||
postStream.appendPost(Discourse.Post.create({id: 1, post_number: 1, topic_id: 10101}));
|
const store = postStream.store;
|
||||||
|
|
||||||
var user = Discourse.User.create({username: 'eviltrout', name: 'eviltrout', id: 321});
|
postStream.appendPost(store.createRecord('post', {id: 1, post_number: 1, topic_id: 10101}));
|
||||||
var stagedPost = Discourse.Post.create({ raw: 'hello world this is my new post', topic_id: 10101 });
|
|
||||||
|
|
||||||
var topic = postStream.get('topic');
|
const user = Discourse.User.create({username: 'eviltrout', name: 'eviltrout', id: 321});
|
||||||
|
const stagedPost = store.createRecord('post', { raw: 'hello world this is my new post', topic_id: 10101 });
|
||||||
|
|
||||||
|
const topic = postStream.get('topic');
|
||||||
topic.setProperties({
|
topic.setProperties({
|
||||||
posts_count: 1,
|
posts_count: 1,
|
||||||
highest_post_number: 1
|
highest_post_number: 1
|
||||||
});
|
});
|
||||||
|
|
||||||
// Stage the new post in the stream
|
// Stage the new post in the stream
|
||||||
var result = postStream.stagePost(stagedPost, user);
|
const result = postStream.stagePost(stagedPost, user);
|
||||||
equal(result, "staged", "it returns staged");
|
equal(result, "staged", "it returns staged");
|
||||||
equal(topic.get('highest_post_number'), 2, "it updates the highest_post_number");
|
equal(topic.get('highest_post_number'), 2, "it updates the highest_post_number");
|
||||||
ok(postStream.get('loading'), "it is loading while the post is being staged");
|
ok(postStream.get('loading'), "it is loading while the post is being staged");
|
||||||
|
@ -345,16 +353,18 @@ test("staging and undoing a new post", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("staging and committing a post", function() {
|
test("staging and committing a post", function() {
|
||||||
var postStream = buildStream(10101, [1]);
|
const postStream = buildStream(10101, [1]);
|
||||||
postStream.appendPost(Discourse.Post.create({id: 1, post_number: 1, topic_id: 10101}));
|
const store = postStream.store;
|
||||||
var user = Discourse.User.create({username: 'eviltrout', name: 'eviltrout', id: 321});
|
|
||||||
var stagedPost = Discourse.Post.create({ raw: 'hello world this is my new post', topic_id: 10101 });
|
|
||||||
|
|
||||||
var topic = postStream.get('topic');
|
postStream.appendPost(store.createRecord('post', {id: 1, post_number: 1, topic_id: 10101}));
|
||||||
|
const user = Discourse.User.create({username: 'eviltrout', name: 'eviltrout', id: 321});
|
||||||
|
const stagedPost = store.createRecord('post', { raw: 'hello world this is my new post', topic_id: 10101 });
|
||||||
|
|
||||||
|
const topic = postStream.get('topic');
|
||||||
topic.set('posts_count', 1);
|
topic.set('posts_count', 1);
|
||||||
|
|
||||||
// Stage the new post in the stream
|
// Stage the new post in the stream
|
||||||
var result = postStream.stagePost(stagedPost, user);
|
let result = postStream.stagePost(stagedPost, user);
|
||||||
equal(result, "staged", "it returns staged");
|
equal(result, "staged", "it returns staged");
|
||||||
|
|
||||||
ok(postStream.get('loading'), "it is loading while the post is being staged");
|
ok(postStream.get('loading'), "it is loading while the post is being staged");
|
||||||
|
@ -369,7 +379,7 @@ test("staging and committing a post", function() {
|
||||||
|
|
||||||
equal(postStream.get('filteredPostsCount'), 2, "it increases the filteredPostsCount");
|
equal(postStream.get('filteredPostsCount'), 2, "it increases the filteredPostsCount");
|
||||||
|
|
||||||
var found = postStream.findLoadedPost(stagedPost.get('id'));
|
const found = postStream.findLoadedPost(stagedPost.get('id'));
|
||||||
present(found, "the post is in the identity map");
|
present(found, "the post is in the identity map");
|
||||||
ok(postStream.indexOf(stagedPost) > -1, "the post is in the stream");
|
ok(postStream.indexOf(stagedPost) > -1, "the post is in the stream");
|
||||||
equal(found.get('raw'), 'different raw value', 'it also updated the value in the stream');
|
equal(found.get('raw'), 'different raw value', 'it also updated the value in the stream');
|
||||||
|
@ -377,7 +387,8 @@ test("staging and committing a post", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('triggerNewPostInStream', function() {
|
test('triggerNewPostInStream', function() {
|
||||||
var postStream = buildStream(225566);
|
const postStream = buildStream(225566);
|
||||||
|
const store = postStream.store;
|
||||||
|
|
||||||
sandbox.stub(postStream, 'appendMore');
|
sandbox.stub(postStream, 'appendMore');
|
||||||
sandbox.stub(postStream, 'refresh');
|
sandbox.stub(postStream, 'refresh');
|
||||||
|
@ -399,7 +410,7 @@ test('triggerNewPostInStream', function() {
|
||||||
ok(!postStream.appendMore.calledOnce, "it wont't delegate to appendMore because the last post is not loaded");
|
ok(!postStream.appendMore.calledOnce, "it wont't delegate to appendMore because the last post is not loaded");
|
||||||
|
|
||||||
postStream.cancelFilter();
|
postStream.cancelFilter();
|
||||||
postStream.appendPost(Discourse.Post.create({id: 1, post_number: 2}));
|
postStream.appendPost(store.createRecord('post', {id: 1, post_number: 2}));
|
||||||
postStream.triggerNewPostInStream(2);
|
postStream.triggerNewPostInStream(2);
|
||||||
ok(postStream.appendMore.calledOnce, "delegates to appendMore because the last post is loaded");
|
ok(postStream.appendMore.calledOnce, "delegates to appendMore because the last post is loaded");
|
||||||
});
|
});
|
||||||
|
@ -408,10 +419,11 @@ test('triggerNewPostInStream', function() {
|
||||||
test("loadedAllPosts when the id changes", function() {
|
test("loadedAllPosts when the id changes", function() {
|
||||||
// This can happen in a race condition between staging a post and it coming through on the
|
// This can happen in a race condition between staging a post and it coming through on the
|
||||||
// message bus. If the id of a post changes we should reconsider the loadedAllPosts property.
|
// message bus. If the id of a post changes we should reconsider the loadedAllPosts property.
|
||||||
var postStream = buildStream(10101, [1, 2]);
|
const postStream = buildStream(10101, [1, 2]);
|
||||||
var postWithoutId = Discourse.Post.create({ raw: 'hello world this is my new post' });
|
const store = postStream.store;
|
||||||
|
const postWithoutId = store.createRecord('post', { raw: 'hello world this is my new post' });
|
||||||
|
|
||||||
postStream.appendPost(Discourse.Post.create({id: 1, post_number: 1}));
|
postStream.appendPost(store.createRecord('post', {id: 1, post_number: 1}));
|
||||||
postStream.appendPost(postWithoutId);
|
postStream.appendPost(postWithoutId);
|
||||||
ok(!postStream.get('loadedAllPosts'), 'the last post is not loaded');
|
ok(!postStream.get('loadedAllPosts'), 'the last post is not loaded');
|
||||||
|
|
||||||
|
@ -420,11 +432,12 @@ test("loadedAllPosts when the id changes", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("comitting and triggerNewPostInStream race condition", function() {
|
test("comitting and triggerNewPostInStream race condition", function() {
|
||||||
var postStream = buildStream(4964);
|
const postStream = buildStream(4964);
|
||||||
|
const store = postStream.store;
|
||||||
|
|
||||||
postStream.appendPost(Discourse.Post.create({id: 1, post_number: 1}));
|
postStream.appendPost(store.createRecord('post', {id: 1, post_number: 1}));
|
||||||
var user = Discourse.User.create({username: 'eviltrout', name: 'eviltrout', id: 321});
|
const user = Discourse.User.create({username: 'eviltrout', name: 'eviltrout', id: 321});
|
||||||
var stagedPost = Discourse.Post.create({ raw: 'hello world this is my new post' });
|
const stagedPost = store.createRecord('post', { raw: 'hello world this is my new post' });
|
||||||
|
|
||||||
postStream.stagePost(stagedPost, user);
|
postStream.stagePost(stagedPost, user);
|
||||||
equal(postStream.get('filteredPostsCount'), 0, "it has no filteredPostsCount yet");
|
equal(postStream.get('filteredPostsCount'), 0, "it has no filteredPostsCount yet");
|
||||||
|
|
|
@ -1,6 +1,21 @@
|
||||||
module('rest-model');
|
module('rest-model');
|
||||||
|
|
||||||
import createStore from 'helpers/create-store';
|
import createStore from 'helpers/create-store';
|
||||||
|
import RestModel from 'discourse/models/rest';
|
||||||
|
|
||||||
|
test('munging', function() {
|
||||||
|
const store = createStore();
|
||||||
|
const Grape = RestModel.extend();
|
||||||
|
Grape.reopenClass({
|
||||||
|
munge: function(json) {
|
||||||
|
json.inverse = 1 - json.percent;
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var g = Grape.create({ store, percent: 0.4 });
|
||||||
|
equal(g.get('inverse'), 0.6, 'it runs `munge` on `create`');
|
||||||
|
});
|
||||||
|
|
||||||
test('update', function() {
|
test('update', function() {
|
||||||
const store = createStore();
|
const store = createStore();
|
||||||
|
|
|
@ -9,6 +9,28 @@ test('createRecord', function() {
|
||||||
equal(widget.get('id'), 111);
|
equal(widget.get('id'), 111);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('createRecord without an `id`', function() {
|
||||||
|
const store = createStore();
|
||||||
|
const widget = store.createRecord('widget', {name: 'hello'});
|
||||||
|
|
||||||
|
ok(!widget.get('id'), 'there is no id');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('createRecord without attributes', function() {
|
||||||
|
const store = createStore();
|
||||||
|
const widget = store.createRecord('widget');
|
||||||
|
|
||||||
|
ok(!widget.get('id'), 'there is no id');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('createRecord with a record as attributes returns that record from the map', function() {
|
||||||
|
const store = createStore();
|
||||||
|
const widget = store.createRecord('widget', {id: 33});
|
||||||
|
const secondWidget = store.createRecord('widget', {id: 33});
|
||||||
|
|
||||||
|
equal(widget, secondWidget, 'they should be the same');
|
||||||
|
});
|
||||||
|
|
||||||
test('find', function() {
|
test('find', function() {
|
||||||
const store = createStore();
|
const store = createStore();
|
||||||
store.find('widget', 123).then(function(w) {
|
store.find('widget', 123).then(function(w) {
|
||||||
|
|
|
@ -90,6 +90,7 @@ if (window.Logster) {
|
||||||
var origDebounce = Ember.run.debounce,
|
var origDebounce = Ember.run.debounce,
|
||||||
createPretendServer = require('helpers/create-pretender', null, null, false).default,
|
createPretendServer = require('helpers/create-pretender', null, null, false).default,
|
||||||
fixtures = require('fixtures/site_fixtures', null, null, false).default,
|
fixtures = require('fixtures/site_fixtures', null, null, false).default,
|
||||||
|
flushMap = require('discourse/models/store', null, null, false).flushMap,
|
||||||
server;
|
server;
|
||||||
|
|
||||||
QUnit.testStart(function(ctx) {
|
QUnit.testStart(function(ctx) {
|
||||||
|
@ -120,6 +121,7 @@ QUnit.testDone(function() {
|
||||||
|
|
||||||
// Destroy any modals
|
// Destroy any modals
|
||||||
$('.modal-backdrop').remove();
|
$('.modal-backdrop').remove();
|
||||||
|
flushMap();
|
||||||
|
|
||||||
server.shutdown();
|
server.shutdown();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue