Project

General

Profile

Feature #17720 » filter_after_updated_by_and_last_updated_by_v2.patch

Marius BĂLTEANU, 2016-10-09 12:42

View differences:

app/models/issue_query.rb
124 124
    add_available_filter "priority_id",
125 125
      :type => :list, :values => IssuePriority.all.collect{|s| [s.name, s.id.to_s] }
126 126

  
127
    author_values = []
128
    author_values << ["<< #{l(:label_me)} >>", "me"] if User.current.logged?
129
    author_values += users.collect{|s| [s.name, s.id.to_s] }
127
    user_values = []
128
    user_values << ["<< #{l(:label_me)} >>", "me"] if User.current.logged?
129
    user_values += users.collect{|s| [s.name, s.id.to_s] }
130 130
    add_available_filter("author_id",
131
      :type => :list, :values => author_values
132
    ) unless author_values.empty?
131
      :type => :list, :values => user_values
132
    ) unless user_values.empty?
133 133

  
134 134
    assigned_to_values = []
135 135
    assigned_to_values << ["<< #{l(:label_me)} >>", "me"] if User.current.logged?
......
194 194
        :values => subprojects.collect{|s| [s.name, s.id.to_s] }
195 195
    end
196 196

  
197
    unless user_values.empty?
198
      add_available_filter("updated_by",
199
        :type => :list, :values => user_values
200
      )
201

  
202
      add_available_filter("last_updated_by",
203
        :type => :list, :values => user_values
204
      )
205
    end
206

  
197 207
    add_custom_fields_filters(issue_custom_fields)
198 208

  
199 209
    add_associations_custom_fields_filters :project, :author, :assigned_to, :fixed_version
......
504 514
    end
505 515
  end
506 516

  
517
  def sql_for_updated_by_field(field, operator, value)
518
    db_table = Journal.table_name
519

  
520
    "#{Issue.table_name}.id IN (SELECT #{db_table}.journalized_id FROM #{db_table} WHERE #{db_table}.journalized_type='Issue' AND #{db_table}.journalized_id = #{Issue.table_name}.id AND " +
521
      sql_for_field(field, operator, value, db_table, 'user_id') + ')'
522
  end
523

  
524
  def sql_for_last_updated_by_field(field, operator, value)
525
    db_table = Journal.table_name
526

  
527
    "#{Issue.table_name}.id IN (SELECT max(#{db_table}.journalized_id) FROM #{db_table} WHERE #{db_table}.journalized_type='Issue' AND #{db_table}.created_on = #{Issue.table_name}.updated_on AND #{db_table}.journalized_id = #{Issue.table_name}.id AND " +
528
      sql_for_field(field, operator, value, db_table, 'user_id') + ')'
529
  end
530

  
507 531
  def sql_for_relations(field, operator, value, options={})
508 532
    relation_options = IssueRelation::TYPES[field]
509 533
    return relation_options unless relation_options
app/models/query.rb
695 695
      operator = operator_for(field)
696 696

  
697 697
      # "me" value substitution
698
      if %w(assigned_to_id author_id user_id watcher_id).include?(field)
698
      if %w(assigned_to_id author_id user_id watcher_id updated_by last_updated_by).include?(field)
699 699
        if v.delete("me")
700 700
          if User.current.logged?
701 701
            v.push(User.current.id.to_s)
config/locales/en.yml
365 365
  field_default_version: Default version
366 366
  field_remote_ip: IP address
367 367
  field_textarea_font: Font used for text areas
368
  field_updated_by: Updated by
369
  field_last_updated_by: Last updated by
368 370

  
369 371
  setting_app_title: Application title
370 372
  setting_app_subtitle: Application subtitle
test/fixtures/issues.yml
1
--- 
2
issues_001: 
1
---
2
issues_001:
3 3
  created_on: <%= 3.days.ago.to_s(:db) %>
4 4
  project_id: 1
5
  updated_on: <%= 1.day.ago.to_s(:db) %>
5
  updated_on: <%= 1.days.ago.to_date.to_s(:db) %>
6 6
  priority_id: 4
7 7
  subject: Cannot print recipes
8 8
  id: 1
9
  fixed_version_id: 
9
  fixed_version_id:
10 10
  category_id: 1
11 11
  description: Unable to print recipes
12 12
  tracker_id: 1
13
  assigned_to_id: 
13
  assigned_to_id:
14 14
  author_id: 2
15 15
  status_id: 1
16 16
  start_date: <%= 1.day.ago.to_date.to_s(:db) %>
......
19 19
  lft: 1
20 20
  rgt: 2
21 21
  lock_version: 3
22
issues_002: 
22
issues_002:
23 23
  created_on: 2006-07-19 21:04:21 +02:00
24 24
  project_id: 1
25 25
  updated_on: 2006-07-19 21:09:50 +02:00
......
27 27
  subject: Add ingredients categories
28 28
  id: 2
29 29
  fixed_version_id: 2
30
  category_id: 
30
  category_id:
31 31
  description: Ingredients of the recipe should be classified by categories
32 32
  tracker_id: 2
33 33
  assigned_to_id: 3
34 34
  author_id: 2
35 35
  status_id: 2
36 36
  start_date: <%= 2.day.ago.to_date.to_s(:db) %>
37
  due_date: 
37
  due_date:
38 38
  root_id: 2
39 39
  lft: 1
40 40
  rgt: 2
41 41
  lock_version: 3
42 42
  done_ratio: 30
43
issues_003: 
43
issues_003:
44 44
  created_on: 2006-07-19 21:07:27 +02:00
45 45
  project_id: 1
46 46
  updated_on: 2006-07-19 21:07:27 +02:00
47 47
  priority_id: 4
48 48
  subject: Error 281 when updating a recipe
49 49
  id: 3
50
  fixed_version_id: 
51
  category_id: 
50
  fixed_version_id:
51
  category_id:
52 52
  description: Error 281 is encountered when saving a recipe
53 53
  tracker_id: 1
54 54
  assigned_to_id: 3
......
59 59
  root_id: 3
60 60
  lft: 1
61 61
  rgt: 2
62
issues_004: 
62
issues_004:
63 63
  created_on: <%= 5.days.ago.to_s(:db) %>
64 64
  project_id: 2
65 65
  updated_on: <%= 2.days.ago.to_s(:db) %>
66 66
  priority_id: 4
67 67
  subject: Issue on project 2
68 68
  id: 4
69
  fixed_version_id: 
70
  category_id: 
69
  fixed_version_id:
70
  category_id:
71 71
  description: Issue on project 2
72 72
  tracker_id: 1
73 73
  assigned_to_id: 2
......
76 76
  root_id: 4
77 77
  lft: 1
78 78
  rgt: 2
79
issues_005: 
79
issues_005:
80 80
  created_on: <%= 5.days.ago.to_s(:db) %>
81 81
  project_id: 3
82 82
  updated_on: <%= 2.days.ago.to_s(:db) %>
83 83
  priority_id: 4
84 84
  subject: Subproject issue
85 85
  id: 5
86
  fixed_version_id: 
87
  category_id: 
86
  fixed_version_id:
87
  category_id:
88 88
  description: This is an issue on a cookbook subproject
89 89
  tracker_id: 1
90
  assigned_to_id: 
90
  assigned_to_id:
91 91
  author_id: 2
92 92
  status_id: 1
93 93
  root_id: 5
94 94
  lft: 1
95 95
  rgt: 2
96
issues_006: 
96
issues_006:
97 97
  created_on: <%= 1.minute.ago.to_s(:db) %>
98 98
  project_id: 5
99
  updated_on: <%= 1.minute.ago.to_s(:db) %>
99
  updated_on: <%= 1.days.ago.to_date.to_s(:db) %>
100 100
  priority_id: 4
101 101
  subject: Issue of a private subproject
102 102
  id: 6
103
  fixed_version_id: 
104
  category_id: 
103
  fixed_version_id:
104
  category_id:
105 105
  description: This is an issue of a private subproject of cookbook
106 106
  tracker_id: 1
107
  assigned_to_id: 
107
  assigned_to_id:
108 108
  author_id: 2
109 109
  status_id: 1
110 110
  start_date: <%= Date.today.to_s(:db) %>
......
112 112
  root_id: 6
113 113
  lft: 1
114 114
  rgt: 2
115
issues_007: 
115
issues_007:
116 116
  created_on: <%= 10.days.ago.to_s(:db) %>
117 117
  project_id: 1
118 118
  updated_on: <%= 10.days.ago.to_s(:db) %>
119 119
  priority_id: 5
120 120
  subject: Issue due today
121 121
  id: 7
122
  fixed_version_id: 
123
  category_id: 
122
  fixed_version_id:
123
  category_id:
124 124
  description: This is an issue that is due today
125 125
  tracker_id: 1
126
  assigned_to_id: 
126
  assigned_to_id:
127 127
  author_id: 2
128 128
  status_id: 1
129 129
  start_date: <%= 10.days.ago.to_s(:db) %>
......
132 132
  root_id: 7
133 133
  lft: 1
134 134
  rgt: 2
135
issues_008: 
135
issues_008:
136 136
  created_on: <%= 10.days.ago.to_s(:db) %>
137 137
  project_id: 1
138 138
  updated_on: <%= 10.days.ago.to_s(:db) %>
139 139
  priority_id: 5
140 140
  subject: Closed issue
141 141
  id: 8
142
  fixed_version_id: 
143
  category_id: 
142
  fixed_version_id:
143
  category_id:
144 144
  description: This is a closed issue.
145 145
  tracker_id: 1
146
  assigned_to_id: 
146
  assigned_to_id:
147 147
  author_id: 2
148 148
  status_id: 5
149
  start_date: 
150
  due_date: 
149
  start_date:
150
  due_date:
151 151
  lock_version: 0
152 152
  root_id: 8
153 153
  lft: 1
154 154
  rgt: 2
155 155
  closed_on: <%= 3.days.ago.to_s(:db) %>
156
issues_009: 
156
issues_009:
157 157
  created_on: <%= 1.minute.ago.to_s(:db) %>
158 158
  project_id: 5
159 159
  updated_on: <%= 1.minute.ago.to_s(:db) %>
160 160
  priority_id: 5
161 161
  subject: Blocked Issue
162 162
  id: 9
163
  fixed_version_id: 
164
  category_id: 
163
  fixed_version_id:
164
  category_id:
165 165
  description: This is an issue that is blocked by issue #10
166 166
  tracker_id: 1
167
  assigned_to_id: 
167
  assigned_to_id:
168 168
  author_id: 2
169 169
  status_id: 1
170 170
  start_date: <%= Date.today.to_s(:db) %>
......
172 172
  root_id: 9
173 173
  lft: 1
174 174
  rgt: 2
175
issues_010: 
175
issues_010:
176 176
  created_on: <%= 1.minute.ago.to_s(:db) %>
177 177
  project_id: 5
178 178
  updated_on: <%= 1.minute.ago.to_s(:db) %>
179 179
  priority_id: 5
180 180
  subject: Issue Doing the Blocking
181 181
  id: 10
182
  fixed_version_id: 
183
  category_id: 
182
  fixed_version_id:
183
  category_id:
184 184
  description: This is an issue that blocks issue #9
185 185
  tracker_id: 1
186
  assigned_to_id: 
186
  assigned_to_id:
187 187
  author_id: 2
188 188
  status_id: 1
189 189
  start_date: <%= Date.today.to_s(:db) %>
......
191 191
  root_id: 10
192 192
  lft: 1
193 193
  rgt: 2
194
issues_011: 
194
issues_011:
195 195
  created_on: <%= 3.days.ago.to_s(:db) %>
196 196
  project_id: 1
197 197
  updated_on: <%= 1.day.ago.to_s(:db) %>
198 198
  priority_id: 5
199 199
  subject: Closed issue on a closed version
200 200
  id: 11
201
  fixed_version_id: 1 
201
  fixed_version_id: 1
202 202
  category_id: 1
203 203
  description:
204 204
  tracker_id: 1
205
  assigned_to_id: 
205
  assigned_to_id:
206 206
  author_id: 2
207 207
  status_id: 5
208 208
  start_date: <%= 1.day.ago.to_date.to_s(:db) %>
......
211 211
  lft: 1
212 212
  rgt: 2
213 213
  closed_on: <%= 1.day.ago.to_s(:db) %>
214
issues_012: 
214
issues_012:
215 215
  created_on: <%= 3.days.ago.to_s(:db) %>
216 216
  project_id: 1
217 217
  updated_on: <%= 1.day.ago.to_s(:db) %>
218 218
  priority_id: 5
219 219
  subject: Closed issue on a locked version
220 220
  id: 12
221
  fixed_version_id: 2 
221
  fixed_version_id: 2
222 222
  category_id: 1
223 223
  description:
224 224
  tracker_id: 1
225
  assigned_to_id: 
225
  assigned_to_id:
226 226
  author_id: 3
227 227
  status_id: 5
228 228
  start_date: <%= 1.day.ago.to_date.to_s(:db) %>
......
238 238
  priority_id: 4
239 239
  subject: Subproject issue two
240 240
  id: 13
241
  fixed_version_id: 
242
  category_id: 
241
  fixed_version_id:
242
  category_id:
243 243
  description: This is a second issue on a cookbook subproject
244 244
  tracker_id: 1
245
  assigned_to_id: 
245
  assigned_to_id:
246 246
  author_id: 2
247 247
  status_id: 1
248 248
  root_id: 13
......
252 252
  id: 14
253 253
  created_on: <%= 15.days.ago.to_s(:db) %>
254 254
  project_id: 3
255
  updated_on: <%= 15.days.ago.to_s(:db) %>
255
  updated_on: <%= 15.days.ago.to_date.to_s(:db) %>
256 256
  priority_id: 5
257 257
  subject: Private issue on public project
258
  fixed_version_id: 
259
  category_id: 
258
  fixed_version_id:
259
  category_id:
260 260
  description: This is a private issue
261 261
  tracker_id: 1
262
  assigned_to_id: 
262
  assigned_to_id:
263 263
  author_id: 2
264 264
  status_id: 1
265 265
  is_private: true
test/fixtures/journals.yml
1
--- 
1
---
2 2
journals_001:
3 3
  created_on: <%= 2.days.ago.to_date.to_s(:db) %>
4 4
  notes: "Journal notes"
......
6 6
  journalized_type: Issue
7 7
  user_id: 1
8 8
  journalized_id: 1
9
journals_002: 
9
journals_002:
10 10
  created_on: <%= 1.days.ago.to_date.to_s(:db) %>
11 11
  notes: "Some notes with Redmine links: #2, r2."
12 12
  id: 2
......
14 14
  user_id: 2
15 15
  journalized_id: 1
16 16
journals_003:
17
  created_on: <%= 1.days.ago.to_date.to_s(:db) %>
17
  created_on: 2006-07-19 21:09:50 +02:00
18 18
  notes: "A comment with inline image: !picture.jpg! and a reference to #1 and r2."
19 19
  id: 3
20 20
  journalized_type: Issue
......
29 29
  journalized_id: 6
30 30
journals_005:
31 31
  id: 5
32
  created_on: <%= 1.days.ago.to_date.to_s(:db) %>
32
  created_on: <%= 15.days.ago.to_date.to_s(:db) %>
33 33
  notes: "A comment on a private issue."
34 34
  user_id: 2
35 35
  journalized_type: Issue
36 36
  journalized_id: 14
37
journals_006:
38
  id: 6
39
  created_on: 2006-07-19 21:07:27 +02:00
40
  notes: "New updates"
41
  user_id: 3
42
  journalized_type: Issue
43
  journalized_id: 3
test/unit/issue_test.rb
2702 2702
  end
2703 2703

  
2704 2704
  def test_last_journal_id_without_journals_should_return_nil
2705
    assert_nil Issue.find(3).last_journal_id
2705
    assert_nil Issue.find(4).last_journal_id
2706 2706
  end
2707 2707

  
2708 2708
  def test_journals_after_should_return_journals_with_greater_id
test/unit/query_test.rb
691 691
    assert !result.include?(i3)
692 692
  end
693 693

  
694
  def test_filter_updated_by
695
    query = IssueQuery.new(:name => '_')
696
    filter_name = "updated_by"
697
    assert_include filter_name, query.available_filters.keys
698

  
699
    query.filters = {filter_name => {:operator => '=', :values => [2]}}
700
    assert_equal [1,2,14], find_issues_with_query(query).map(&:id).uniq.sort
701

  
702
    query.filters = {filter_name => {:operator => '=', :values => [4]}}
703
    assert_equal [], find_issues_with_query(query).map(&:id).uniq.sort
704

  
705
    query.filters = {filter_name => {:operator => '!', :values => [3]}, 'project_id' => {:operator => '=', :values =>[3]}}
706
    assert_equal [14], find_issues_with_query(query).map(&:id).uniq.sort
707
  end
708

  
709
  def test_filter_updated_by_me
710
    User.current = User.find(1)
711

  
712
    query = IssueQuery.new(:name => '_', :filters => { "updated_by" => {:operator => '=', :values => ['me']}})
713
    assert_equal [1,6], find_issues_with_query(query).map(&:id).uniq.sort
714
  end
715

  
716
  def test_filter_last_updated_by
717
    query = IssueQuery.new(:name => '_')
718
    filter_name = "last_updated_by"
719
    assert_include filter_name, query.available_filters.keys
720

  
721
    query.filters = {filter_name => {:operator => '=', :values => [2]}}
722
    assert_equal [1,2,14], find_issues_with_query(query).map(&:id).uniq.sort
723

  
724
    query.filters = {filter_name => {:operator => '!', :values => [1,2]}}
725
    assert_equal [3], find_issues_with_query(query).map(&:id).uniq.sort
726
  end
727

  
694 728
  def test_user_custom_field_filtered_on_me
695 729
    User.current = User.find(2)
696 730
    cf = IssueCustomField.create!(:field_format => 'user', :is_for_all => true, :is_filter => true, :name => 'User custom field', :tracker_ids => [1])
(2-2/8)