FEATURE: update existing users when group default notifications changed. (#13434)

FEATURE: update existing users when group default notifications changed. (#13434)

Currently, the changes will only affect the users added after.

diff --git a/app/assets/javascripts/admin/addon/controllers/modals/site-setting-default-categories.js b/app/assets/javascripts/admin/addon/controllers/modals/site-setting-default-categories.js
index c46fe08..8c3a264 100644
--- a/app/assets/javascripts/admin/addon/controllers/modals/site-setting-default-categories.js
+++ b/app/assets/javascripts/admin/addon/controllers/modals/site-setting-default-categories.js
@@ -1,20 +1,5 @@
 import Controller from "@ember/controller";
 import ModalFunctionality from "discourse/mixins/modal-functionality";
+import ModalUpdateExistingUsers from "discourse/mixins/modal-update-existing-users";
 
-export default Controller.extend(ModalFunctionality, {
-  onShow() {
-    this.set("updateExistingUsers", null);
-  },
-
-  actions: {
-    updateExistingUsers() {
-      this.set("updateExistingUsers", true);
-      this.send("closeModal");
-    },
-
-    cancel() {
-      this.set("updateExistingUsers", false);
-      this.send("closeModal");
-    },
-  },
-});
+export default Controller.extend(ModalFunctionality, ModalUpdateExistingUsers);
diff --git a/app/assets/javascripts/discourse/app/components/group-manage-save-button.js b/app/assets/javascripts/discourse/app/components/group-manage-save-button.js
index 82cc182..3c7e17d 100644
--- a/app/assets/javascripts/discourse/app/components/group-manage-save-button.js
+++ b/app/assets/javascripts/discourse/app/components/group-manage-save-button.js
@@ -4,10 +4,12 @@ import I18n from "I18n";
 import discourseComputed from "discourse-common/utils/decorators";
 import { popupAjaxError } from "discourse/lib/ajax-error";
 import { popupAutomaticMembershipAlert } from "discourse/controllers/groups-new";
+import showModal from "discourse/lib/show-modal";
 
 export default Component.extend({
   saving: null,
   disabled: false,
+  updateExistingUsers: null,
 
   @discourseComputed("saving")
   savingText(saving) {
@@ -28,14 +30,37 @@ export default Component.extend({
         group.automatic_membership_email_domains
       );
 
+      const opts = {};
+      if (this.updateExistingUsers !== null) {
+        opts.update_existing_users = this.updateExistingUsers;
+      }
+
       return group
-        .save()
+        .save(opts)
         .then((data) => {
+          if (data.user_count) {
+            const controller = showModal("group-default-notifications", {
+              model: {
+                count: data.user_count,
+              },
+            });
+
+            controller.set("onClose", () => {
+              this.updateExistingUsers = controller.updateExistingUsers;
+              this.send("save");
+            });
+
+            return;
+          }
+
           if (data.route_to) {
             DiscourseURL.routeTo(data.route_to);
           }
 
-          this.set("saved", true);
+          this.setProperties({
+            saved: true,
+            updateExistingUsers: null,
+          });
 
           if (this.afterSave) {
             this.afterSave();
diff --git a/app/assets/javascripts/discourse/app/controllers/group-default-notifications.js b/app/assets/javascripts/discourse/app/controllers/group-default-notifications.js
new file mode 100644
index 0000000..8c3a264
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/controllers/group-default-notifications.js
@@ -0,0 +1,5 @@
+import Controller from "@ember/controller";
+import ModalFunctionality from "discourse/mixins/modal-functionality";
+import ModalUpdateExistingUsers from "discourse/mixins/modal-update-existing-users";
+
+export default Controller.extend(ModalFunctionality, ModalUpdateExistingUsers);
diff --git a/app/assets/javascripts/discourse/app/mixins/modal-update-existing-users.js b/app/assets/javascripts/discourse/app/mixins/modal-update-existing-users.js
new file mode 100644
index 0000000..6990615
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/mixins/modal-update-existing-users.js
@@ -0,0 +1,19 @@
+import Mixin from "@ember/object/mixin";
+
+export default Mixin.create({
+  onShow() {
+    this.set("updateExistingUsers", null);
+  },
+
+  actions: {
+    updateExistingUsers() {
+      this.set("updateExistingUsers", true);
+      this.send("closeModal");
+    },
+
+    cancel() {
+      this.set("updateExistingUsers", false);
+      this.send("closeModal");
+    },
+  },
+});
diff --git a/app/assets/javascripts/discourse/app/models/group.js b/app/assets/javascripts/discourse/app/models/group.js
index 23a8e54..5fcbf46 100644
--- a/app/assets/javascripts/discourse/app/models/group.js
+++ b/app/assets/javascripts/discourse/app/models/group.js
@@ -292,10 +292,10 @@ const Group = RestModel.extend({
     });
   },
 
-  save() {
+  save(opts = {}) {
     return ajax(`/groups/${this.id}`, {
       type: "PUT",
-      data: { group: this.asJSON() },
+      data: Object.assign({ group: this.asJSON() }, opts),
     });
   },
 
diff --git a/app/assets/javascripts/discourse/app/templates/modal/group-default-notifications.hbs b/app/assets/javascripts/discourse/app/templates/modal/group-default-notifications.hbs
new file mode 100644
index 0000000..1bb030c
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/templates/modal/group-default-notifications.hbs
@@ -0,0 +1,8 @@
+{{#d-modal-body title="groups.default_notifications.modal_title"}}
+  {{i18n "groups.default_notifications.modal_description" count=model.count}}
+{{/d-modal-body}}
+
+<div class="modal-footer">
+  {{d-button action=(action "updateExistingUsers") class="btn-primary" label="groups.default_notifications.modal_yes"}}
+  {{d-button action=(action "cancel") label="groups.default_notifications.modal_no"}}
+</div>
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 14687f7..ec07ac6 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -155,10 +155,25 @@ class GroupsController < ApplicationController
     params_with_permitted = group_params(automatic: group.automatic)
     clear_disabled_email_settings(group, params_with_permitted)
 
+    categories, tags = []
+    if !group.automatic || current_user.admin
+      categories, tags = user_default_notifications(group, params_with_permitted)
+
+      if params[:update_existing_users].blank?
+        user_count = count_existing_users(group.group_users, categories, tags)
+
+        if user_count > 0
+          render json: { user_count: user_count }
+          return
+        end
+      end
+    end
+
     if group.update(params_with_permitted)
       GroupActionLogger.new(current_user, group, skip_guardian: true).log_change_group_settings
       group.record_email_setting_changes!(current_user)
       group.expire_imap_mailbox_cache
+      update_existing_users(group.group_users, categories, tags) if categories.present? || tags.present?
 
       if guardian.can_see?(group)
         render json: success_json
@@ -757,4 +772,154 @@ class GroupsController < ApplicationController
       params_with_permitted[:email_password] = nil
     end
   end
+
+  def user_default_notifications(group, params)
+    category_notifications = group.group_category_notification_defaults.pluck(:category_id, :notification_level).to_h
+    tag_notifications = group.group_tag_notification_defaults.pluck(:tag_id, :notification_level).to_h
+    categories = {}
+    tags = {}
+
+    NotificationLevels.all.each do |key, value|
+      category_ids = (params["#{key}_category_ids".to_sym] || []) - ["-1"]
+
+      category_ids.each do |category_id|
+        category_id = category_id.to_i
+        old_value = category_notifications[category_id]
+
+        metadata = {
+          old_value: old_value,
+          new_value: value
+        }
+
+        if old_value.blank?
+          metadata[:action] = :create
+        elsif old_value == value
+          category_notifications.delete(category_id)
+          next
+        else
+          metadata[:action] = :update
+        end
+
+        categories[category_id] = metadata
+      end
+

[... diff too long, it was truncated ...]

GitHub sha: d6fc39c8860f86410b2a20702fa0bac4f37b8978

This commit appears in #13434 which was approved by eviltrout. It was merged by vinothkannans.