From 2eab288dc9d448b24a388026bda9a62e260cb15b Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Tue, 15 Apr 2014 15:33:08 -0400 Subject: [PATCH] Port "Summarize Topic" to query-params-new --- .../discourse/controllers/topic_controller.js | 15 +++++ app/assets/javascripts/discourse/lib/url.js | 17 +++-- .../discourse/models/post_stream.js | 12 +--- .../discourse/routes/discourse_location.js | 62 +++---------------- .../routes/topic_from_params_route.js | 18 +----- .../discourse/routes/topic_route.js | 48 ++++++++++---- .../views/topic_map_container_view.js | 5 +- app/assets/javascripts/env.js | 3 +- app/controllers/topics_controller.rb | 2 +- 9 files changed, 78 insertions(+), 104 deletions(-) diff --git a/app/assets/javascripts/discourse/controllers/topic_controller.js b/app/assets/javascripts/discourse/controllers/topic_controller.js index 1361ba81d77..fc2febaf8b1 100644 --- a/app/assets/javascripts/discourse/controllers/topic_controller.js +++ b/app/assets/javascripts/discourse/controllers/topic_controller.js @@ -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(); diff --git a/app/assets/javascripts/discourse/lib/url.js b/app/assets/javascripts/discourse/lib/url.js index a9c0be00d75..da8231403ce 100644 --- a/app/assets/javascripts/discourse/lib/url.js +++ b/app/assets/javascripts/discourse/lib/url.js @@ -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; diff --git a/app/assets/javascripts/discourse/models/post_stream.js b/app/assets/javascripts/discourse/models/post_stream.js index 1740c4fcaed..4179812ffc5 100644 --- a/app/assets/javascripts/discourse/models/post_stream.js +++ b/app/assets/javascripts/discourse/models/post_stream.js @@ -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); }); diff --git a/app/assets/javascripts/discourse/routes/discourse_location.js b/app/assets/javascripts/discourse/routes/discourse_location.js index 0693a65d8dd..f5a6ed2d837 100644 --- a/app/assets/javascripts/discourse/routes/discourse_location.js +++ b/app/assets/javascripts/discourse/routes/discourse_location.js @@ -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() { diff --git a/app/assets/javascripts/discourse/routes/topic_from_params_route.js b/app/assets/javascripts/discourse/routes/topic_from_params_route.js index c6314834b1a..ded638a392c 100644 --- a/app/assets/javascripts/discourse/routes/topic_from_params_route.js +++ b/app/assets/javascripts/discourse/routes/topic_from_params_route.js @@ -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'); diff --git a/app/assets/javascripts/discourse/routes/topic_route.js b/app/assets/javascripts/discourse/routes/topic_route.js index 122dca61453..9e136bafb4e 100644 --- a/app/assets/javascripts/discourse/routes/topic_route.js +++ b/app/assets/javascripts/discourse/routes/topic_route.js @@ -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) { diff --git a/app/assets/javascripts/discourse/views/topic_map_container_view.js b/app/assets/javascripts/discourse/views/topic_map_container_view.js index 48a48e201f3..13dd85089b3 100644 --- a/app/assets/javascripts/discourse/views/topic_map_container_view.js +++ b/app/assets/javascripts/discourse/views/topic_map_container_view.js @@ -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 diff --git a/app/assets/javascripts/env.js b/app/assets/javascripts/env.js index a8781abcb8e..f17440c6cb4 100644 --- a/app/assets/javascripts/env.js +++ b/app/assets/javascripts/env.js @@ -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 = {}; diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index bb0dc41e630..a802ec86725 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -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)