diff --git a/app/assets/javascripts/discourse/models/category.js.es6 b/app/assets/javascripts/discourse/models/category.js.es6 index 906d4e8fdf2..01e281c62b0 100644 --- a/app/assets/javascripts/discourse/models/category.js.es6 +++ b/app/assets/javascripts/discourse/models/category.js.es6 @@ -198,76 +198,71 @@ var _uncategorized; Category.reopenClass({ - findUncategorized: function() { + findUncategorized() { _uncategorized = _uncategorized || Category.list().findBy('id', Discourse.Site.currentProp('uncategorized_category_id')); return _uncategorized; }, - slugFor: function(category) { + slugFor(category) { if (!category) return ""; - var parentCategory = Em.get(category, 'parentCategory'), - result = ""; + const parentCategory = Em.get(category, 'parentCategory'); + let result = ""; if (parentCategory) { result = Category.slugFor(parentCategory) + "/"; } - var id = Em.get(category, 'id'), - slug = Em.get(category, 'slug'); + const id = Em.get(category, 'id'), + slug = Em.get(category, 'slug'); - if (!slug || slug.trim().length === 0) return result + id + "-category"; - return result + slug; + return !slug || slug.trim().length === 0 ? `${result}${id}-category` : result + slug; }, - list: function() { - if (Discourse.SiteSettings.fixed_category_positions) { - return Discourse.Site.currentProp('categories'); - } else { - return Discourse.Site.currentProp('sortedCategories'); - } + list() { + return Discourse.SiteSettings.fixed_category_positions ? + Discourse.Site.currentProp('categories') : + Discourse.Site.currentProp('sortedCategories'); }, - listByActivity: function() { + listByActivity() { return Discourse.Site.currentProp('sortedCategories'); }, - idMap: function() { + idMap() { return Discourse.Site.currentProp('categoriesById'); }, - findSingleBySlug: function(slug) { - return Category.list().find(function(c) { - return Category.slugFor(c) === slug; - }); + findSingleBySlug(slug) { + return Category.list().find(c => Category.slugFor(c) === slug); }, - findById: function(id) { + findById(id) { if (!id) { return; } return Category.idMap()[id]; }, - findByIds: function(ids){ - var categories = []; - _.each(ids, function(id){ - var found = Category.findById(id); - if(found){ + findByIds(ids) { + const categories = []; + _.each(ids, id => { + const found = Category.findById(id); + if (found) { categories.push(found); } }); return categories; }, - findBySlug: function(slug, parentSlug) { - var categories = Category.list(), - category; + findBySlug(slug, parentSlug) { + const categories = Category.list(); + let category; if (parentSlug) { - var parentCategory = Category.findSingleBySlug(parentSlug); + const parentCategory = Category.findSingleBySlug(parentSlug); if (parentCategory) { if (slug === 'none') { return parentCategory; } - category = categories.find(function(item) { + category = categories.find(item => { return item && item.get('parentCategory') === parentCategory && Category.slugFor(item) === (parentSlug + "/" + slug); }); } @@ -287,7 +282,7 @@ Category.reopenClass({ }, reloadById(id) { - return Discourse.ajax("/c/" + id + "/show.json"); + return Discourse.ajax(`/c/${id}/show.json`); } }); diff --git a/app/assets/javascripts/discourse/models/site.js.es6 b/app/assets/javascripts/discourse/models/site.js.es6 index deddc23d3ca..988ba1eac7a 100644 --- a/app/assets/javascripts/discourse/models/site.js.es6 +++ b/app/assets/javascripts/discourse/models/site.js.es6 @@ -1,3 +1,4 @@ +import computed from "ember-addons/ember-computed-decorators"; import Archetype from 'discourse/models/archetype'; import PostActionType from 'discourse/models/post-action-type'; import Singleton from 'discourse/mixins/singleton'; @@ -7,30 +8,30 @@ const Site = RestModel.extend({ isReadOnly: Em.computed.alias('is_readonly'), - notificationLookup: function() { + @computed("notification_types") + notificationLookup(notificationTypes) { const result = []; - _.each(this.get('notification_types'), function(v,k) { - result[v] = k; - }); + _.each(notificationTypes, (v, k) => result[v] = k); return result; - }.property('notification_types'), + }, - flagTypes: function() { + @computed("post_action_types.@each") + flagTypes() { const postActionTypes = this.get('post_action_types'); if (!postActionTypes) return []; return postActionTypes.filterProperty('is_flag', true); - }.property('post_action_types.@each'), + }, topicCountDesc: ['topic_count:desc'], categoriesByCount: Ember.computed.sort('categories', 'topicCountDesc'), // Sort subcategories under parents - sortedCategories: function() { - const cats = this.get('categoriesByCount'), - result = [], - remaining = {}; + @computed("categoriesByCount", "categories.@each") + sortedCategories(cats) { + const result = [], + remaining = {}; - cats.forEach(function(c) { + cats.forEach(c => { const parentCategoryId = parseInt(c.get('parent_category_id'), 10); if (!parentCategoryId) { result.pushObject(c); @@ -40,17 +41,17 @@ const Site = RestModel.extend({ } }); - Ember.keys(remaining).forEach(function(parentCategoryId) { + Ember.keys(remaining).forEach(parentCategoryId => { const category = result.findBy('id', parseInt(parentCategoryId, 10)), - index = result.indexOf(category); + index = result.indexOf(category); if (index !== -1) { - result.replace(index+1, 0, remaining[parentCategoryId]); + result.replace(index + 1, 0, remaining[parentCategoryId]); } }); return result; - }.property("categories.@each"), + }, postActionTypeById(id) { return this.get("postActionByIdLookup.action" + id); @@ -98,16 +99,14 @@ Site.reopenClass(Singleton, { create() { const result = this._super.apply(this, arguments); - const store = result.store; + if (result.categories) { result.categoriesById = {}; - result.categories = _.map(result.categories, function(c) { - return result.categoriesById[c.id] = store.createRecord('category', c); - }); + result.categories = _.map(result.categories, c => result.categoriesById[c.id] = store.createRecord('category', c)); // Associate the categories with their parents - result.categories.forEach(function (c) { + result.categories.forEach(c => { if (c.get('parent_category_id')) { c.set('parentCategory', result.categoriesById[c.get('parent_category_id')]); } @@ -115,16 +114,13 @@ Site.reopenClass(Singleton, { } if (result.trust_levels) { - result.trustLevels = result.trust_levels.map(function (tl) { - return Discourse.TrustLevel.create(tl); - }); - + result.trustLevels = result.trust_levels.map(tl => Discourse.TrustLevel.create(tl)); delete result.trust_levels; } if (result.post_action_types) { result.postActionByIdLookup = Em.Object.create(); - result.post_action_types = _.map(result.post_action_types,function(p) { + result.post_action_types = _.map(result.post_action_types, p => { const actionType = PostActionType.create(p); result.postActionByIdLookup.set("action" + p.id, actionType); return actionType; @@ -133,7 +129,7 @@ Site.reopenClass(Singleton, { if (result.topic_flag_types) { result.topicFlagByIdLookup = Em.Object.create(); - result.topic_flag_types = _.map(result.topic_flag_types,function(p) { + result.topic_flag_types = _.map(result.topic_flag_types, p => { const actionType = PostActionType.create(p); result.topicFlagByIdLookup.set("action" + p.id, actionType); return actionType; @@ -141,16 +137,14 @@ Site.reopenClass(Singleton, { } if (result.archetypes) { - result.archetypes = _.map(result.archetypes,function(a) { + result.archetypes = _.map(result.archetypes, a => { a.site = result; return Archetype.create(a); }); } if (result.user_fields) { - result.user_fields = result.user_fields.map(function(uf) { - return Ember.Object.create(uf); - }); + result.user_fields = result.user_fields.map(uf => Ember.Object.create(uf)); } return result; 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 1921552850e..58f945ac969 100644 --- a/app/assets/javascripts/discourse/routes/build-category-route.js.es6 +++ b/app/assets/javascripts/discourse/routes/build-category-route.js.es6 @@ -1,15 +1,15 @@ import { queryParams, filterQueryParams, findTopicList } from 'discourse/routes/build-topic-route'; // A helper function to create a category route with parameters -export default function(filter, params) { +export default (filter, params) => { return Discourse.Route.extend({ queryParams: queryParams, - model: function(modelParams) { + model(modelParams) { return Discourse.Category.findBySlug(modelParams.slug, modelParams.parentSlug); }, - afterModel: function(model, transition) { + afterModel(model, transition) { if (!model) { this.replaceWith('/404'); return; @@ -20,9 +20,9 @@ export default function(filter, params) { this._retrieveTopicList(model, transition)]); }, - _setupNavigation: function(model) { - var noSubcategories = params && !!params.no_subcategories, - filterMode = "c/" + Discourse.Category.slugFor(model) + (noSubcategories ? "/none" : "") + "/l/" + filter; + _setupNavigation(model) { + const noSubcategories = params && !!params.no_subcategories, + filterMode = `c/${Discourse.Category.slugFor(model)}${noSubcategories ? "/none" : ""}/l/${filter}`; this.controllerFor('navigation/category').setProperties({ category: model, @@ -32,42 +32,38 @@ export default function(filter, params) { }); }, - _createSubcategoryList: function(model) { + _createSubcategoryList(model) { this._categoryList = null; if (Em.isNone(model.get('parentCategory')) && Discourse.SiteSettings.show_subcategory_list) { - var self = this; - return Discourse.CategoryList.listForParent(this.store, model).then(function(list) { - self._categoryList = list; - }); + return Discourse.CategoryList.listForParent(this.store, model) + .then(list => this._categoryList = list); } // If we're not loading a subcategory list just resolve return Em.RSVP.resolve(); }, - _retrieveTopicList: function(model, transition) { - var listFilter = "c/" + Discourse.Category.slugFor(model) + "/l/" + filter, - self = this; + _retrieveTopicList(model, transition) { + const listFilter = `c/${Discourse.Category.slugFor(model)}/l/${filter}`, + findOpts = filterQueryParams(transition.queryParams, params), + extras = { cached: this.isPoppedState(transition) }; - var findOpts = filterQueryParams(transition.queryParams, params), - extras = { cached: this.isPoppedState(transition) }; - - return findTopicList(this.store, this.topicTrackingState, listFilter, findOpts, extras).then(function(list) { + return findTopicList(this.store, this.topicTrackingState, listFilter, findOpts, extras).then(list => { Discourse.TopicList.hideUniformCategory(list, model); - self.set('topics', list); + this.set('topics', list); }); }, - titleToken: function() { - var filterText = I18n.t('filters.' + filter.replace('/', '.') + '.title', {count: 0}), - model = this.currentModel; + titleToken() { + const filterText = I18n.t('filters.' + filter.replace('/', '.') + '.title', { count: 0 }), + model = this.currentModel; return I18n.t('filters.with_category', { filter: filterText, category: model.get('name') }); }, - setupController: function(controller, model) { - var topics = this.get('topics'), - periodId = topics.get('for_period') || (filter.indexOf('/') > 0 ? filter.split('/')[1] : ''); + setupController(controller, model) { + const topics = this.get('topics'), + periodId = topics.get('for_period') || (filter.indexOf('/') > 0 ? filter.split('/')[1] : ''); this.controllerFor('navigation/category').set('canCreateTopic', topics.get('can_create_topic')); this.controllerFor('discovery/topics').setProperties({ @@ -87,7 +83,7 @@ export default function(filter, params) { this.openTopicDraft(topics); }, - renderTemplate: function() { + renderTemplate() { this.render('navigation/category', { outlet: 'navigation-bar' }); if (this._categoryList) { @@ -96,13 +92,13 @@ export default function(filter, params) { this.render('discovery/topics', { controller: 'discovery/topics', outlet: 'list-container' }); }, - deactivate: function() { + deactivate() { this._super(); this.searchService.set('searchContext', null); }, actions: { - setNotification: function(notification_level){ + setNotification(notification_level) { this.currentModel.setNotification(notification_level); } } diff --git a/app/assets/javascripts/discourse/routes/discovery-categories.js.es6 b/app/assets/javascripts/discourse/routes/discovery-categories.js.es6 index 47a04ae92a0..072f33e47d7 100644 --- a/app/assets/javascripts/discourse/routes/discovery-categories.js.es6 +++ b/app/assets/javascripts/discourse/routes/discovery-categories.js.es6 @@ -16,7 +16,7 @@ const DiscoveryCategoriesRoute = Discourse.Route.extend(OpenComposer, { // if default page is categories PreloadStore.remove("topic_list"); - return Discourse.CategoryList.list(this.store, 'categories').then((list) => { + return Discourse.CategoryList.list(this.store, 'categories').then(list => { const tracking = this.topicTrackingState; if (tracking) { tracking.sync(list, "categories"); @@ -34,8 +34,10 @@ const DiscoveryCategoriesRoute = Discourse.Route.extend(OpenComposer, { setupController(controller, model) { controller.set("model", model); - this.controllerFor("navigation/categories").set("canCreateCategory", model.get("can_create_category")); - this.controllerFor("navigation/categories").set("canCreateTopic", model.get("can_create_topic")); + this.controllerFor("navigation/categories").setProperties({ + canCreateCategory: model.get("can_create_category"), + canCreateTopic: model.get("can_create_topic"), + }); this.openTopicDraft(model); }, diff --git a/app/models/category_list.rb b/app/models/category_list.rb index 1472a27501f..6f445feaa14 100644 --- a/app/models/category_list.rb +++ b/app/models/category_list.rb @@ -83,9 +83,16 @@ class CategoryList @categories = @categories.to_a + category_user = {} + unless @guardian.anonymous? + category_user = Hash[*CategoryUser.where(user: @guardian.user).pluck(:category_id, :notification_level).flatten] + end + allowed_topic_create = Set.new(Category.topic_create_allowed(@guardian).pluck(:id)) @categories.each do |category| + category.notification_level = category_user[category.id] category.permission = CategoryGroup.permission_types[:full] if allowed_topic_create.include?(category.id) + category.has_children = category.subcategories.present? end if @options[:parent_category_id].blank?