]> source.dussan.org Git - redmine.git/commitdiff
Adds Watcher list to the list of available query columns for issues (#29894).
authorMarius Balteanu <marius.balteanu@zitec.com>
Sun, 28 Apr 2024 07:26:29 +0000 (07:26 +0000)
committerMarius Balteanu <marius.balteanu@zitec.com>
Sun, 28 Apr 2024 07:26:29 +0000 (07:26 +0000)
Patch by Felix Schäfer (@felix).

git-svn-id: https://svn.redmine.org/redmine/trunk@22793 e93f8b46-1217-0410-a6f0-8f06a7374b81

app/assets/stylesheets/application.css
app/assets/stylesheets/rtl.css
app/helpers/queries_helper.rb
app/models/issue_query.rb
app/models/query.rb
lib/redmine/export/pdf/issues_pdf_helper.rb
test/functional/issues_controller_test.rb

index 31b31451be9d42eea01819738c0323814aaed2c4..2d82fba7d20d622dd314d646bfff7f2d5e155907 100644 (file)
@@ -292,10 +292,11 @@ tr.project.closed, tr.project.archived { color: #aaa; }
 tr.project.closed a, tr.project.archived a { color: #aaa; }
 
 tr.issue { text-align: center; white-space: nowrap; }
-tr.issue td.subject, tr.issue td.parent-subject, tr.issue td.category, td.assigned_to, td.last_updated_by, tr.issue td.string, tr.issue td.text, tr.issue td.list, tr.issue td.relations, tr.issue td.parent { white-space: normal; }
+tr.issue td.subject, tr.issue td.parent-subject, tr.issue td.category, td.assigned_to, td.last_updated_by, tr.issue td.string, tr.issue td.text, tr.issue td.list, tr.issue td.relations, tr.issue td.parent, tr.issue td.watcher_users { white-space: normal; }
 tr.issue td.relations { text-align: left; }
 tr.issue td.done_ratio table.progress { margin-left:auto; margin-right: auto;}
-tr.issue td.relations span {white-space: nowrap;}
+tr.issue td.relations span, tr.issue td.watcher_users a {white-space: nowrap;}
+tr.issue td.watcher_users ul {list-style: none; padding: 0; margin: 0}
 table.issues td.block_column {color:#777; font-size:90%; padding:4px 4px 4px 24px; text-align:left; white-space:normal;}
 table.issues td.block_column span {font-weight: bold; display: block; margin-bottom: 4px;}
 table.issues td.block_column pre {white-space:normal;}
index a8e919de60d10f015dbe36e5d6750d6052ff51ae..65988f5097c85075911282c461d559139203991c 100644 (file)
@@ -61,7 +61,7 @@ tr.project.idnt-7 td.name {padding-left:0; padding-right:9.5em;}
 tr.project.idnt-8 td.name {padding-left:0; padding-right:11em;}
 tr.project.idnt-9 td.name {padding-left:0; padding-right:12.5em;}
 
-tr.issue td.subject, tr.issue td.relations { text-align:right; }
+tr.issue td.subject, tr.issue td.relations, tr.issue td.watcher_users { text-align:right; }
 tr.issue td.done_ratio table.progress { margin-left:auto; margin-right: auto;}
 
 table.issues td.description {padding:4px 24px 4px 4px; text-align:right;}
index 7d132642b923e79b721b2928198d7b57d98a33a2..b9234bd1f8d1b4deaa57bf3408baa22df1c43186 100644 (file)
@@ -277,6 +277,8 @@ module QueriesHelper
         link_to_if(value > 0, format_hours(value), project_time_entries_path(item.project, :issue_id => "~#{item.id}"))
       when :attachments
         value.to_a.map {|a| format_object(a)}.join(" ").html_safe
+      when :watcher_users
+        content_tag('ul', value.to_a.map {|user| content_tag('li', format_object(user))}.join.html_safe)
       else
         format_object(value)
       end
@@ -300,6 +302,8 @@ module QueriesHelper
     case column.name
     when :attachments
       value.to_a.map {|a| a.filename}.join("\n")
+    when :watcher_users
+      value.to_a.join("\n")
     else
       format_object(value, false) do |value|
         case value.class.name
index 97df44b02f0b94ea6f0ab3edab60c442a1e5538d..91678874e82594ab5ee8cc9c5e00bfb5a9951f29 100644 (file)
@@ -40,6 +40,7 @@ class IssueQuery < Query
     QueryColumn.new(:assigned_to,
                     :sortable => lambda {User.fields_for_order_statement},
                     :groupable => true),
+    WatcherQueryColumn.new(:watcher_users, :caption => :label_issue_watchers),
     TimestampQueryColumn.new(:updated_on, :sortable => "#{Issue.table_name}.updated_on",
                              :default_order => 'desc', :groupable => true),
     QueryColumn.new(:category, :sortable => "#{IssueCategory.table_name}.name", :groupable => true),
@@ -404,6 +405,9 @@ class IssueQuery < Query
     if has_custom_field_column?
       scope = scope.preload(:custom_values)
     end
+    if has_column?(:watcher_users)
+      scope = scope.preload(:watcher_users)
+    end
 
     issues = scope.to_a
 
index 2bcc1b1295729a3c30df0e17d996b9ec90e465d0..90970c96e6d53a6c31ebf13c8b90013688523525 100644 (file)
@@ -104,6 +104,14 @@ class TimestampQueryColumn < QueryColumn
   end
 end
 
+class WatcherQueryColumn < QueryColumn
+  def value_object(object)
+    return nil unless User.current.allowed_to?(:"view_#{object.class.name.underscore}_watchers", object.try(:project))
+
+    super
+  end
+end
+
 class QueryAssociationColumn < QueryColumn
   def initialize(association, attribute, options={})
     @association = association
index 6a6f09437caee67d43a77e73215ebf5641acc2de..1b94685f3964a145d6b2d81ea778106d9c3d669e 100644 (file)
@@ -402,6 +402,8 @@ module Redmine
                   value = "  " * level + value
                 when :attachments
                   value = value.to_a.map {|a| a.filename}.join("\n")
+                when :watcher_users
+                  value = value.to_a.join("\n")
                 end
                 if value.is_a?(Date)
                   format_date(value)
index 014a2d835e11c2fccb873aae50615a632e0878c0..7b8147ece16d545a70965fc36cc620eb6c4dda11 100644 (file)
@@ -1923,6 +1923,67 @@ class IssuesControllerTest < Redmine::ControllerTest
     assert_include "\"source.rb\npicture.jpg\"", response.body
   end
 
+  def test_index_with_watchers_column
+    @request.session[:user_id] = 2
+    get(
+      :index,
+      :params => {
+        :c => %w(subject watcher_users),
+        :set_filter => '1',
+        :sort => 'id',
+      }
+    )
+
+    assert_response :success
+    assert_select 'td.watcher_users'
+    assert_select 'tr#issue-2' do
+      assert_select 'td.watcher_users' do
+        assert_select 'a[href=?]', '/users/1', :text => User.find(1).name
+        assert_select 'a[href=?]', '/users/3', :text => User.find(3).name
+      end
+    end
+  end
+
+  def test_index_with_watchers_column_only_visible_watchers
+    @request.session[:user_id] = 3
+    User.find(3).roles.first.remove_permission! :view_issue_watchers
+    get(
+      :index,
+      :params => {
+        :c => %w(subject watcher_users),
+        :set_filter => '1',
+        :sort => 'id',
+      }
+    )
+
+    assert_response :success
+    assert_select 'td.watcher_users'
+    assert_select 'tr#issue-2' do
+      assert_select 'td.watcher_users' do
+        assert_select 'a[href=?]', '/users/1', 0
+        # Currently not implemented, see https://www.redmine.org/issues/29894#note-17
+        # You can only know that you are a watcher yourself
+        # assert_select 'a[href=?]', '/users/3', :text => User.find(3).name
+      end
+    end
+  end
+
+  def test_index_with_watchers_column_as_csv
+    @request.session[:user_id] = 2
+    get(
+      :index,
+      :params => {
+        :c => %w(subject watcher_users),
+        :set_filter => '1',
+        :sort => 'id',
+        :format => 'csv',
+      }
+    )
+
+    assert_response :success
+    assert_include "\"#{User.find(1).name}\n#{User.find(3).name}\"", response.body
+  end
+
   def test_index_with_estimated_hours_total
     Issue.delete_all
     Issue.generate!(:estimated_hours => '5:30')