diff --git a/app/assets/javascripts/discourse/views/discovery-categories.js.es6 b/app/assets/javascripts/discourse/components/discovery-categories.js.es6 similarity index 82% rename from app/assets/javascripts/discourse/views/discovery-categories.js.es6 rename to app/assets/javascripts/discourse/components/discovery-categories.js.es6 index ee4b13d7d..d4b969b56 100644 --- a/app/assets/javascripts/discourse/views/discovery-categories.js.es6 +++ b/app/assets/javascripts/discourse/components/discovery-categories.js.es6 @@ -3,7 +3,9 @@ import { on } from 'ember-addons/ember-computed-decorators'; const CATEGORIES_LIST_BODY_CLASS = "categories-list"; -export default Ember.View.extend(UrlRefresh, { +export default Ember.Component.extend(UrlRefresh, { + classNames: ['contents'], + @on("didInsertElement") addBodyClass() { $('body').addClass(CATEGORIES_LIST_BODY_CLASS); diff --git a/app/assets/javascripts/discourse/views/discovery-topics.js.es6 b/app/assets/javascripts/discourse/components/discovery-topics-list.js.es6 similarity index 68% rename from app/assets/javascripts/discourse/views/discovery-topics.js.es6 rename to app/assets/javascripts/discourse/components/discovery-topics-list.js.es6 index ef5e3712c..d5a67e3f6 100644 --- a/app/assets/javascripts/discourse/views/discovery-topics.js.es6 +++ b/app/assets/javascripts/discourse/components/discovery-topics-list.js.es6 @@ -1,27 +1,15 @@ -import UrlRefresh from 'discourse/mixins/url-refresh'; -import LoadMore from "discourse/mixins/load-more"; import { on, observes } from "ember-addons/ember-computed-decorators"; +import LoadMore from "discourse/mixins/load-more"; +import UrlRefresh from 'discourse/mixins/url-refresh'; -export default Ember.View.extend(LoadMore, UrlRefresh, { +const DiscoveryTopicsListComponent = Ember.Component.extend(UrlRefresh, LoadMore, { + _viaComponent: true, + + classNames: ['contents'], eyelineSelector: '.topic-list-item', - actions: { - loadMore() { - const self = this; - Discourse.notifyTitle(0); - this.get('controller').loadMoreTopics().then(hasMoreResults => { - Ember.run.schedule('afterRender', () => self.saveScrollPosition()); - if (!hasMoreResults) { - this.get('eyeline').flushRest(); - } else if ($(window).height() >= $(document).height()) { - this.send("loadMore"); - } - }); - } - }, - @on("didInsertElement") - @observes("controller.model") + @observes("model") _readjustScrollPosition() { const scrollTo = this.session.get('topicListScrollPosition'); if (scrollTo && scrollTo >= 0) { @@ -31,19 +19,33 @@ export default Ember.View.extend(LoadMore, UrlRefresh, { } }, - @observes("controller.topicTrackingState.incomingCount") + @observes("incomingCount") _updateTitle() { - Discourse.notifyTitle(this.get('controller.topicTrackingState.incomingCount')); + Discourse.notifyTitle(this.get('incomingCount')); }, - // Remember where we were scrolled to saveScrollPosition() { this.session.set('topicListScrollPosition', $(window).scrollTop()); }, - // When the topic list is scrolled scrolled() { this._super(); this.saveScrollPosition(); + }, + + actions: { + loadMore() { + Discourse.notifyTitle(0); + this.get('model').loadMore().then(hasMoreResults => { + Ember.run.schedule('afterRender', () => this.saveScrollPosition()); + if (!hasMoreResults) { + this.get('eyeline').flushRest(); + } else if ($(window).height() >= $(document).height()) { + this.send("loadMore"); + } + }); + } } }); + +export default DiscoveryTopicsListComponent; diff --git a/app/assets/javascripts/discourse/components/group-post-stream.js.es6 b/app/assets/javascripts/discourse/components/group-post-stream.js.es6 new file mode 100644 index 000000000..fc83f2dbb --- /dev/null +++ b/app/assets/javascripts/discourse/components/group-post-stream.js.es6 @@ -0,0 +1,8 @@ +export default Ember.Component.extend({ + actions: { + // TODO: When on Ember 1.13, use a closure action + loadMore() { + this.sendAction('loadMore'); + } + } +}); diff --git a/app/assets/javascripts/discourse/controllers/discovery/topics.js.es6 b/app/assets/javascripts/discourse/controllers/discovery/topics.js.es6 index 5e8695063..cc411691c 100644 --- a/app/assets/javascripts/discourse/controllers/discovery/topics.js.es6 +++ b/app/assets/javascripts/discourse/controllers/discovery/topics.js.es6 @@ -138,11 +138,8 @@ const controllerOpts = { return I18n.t("topics.none.educate." + split[0], { userPrefsUrl: Discourse.getURL("/users/") + (Discourse.User.currentProp("username_lower")) + "/preferences" }); - }.property('allLoaded', 'model.topics.length'), + }.property('allLoaded', 'model.topics.length') - loadMoreTopics() { - return this.get('model').loadMore(); - } }; Ember.keys(queryParams).forEach(function(p) { diff --git a/app/assets/javascripts/discourse/controllers/group-index.js.es6 b/app/assets/javascripts/discourse/controllers/group-index.js.es6 new file mode 100644 index 000000000..7a5a5bf98 --- /dev/null +++ b/app/assets/javascripts/discourse/controllers/group-index.js.es6 @@ -0,0 +1,27 @@ +import { fmt } from 'discourse/lib/computed'; + +export default Ember.ArrayController.extend({ + needs: ['group'], + loading: false, + emptyText: fmt('type', 'groups.empty.%@'), + + actions: { + loadMore() { + + if (this.get('loading')) { return; } + this.set('loading', true); + const posts = this.get('model'); + if (posts && posts.length) { + const beforePostId = posts[posts.length-1].get('id'); + const group = this.get('controllers.group.model'); + + const opts = { beforePostId, type: this.get('type') }; + group.findPosts(opts).then(newPosts => { + posts.addObjects(newPosts); + this.set('loading', false); + }); + } + } + } +}); + diff --git a/app/assets/javascripts/discourse/controllers/group/index.js.es6 b/app/assets/javascripts/discourse/controllers/group/index.js.es6 deleted file mode 100644 index 60df6a2cd..000000000 --- a/app/assets/javascripts/discourse/controllers/group/index.js.es6 +++ /dev/null @@ -1,28 +0,0 @@ -/** - Handles displaying posts within a group -**/ -export default Ember.ArrayController.extend({ - needs: ['group'], - loading: false, - - actions: { - loadMore: function() { - - if (this.get('loading')) { return; } - this.set('loading', true); - var posts = this.get('model'), - self = this; - if (posts && posts.length) { - var lastPostId = posts[posts.length-1].get('id'), - group = this.get('controllers.group.model'); - - var opts = {beforePostId: lastPostId, type: this.get('type')}; - group.findPosts(opts).then(function(newPosts) { - posts.addObjects(newPosts); - self.set('loading', false); - }); - } - } - } -}); - diff --git a/app/assets/javascripts/discourse/controllers/group/members.js.es6 b/app/assets/javascripts/discourse/controllers/group/members.js.es6 index 246a5f80c..09c4b9a63 100644 --- a/app/assets/javascripts/discourse/controllers/group/members.js.es6 +++ b/app/assets/javascripts/discourse/controllers/group/members.js.es6 @@ -1,5 +1,6 @@ import { popupAjaxError } from 'discourse/lib/ajax-error'; import computed from 'ember-addons/ember-computed-decorators'; +import Group from 'discourse/models/group'; export default Ember.Controller.extend({ loading: false, @@ -30,10 +31,7 @@ export default Ember.Controller.extend({ }, loadMore() { - const Group = require('discourse/models/group').default; - if (this.get("loading")) { return; } - // we've reached the end if (this.get("model.members.length") >= this.get("model.user_count")) { return; } this.set("loading", true); diff --git a/app/assets/javascripts/discourse/controllers/group/mentions.js.es6 b/app/assets/javascripts/discourse/controllers/group/mentions.js.es6 deleted file mode 100644 index 81fa5a8ff..000000000 --- a/app/assets/javascripts/discourse/controllers/group/mentions.js.es6 +++ /dev/null @@ -1,3 +0,0 @@ -import IndexController from 'discourse/controllers/group/index'; - -export default IndexController.extend({type: 'mentions'}); diff --git a/app/assets/javascripts/discourse/controllers/group/topics.js.es6 b/app/assets/javascripts/discourse/controllers/group/topics.js.es6 deleted file mode 100644 index 942335032..000000000 --- a/app/assets/javascripts/discourse/controllers/group/topics.js.es6 +++ /dev/null @@ -1,3 +0,0 @@ -import IndexController from 'discourse/controllers/group/index'; - -export default IndexController.extend({type: 'topics'}); diff --git a/app/assets/javascripts/discourse/lib/app-events.js.es6 b/app/assets/javascripts/discourse/lib/app-events.js.es6 index 597c21b83..59257700f 100644 --- a/app/assets/javascripts/discourse/lib/app-events.js.es6 +++ b/app/assets/javascripts/discourse/lib/app-events.js.es6 @@ -1,25 +1 @@ - -var id = 1; -function newKey() { - return "_view_app_event_" + (id++); -} - -function createViewListener(eventName, cb) { - var extension = {}; - extension[newKey()] = function() { - this.appEvents.on(eventName, this, cb); - }.on('didInsertElement'); - - extension[newKey()] = function() { - this.appEvents.off(eventName, this, cb); - }.on('willDestroyElement'); - - return extension; -} - -function listenForViewEvent(viewClass, eventName, cb) { - viewClass.reopen(createViewListener(eventName, cb)); -} - -export { listenForViewEvent, createViewListener }; export default Ember.Object.extend(Ember.Evented); diff --git a/app/assets/javascripts/discourse/lib/click-track.js.es6 b/app/assets/javascripts/discourse/lib/click-track.js.es6 index 799c26ada..b25dacd98 100644 --- a/app/assets/javascripts/discourse/lib/click-track.js.es6 +++ b/app/assets/javascripts/discourse/lib/click-track.js.es6 @@ -1,4 +1,5 @@ import DiscourseURL from 'discourse/lib/url'; +import { wantsNewWindow } from 'discourse/lib/intercept-click'; export function isValidLink($link) { return ($link.hasClass("track-link") || @@ -52,7 +53,7 @@ export default { } // if they want to open in a new tab, do an AJAX request - if (e.shiftKey || e.metaKey || e.ctrlKey || e.which === 2) { + if (wantsNewWindow(e)) { Discourse.ajax("/clicks/track", { data: { url: href, diff --git a/app/assets/javascripts/discourse/lib/intercept-click.js.es6 b/app/assets/javascripts/discourse/lib/intercept-click.js.es6 index 658f55db6..09367beca 100644 --- a/app/assets/javascripts/discourse/lib/intercept-click.js.es6 +++ b/app/assets/javascripts/discourse/lib/intercept-click.js.es6 @@ -1,12 +1,16 @@ import DiscourseURL from 'discourse/lib/url'; +export function wantsNewWindow(e) { + return (e.isDefaultPrevented() || e.shiftKey || e.metaKey || e.ctrlKey || (e.button && e.button !== 0)); +} + /** Discourse does some server side rendering of HTML, such as the `cooked` contents of posts. The downside of this in an Ember app is the links will not go through the router. This jQuery code intercepts clicks on those links and routes them properly. **/ export default function interceptClick(e) { - if (e.isDefaultPrevented() || e.shiftKey || e.metaKey || e.ctrlKey) { return; } + if (wantsNewWindow(e)) { return; } const $currentTarget = $(e.currentTarget), href = $currentTarget.attr('href'); diff --git a/app/assets/javascripts/discourse/mixins/url-refresh.js.es6 b/app/assets/javascripts/discourse/mixins/url-refresh.js.es6 index e5ab51cb3..bf1710d1c 100644 --- a/app/assets/javascripts/discourse/mixins/url-refresh.js.es6 +++ b/app/assets/javascripts/discourse/mixins/url-refresh.js.es6 @@ -1,12 +1,16 @@ // A Mixin that a view can use to listen for 'url:refresh' when -// it is on screen, and will send an action to the controller to -// refresh its data. +// it is on screen, and will send an action to refresh its data. // // This is useful if you want to get around Ember's default // behavior of not refreshing when navigating to the same place. +export default { + didInsertElement() { + this._super(); + this.appEvents.on('url:refresh', () => this.sendAction('refresh')); + }, -import { createViewListener } from 'discourse/lib/app-events'; - -export default createViewListener('url:refresh', function() { - this.get('controller').send('refresh'); -}); + willDestroyElement() { + this._super(); + this.appEvents.off('url:refresh'); + } +}; diff --git a/app/assets/javascripts/discourse/routes/group-index.js.es6 b/app/assets/javascripts/discourse/routes/group-index.js.es6 index bb8ecaeb0..a7baf27a1 100644 --- a/app/assets/javascripts/discourse/routes/group-index.js.es6 +++ b/app/assets/javascripts/discourse/routes/group-index.js.es6 @@ -1,14 +1,24 @@ -export default Discourse.Route.extend({ - actions: { - didTransition() { return true; } - }, +export function buildIndex(type) { + return Discourse.Route.extend({ + type, - model() { - return this.modelFor("group").findPosts(); - }, + model() { + return this.modelFor("group").findPosts({ type }); + }, - setupController(controller, model) { - controller.set("model", model); - this.controllerFor("group").set("showing", "posts"); - } -}); + setupController(controller, model) { + this.controllerFor('group-index').setProperties({ model, type }); + this.controllerFor("group").set("showing", type); + }, + + renderTemplate() { + this.render('group-index'); + }, + + actions: { + didTransition() { return true; } + } + }); +} + +export default buildIndex('posts'); diff --git a/app/assets/javascripts/discourse/routes/group-members.js.es6 b/app/assets/javascripts/discourse/routes/group-members.js.es6 index 22e328cac..c6e00e802 100644 --- a/app/assets/javascripts/discourse/routes/group-members.js.es6 +++ b/app/assets/javascripts/discourse/routes/group-members.js.es6 @@ -8,5 +8,4 @@ export default Discourse.Route.extend({ controller.set("model", model); model.findMembers(); } - }); diff --git a/app/assets/javascripts/discourse/routes/group-mentions.js.es6 b/app/assets/javascripts/discourse/routes/group-mentions.js.es6 index 1054fb18d..d5c7471f5 100644 --- a/app/assets/javascripts/discourse/routes/group-mentions.js.es6 +++ b/app/assets/javascripts/discourse/routes/group-mentions.js.es6 @@ -1,11 +1,3 @@ -export default Discourse.Route.extend({ +import { buildIndex } from 'discourse/routes/group-index'; - model() { - return this.modelFor("group").findPosts({type: 'mentions'}); - }, - - setupController(controller, model) { - controller.set("model", model); - this.controllerFor("group").set("showing", "mentions"); - } -}); +export default buildIndex('mentions'); diff --git a/app/assets/javascripts/discourse/routes/group-messages.js.es6 b/app/assets/javascripts/discourse/routes/group-messages.js.es6 index 34e077e36..df27a3f79 100644 --- a/app/assets/javascripts/discourse/routes/group-messages.js.es6 +++ b/app/assets/javascripts/discourse/routes/group-messages.js.es6 @@ -1,11 +1,3 @@ -export default Discourse.Route.extend({ +import { buildIndex } from 'discourse/routes/group-index'; - model() { - return this.modelFor("group").findPosts({type: 'messages'}); - }, - - setupController(controller, model) { - controller.set("model", model); - this.controllerFor("group").set("showing", "messages"); - } -}); +export default buildIndex('messages'); diff --git a/app/assets/javascripts/discourse/routes/group-topics.js.es6 b/app/assets/javascripts/discourse/routes/group-topics.js.es6 index 397572e77..991bb7475 100644 --- a/app/assets/javascripts/discourse/routes/group-topics.js.es6 +++ b/app/assets/javascripts/discourse/routes/group-topics.js.es6 @@ -1,11 +1,3 @@ -export default Discourse.Route.extend({ +import { buildIndex } from 'discourse/routes/group-index'; - model() { - return this.modelFor("group").findPosts({type: 'topics'}); - }, - - setupController(controller, model) { - controller.set("model", model); - this.controllerFor("group").set("showing", "topics"); - } -}); +export default buildIndex('topics'); diff --git a/app/assets/javascripts/discourse/templates/components/group-post-stream.js.hbs b/app/assets/javascripts/discourse/templates/components/group-post-stream.js.hbs index 42af3ae45..9ab4c17c6 100644 --- a/app/assets/javascripts/discourse/templates/components/group-post-stream.js.hbs +++ b/app/assets/javascripts/discourse/templates/components/group-post-stream.js.hbs @@ -1,7 +1,9 @@ -