From 94d8d3c80f8bfb99912bd7e7c0f4565a457c328e Mon Sep 17 00:00:00 2001 From: Toby Zerner Date: Sat, 2 May 2015 08:43:38 +0930 Subject: [PATCH] Extensibility: discussion list params Also give the root controller the name of the current route so they can easily route back to it --- .../forum/src/components/discussion-list.js | 51 +++++++++--------- .../js/forum/src/components/index-page.js | 53 +++++++++++++++---- .../core/js/lib/components/select-input.js | 2 +- framework/core/js/lib/utils/map-routes.js | 1 + 4 files changed, 70 insertions(+), 37 deletions(-) diff --git a/framework/core/js/forum/src/components/discussion-list.js b/framework/core/js/forum/src/components/discussion-list.js index 3ff7818ab..7e4b2b35a 100644 --- a/framework/core/js/forum/src/components/discussion-list.js +++ b/framework/core/js/forum/src/components/discussion-list.js @@ -16,19 +16,30 @@ export default class DiscussionList extends Component { this.loading = m.prop(true); this.moreResults = m.prop(false); this.discussions = m.prop([]); - this.sort = m.prop(this.props.sort || 'recent'); - this.sortOptions = m.prop([ - {key: 'recent', value: 'Recent', sort: 'recent'}, - {key: 'replies', value: 'Replies', sort: '-replies'}, - {key: 'newest', value: 'Newest', sort: '-created'}, - {key: 'oldest', value: 'Oldest', sort: 'created'} - ]); this.refresh(); app.session.on('loggedIn', this.loggedInHandler = this.refresh.bind(this)) } + params() { + var params = {}; + for (var i in this.props.params) { + params[i] = this.props.params[i]; + } + params.sort = this.sortMap()[params.sort]; + return params; + } + + sortMap() { + return { + recent: 'recent', + replies: '-replies', + newest: '-created', + oldest: 'created' + }; + } + refresh() { m.startComputation(); this.loading(true); @@ -42,26 +53,16 @@ export default class DiscussionList extends Component { } terminalPostType() { - return ['newest', 'oldest'].indexOf(this.sort()) !== -1 ? 'start' : 'last' + return ['newest', 'oldest'].indexOf(this.props.sort) !== -1 ? 'start' : 'last' } countType() { - return this.sort() === 'replies' ? 'replies' : 'unread'; + return this.props.sort === 'replies' ? 'replies' : 'unread'; } loadResults(start) { - var self = this; - - var sort = this.sortOptions()[0].sort; - this.sortOptions().some(function(option) { - if (option.key === self.sort()) { - sort = option.sort; - return true; - } - }); - - var params = {sort, start}; - + var params = this.params(); + params.start = start; return app.store.find('discussions', params); } @@ -97,10 +98,10 @@ export default class DiscussionList extends Component { view() { return m('div', [ m('ul.discussions-list', [ - this.discussions().map(function(discussion) { + this.discussions().map(discussion => { var startUser = discussion.startUser() var isUnread = discussion.isUnread() - var displayUnread = this.props.countType !== 'replies' && isUnread + var displayUnread = this.countType() !== 'replies' && isUnread var jumpTo = Math.min(discussion.lastPostNumber(), (discussion.readNumber() || 0) + 1) var controls = discussion.controls(this).toArray(); @@ -135,7 +136,7 @@ export default class DiscussionList extends Component { m('span.label', displayUnread ? 'unread' : 'replies') ]) ]) - }.bind(this)) + }) ]), this.loading() ? LoadingIndicator.component() @@ -159,7 +160,7 @@ export default class DiscussionList extends Component { items.add('terminalPost', TerminalPost.component({ discussion, - lastPost: this.props.terminalPostType !== 'start' + lastPost: this.terminalPostType() !== 'start' }) ); diff --git a/framework/core/js/forum/src/components/index-page.js b/framework/core/js/forum/src/components/index-page.js index baa79fce4..eb20353d6 100644 --- a/framework/core/js/forum/src/components/index-page.js +++ b/framework/core/js/forum/src/components/index-page.js @@ -18,15 +18,17 @@ export default class IndexPage extends Component { constructor(props) { super(props); + var params = this.params(); if (app.cache.discussionList) { - if (app.cache.discussionList.props.sort !== m.route.param('sort')) { - app.cache.discussionList = null; - } + Object.keys(params).some(key => { + if (app.cache.discussionList.props.params[key] !== params[key]) { + app.cache.discussionList = null; + return true; + } + }); } if (!app.cache.discussionList) { - app.cache.discussionList = new DiscussionList({ - sort: m.route.param('sort') - }); + app.cache.discussionList = new DiscussionList({params}); } app.history.push('index'); @@ -34,10 +36,34 @@ export default class IndexPage extends Component { app.composer.minimize(); } + /** + Params that stick between filter changes + */ + stickyParams() { + return { + sort: m.route.param('sort'), + show: m.route.param('show'), + q: m.route.param('q') + } + } + + /** + Params which are passed to the DiscussionList + */ + params() { + var params = this.stickyParams(); + params.filter = m.route.param('filter'); + return params; + } + reorder(sort) { - var filter = m.route.param('filter') || ''; - var params = sort !== 'recent' ? {sort} : {}; - m.route(app.route('index.filter', {filter}, params)); + var params = this.params(); + if (sort === 'recent') { + delete params.sort; + } else { + params.sort = sort; + } + m.route(app.route(this.props.routeName, params)); } /** @@ -47,6 +73,11 @@ export default class IndexPage extends Component { @return void */ view() { + var sortOptions = {}; + for (var i in app.cache.discussionList.sortMap()) { + sortOptions[i] = i.substr(0, 1).toUpperCase()+i.substr(1); + } + return m('div.index-area', {config: this.onload.bind(this)}, [ WelcomeHero.component(), m('div.container', [ @@ -57,8 +88,8 @@ export default class IndexPage extends Component { m('div.index-toolbar', [ m('div.index-toolbar-view', [ SelectInput.component({ - options: app.cache.discussionList.sortOptions(), - value: app.cache.discussionList.sort(), + options: sortOptions, + value: m.route.param('sort'), onchange: this.reorder.bind(this) }), ]), diff --git a/framework/core/js/lib/components/select-input.js b/framework/core/js/lib/components/select-input.js index aa4081ed8..c55aab702 100644 --- a/framework/core/js/lib/components/select-input.js +++ b/framework/core/js/lib/components/select-input.js @@ -5,7 +5,7 @@ export default class SelectInput extends Component { view(ctrl) { return m('span.select-input', [ m('select.form-control', {onchange: m.withAttr('value', this.props.onchange.bind(ctrl)), value: this.props.value}, [ - this.props.options.map(function(option) { return m('option', {value: option.key}, option.value) }) + Object.keys(this.props.options).map(key => m('option', {value: key}, this.props.options[key])) ]), icon('sort') ]) diff --git a/framework/core/js/lib/utils/map-routes.js b/framework/core/js/lib/utils/map-routes.js index 4c66f3652..25d6af8b1 100644 --- a/framework/core/js/lib/utils/map-routes.js +++ b/framework/core/js/lib/utils/map-routes.js @@ -1,6 +1,7 @@ export default function mapRoutes(routes) { var map = {}; for (var r in routes) { + routes[r][1].props.routeName = r; map[routes[r][0]] = routes[r][1]; } return map;