diff --git a/app/assets/javascripts/discourse/components/top-period-buttons.js.es6 b/app/assets/javascripts/discourse/components/top-period-buttons.js.es6 new file mode 100644 index 00000000000..eec8000a46b --- /dev/null +++ b/app/assets/javascripts/discourse/components/top-period-buttons.js.es6 @@ -0,0 +1,3 @@ +export default Ember.Component.extend({ + classNames: ['top-title-buttons'] +}); diff --git a/app/assets/javascripts/discourse/components/top-period-chooser.js.es6 b/app/assets/javascripts/discourse/components/top-period-chooser.js.es6 new file mode 100644 index 00000000000..ee63a0ae4c9 --- /dev/null +++ b/app/assets/javascripts/discourse/components/top-period-chooser.js.es6 @@ -0,0 +1,31 @@ +import CleansUp from 'discourse/mixins/cleans-up'; + +export default Ember.Component.extend(CleansUp, { + classNames: 'period-chooser', + showPeriods: false, + + cleanUp: function() { + this.set('showPeriods', false); + $('html').off('mousedown.top-period'); + }, + + _clickToClose: function() { + var self = this; + $('html').off('mousedown.top-period').on('mousedown.top-period', function(e) { + var $target = $(e.target); + if (($target.prop('id') === 'topic-entrance') || (self.$().has($target).length !== 0)) { + return; + } + self.cleanUp(); + }); + }, + + click: function() { + if (!this.get('showPeriods')) { + var $chevron = this.$('i.fa-caret-down'); + this.$('#period-popup').css($chevron.position()); + this.set('showPeriods', true); + this._clickToClose(); + } + } +}); diff --git a/app/assets/javascripts/discourse/components/top-title-button.js.es6 b/app/assets/javascripts/discourse/components/top-title-button.js.es6 new file mode 100644 index 00000000000..8da2fd50787 --- /dev/null +++ b/app/assets/javascripts/discourse/components/top-title-button.js.es6 @@ -0,0 +1,13 @@ +import TopTitle from 'discourse/components/top-title'; + +export default TopTitle.extend({ + tagName: 'button', + classNameBindings: [':btn', ':btn-default', 'unless:hidden'], + + click: function() { + var url = this.get('period.showMoreUrl'); + if (url) { + Discourse.URL.routeTo(url); + } + } +}); diff --git a/app/assets/javascripts/discourse/components/top-title.js.es6 b/app/assets/javascripts/discourse/components/top-title.js.es6 new file mode 100644 index 00000000000..31c03461d58 --- /dev/null +++ b/app/assets/javascripts/discourse/components/top-title.js.es6 @@ -0,0 +1,8 @@ +export default Ember.Component.extend({ + tagName: 'h2', + + _shouldRerender: Discourse.View.renderIfChanged('period.title'), + render: function(buffer) { + buffer.push(" " + this.get('period.title')); + } +}); diff --git a/app/assets/javascripts/discourse/controllers/discovery.js.es6 b/app/assets/javascripts/discourse/controllers/discovery.js.es6 index 5fe00057a92..16cb2000f63 100644 --- a/app/assets/javascripts/discourse/controllers/discovery.js.es6 +++ b/app/assets/javascripts/discourse/controllers/discovery.js.es6 @@ -1,10 +1,15 @@ import ObjectController from 'discourse/controllers/object'; +import TopPeriod from 'discourse/models/top-period'; export default ObjectController.extend({ + needs: ['navigation/category'], loading: false, loadingSpinner: false, scheduledSpinner: null, + category: Em.computed.alias('controllers.navigation/category.category'), + noSubcategories: Em.computed.alias('controllers.navigation/category.noSubcategories'), + showMoreUrl: function(period) { var url = '', category = this.get('category'); if (category) { @@ -14,8 +19,15 @@ export default ObjectController.extend({ return url; }, - showMoreDailyUrl: function() { return this.showMoreUrl('daily'); }.property('category', 'noSubcategories'), - showMoreWeeklyUrl: function() { return this.showMoreUrl('weekly'); }.property('category', 'noSubcategories'), - showMoreMonthlyUrl: function() { return this.showMoreUrl('monthly'); }.property('category', 'noSubcategories'), - showMoreYearlyUrl: function() { return this.showMoreUrl('yearly'); }.property('category', 'noSubcategories') + periods: function() { + var self = this, + periods = []; + Discourse.Site.currentProp('periods').forEach(function(p) { + periods.pushObject(TopPeriod.create({ id: p, + showMoreUrl: self.showMoreUrl(p), + periods: periods })); + }); + return periods; + }.property('category', 'noSubcategories'), + }); diff --git a/app/assets/javascripts/discourse/controllers/discovery/top.js.es6 b/app/assets/javascripts/discourse/controllers/discovery/top.js.es6 index 7bb194ad56f..1bce2033a2c 100644 --- a/app/assets/javascripts/discourse/controllers/discovery/top.js.es6 +++ b/app/assets/javascripts/discourse/controllers/discovery/top.js.es6 @@ -3,6 +3,14 @@ import DiscoveryController from 'discourse/controllers/discovery'; export default DiscoveryController.extend({ needs: ['discovery'], + period: function() { + return this.get('controllers.discovery.periods').findBy('id', this.get('periodId')); + }.property('periodId'), + + topicList: function() { + return this.get('model.' + this.get('periodId')); + }.property('periodId'), + actions: { refresh: function() { var self = this; @@ -16,7 +24,6 @@ export default DiscoveryController.extend({ self.send('loadingComplete'); }); } - }, + } - hasDisplayedAllTopLists: Em.computed.and('content.yearly', 'content.monthly', 'content.weekly', 'content.daily') }); diff --git a/app/assets/javascripts/discourse/mixins/cleans-up.js.es6 b/app/assets/javascripts/discourse/mixins/cleans-up.js.es6 new file mode 100644 index 00000000000..2c180ec9b6c --- /dev/null +++ b/app/assets/javascripts/discourse/mixins/cleans-up.js.es6 @@ -0,0 +1,11 @@ +// Include this mixin if you want to be notified when the dom should be +// cleaned (usually on route change.) +export default Ember.Mixin.create({ + _initializeChooser: function() { + this.appEvents.on('dom:clean', this, "cleanUp"); + }.on('didInsertElement'), + + _clearChooser: function() { + this.appEvents.off('dom:clean', this, "cleanUp"); + }.on('willDestroyElement') +}); diff --git a/app/assets/javascripts/discourse/models/top-period.js.es6 b/app/assets/javascripts/discourse/models/top-period.js.es6 new file mode 100644 index 00000000000..9aef0fcdade --- /dev/null +++ b/app/assets/javascripts/discourse/models/top-period.js.es6 @@ -0,0 +1,30 @@ +export default Ember.Object.extend({ + title: null, + + availablePeriods: function() { + var periods = this.get('periods'); + if (!periods) { return; } + + var self = this; + return periods.filter(function(p) { + return p !== self; + }); + }.property('showMoreUrl'), + + _createTitle: function() { + var id = this.get('id'); + if (id) { + var title = "this_week"; + if (id === "yearly") { + title = "this_year"; + } else if (id === "monthly") { + title = "this_month"; + } else if (id === "daily") { + title = "today"; + } + + this.set('title', I18n.t("filters.top." + title)); + } + }.on('init') + +}); diff --git a/app/assets/javascripts/discourse/models/top_list.js b/app/assets/javascripts/discourse/models/top_list.js index d5ccb19efb5..7ea8bf5ead6 100644 --- a/app/assets/javascripts/discourse/models/top_list.js +++ b/app/assets/javascripts/discourse/models/top_list.js @@ -27,6 +27,7 @@ Discourse.TopList.reopenClass({ if (result[period]) { // instanciate a new topic list with no sorting topList.set(period, Discourse.TopicList.from(result[period])); + topList.set('periodId', period); } }); diff --git a/app/assets/javascripts/discourse/routes/build-category-route.js.es6 b/app/assets/javascripts/discourse/routes/build-category-route.js.es6 index 1f4faa35047..31ec0f56ac6 100644 --- a/app/assets/javascripts/discourse/routes/build-category-route.js.es6 +++ b/app/assets/javascripts/discourse/routes/build-category-route.js.es6 @@ -62,7 +62,8 @@ export default function(filter, params) { setupController: function(controller, model) { var topics = this.get('topics'), - period = filter.indexOf('/') > 0 ? filter.split('/')[1] : '', + periods = this.controllerFor('discovery').get('periods'), + periodId = filter.indexOf('/') > 0 ? filter.split('/')[1] : '', filterText = I18n.t('filters.' + filter.replace('/', '.') + '.title', {count: 0}); Discourse.set('title', I18n.t('filters.with_category', { filter: filterText, category: model.get('name') })); @@ -71,7 +72,7 @@ export default function(filter, params) { this.controllerFor('discovery/topics').setProperties({ model: topics, category: model, - period: period, + period: periods.findBy('id', periodId), selected: [], noSubcategories: params && !!params.no_subcategories }); diff --git a/app/assets/javascripts/discourse/routes/build-topic-route.js.es6 b/app/assets/javascripts/discourse/routes/build-topic-route.js.es6 index 8a5d419e461..d1b9cd92440 100644 --- a/app/assets/javascripts/discourse/routes/build-topic-route.js.es6 +++ b/app/assets/javascripts/discourse/routes/build-topic-route.js.es6 @@ -35,7 +35,8 @@ export default function(filter) { return 'queryParams.' + v; }))); - var period = filter.indexOf('/') > 0 ? filter.split('/')[1] : '', + var periods = this.controllerFor('discovery').get('periods'), + periodId = filter.indexOf('/') > 0 ? filter.split('/')[1] : '', filterText = I18n.t('filters.' + filter.replace('/', '.') + '.title', {count: 0}); if (filter === Discourse.Utilities.defaultHomepage()) { @@ -47,7 +48,7 @@ export default function(filter) { this.controllerFor('discovery/topics').setProperties({ model: model, category: null, - period: period, + period: periods.findBy('id', periodId), selected: [] }); diff --git a/app/assets/javascripts/discourse/templates/components/top-period-buttons.js.handlebars b/app/assets/javascripts/discourse/templates/components/top-period-buttons.js.handlebars new file mode 100644 index 00000000000..718880e7186 --- /dev/null +++ b/app/assets/javascripts/discourse/templates/components/top-period-buttons.js.handlebars @@ -0,0 +1,3 @@ +{{#each period.availablePeriods}} + {{top-title-button period=this}} +{{/each}} diff --git a/app/assets/javascripts/discourse/templates/components/top-period-chooser.js.handlebars b/app/assets/javascripts/discourse/templates/components/top-period-chooser.js.handlebars new file mode 100644 index 00000000000..f82a1446af2 --- /dev/null +++ b/app/assets/javascripts/discourse/templates/components/top-period-chooser.js.handlebars @@ -0,0 +1,10 @@ +{{top-title period=period}} + + +
+ +
diff --git a/app/assets/javascripts/discourse/templates/discovery/top.js.handlebars b/app/assets/javascripts/discourse/templates/discovery/top.js.handlebars index aa6a5e2c232..270702b9ba3 100644 --- a/app/assets/javascripts/discourse/templates/discovery/top.js.handlebars +++ b/app/assets/javascripts/discourse/templates/discovery/top.js.handlebars @@ -2,44 +2,22 @@ {{#if currentUser.redirected_to_top_reason}}
{{currentUser.redirected_to_top_reason}}
{{/if}} - {{#if content.yearly}} + + {{#if topicList}}
-

{{i18n filters.top.this_year}}

- {{basic-topic-list topicList=content.yearly hideCategory=hideCategory postsAction="showTopicEntrance"}} - {{#if content.yearly.topics.length}}{{i18n show_more}}{{/if}} -
- {{/if}} - {{#if content.monthly}} -
-

{{i18n filters.top.this_month}}

- {{basic-topic-list topicList=content.monthly hideCategory=hideCategory postsAction="showTopicEntrance"}} - {{#if content.monthly.topics.length}}{{i18n show_more}}{{/if}} -
- {{/if}} - {{#if content.weekly}} -
-

{{i18n filters.top.this_week}}

- {{basic-topic-list topicList=content.weekly hideCategory=hideCategory postsAction="showTopicEntrance"}} - {{#if content.weekly.topics.length}}{{i18n show_more}}{{/if}} -
- {{/if}} - {{#if content.daily}} -
-

{{i18n filters.top.today}}

- {{basic-topic-list topicList=content.daily hideCategory=hideCategory postsAction="showTopicEntrance"}} - {{#if content.daily.topics.length}}{{i18n show_more}}{{/if}} + {{top-period-chooser period=period}} + {{basic-topic-list topicList=topicList hideCategory=hideCategory postsAction="showTopicEntrance"}} + {{#if topicList.topics.length}}{{i18n show_more}}{{/if}}
{{/if}} + diff --git a/app/assets/javascripts/discourse/templates/discovery/topics.js.handlebars b/app/assets/javascripts/discourse/templates/discovery/topics.js.handlebars index cee89c8b8aa..92e101e158c 100644 --- a/app/assets/javascripts/discourse/templates/discovery/topics.js.handlebars +++ b/app/assets/javascripts/discourse/templates/discovery/topics.js.handlebars @@ -18,10 +18,9 @@
{{#if top}} - {{#if yearly}}

 {{i18n filters.top.this_year}}

{{/if}} - {{#if monthly}}

 {{i18n filters.top.this_month}}

{{/if}} - {{#if weekly}}

 {{i18n filters.top.this_week}}

{{/if}} - {{#if daily}}

 {{i18n filters.top.today}}

{{/if}} +
+ {{top-period-chooser period=period}} +
{{/if}} {{#if showTable}} @@ -101,11 +100,7 @@ {{#if top}}

{{#link-to "discovery.categories"}}{{i18n topic.browse_all_categories}}{{/link-to}}, {{#link-to 'discovery.latest'}}{{i18n topic.view_latest_topics}}{{/link-to}} {{i18n or}} {{i18n filters.top.other_periods}} - {{#unless yearly}}{{i18n filters.top.this_year}}{{/unless}} - {{#unless monthly}}{{i18n filters.top.this_month}}{{/unless}} - {{#unless weekly}}{{i18n filters.top.this_week}}{{/unless}} - {{#unless daily}}{{i18n filters.top.today}}{{/unless}} -

+ {{top-period-buttons period=period}} {{else}} {{{footerEducation}}}

diff --git a/app/assets/javascripts/discourse/templates/mobile/discovery/topics.js.handlebars b/app/assets/javascripts/discourse/templates/mobile/discovery/topics.js.handlebars index 9864db826f5..7a89824ff22 100644 --- a/app/assets/javascripts/discourse/templates/mobile/discovery/topics.js.handlebars +++ b/app/assets/javascripts/discourse/templates/mobile/discovery/topics.js.handlebars @@ -1,10 +1,9 @@
{{#if showTable}} {{#if top}} - {{#if yearly}}

 {{i18n filters.top.this_year}}

{{/if}} - {{#if monthly}}

 {{i18n filters.top.this_month}}

{{/if}} - {{#if weekly}}

 {{i18n filters.top.this_week}}

{{/if}} - {{#if daily}}

 {{i18n filters.top.today}}

{{/if}} +
+ {{top-period-chooser period=period}} +
{{/if}}

{{#if topicTrackingState.hasIncoming}} @@ -47,10 +46,7 @@ {{#if top}}

{{#link-to "discovery.categories"}}{{i18n topic.browse_all_categories}}{{/link-to}}, {{#link-to 'discovery.latest'}}{{i18n topic.view_latest_topics}}{{/link-to}} {{i18n or}} {{i18n filters.top.other_periods}} - {{#unless yearly}}{{i18n filters.top.this_year}}{{/unless}} - {{#unless monthly}}{{i18n filters.top.this_month}}{{/unless}} - {{#unless weekly}}{{i18n filters.top.this_week}}{{/unless}} - {{#unless daily}}{{i18n filters.top.today}}{{/unless}} + {{top-period-buttons period=period}}

{{else}} {{{footerEducation}}} diff --git a/app/assets/javascripts/discourse/views/poster-expansion.js.es6 b/app/assets/javascripts/discourse/views/poster-expansion.js.es6 index e337e5c2e1b..ed94388914d 100644 --- a/app/assets/javascripts/discourse/views/poster-expansion.js.es6 +++ b/app/assets/javascripts/discourse/views/poster-expansion.js.es6 @@ -1,13 +1,14 @@ +import CleansUp from 'discourse/mixins/cleans-up'; + var clickOutsideEventName = "mousedown.outside-poster-expansion"; -export default Discourse.View.extend({ +export default Discourse.View.extend(CleansUp, { elementId: 'poster-expansion', classNameBindings: ['controller.visible::hidden', 'controller.showBadges'], _setup: function() { var self = this; this.appEvents.on('poster:expand', this, '_posterExpand'); - this.appEvents.on('dom:clean', this, '_cleanUp'); $('html').off(clickOutsideEventName).on(clickOutsideEventName, function(e) { if (self.get('controller.visible')) { @@ -43,14 +44,13 @@ export default Discourse.View.extend({ }); }, - _cleanUp: function() { + cleanUp: function() { this.get('controller').close(); }, _removeEvents: function() { $('html').off(clickOutsideEventName); this.appEvents.off('poster:expand', this, '_posterExpand'); - this.appEvents.off('dom:clean', this, '_cleanUp'); }.on('willDestroyElement') }); diff --git a/app/assets/javascripts/discourse/views/topic-entrance.js.es6 b/app/assets/javascripts/discourse/views/topic-entrance.js.es6 index 3ec95e2f140..76140158adf 100644 --- a/app/assets/javascripts/discourse/views/topic-entrance.js.es6 +++ b/app/assets/javascripts/discourse/views/topic-entrance.js.es6 @@ -1,3 +1,5 @@ +import CleansUp from 'discourse/mixins/cleans-up'; + export default Ember.View.extend({ elementId: 'topic-entrance', classNameBindings: ['visible::hidden'], @@ -29,27 +31,22 @@ export default Ember.View.extend({ if (($target.prop('id') === 'topic-entrance') || ($self.has($target).length !== 0)) { return; } - self._cleanUp(); + self.cleanUp(); }); }.observes('controller.position'), _removed: function() { $('html').off('mousedown.topic-entrance'); - this.appEvents.off('dom:clean', this, '_cleanUp'); }.on('willDestroyElement'), - _cleanUp: function() { + cleanUp: function() { this.set('controller.model', null); $('html').off('mousedown.topic-entrance'); }, - _wireClean: function() { - this.appEvents.on('dom:clean', this, '_cleanUp'); - }.on('didInsertElement'), - keyDown: function(e) { if (e.which === 27) { - this._cleanUp(); + this.cleanUp(); } } diff --git a/app/assets/javascripts/main_include.js b/app/assets/javascripts/main_include.js index 8c7ee2da76d..4154db67e2f 100644 --- a/app/assets/javascripts/main_include.js +++ b/app/assets/javascripts/main_include.js @@ -19,6 +19,7 @@ //= require ./discourse/models/user_action //= require ./discourse/models/composer //= require ./discourse/models/topic +//= require ./discourse/models/top-period //= require ./discourse/controllers/controller //= require ./discourse/controllers/discovery-sortable //= require ./discourse/controllers/object @@ -34,6 +35,7 @@ //= require ./discourse/routes/discourse_route //= require ./discourse/routes/build-topic-route //= require ./discourse/routes/discourse_restricted_user_route +//= require ./discourse/components/top-title //= require ./discourse/components/text-field //= require ./discourse/helpers/user-avatar //= require ./discourse/helpers/cold-age-class diff --git a/app/assets/stylesheets/common/base/_topic-list.scss b/app/assets/stylesheets/common/base/_topic-list.scss index 4649d7f95c7..2493d54812d 100644 --- a/app/assets/stylesheets/common/base/_topic-list.scss +++ b/app/assets/stylesheets/common/base/_topic-list.scss @@ -260,3 +260,48 @@ ol.category-breadcrumb { .topic-statuses .fa { padding-right: 3px; } + +.period-chooser { + h2 { + float: left; + } + + button { + outline: 0; + background: transparent; + border: 0; + font-size: 20px; + padding: 5px 10px 0 10px; + } + + #period-popup { + border: 1px solid scale-color-diff(); + padding: 5px; + background: $secondary; + position: absolute; + z-index: 1110; + @include box-shadow(0 2px 2px rgba(0,0,0, .4)); + + ul { + list-style: none; + margin: 0; + padding: 0; + + li { + margin: 0; + padding: 0; + a { + display: block; + padding: 5px; + } + &:hover { + background-color: dark-light-diff($highlight, $secondary, 50%, -70%); + } + } + } + } +} + +.top-title-buttons { + display: inline; +} diff --git a/app/assets/stylesheets/mobile/topic-list.scss b/app/assets/stylesheets/mobile/topic-list.scss index 616c94c68db..8de4ffad9ab 100644 --- a/app/assets/stylesheets/mobile/topic-list.scss +++ b/app/assets/stylesheets/mobile/topic-list.scss @@ -296,3 +296,9 @@ ol.category-breadcrumb { max-width: 100%; padding: 8px 0; } + +.period-chooser { + button { + margin-top: 10px; + } +} diff --git a/app/controllers/list_controller.rb b/app/controllers/list_controller.rb index 18ec8d64d4a..1e50370eda5 100644 --- a/app/controllers/list_controller.rb +++ b/app/controllers/list_controller.rb @@ -317,11 +317,7 @@ class ListController < ApplicationController options[:per_page] = SiteSetting.topics_per_period_in_top_summary topic_query = TopicQuery.new(current_user, options) - if current_user.present? - periods = [ListController.best_period_for(current_user.previous_visit_at, options[:category])] - else - periods = TopTopic.periods - end + periods = [ListController.best_period_for(current_user.try(:previous_visit_at), options[:category])] periods.each { |period| top.send("#{period}=", topic_query.list_top_for(period)) }