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)