6375_add_last_updated_by_column_r16248_v3.patch

Marius BALTEANU, 2017-01-26 10:52

Download (7.02 KB)

View differences:

app/models/issue.rb
245 245
    @spent_hours = nil
246 246
    @total_spent_hours = nil
247 247
    @total_estimated_hours = nil
248
    @last_updated_by = nil
248 249
    base_reload(*args)
249 250
  end
250 251

  
......
1069 1070
    @relations ||= IssueRelation::Relations.new(self, (relations_from + relations_to).sort)
1070 1071
  end
1071 1072

  
1073
  def last_updated_by
1074
    if @last_updated_by
1075
      @last_updated_by
1076
    else
1077
      journal = self.journals.preload(:user).visible.last
1078
      journal.user if journal
1079
    end
1080
  end
1081

  
1072 1082
  # Preloads relations for a collection of issues
1073 1083
  def self.load_relations(issues)
1074 1084
    if issues.any?
......
1132 1142
      where(:ancestors => {:id => issues.map(&:id)})
1133 1143
  end
1134 1144

  
1145
  # Preloads users who updated last a collection of issues
1146
  def self.load_visible_last_updated_by(issues)
1147
     if issues.any?
1148
      issue_ids = issues.map(&:id)
1149
      journals = Journal.joins(issue: :project).preload(:user).
1150
        where(:journalized_type => 'Issue', :journalized_id => issue_ids).
1151
        where(Journal.visible_notes_condition(User.current, :skip_pre_condition => true)).to_a
1152

  
1153
      issues.each do |issue|
1154
        journal = journals.select{|journal| journal.journalized_id == issue.id}
1155
        issue.instance_variable_set "@last_updated_by", (journal.empty? ? '' : journal.last.user)
1156
      end
1157
    end
1158
  end
1159

  
1135 1160
  # Finds an issue relation given its id.
1136 1161
  def find_relation(relation_id)
1137 1162
    IssueRelation.where("issue_to_id = ? OR issue_from_id = ?", id, id).find(relation_id)
app/models/issue_query.rb
43 43
    QueryColumn.new(:done_ratio, :sortable => "#{Issue.table_name}.done_ratio", :groupable => true),
44 44
    QueryColumn.new(:created_on, :sortable => "#{Issue.table_name}.created_on", :default_order => 'desc'),
45 45
    QueryColumn.new(:closed_on, :sortable => "#{Issue.table_name}.closed_on", :default_order => 'desc'),
46
    QueryColumn.new(:last_updated_by, :sortable => lambda {User.fields_for_order_statement("last_journal_user")}),
46 47
    QueryColumn.new(:relations, :caption => :label_related_issues),
47 48
    QueryColumn.new(:description, :inline => false)
48 49
  ]
......
294 295
    if has_column?(:total_spent_hours)
295 296
      Issue.load_visible_total_spent_hours(issues)
296 297
    end
298
    if has_column?(:last_updated_by)
299
      Issue.load_visible_last_updated_by(issues)
300
    end
297 301
    if has_column?(:relations)
298 302
      Issue.load_visible_relations(issues)
299 303
    end
......
556 560
      if order_options.include?('users')
557 561
        joins << "LEFT OUTER JOIN #{User.table_name} ON #{User.table_name}.id = #{queried_table_name}.assigned_to_id"
558 562
      end
563
      if order_options.include?('last_journal_user')
564
        joins << "LEFT OUTER JOIN #{Journal.table_name} ON #{Journal.table_name}.id = (SELECT MAX(#{Journal.table_name}.id) FROM #{Journal.table_name}" +
565
                " WHERE #{Journal.table_name}.journalized_type='Issue' AND #{Journal.table_name}.journalized_id=#{Issue.table_name}.id AND #{Journal.visible_notes_condition(User.current, :skip_pre_condition => true)})" +
566
                " LEFT OUTER JOIN #{User.table_name} last_journal_user ON last_journal_user.id = #{Journal.table_name}.user_id";
567
      end
559 568
      if order_options.include?('versions')
560 569
        joins << "LEFT OUTER JOIN #{Version.table_name} ON #{Version.table_name}.id = #{queried_table_name}.fixed_version_id"
561 570
      end
public/stylesheets/application.css
254 254
tr.project.idnt-9 td.name {padding-left: 12.5em;}
255 255

  
256 256
tr.issue { text-align: center; white-space: nowrap; }
257
tr.issue td.subject, tr.issue td.category, td.assigned_to, tr.issue td.string, tr.issue td.text, tr.issue td.list, tr.issue td.relations, tr.issue td.parent { white-space: normal; }
257
tr.issue td.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; }
258 258
tr.issue td.relations { text-align: left; }
259 259
tr.issue td.done_ratio table.progress { margin-left:auto; margin-right: auto;}
260 260
tr.issue td.relations span {white-space: nowrap;}
test/unit/query_test.rb
29 29
           :queries,
30 30
           :projects_trackers,
31 31
           :custom_fields_trackers,
32
           :workflows
32
           :workflows, :journals
33 33

  
34 34
  def setup
35 35
    User.current = nil
......
759 759
      query = IssueQuery.new(:name => '_')
760 760
      filter_name = "updated_by"
761 761
      assert_include filter_name, query.available_filters.keys
762
  
762

  
763 763
      query.filters = {filter_name => {:operator => '=', :values => ['me']}}
764 764
      assert_equal [2], find_issues_with_query(query).map(&:id).sort
765 765
    end
......
1287 1287
    assert_not_nil issues.first.instance_variable_get("@spent_hours")
1288 1288
  end
1289 1289

  
1290
  def test_query_should_preload_last_updated_by
1291
    q = IssueQuery.new(:name => '_', :column_names => [:subject, :last_updated_by])
1292
    assert q.has_column?(:last_updated_by)
1293
    issues = q.issues
1294
    assert_not_nil issues.first.instance_variable_get("@last_updated_by")
1295
  end
1296

  
1297
  def test_query_with_last_updated_by_column
1298
    q = IssueQuery.new(:name => '_', :column_names => [:subject, :last_updated_by])
1299
    q.filters = {"project_id" => {:operator => '=', :values => [1]}}
1300

  
1301
    assert_equal ["User", "User", "String", "String", "String", "String", "String"], q.issues.map { |i| i.last_updated_by.class.name}
1302
    assert_equal ["John Smith", "John Smith", "", "", "", "", ""], q.issues.map { |i| i.last_updated_by.to_s }
1303
  end
1304

  
1290 1305
  def test_groupable_columns_should_include_custom_fields
1291 1306
    q = IssueQuery.new
1292 1307
    column = q.groupable_columns.detect {|c| c.name == :cf_1}
......
1349 1364
    end
1350 1365
  end
1351 1366

  
1367
  def test_sortable_columns_should_sort_last_updated_by_according_to_user_format_setting
1368
    with_settings :user_format => 'lastname_comma_firstname' do
1369
      q = IssueQuery.new
1370
      q.sort_criteria = [['last_updated_by', 'desc']]
1371

  
1372
      assert q.sortable_columns.has_key?('last_updated_by')
1373
      assert_equal %w(last_journal_user.lastname last_journal_user.firstname last_journal_user.id), q.sortable_columns['last_updated_by']
1374
    end
1375
  end
1376

  
1352 1377
  def test_sortable_columns_should_include_custom_field
1353 1378
    q = IssueQuery.new
1354 1379
    assert q.sortable_columns['cf_1']