diff --git a/app/assets/javascripts/admin/mixins/setting-component.js.es6 b/app/assets/javascripts/admin/mixins/setting-component.js.es6 index bd731758991..6da9f010da8 100644 --- a/app/assets/javascripts/admin/mixins/setting-component.js.es6 +++ b/app/assets/javascripts/admin/mixins/setting-component.js.es6 @@ -125,7 +125,6 @@ export default Mixin.create({ "default_email_messages_level", "default_email_mailing_list_mode", "default_email_mailing_list_mode_frequency", - "disable_mailing_list_mode", "default_email_previous_replies", "default_email_in_reply_to", "default_other_new_topic_duration_minutes", @@ -151,19 +150,31 @@ export default Mixin.create({ const key = this.buffered.get("setting"); if (defaultUserPreferences.includes(key)) { - ajax("/about.json").then(result => { - const controller = showModal("site-setting-default-categories", { - model: { - count: result.about.stats.user_count, - key: key.replace(/_/g, " ") - }, - admin: true - }); + const data = {}; + data[key] = this.buffered.get("value"); - controller.set("onClose", () => { - this.updateExistingUsers = controller.updateExistingUsers; + ajax(`/admin/site_settings/${key}/user_count.json`, { + type: "PUT", + data + }).then(result => { + const count = result.user_count; + + if (count > 0) { + const controller = showModal("site-setting-default-categories", { + model: { + count: result.user_count, + key: key.replace(/_/g, " ") + }, + admin: true + }); + + controller.set("onClose", () => { + this.updateExistingUsers = controller.updateExistingUsers; + this.send("save"); + }); + } else { this.send("save"); - }); + } }); } else { this.send("save"); diff --git a/app/controllers/admin/site_settings_controller.rb b/app/controllers/admin/site_settings_controller.rb index 689b7bdc437..385a4facf62 100644 --- a/app/controllers/admin/site_settings_controller.rb +++ b/app/controllers/admin/site_settings_controller.rb @@ -26,28 +26,6 @@ class Admin::SiteSettingsController < Admin::AdminController SiteSetting.set_and_log(id, value, current_user) if update_existing_users - user_options = { - default_email_mailing_list_mode: "mailing_list_mode", - default_email_mailing_list_mode_frequency: "mailing_list_mode_frequency", - default_email_level: "email_level", - default_email_messages_level: "email_messages_level", - default_topics_automatic_unpin: "automatically_unpin_topics", - default_email_previous_replies: "email_previous_replies", - default_email_in_reply_to: "email_in_reply_to", - default_other_enable_quoting: "enable_quoting", - default_other_enable_defer: "enable_defer", - default_other_external_links_in_new_tab: "external_links_in_new_tab", - default_other_dynamic_favicon: "dynamic_favicon", - default_other_new_topic_duration_minutes: "new_topic_duration_minutes", - default_other_auto_track_topics_after_msecs: "auto_track_topics_after_msecs", - default_other_notification_level_when_replying: "notification_level_when_replying", - default_other_like_notification_frequency: "like_notification_frequency", - default_email_digest_frequency: "digest_after_minutes", - default_include_tl0_in_digests: "include_tl0_in_digests", - default_text_size: "text_size_key", - default_title_count_mode: "title_count_mode_key" - } - new_value = value || "" if (user_option = user_options[id.to_sym]).present? @@ -128,8 +106,103 @@ class Admin::SiteSettingsController < Admin::AdminController render body: nil end + def user_count + params.require(:site_setting_id) + id = params[:site_setting_id] + raise Discourse::NotFound unless id.start_with?("default_") + new_value = params[id] || "" + + raise_access_hidden_setting(id) + previous_value = SiteSetting.send(id) || "" + json = {} + + if (user_option = user_options[id.to_sym]).present? + if user_option == "text_size_key" + previous_value = UserOption.text_sizes[previous_value.to_sym] + elsif user_option == "title_count_mode_key" + previous_value = UserOption.title_count_modes[previous_value.to_sym] + end + + json[:user_count] = UserOption.where(user_option => previous_value).count + elsif id.start_with?("default_categories_") + previous_category_ids = previous_value.split("|") + new_category_ids = new_value.split("|") + + case id + when "default_categories_watching" + notification_level = NotificationLevels.all[:watching] + when "default_categories_tracking" + notification_level = NotificationLevels.all[:tracking] + when "default_categories_muted" + notification_level = NotificationLevels.all[:muted] + when "default_categories_watching_first_post" + notification_level = NotificationLevels.all[:watching_first_post] + end + + user_ids = CategoryUser.where(category_id: previous_category_ids - new_category_ids, notification_level: notification_level).distinct.pluck(:user_id) + user_ids += User + .joins("CROSS JOIN categories c") + .joins("LEFT JOIN category_users cu ON users.id = cu.user_id AND c.id = cu.category_id") + .where("c.id IN (?) AND cu.notification_level IS NULL", new_category_ids - previous_category_ids) + .distinct + .pluck("users.id") + + json[:user_count] = user_ids.uniq.count + 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) + + case id + when "default_tags_watching" + notification_level = TagUser.notification_levels[:watching] + when "default_tags_tracking" + notification_level = TagUser.notification_levels[:tracking] + when "default_tags_muted" + notification_level = TagUser.notification_levels[:muted] + when "default_tags_watching_first_post" + notification_level = TagUser.notification_levels[:watching_first_post] + end + + user_ids = TagUser.where(tag_id: previous_tag_ids - new_tag_ids, notification_level: notification_level).distinct.pluck(:user_id) + user_ids += User + .joins("CROSS JOIN tags t") + .joins("LEFT JOIN tag_users tu ON users.id = tu.user_id AND t.id = tu.tag_id") + .where("t.id IN (?) AND tu.notification_level IS NULL", new_tag_ids - previous_tag_ids) + .distinct + .pluck("users.id") + + json[:user_count] = user_ids.uniq.count + end + + render json: json + end + private + def user_options + { + default_email_mailing_list_mode: "mailing_list_mode", + default_email_mailing_list_mode_frequency: "mailing_list_mode_frequency", + default_email_level: "email_level", + default_email_messages_level: "email_messages_level", + default_topics_automatic_unpin: "automatically_unpin_topics", + default_email_previous_replies: "email_previous_replies", + default_email_in_reply_to: "email_in_reply_to", + default_other_enable_quoting: "enable_quoting", + default_other_enable_defer: "enable_defer", + default_other_external_links_in_new_tab: "external_links_in_new_tab", + default_other_dynamic_favicon: "dynamic_favicon", + default_other_new_topic_duration_minutes: "new_topic_duration_minutes", + default_other_auto_track_topics_after_msecs: "auto_track_topics_after_msecs", + default_other_notification_level_when_replying: "notification_level_when_replying", + default_other_like_notification_frequency: "like_notification_frequency", + default_email_digest_frequency: "digest_after_minutes", + default_include_tl0_in_digests: "include_tl0_in_digests", + default_text_size: "text_size_key", + default_title_count_mode: "title_count_mode_key" + } + end + def raise_access_hidden_setting(id) # note, as of Ruby 2.3 symbols are GC'd so this is considered safe if SiteSetting.hidden_settings.include?(id.to_sym) diff --git a/config/routes.rb b/config/routes.rb index 8fb57fab5e6..af088105b7a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -74,6 +74,8 @@ Discourse::Application.routes.draw do collection do get "category/:id" => "site_settings#index" end + + put "user_count" => "site_settings#user_count" end get "reports" => "reports#index" diff --git a/spec/requests/admin/site_settings_controller_spec.rb b/spec/requests/admin/site_settings_controller_spec.rb index 166df37b40c..9e21a2d37e2 100644 --- a/spec/requests/admin/site_settings_controller_spec.rb +++ b/spec/requests/admin/site_settings_controller_spec.rb @@ -163,6 +163,51 @@ describe Admin::SiteSettingsController do end end + describe '#user_count' do + let(:user) { Fabricate(:user) } + let(:tracking) { NotificationLevels.all[:tracking] } + + it 'should return correct user count for default categories change' do + category_id = Fabricate(:category).id + + put "/admin/site_settings/default_categories_watching/user_count.json", params: { + default_categories_watching: category_id + } + + expect(JSON.parse(response.body)["user_count"]).to eq(User.count) + + CategoryUser.create!(category_id: category_id, notification_level: tracking, user: user) + + put "/admin/site_settings/default_categories_watching/user_count.json", params: { + default_categories_watching: category_id + } + + expect(JSON.parse(response.body)["user_count"]).to eq(User.count - 1) + + SiteSetting.setting(:default_categories_watching, "") + end + + it 'should return correct user count for default tags change' do + tag = Fabricate(:tag) + + put "/admin/site_settings/default_tags_watching/user_count.json", params: { + default_tags_watching: tag.name + } + + expect(JSON.parse(response.body)["user_count"]).to eq(User.count) + + TagUser.create!(tag_id: tag.id, notification_level: tracking, user: user) + + put "/admin/site_settings/default_tags_watching/user_count.json", params: { + default_tags_watching: tag.name + } + + expect(JSON.parse(response.body)["user_count"]).to eq(User.count - 1) + + SiteSetting.setting(:default_tags_watching, "") + end + end + describe 'upload site settings' do it 'can remove the site setting' do SiteSetting.test_upload = Fabricate(:upload)