mirror of
https://github.com/discourse/discourse.git
synced 2025-09-10 21:01:33 +08:00
Port "Summarize Topic" to query-params-new
This commit is contained in:
parent
fdb751296a
commit
2eab288dc9
9 changed files with 78 additions and 104 deletions
|
@ -13,6 +13,21 @@ Discourse.TopicController = Discourse.ObjectController.extend(Discourse.Selected
|
||||||
editingTopic: false,
|
editingTopic: false,
|
||||||
selectedPosts: null,
|
selectedPosts: null,
|
||||||
selectedReplies: 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() {
|
init: function() {
|
||||||
this._super();
|
this._super();
|
||||||
|
|
|
@ -31,7 +31,14 @@ Discourse.URL = Em.Object.createWithMixins({
|
||||||
// which triggers a replaceState even though the topic hasn't fully loaded yet!
|
// which triggers a replaceState even though the topic hasn't fully loaded yet!
|
||||||
Em.run.next(function() {
|
Em.run.next(function() {
|
||||||
var location = Discourse.URL.get('router.location');
|
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);
|
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.
|
Redirect to a URL.
|
||||||
This has been extracted so it can be tested.
|
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.
|
// Abort routing, we have replaced our state.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
this.set('queryParams', null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -118,9 +118,9 @@ Discourse.PostStream = Em.Object.extend({
|
||||||
if (this.get('summary')) { result.filter = "summary"; }
|
if (this.get('summary')) { result.filter = "summary"; }
|
||||||
|
|
||||||
var userFilters = this.get('userFilters');
|
var userFilters = this.get('userFilters');
|
||||||
if (userFilters) {
|
if (!Em.isEmpty(userFilters)) {
|
||||||
var userFiltersArray = this.get('userFilters').toArray();
|
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;
|
return result;
|
||||||
|
@ -189,11 +189,9 @@ Discourse.PostStream = Em.Object.extend({
|
||||||
Toggle summary mode for the stream.
|
Toggle summary mode for the stream.
|
||||||
|
|
||||||
@method toggleSummary
|
@method toggleSummary
|
||||||
@returns {Ember.Deferred} a promise that resolves when the summary stream has loaded.
|
|
||||||
**/
|
**/
|
||||||
toggleSummary: function() {
|
toggleSummary: function() {
|
||||||
var userFilters = this.get('userFilters');
|
this.get('userFilters').clear();
|
||||||
userFilters.clear();
|
|
||||||
this.toggleProperty('summary');
|
this.toggleProperty('summary');
|
||||||
return this.refresh();
|
return this.refresh();
|
||||||
},
|
},
|
||||||
|
@ -202,7 +200,6 @@ Discourse.PostStream = Em.Object.extend({
|
||||||
Filter the stream to a particular user.
|
Filter the stream to a particular user.
|
||||||
|
|
||||||
@method toggleParticipant
|
@method toggleParticipant
|
||||||
@returns {Ember.Deferred} a promise that resolves when the filtered stream has loaded.
|
|
||||||
**/
|
**/
|
||||||
toggleParticipant: function(username) {
|
toggleParticipant: function(username) {
|
||||||
var userFilters = this.get('userFilters');
|
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.
|
@returns {Ember.Deferred} a promise that is resolved when the posts have been inserted into the stream.
|
||||||
**/
|
**/
|
||||||
refresh: function(opts) {
|
refresh: function(opts) {
|
||||||
|
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
opts.nearPost = parseInt(opts.nearPost, 10);
|
opts.nearPost = parseInt(opts.nearPost, 10);
|
||||||
|
|
||||||
|
@ -247,8 +243,6 @@ Discourse.PostStream = Em.Object.extend({
|
||||||
topic.updateFromJson(json);
|
topic.updateFromJson(json);
|
||||||
self.updateFromJson(json.post_stream);
|
self.updateFromJson(json.post_stream);
|
||||||
self.setProperties({ loadingFilter: false, loaded: true });
|
self.setProperties({ loadingFilter: false, loaded: true });
|
||||||
|
|
||||||
Discourse.URL.set('queryParams', self.get('streamFilters'));
|
|
||||||
}).catch(function(result) {
|
}).catch(function(result) {
|
||||||
self.errorLoading(result);
|
self.errorLoading(result);
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,34 +6,6 @@ var get = Ember.get, set = Ember.set;
|
||||||
var popstateFired = false;
|
var popstateFired = false;
|
||||||
var supportsHistoryState = window.history && 'state' in window.history;
|
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 = [];
|
var popstateCallbacks = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -59,12 +31,6 @@ Ember.DiscourseLocation = Ember.Object.extend({
|
||||||
@method initState
|
@method initState
|
||||||
*/
|
*/
|
||||||
initState: function() {
|
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);
|
set(this, 'history', get(this, 'history') || window.history);
|
||||||
this.replaceState(this.formatURL(this.getURL()));
|
this.replaceState(this.formatURL(this.getURL()));
|
||||||
},
|
},
|
||||||
|
@ -86,11 +52,17 @@ Ember.DiscourseLocation = Ember.Object.extend({
|
||||||
*/
|
*/
|
||||||
getURL: function() {
|
getURL: function() {
|
||||||
var rootURL = (Discourse.BaseUri === undefined ? "/" : Discourse.BaseUri),
|
var rootURL = (Discourse.BaseUri === undefined ? "/" : Discourse.BaseUri),
|
||||||
url = get(this, 'location').pathname;
|
location = get(this, 'location'),
|
||||||
|
url = location.pathname;
|
||||||
|
|
||||||
rootURL = rootURL.replace(/\/$/, '');
|
rootURL = rootURL.replace(/\/$/, '');
|
||||||
url = url.replace(rootURL, '');
|
url = url.replace(rootURL, '');
|
||||||
|
|
||||||
|
if (Ember.FEATURES.isEnabled("query-params-new")) {
|
||||||
|
var search = location.search || '';
|
||||||
|
url += search;
|
||||||
|
}
|
||||||
|
|
||||||
return url;
|
return url;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -186,24 +158,6 @@ Ember.DiscourseLocation = Ember.Object.extend({
|
||||||
this._previousURL = this.getURL();
|
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
|
@private
|
||||||
|
|
||||||
|
@ -244,7 +198,7 @@ Ember.DiscourseLocation = Ember.Object.extend({
|
||||||
rootURL = rootURL.replace(/\/$/, '');
|
rootURL = rootURL.replace(/\/$/, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
return rootURL + url + this.get('queryParamsString');
|
return rootURL + url;
|
||||||
},
|
},
|
||||||
|
|
||||||
willDestroy: function() {
|
willDestroy: function() {
|
||||||
|
|
|
@ -11,24 +11,8 @@ Discourse.TopicFromParamsRoute = Discourse.Route.extend({
|
||||||
setupController: function(controller, params) {
|
setupController: function(controller, params) {
|
||||||
params = params || {};
|
params = params || {};
|
||||||
params.track_visit = true;
|
params.track_visit = true;
|
||||||
|
|
||||||
var topic = this.modelFor('topic'),
|
var topic = this.modelFor('topic'),
|
||||||
postStream = topic.get('postStream'),
|
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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var topicController = this.controllerFor('topic'),
|
var topicController = this.controllerFor('topic'),
|
||||||
composerController = this.controllerFor('composer');
|
composerController = this.controllerFor('composer');
|
||||||
|
|
|
@ -9,6 +9,17 @@
|
||||||
Discourse.TopicRoute = Discourse.Route.extend({
|
Discourse.TopicRoute = Discourse.Route.extend({
|
||||||
redirect: function() { Discourse.redirectIfLoginRequired(this); },
|
redirect: function() { Discourse.redirectIfLoginRequired(this); },
|
||||||
|
|
||||||
|
queryParams: {
|
||||||
|
filter: {
|
||||||
|
refreshModel: false,
|
||||||
|
replace: true
|
||||||
|
},
|
||||||
|
username_filters: {
|
||||||
|
refreshModel: false,
|
||||||
|
replace: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
// Modals that can pop up within a topic
|
// Modals that can pop up within a topic
|
||||||
showPosterExpansion: function(post) {
|
showPosterExpansion: function(post) {
|
||||||
|
@ -88,16 +99,32 @@ Discourse.TopicRoute = Discourse.Route.extend({
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
model: function(params) {
|
setupParams: function(topic, params) {
|
||||||
var currentModel = this.modelFor('topic');
|
var postStream = topic.get('postStream');
|
||||||
if (currentModel && (currentModel.get('id') === parseInt(params.id, 10))) {
|
postStream.set('summary', Em.get(params, 'filter') === 'summary');
|
||||||
// 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
|
var usernames = Em.get(params, 'username_filters'),
|
||||||
// button was hit.
|
userFilters = postStream.get('userFilters');
|
||||||
currentModel.set('postStream.loaded', true);
|
|
||||||
return currentModel;
|
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() {
|
activate: function() {
|
||||||
|
@ -130,9 +157,6 @@ Discourse.TopicRoute = Discourse.Route.extend({
|
||||||
headerController.set('topic', null);
|
headerController.set('topic', null);
|
||||||
headerController.set('showExtraInfo', false);
|
headerController.set('showExtraInfo', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear any filters when we leave the route
|
|
||||||
Discourse.URL.set('queryParams', null);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
setupController: function(controller, model) {
|
setupController: function(controller, model) {
|
||||||
|
|
|
@ -33,7 +33,10 @@ Discourse.TopicMapContainerView = Discourse.ContainerView.extend({
|
||||||
|
|
||||||
// If we have a summary capability
|
// If we have a summary capability
|
||||||
if (topic.get('has_summary')) {
|
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
|
// If we have a private message
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
window.ENV = {
|
window.ENV = {
|
||||||
CP_DEFAULT_CACHEABLE: true,
|
CP_DEFAULT_CACHEABLE: true,
|
||||||
VIEW_PRESERVES_CONTEXT: true,
|
VIEW_PRESERVES_CONTEXT: true,
|
||||||
MANDATORY_SETTER: false
|
MANDATORY_SETTER: false,
|
||||||
|
FEATURES: {'query-params-new': true}
|
||||||
};
|
};
|
||||||
|
|
||||||
window.Discourse = {};
|
window.Discourse = {};
|
||||||
|
|
|
@ -38,7 +38,7 @@ class TopicsController < ApplicationController
|
||||||
opts = params.slice(:username_filters, :filter, :page, :post_number)
|
opts = params.slice(:username_filters, :filter, :page, :post_number)
|
||||||
username_filters = opts[:username_filters]
|
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
|
begin
|
||||||
@topic_view = TopicView.new(params[:id] || params[:topic_id], current_user, opts)
|
@topic_view = TopicView.new(params[:id] || params[:topic_id], current_user, opts)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue