agileware-jp / redmine_issue_templates

Redmine Issue Template. Pull requests, reporting issues, stars and sponsoring are always welcome!
https://www.redmine.org/plugins/redmine_issue_templates
GNU General Public License v2.0
70 stars 32 forks source link

show all available watchers in json generator #32

Closed maimai77 closed 2 years ago

maimai77 commented 2 years ago

IssuesHelper#users_for_new_issue_watchers returns empty array when there are more than 20 project members.

sanak commented 2 years ago

Hi @maimai77 @nishidayuya,

I tried this PR branch which relates with #31, but the change seems to drop Groups from the Watcher list. (I checked it on Private child of eCookbook after loading Redmine test data by bundle exec rake db:fixtures:load.)

I felt that the following comment's Suggestion-A way seems to be better, https://github.com/agileware-jp/redmine_issue_templates/issues/31#issuecomment-1176250655

so I tried it with the following changes and it seems to work as I expected at least the issue template setting view.

--- a/app/controllers/concerns/issue_templates_common.rb
+++ b/app/controllers/concerns/issue_templates_common.rb
@@ -109,7 +109,7 @@ module IssueTemplatesCommon

       if field == 'watcher_user_ids' && project_id.present?
         issue = Issue.new(tracker_id: tracker_id, project_id: project_id)
-        watchers = helpers.users_for_new_issue_watchers(issue)
+        watchers = users_for_new_issue_watchers_with_limit(issue, nil)
         value[:field_format] = 'list'

         value[:possible_values] = watchers.map { |user| "#{user.name} :#{user.id}" }
@@ -149,4 +149,21 @@ module IssueTemplatesCommon
     logger&.info "core_fields_map_by_tracker_id failed due to this error: #{e.message}"
     {}
   end
+
+  # https://github.com/redmine/redmine/blob/master/app/helpers/issues_helper.rb
+  # Returns an array of users that are proposed as watchers
+  # on the new issue form
+  def users_for_new_issue_watchers_with_limit(issue, limit = 21)
+    users = issue.watcher_users.select{|u| u.status == User::STATUS_ACTIVE}
+    if limit.present?
+      assignable_watchers = issue.project.principals.assignable_watchers.limit(limit)
+      if assignable_watchers.size < limit
+        users += assignable_watchers.sort
+      end
+    else
+      assignable_watchers = issue.project.principals.assignable_watchers
+      users += assignable_watchers.sort
+    end
+    users.uniq
+  end
 end

By the way, even if applying above changes, I couldn't set default watchers on a new issue view when more than 21 members, because Redmine seems to cut watcher checkbox list and show only Search for watchers to add link. new-issue-watchers-list1

In this (>= 21 members) case, clicking Search for watchers to add link, then selecting all members from the setting, then clicking Add button steps are necessary, but I couldn't achieve it yet by code... new-issue-watchers-list2

Here is my trial code, so if someone know how to achieve it, sharing the information is helpful... 🙇

--- a/assets/javascripts/issue_templates.js
+++ b/assets/javascripts/issue_templates.js
@@ -423,12 +423,27 @@ ISSUE_TEMPLATE.prototype = {
     document.getElementById('issue_template').dispatchEvent(changeEvent)
   },
   checkSelectedWatchers: function (values) {
-    let targets = document.querySelectorAll('input[name="issue[watcher_user_ids][]"]')
-    for (let i = 0; i < targets.length; i++) {
-      let target = targets[i]
-      if (values.includes(target.value)) {
-        target.checked = true
+    let targets = document.querySelectorAll('input[type="checkbox"][name="issue[watcher_user_ids][]"]')
+    if (targets.length > 0) {
+      for (let i = 0; i < targets.length; i++) {
+        let target = targets[i]
+        if (values.includes(target.value)) {
+          target.checked = true
+        }
+      }
+    } else {
+      // Click "Search for watchers to add" link to open "Add watchers" dialog
+      document.querySelector('span.search_for_watchers a').click()
+      // Check watchers from template setting
+      let searchTargets = document.querySelectorAll('div#users_for_watcher input[name="watcher[user_ids][]"]')
+      for (let i = 0; i < searchTargets.length; i++) {
+        let target = searchTargets[i]
+        if (values.includes(target.value)) {
+          target.checked = true
+        }
       }
+      // Click "Add" button to apply checked watchers and close the dialog
+      document.querySelector('form#new-watcher-form input[type="submit"]').click()
     }
   },
sanak commented 2 years ago

Here is my trial code, so if someone know how to achieve it, sharing the information is helpful... 🙇

Well, I solve this issue with using the following MutationObserver way. https://stackoverflow.com/questions/5525071/how-to-wait-until-an-element-exists/16726669#16726669

Also, I created the following PR #33 which covers above my comments.

Thanks,