Port "Summarize Topic" to query-params-new

This commit is contained in:
Robin Ward 2014-04-15 15:33:08 -04:00
parent fdb751296a
commit 2eab288dc9
9 changed files with 78 additions and 104 deletions

View File

@ -13,6 +13,21 @@ Discourse.TopicController = Discourse.ObjectController.extend(Discourse.Selected
editingTopic: false,
selectedPosts: null,
selectedReplies: null,
queryParams: ['filter', 'username_filters'],
filter: function(key, value) {
if (arguments.length > 1) {
this.set('postStream.summary', value === "summary");
}
return this.get('postStream.summary') ? "summary" : null;
}.property('postStream.summary'),
username_filters: function(key, value) {
// TODO: Ember bug? If I don't have a value parameter this does not update
if (value) {
}
return this.get('postStream.streamFilters.username_filters');
}.property("postStream.streamFilters.username_filters"),
init: function() {
this._super();

View File

@ -31,7 +31,14 @@ Discourse.URL = Em.Object.createWithMixins({
// which triggers a replaceState even though the topic hasn't fully loaded yet!
Em.run.next(function() {
var location = Discourse.URL.get('router.location');
if (location && location.replaceURL) { location.replaceURL(path); }
if (location && location.replaceURL) {
if (Ember.FEATURES.isEnabled("query-params-new")) {
var search = Discourse.__container__.lookup('router:main').get('location.location.search') || '';
path += search;
}
location.replaceURL(path);
}
});
}
},
@ -78,13 +85,6 @@ Discourse.URL = Em.Object.createWithMixins({
return this.handleURL(path);
},
/**
Replaces the query parameters in the URL. Use no parameters to clear them.
@method replaceQueryParams
**/
queryParams: Em.computed.alias('router.location.queryParams'),
/**
Redirect to a URL.
This has been extracted so it can be tested.
@ -174,7 +174,6 @@ Discourse.URL = Em.Object.createWithMixins({
// Abort routing, we have replaced our state.
return true;
}
this.set('queryParams', null);
}
return false;

View File

@ -118,9 +118,9 @@ Discourse.PostStream = Em.Object.extend({
if (this.get('summary')) { result.filter = "summary"; }
var userFilters = this.get('userFilters');
if (userFilters) {
if (!Em.isEmpty(userFilters)) {
var userFiltersArray = this.get('userFilters').toArray();
if (userFiltersArray.length > 0) { result.username_filters = userFiltersArray; }
if (userFiltersArray.length > 0) { result.username_filters = userFiltersArray.join(","); }
}
return result;
@ -189,11 +189,9 @@ Discourse.PostStream = Em.Object.extend({
Toggle summary mode for the stream.
@method toggleSummary
@returns {Ember.Deferred} a promise that resolves when the summary stream has loaded.
**/
toggleSummary: function() {
var userFilters = this.get('userFilters');
userFilters.clear();
this.get('userFilters').clear();
this.toggleProperty('summary');
return this.refresh();
},
@ -202,7 +200,6 @@ Discourse.PostStream = Em.Object.extend({
Filter the stream to a particular user.
@method toggleParticipant
@returns {Ember.Deferred} a promise that resolves when the filtered stream has loaded.
**/
toggleParticipant: function(username) {
var userFilters = this.get('userFilters');
@ -226,7 +223,6 @@ Discourse.PostStream = Em.Object.extend({
@returns {Ember.Deferred} a promise that is resolved when the posts have been inserted into the stream.
**/
refresh: function(opts) {
opts = opts || {};
opts.nearPost = parseInt(opts.nearPost, 10);
@ -247,8 +243,6 @@ Discourse.PostStream = Em.Object.extend({
topic.updateFromJson(json);
self.updateFromJson(json.post_stream);
self.setProperties({ loadingFilter: false, loaded: true });
Discourse.URL.set('queryParams', self.get('streamFilters'));
}).catch(function(result) {
self.errorLoading(result);
});

View File

@ -6,34 +6,6 @@ var get = Ember.get, set = Ember.set;
var popstateFired = false;
var supportsHistoryState = window.history && 'state' in window.history;
// Thanks: https://gist.github.com/kares/956897
var re = /([^&=]+)=?([^&]*)/g;
var decode = function(str) {
return decodeURIComponent(str.replace(/\+/g, ' '));
};
$.parseParams = function(query) {
var params = {}, e;
if (query) {
if (query.substr(0, 1) === '?') {
query = query.substr(1);
}
while (e = re.exec(query)) {
var k = decode(e[1]);
var v = decode(e[2]);
if (params[k] !== undefined) {
if (!$.isArray(params[k])) {
params[k] = [params[k]];
}
params[k].push(v);
} else {
params[k] = v;
}
}
}
return params;
};
var popstateCallbacks = [];
/**
@ -59,12 +31,6 @@ Ember.DiscourseLocation = Ember.Object.extend({
@method initState
*/
initState: function() {
var location = this.get('location');
if (location && location.search) {
this.set('queryParams', $.parseParams(location.search));
}
set(this, 'history', get(this, 'history') || window.history);
this.replaceState(this.formatURL(this.getURL()));
},
@ -86,11 +52,17 @@ Ember.DiscourseLocation = Ember.Object.extend({
*/
getURL: function() {
var rootURL = (Discourse.BaseUri === undefined ? "/" : Discourse.BaseUri),
url = get(this, 'location').pathname;
location = get(this, 'location'),
url = location.pathname;
rootURL = rootURL.replace(/\/$/, '');
url = url.replace(rootURL, '');
if (Ember.FEATURES.isEnabled("query-params-new")) {
var search = location.search || '';
url += search;
}
return url;
},
@ -186,24 +158,6 @@ Ember.DiscourseLocation = Ember.Object.extend({
this._previousURL = this.getURL();
},
queryParamsString: function() {
var params = this.get('queryParams');
if (Em.isEmpty(params) || Em.isEmpty(Object.keys(params))) {
return "";
} else {
return "?" + decodeURIComponent($.param(params, true));
}
}.property('queryParams'),
// When our query params change, update the URL
queryParamsStringChanged: function() {
var loc = this;
Em.run.next(function () {
loc.replaceState(loc.formatURL(loc.getURL()));
});
}.observes('queryParamsString'),
/**
@private
@ -244,7 +198,7 @@ Ember.DiscourseLocation = Ember.Object.extend({
rootURL = rootURL.replace(/\/$/, '');
}
return rootURL + url + this.get('queryParamsString');
return rootURL + url;
},
willDestroy: function() {

View File

@ -11,24 +11,8 @@ Discourse.TopicFromParamsRoute = Discourse.Route.extend({
setupController: function(controller, params) {
params = params || {};
params.track_visit = true;
var topic = this.modelFor('topic'),
postStream = topic.get('postStream'),
queryParams = Discourse.URL.get('queryParams');
if (queryParams) {
// Set summary on the postStream if present
postStream.set('summary', Em.get(queryParams, 'filter') === 'summary');
// Set any username filters on the postStream
var userFilters = Em.get(queryParams, 'username_filters') || Em.get(queryParams, 'username_filters[]');
if (userFilters) {
if (typeof userFilters === "string") { userFilters = [userFilters]; }
userFilters.forEach(function (username) {
postStream.get('userFilters').add(username);
});
}
}
postStream = topic.get('postStream');
var topicController = this.controllerFor('topic'),
composerController = this.controllerFor('composer');

View File

@ -9,6 +9,17 @@
Discourse.TopicRoute = Discourse.Route.extend({
redirect: function() { Discourse.redirectIfLoginRequired(this); },
queryParams: {
filter: {
refreshModel: false,
replace: true
},
username_filters: {
refreshModel: false,
replace: true
}
},
actions: {
// Modals that can pop up within a topic
showPosterExpansion: function(post) {
@ -88,16 +99,32 @@ Discourse.TopicRoute = Discourse.Route.extend({
},
model: function(params) {
var currentModel = this.modelFor('topic');
if (currentModel && (currentModel.get('id') === parseInt(params.id, 10))) {
// If we've recovered the currentModel (for example, hitting the forward button and we
// popped it off the state), get rid of the `loaded` attribute we set when the back
// button was hit.
currentModel.set('postStream.loaded', true);
return currentModel;
setupParams: function(topic, params) {
var postStream = topic.get('postStream');
postStream.set('summary', Em.get(params, 'filter') === 'summary');
var usernames = Em.get(params, 'username_filters'),
userFilters = postStream.get('userFilters');
userFilters.clear();
if (!Em.isEmpty(usernames) && usernames !== 'undefined') {
userFilters.addObjects(usernames.split(','));
}
return topic;
},
model: function(params) {
var topic = this.modelFor('topic');
if (topic && (topic.get('id') === parseInt(params.id, 10))) {
this.setupParams(topic, params);
// If we have the existing model, refresh it
return topic.get('postStream').refresh().then(function() {
return topic;
});
} else {
return this.setupParams(Discourse.Topic.create(_.omit(params, 'username_filters', 'filter')), params);
}
return Discourse.Topic.create(params);
},
activate: function() {
@ -130,9 +157,6 @@ Discourse.TopicRoute = Discourse.Route.extend({
headerController.set('topic', null);
headerController.set('showExtraInfo', false);
}
// Clear any filters when we leave the route
Discourse.URL.set('queryParams', null);
},
setupController: function(controller, model) {

View File

@ -33,7 +33,10 @@ Discourse.TopicMapContainerView = Discourse.ContainerView.extend({
// If we have a summary capability
if (topic.get('has_summary')) {
container.attachViewWithArgs({ topic: topic }, Discourse.ToggleSummaryComponent);
container.attachViewWithArgs({
topic: topic,
filterBinding: 'controller.filter'
}, Discourse.ToggleSummaryComponent);
}
// If we have a private message

View File

@ -3,7 +3,8 @@
window.ENV = {
CP_DEFAULT_CACHEABLE: true,
VIEW_PRESERVES_CONTEXT: true,
MANDATORY_SETTER: false
MANDATORY_SETTER: false,
FEATURES: {'query-params-new': true}
};
window.Discourse = {};

View File

@ -38,7 +38,7 @@ class TopicsController < ApplicationController
opts = params.slice(:username_filters, :filter, :page, :post_number)
username_filters = opts[:username_filters]
opts[:username_filters] = [username_filters] if username_filters.is_a?(String)
opts[:username_filters] = username_filters.split(',') if username_filters.is_a?(String)
begin
@topic_view = TopicView.new(params[:id] || params[:topic_id], current_user, opts)