From 72aa26c8c55b75e16fc11c32bc728f510f7c200d Mon Sep 17 00:00:00 2001 From: Vinoth Kannan Date: Fri, 1 Nov 2019 12:40:13 +0530 Subject: [PATCH] FEATURE: New site settings for default tags in user preferences. (#8283) --- .../admin/components/site-setting.js.es6 | 4 ++ .../components/site-settings/tag-list.js.es6 | 15 ++++++ .../admin/mixins/setting-component.js.es6 | 3 +- .../components/site-settings/tag-list.hbs | 3 ++ .../admin/site_settings_controller.rb | 29 ++++++++++- app/models/user.rb | 18 +++++++ config/locales/server.en.yml | 6 +++ config/site_settings.yml | 13 +++++ lib/site_settings/type_supervisor.rb | 1 + lib/site_settings/validations.rb | 52 +++++++++++++++++++ spec/models/user_spec.rb | 10 ++++ .../admin/site_settings_controller_spec.rb | 38 ++++++++++++++ 12 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 app/assets/javascripts/admin/components/site-settings/tag-list.js.es6 create mode 100644 app/assets/javascripts/admin/templates/components/site-settings/tag-list.hbs diff --git a/app/assets/javascripts/admin/components/site-setting.js.es6 b/app/assets/javascripts/admin/components/site-setting.js.es6 index 0289f4cdf4d..90c886c3a65 100644 --- a/app/assets/javascripts/admin/components/site-setting.js.es6 +++ b/app/assets/javascripts/admin/components/site-setting.js.es6 @@ -40,6 +40,10 @@ export default Component.extend(BufferedContent, SettingComponent, { "default_categories_tracking", "default_categories_muted", "default_categories_watching_first_post", + "default_tags_watching", + "default_tags_tracking", + "default_tags_muted", + "default_tags_watching_first_post", "default_text_size", "default_title_count_mode" ]; diff --git a/app/assets/javascripts/admin/components/site-settings/tag-list.js.es6 b/app/assets/javascripts/admin/components/site-settings/tag-list.js.es6 new file mode 100644 index 00000000000..417ad622cb8 --- /dev/null +++ b/app/assets/javascripts/admin/components/site-settings/tag-list.js.es6 @@ -0,0 +1,15 @@ +import Component from "@ember/component"; +import computed from "ember-addons/ember-computed-decorators"; + +export default Component.extend({ + @computed("value") + selectedTags: { + get(value) { + return value.split("|"); + }, + set(value) { + this.set("value", value.join("|")); + return value; + } + } +}); diff --git a/app/assets/javascripts/admin/mixins/setting-component.js.es6 b/app/assets/javascripts/admin/mixins/setting-component.js.es6 index 409c1b33595..3a7ab2e2c46 100644 --- a/app/assets/javascripts/admin/mixins/setting-component.js.es6 +++ b/app/assets/javascripts/admin/mixins/setting-component.js.es6 @@ -17,7 +17,8 @@ const CUSTOM_TYPES = [ "compact_list", "secret_list", "upload", - "group_list" + "group_list", + "tag_list" ]; const AUTO_REFRESH_ON_SAVE = ["logo", "logo_small", "large_icon"]; diff --git a/app/assets/javascripts/admin/templates/components/site-settings/tag-list.hbs b/app/assets/javascripts/admin/templates/components/site-settings/tag-list.hbs new file mode 100644 index 00000000000..84c6623cfbb --- /dev/null +++ b/app/assets/javascripts/admin/templates/components/site-settings/tag-list.hbs @@ -0,0 +1,3 @@ +{{tag-chooser tags=selectedTags}} +
{{{unbound setting.description}}}
+{{setting-validation-message message=validationMessage}} diff --git a/app/controllers/admin/site_settings_controller.rb b/app/controllers/admin/site_settings_controller.rb index fdc6179187c..689b7bdc437 100644 --- a/app/controllers/admin/site_settings_controller.rb +++ b/app/controllers/admin/site_settings_controller.rb @@ -92,8 +92,35 @@ class Admin::SiteSettingsController < Admin::AdminController users.each { |user| category_users << { category_id: category_id, user_id: user.id, notification_level: notification_level } } CategoryUser.insert_all!(category_users) end + end + elsif id.start_with?("default_tags_") + previous_tag_ids = Tag.where(name: previous_value.split("|")).pluck(:id) + new_tag_ids = Tag.where(name: new_value.split("|")).pluck(:id) + now = Time.zone.now - CategoryUser.where(category_id: category_id, notification_level: notification_level).first_or_create!(notification_level: notification_level) + case id + when "default_tags_watching" + notification_level = NotificationLevels.all[:watching] + when "default_tags_tracking" + notification_level = NotificationLevels.all[:tracking] + when "default_tags_muted" + notification_level = NotificationLevels.all[:muted] + when "default_tags_watching_first_post" + notification_level = NotificationLevels.all[:watching_first_post] + end + + (previous_tag_ids - new_tag_ids).each do |tag_id| + TagUser.where(tag_id: tag_id, notification_level: notification_level).delete_all + end + + (new_tag_ids - previous_tag_ids).each do |tag_id| + skip_user_ids = TagUser.where(tag_id: tag_id).pluck(:user_id) + + User.where.not(id: skip_user_ids).select(:id).find_in_batches do |users| + tag_users = [] + users.each { |user| tag_users << { tag_id: tag_id, user_id: user.id, notification_level: notification_level, created_at: now, updated_at: now } } + TagUser.insert_all!(tag_users) + end end end end diff --git a/app/models/user.rb b/app/models/user.rb index 0249ca5d0fa..aa5ac937a02 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -117,6 +117,7 @@ class User < ActiveRecord::Base after_create :set_random_avatar after_create :ensure_in_trust_level_group after_create :set_default_categories_preferences + after_create :set_default_tags_preferences after_update :trigger_user_updated_event, if: :saved_change_to_uploaded_avatar_id? after_update :trigger_user_automatic_group_refresh, if: :saved_change_to_staged? @@ -1419,6 +1420,23 @@ class User < ActiveRecord::Base end end + def set_default_tags_preferences + return if self.staged? + + values = [] + + %w{watching watching_first_post tracking muted}.each do |s| + tag_names = SiteSetting.get("default_tags_#{s}").split("|") + now = Time.zone.now + + Tag.where(name: tag_names).pluck(:id).each do |tag_id| + values << { user_id: self.id, tag_id: tag_id, notification_level: TagUser.notification_levels[s.to_sym], created_at: now, updated_at: now } + end + end + + TagUser.insert_all!(values) if values.present? + end + def self.purge_unactivated return [] if SiteSetting.purge_unactivated_users_grace_period_days <= 0 diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index b0aa5591066..c7e926513aa 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -198,6 +198,7 @@ en: one: "You specified the invalid choice %{name}" other: "You specified the invalid choices %{name}" default_categories_already_selected: "You cannot select a category used in another list." + default_tags_already_selected: "You cannot select a tag used in another list." s3_upload_bucket_is_required: "You cannot enable uploads to S3 unless you've provided the 's3_upload_bucket'." enable_s3_uploads_is_required: "You cannot enable inventory to S3 unless you've enabled the S3 uploads." s3_backup_requires_s3_settings: "You cannot use S3 as backup location unless you've provided the '%{setting_name}'." @@ -2065,6 +2066,11 @@ en: default_categories_muted: "List of categories that are muted by default." default_categories_watching_first_post: "List of categories in which first post in each new topic will be watched by default." + default_tags_watching: "List of tags that are watched by default." + default_tags_tracking: "List of tags that are tracked by default." + default_tags_muted: "List of tags that are muted by default." + default_tags_watching_first_post: "List of tags in which first post in each new topic will be watched by default." + default_text_size: "Text size which is selected by default" default_title_count_mode: "Default mode for the page title counter" diff --git a/config/site_settings.yml b/config/site_settings.yml index e6c1e167704..a70e811b79a 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -2023,6 +2023,19 @@ user_preferences: type: category_list default: "" + default_tags_watching: + type: tag_list + default: "" + default_tags_tracking: + type: tag_list + default: "" + default_tags_muted: + type: tag_list + default: "" + default_tags_watching_first_post: + type: tag_list + default: "" + default_text_size: type: enum default: normal diff --git a/lib/site_settings/type_supervisor.rb b/lib/site_settings/type_supervisor.rb index 0f96b379086..420c64f60be 100644 --- a/lib/site_settings/type_supervisor.rb +++ b/lib/site_settings/type_supervisor.rb @@ -33,6 +33,7 @@ class SiteSettings::TypeSupervisor upload: 18, group: 19, group_list: 20, + tag_list: 21, ) end diff --git a/lib/site_settings/validations.rb b/lib/site_settings/validations.rb index b8323e61213..be622022c7b 100644 --- a/lib/site_settings/validations.rb +++ b/lib/site_settings/validations.rb @@ -65,6 +65,58 @@ module SiteSettings::Validations validate_default_categories(category_ids, default_categories_selected) end + def validate_default_tags(tag_names, default_tags_selected) + validate_error :default_tags_already_selected if (tag_names & default_tags_selected).size > 0 + end + + def validate_default_tags_watching(new_val) + tag_names = new_val.split('|').to_set + + default_tags_selected = [ + SiteSetting.default_tags_tracking.split("|"), + SiteSetting.default_tags_muted.split("|"), + SiteSetting.default_tags_watching_first_post.split("|") + ].flatten.to_set + + validate_default_tags(tag_names, default_tags_selected) + end + + def validate_default_tags_tracking(new_val) + tag_names = new_val.split('|').to_set + + default_tags_selected = [ + SiteSetting.default_tags_watching.split("|"), + SiteSetting.default_tags_muted.split("|"), + SiteSetting.default_tags_watching_first_post.split("|") + ].flatten.to_set + + validate_default_tags(tag_names, default_tags_selected) + end + + def validate_default_tags_muted(new_val) + tag_names = new_val.split('|').to_set + + default_tags_selected = [ + SiteSetting.default_tags_watching.split("|"), + SiteSetting.default_tags_tracking.split("|"), + SiteSetting.default_tags_watching_first_post.split("|") + ].flatten.to_set + + validate_default_tags(tag_names, default_tags_selected) + end + + def validate_default_tags_watching_first_post(new_val) + tag_names = new_val.split('|').to_set + + default_tags_selected = [ + SiteSetting.default_tags_watching.split("|"), + SiteSetting.default_tags_tracking.split("|"), + SiteSetting.default_tags_muted.split("|") + ].flatten.to_set + + validate_default_tags(tag_names, default_tags_selected) + end + def validate_enable_s3_uploads(new_val) validate_error :s3_upload_bucket_is_required if new_val == "t" && SiteSetting.s3_upload_bucket.blank? end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 8055ad48a0e..567f94f6df8 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -159,6 +159,16 @@ describe User do end end + context '.set_default_tags_preferences' do + let(:tag) { Fabricate(:tag) } + + it "should set default tag preferences when new user created" do + SiteSetting.default_tags_watching = tag.name + user = Fabricate(:user) + expect(TagUser.exists?(tag_id: tag.id, user_id: user.id, notification_level: TagUser.notification_levels[:watching])).to be_truthy + end + end + describe 'reviewable' do let(:user) { Fabricate(:user, active: false) } fab!(:admin) { Fabricate(:admin) } diff --git a/spec/requests/admin/site_settings_controller_spec.rb b/spec/requests/admin/site_settings_controller_spec.rb index 7e035d7b7ae..166df37b40c 100644 --- a/spec/requests/admin/site_settings_controller_spec.rb +++ b/spec/requests/admin/site_settings_controller_spec.rb @@ -125,6 +125,44 @@ describe Admin::SiteSettingsController do end end + describe 'default tags' do + let(:user1) { Fabricate(:user) } + let(:user2) { Fabricate(:user) } + let(:watching) { NotificationLevels.all[:watching] } + let(:tracking) { NotificationLevels.all[:tracking] } + + let(:tags) { 3.times.collect { Fabricate(:tag) } } + + before do + SiteSetting.setting(:default_tags_watching, tags.first(2).pluck(:name).join("|")) + TagUser.create!(tag_id: tags.last.id, notification_level: tracking, user: user2) + end + + after do + SiteSetting.setting(:default_tags_watching, "") + end + + it 'should update existing users user preference' do + put "/admin/site_settings/default_tags_watching.json", params: { + default_tags_watching: tags.last(2).pluck(:name).join("|"), + updateExistingUsers: true + } + + expect(TagUser.where(tag_id: tags.first.id, notification_level: watching).count).to eq(0) + expect(TagUser.where(tag_id: tags.last.id, notification_level: watching).count).to eq(User.count - 1) + end + + it 'should not update existing users user preference' do + expect { + put "/admin/site_settings/default_tags_watching.json", params: { + default_tags_watching: tags.last(2).pluck(:name).join("|") + } + }.to change { TagUser.where(tag_id: tags.first.id, notification_level: watching).count }.by(0) + + expect(TagUser.where(tag_id: tags.last.id, notification_level: watching).count).to eq(0) + end + end + describe 'upload site settings' do it 'can remove the site setting' do SiteSetting.test_upload = Fabricate(:upload)