Project

General

Profile

Feature #1474 » add_last_notes_column_v2.diff

Marius BĂLTEANU, 2016-12-26 13:45

View differences:

app/helpers/queries_helper.rb
183 183
      value ? (value.visible? ? link_to_issue(value, :subject => false) : "##{value.id}") : ''
184 184
    when :description
185 185
      item.description? ? content_tag('div', textilizable(item, :description), :class => "wiki") : ''
186
    when :last_notes
187
      item.last_notes.present? ? content_tag('div', textilizable(item, :last_notes), :class => "wiki") : ''
186 188
    when :done_ratio
187 189
      progress_bar(value)
188 190
    when :relations
app/models/issue.rb
244 244
    @spent_hours = nil
245 245
    @total_spent_hours = nil
246 246
    @total_estimated_hours = nil
247
    @last_notes = nil
247 248
    base_reload(*args)
248 249
  end
249 250

  
......
1048 1049
    @relations ||= IssueRelation::Relations.new(self, (relations_from + relations_to).sort)
1049 1050
  end
1050 1051

  
1052
  def last_notes
1053
    return self.visible_journals
1054
    if @last_notes
1055
      @last_notes
1056
    else
1057
      notes = self.journals.where.not(notes: '').to_a
1058
      notes.reject!(&:private_notes?) unless User.current.allowed_to?(:view_private_notes, self.project)
1059
      notes.last.notes unless notes.empty?
1060
    end
1061
  end
1062

  
1051 1063
  # Preloads relations for a collection of issues
1052 1064
  def self.load_relations(issues)
1053 1065
    if issues.any?
......
1102 1114
    end
1103 1115
  end
1104 1116

  
1117
  # Preloads visible last notes for a collection of issues
1118
  def self.load_visible_last_notes(issues, user=User.current)
1119
    if issues.any?
1120
      issue_ids = issues.map(&:id)
1121
      logger.debug("="*30)
1122
      notes = Journal.joins(issue: :project).where.not(notes: '').
1123
        where(:issues => {:id => issue_ids}).order("#{Journal.table_name}.id ASC").to_a
1124

  
1125
      issues.each do |issue|
1126
        note = notes.select{|note| note.journalized_id == issue.id}
1127
        note.reject!(&:private_notes?) unless User.current.allowed_to?(:view_private_notes, issue.project)
1128
        issue.instance_variable_set "@last_notes", (note.empty? ? '' : note.last.notes)
1129
      end
1130
    end
1131
  end
1132

  
1105 1133
  # Finds an issue relation given its id.
1106 1134
  def find_relation(relation_id)
1107 1135
    IssueRelation.where("issue_to_id = ? OR issue_from_id = ?", id, id).find(relation_id)
app/models/issue_query.rb
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 46
    QueryColumn.new(:relations, :caption => :label_related_issues),
47
    QueryColumn.new(:description, :inline => false)
47
    QueryColumn.new(:description, :inline => false),
48
    QueryColumn.new(:last_notes, :caption => :label_last_notes, :inline => false)
48 49
  ]
49 50

  
50 51
  def initialize(attributes=nil, *args)
......
330 331
    if has_column?(:relations)
331 332
      Issue.load_visible_relations(issues)
332 333
    end
334
    if has_column?(:last_notes)
335
      Issue.load_visible_last_notes(issues)
336
    end
333 337
    issues
334 338
  rescue ::ActiveRecord::StatementInvalid => e
335 339
    raise StatementInvalid.new(e.message)
app/views/issues/_list.html.erb
33 33
  <% @query.block_columns.each do |column|
34 34
       if (text = column_content(column, issue)) && text.present? -%>
35 35
  <tr class="<%= current_cycle %>">
36
    <td colspan="<%= @query.inline_columns.size + 1 %>" class="<%= column.css_classes %>"><%= text %></td>
36
    <td colspan="<%= @query.inline_columns.size + 1 %>" class="<%= column.css_classes %>">
37
      <% if query.block_columns.count > 1 %>
38
        <span><%= column.caption %></span>
39
      <% end %>
40
      <%= text %>
41
    </td>
37 42
  </tr>
38 43
  <% end -%>
39 44
  <% end -%>
app/views/issues/index.html.erb
37 37
  </p>
38 38
  <p>
39 39
    <label><%= check_box_tag 'csv[description]', '1', @query.has_column?(:description) %> <%= l(:field_description) %></label>
40
    <label><%= check_box_tag 'csv[last_notes]', '1', @query.has_column?(:last_notes) %> <%= l(:label_last_notes) %></label>
40 41
  </p>
41 42
  <% if @issue_count > Setting.issues_export_limit.to_i %>
42 43
  <p class="icon icon-warning">
app/views/timelog/_list.html.erb
50 50
  <% @query.block_columns.each do |column|
51 51
       if (text = column_content(column, issue)) && text.present? -%>
52 52
  <tr class="<%= current_cycle %>">
53
    <td colspan="<%= @query.inline_columns.size + 1 %>" class="<%= column.css_classes %>"><%= text %></td>
53
    <td colspan="<%= @query.inline_columns.size + 1 %>" class="<%= column.css_classes %>">
54
    <% if query.block_columns.count > 1 %>
55
      <span><%= column.caption %></span>
56
    <% end %>
57
    <%= text %>
58
    </td>
54 59
  </tr>
55 60
  <% end -%>
56 61
  <% end -%>
config/locales/en.yml
1009 1009
  label_font_default: Default font
1010 1010
  label_font_monospace: Monospaced font
1011 1011
  label_font_proportional: Proportional font
1012
  label_last_notes: Last notes
1012 1013

  
1013 1014
  button_login: Login
1014 1015
  button_submit: Submit
lib/redmine/export/pdf/issues_pdf_helper.rb
45 45
          pdf.SetFontStyle('',8)
46 46
          pdf.RDMMultiCell(190, 5, "#{format_time(issue.created_on)} - #{issue.author}")
47 47
          pdf.ln
48
  
48

  
49 49
          left = []
50 50
          left << [l(:field_status), issue.status]
51 51
          left << [l(:field_priority), issue.priority]
52 52
          left << [l(:field_assigned_to), issue.assigned_to] unless issue.disabled_core_fields.include?('assigned_to_id')
53 53
          left << [l(:field_category), issue.category] unless issue.disabled_core_fields.include?('category_id')
54 54
          left << [l(:field_fixed_version), issue.fixed_version] unless issue.disabled_core_fields.include?('fixed_version_id')
55
  
55

  
56 56
          right = []
57 57
          right << [l(:field_start_date), format_date(issue.start_date)] unless issue.disabled_core_fields.include?('start_date')
58 58
          right << [l(:field_due_date), format_date(issue.due_date)] unless issue.disabled_core_fields.include?('due_date')
59 59
          right << [l(:field_done_ratio), "#{issue.done_ratio}%"] unless issue.disabled_core_fields.include?('done_ratio')
60 60
          right << [l(:field_estimated_hours), l_hours(issue.estimated_hours)] unless issue.disabled_core_fields.include?('estimated_hours')
61 61
          right << [l(:label_spent_time), l_hours(issue.total_spent_hours)] if User.current.allowed_to?(:view_time_entries, issue.project)
62
  
62

  
63 63
          rows = left.size > right.size ? left.size : right.size
64 64
          while left.size < rows
65 65
            left << nil
......
67 67
          while right.size < rows
68 68
            right << nil
69 69
          end
70
  
70

  
71 71
          half = (issue.visible_custom_field_values.size / 2.0).ceil
72 72
          issue.visible_custom_field_values.each_with_index do |custom_value, i|
73 73
            (i < half ? left : right) << [custom_value.custom_field.name, show_value(custom_value, false)]
74 74
          end
75
  
75

  
76 76
          if pdf.get_rtl
77 77
            border_first_top = 'RT'
78 78
            border_last_top  = 'LT'
......
84 84
            border_first = 'L'
85 85
            border_last  = 'R'
86 86
          end
87
  
87

  
88 88
          rows = left.size > right.size ? left.size : right.size
89 89
          rows.times do |i|
90 90
            heights = []
......
99 99
            item = right[i]
100 100
            heights << pdf.get_string_height(60, item ? item.last.to_s  : "")
101 101
            height = heights.max
102
  
102

  
103 103
            item = left[i]
104 104
            pdf.SetFontStyle('B',9)
105 105
            pdf.RDMMultiCell(35, height, item ? "#{item.first}:" : "", (i == 0 ? border_first_top : border_first), '', 0, 0)
106 106
            pdf.SetFontStyle('',9)
107 107
            pdf.RDMMultiCell(60, height, item ? item.last.to_s : "", (i == 0 ? border_last_top : border_last), '', 0, 0)
108
  
108

  
109 109
            item = right[i]
110 110
            pdf.SetFontStyle('B',9)
111 111
            pdf.RDMMultiCell(35, height, item ? "#{item.first}:" : "",  (i == 0 ? border_first_top : border_first), '', 0, 0)
112 112
            pdf.SetFontStyle('',9)
113 113
            pdf.RDMMultiCell(60, height, item ? item.last.to_s : "", (i == 0 ? border_last_top : border_last), '', 0, 2)
114
  
114

  
115 115
            pdf.set_x(base_x)
116 116
          end
117
  
117

  
118 118
          pdf.SetFontStyle('B',9)
119 119
          pdf.RDMCell(35+155, 5, l(:field_description), "LRT", 1)
120 120
          pdf.SetFontStyle('',9)
121
  
121

  
122 122
          # Set resize image scale
123 123
          pdf.set_image_scale(1.6)
124 124
          text = textilizable(issue, :description,
......
128 128
            :inline_attachments => false
129 129
          )
130 130
          pdf.RDMwriteFormattedCell(35+155, 5, '', '', text, issue.attachments, "LRB")
131
  
131

  
132 132
          unless issue.leaf?
133 133
            truncate_length = (!is_cjk? ? 90 : 65)
134 134
            pdf.SetFontStyle('B',9)
......
145 145
              pdf.ln
146 146
            end
147 147
          end
148
  
148

  
149 149
          relations = issue.relations.select { |r| r.other_issue(issue).visible? }
150 150
          unless relations.empty?
151 151
            truncate_length = (!is_cjk? ? 80 : 60)
......
173 173
          end
174 174
          pdf.RDMCell(190,5, "", "T")
175 175
          pdf.ln
176
  
176

  
177 177
          if issue.changesets.any? &&
178 178
               User.current.allowed_to?(:view_changesets, issue.project)
179 179
            pdf.SetFontStyle('B',9)
......
193 193
              pdf.ln
194 194
            end
195 195
          end
196
  
196

  
197 197
          if assoc[:journals].present?
198 198
            pdf.SetFontStyle('B',9)
199 199
            pdf.RDMCell(190,5, l(:label_history), "B")
......
222 222
              pdf.ln
223 223
            end
224 224
          end
225
  
225

  
226 226
          if issue.attachments.any?
227 227
            pdf.SetFontStyle('B',9)
228 228
            pdf.RDMCell(190,5, l(:label_attachment_plural), "B")
......
249 249
          pdf.footer_date = format_date(User.current.today)
250 250
          pdf.set_auto_page_break(false)
251 251
          pdf.add_page("L")
252
  
252

  
253 253
          # Landscape A4 = 210 x 297 mm
254 254
          page_height   = pdf.get_page_height # 210
255 255
          page_width    = pdf.get_page_width  # 297
......
257 257
          right_margin  = pdf.get_original_margins['right'] # 10
258 258
          bottom_margin = pdf.get_footer_margin
259 259
          row_height    = 4
260
  
260

  
261 261
          # column widths
262 262
          table_width = page_width - right_margin - left_margin
263 263
          col_width = []
......
265 265
            col_width = calc_col_width(issues, query, table_width, pdf)
266 266
            table_width = col_width.inject(0, :+)
267 267
          end
268
  
269
          # use full width if the description is displayed
270
          if table_width > 0 && query.has_column?(:description)
268

  
269
          # use full width if the description or last_notes are displayed
270
          if table_width > 0 && (query.has_column?(:description) || query.has_column?(:last_notes))
271 271
            col_width = col_width.map {|w| w * (page_width - right_margin - left_margin) / table_width}
272 272
            table_width = col_width.inject(0, :+)
273 273
          end
274
  
274

  
275 275
          # title
276 276
          pdf.SetFontStyle('B',11)
277 277
          pdf.RDMCell(190, 8, title)
......
303 303
              end
304 304
              previous_group = group
305 305
            end
306
  
306

  
307 307
            # fetch row values
308 308
            col_values = fetch_row_values(issue, query, level)
309
  
309

  
310 310
            # make new page if it doesn't fit on the current one
311 311
            base_y     = pdf.get_y
312 312
            max_height = get_issues_to_pdf_write_cells(pdf, col_values, col_width)
......
316 316
              render_table_header(pdf, query, col_width, row_height, table_width)
317 317
              base_y = pdf.get_y
318 318
            end
319
  
319

  
320 320
            # write the cells on page
321 321
            issues_to_pdf_write_cells(pdf, col_values, col_width, max_height)
322 322
            pdf.set_y(base_y + max_height)
323
  
323

  
324 324
            if query.has_column?(:description) && issue.description?
325 325
              pdf.set_x(10)
326 326
              pdf.set_auto_page_break(true, bottom_margin)
327 327
              pdf.RDMwriteHTMLCell(0, 5, 10, '', issue.description.to_s, issue.attachments, "LRBT")
328 328
              pdf.set_auto_page_break(false)
329 329
            end
330

  
331
            if query.has_column?(:last_notes) && issue.last_notes.present?
332
              pdf.set_x(10)
333
              pdf.set_auto_page_break(true, bottom_margin)
334
              pdf.RDMwriteHTMLCell(0, 5, 10, '', issue.last_notes.to_s, [], "LRBT")
335
              pdf.set_auto_page_break(false)
336
            end
330 337
          end
331
  
338

  
332 339
          if issues.size == Setting.issues_export_limit.to_i
333 340
            pdf.SetFontStyle('B',10)
334 341
            pdf.RDMCell(0, row_height, '...')
public/stylesheets/application.css
255 255
tr.issue td.relations { text-align: left; }
256 256
tr.issue td.done_ratio table.progress { margin-left:auto; margin-right: auto;}
257 257
tr.issue td.relations span {white-space: nowrap;}
258
table.issues td.description {color:#777; font-size:90%; padding:4px 4px 4px 24px; text-align:left; white-space:normal;}
259
table.issues td.description pre {white-space:normal;}
258
table.issues td.description, table.issues td.last_notes {color:#777; font-size:90%; padding:4px 4px 4px 24px; text-align:left; white-space:normal;}
259
table.issues td.description pre, table.issues td.last_notes pre {white-space:normal;}
260 260

  
261 261
tr.issue.idnt td.subject {background: url(../images/bullet_arrow_right.png) no-repeat 0 50%;}
262 262
tr.issue.idnt-1 td.subject {padding-left: 24px; background-position: 8px 50%;}
test/functional/issues_controller_test.rb
561 561
      str_big5  = "\xa4@\xa4\xeb".force_encoding('Big5')
562 562
      issue = Issue.generate!(:subject => str_utf8)
563 563

  
564
      get :index, :project_id => 1, 
565
                  :f => ['subject'], 
564
      get :index, :project_id => 1,
565
                  :f => ['subject'],
566 566
                  :op => '=', :values => [str_utf8],
567 567
                  :format => 'csv'
568 568
      assert_equal 'text/csv; header=present', @response.content_type
......
580 580
      str_utf8  = "\xe4\xbb\xa5\xe5\x86\x85".force_encoding('UTF-8')
581 581
      issue = Issue.generate!(:subject => str_utf8)
582 582

  
583
      get :index, :project_id => 1, 
584
                  :f => ['subject'], 
583
      get :index, :project_id => 1,
584
                  :f => ['subject'],
585 585
                  :op => '=', :values => [str_utf8],
586 586
                  :c => ['status', 'subject'],
587 587
                  :format => 'csv',
......
603 603
      str1  = "test_index_csv_tw"
604 604
      issue = Issue.generate!(:subject => str1, :estimated_hours => '1234.5')
605 605

  
606
      get :index, :project_id => 1, 
607
                  :f => ['subject'], 
606
      get :index, :project_id => 1,
607
                  :f => ['subject'],
608 608
                  :op => '=', :values => [str1],
609 609
                  :c => ['estimated_hours', 'subject'],
610 610
                  :format => 'csv',
......
620 620
      str1  = "test_index_csv_fr"
621 621
      issue = Issue.generate!(:subject => str1, :estimated_hours => '1234.5')
622 622

  
623
      get :index, :project_id => 1, 
624
                  :f => ['subject'], 
623
      get :index, :project_id => 1,
624
                  :f => ['subject'],
625 625
                  :op => '=', :values => [str1],
626 626
                  :c => ['estimated_hours', 'subject'],
627 627
                  :format => 'csv',
......
696 696
      assert_response :success
697 697
    end
698 698
  end
699
  
699

  
700 700
  def test_index_sort_by_assigned_to
701 701
    get :index, :sort => 'assigned_to'
702 702
    assert_response :success
703
    
703

  
704 704
    assignees = issues_in_list.map(&:assigned_to).compact
705 705
    assert_equal assignees.sort, assignees
706 706
    assert_select 'table.issues.sort-by-assigned-to.sort-asc'
707 707
  end
708
  
708

  
709 709
  def test_index_sort_by_assigned_to_desc
710 710
    get :index, :sort => 'assigned_to:desc'
711 711
    assert_response :success
712
    
712

  
713 713
    assignees = issues_in_list.map(&:assigned_to).compact
714 714
    assert_equal assignees.sort.reverse, assignees
715 715
    assert_select 'table.issues.sort-by-assigned-to.sort-desc'
716 716
  end
717
  
717

  
718 718
  def test_index_group_by_assigned_to
719 719
    get :index, :group_by => 'assigned_to', :sort => 'priority'
720 720
    assert_response :success
721 721
  end
722
  
722

  
723 723
  def test_index_sort_by_author
724 724
    get :index, :sort => 'author', :c => ['author']
725 725
    assert_response :success
726
    
726

  
727 727
    authors = issues_in_list.map(&:author)
728 728
    assert_equal authors.sort, authors
729 729
  end
......
731 731
  def test_index_sort_by_author_desc
732 732
    get :index, :sort => 'author:desc'
733 733
    assert_response :success
734
    
734

  
735 735
    authors = issues_in_list.map(&:author)
736 736
    assert_equal authors.sort.reverse, authors
737 737
  end
738
  
738

  
739 739
  def test_index_group_by_author
740 740
    get :index, :group_by => 'author', :sort => 'priority'
741 741
    assert_response :success
742 742
  end
743
  
743

  
744 744
  def test_index_sort_by_spent_hours
745 745
    get :index, :sort => 'spent_hours:desc'
746 746
    assert_response :success
747 747
    hours = issues_in_list.map(&:spent_hours)
748 748
    assert_equal hours.sort.reverse, hours
749 749
  end
750
  
750

  
751 751
  def test_index_sort_by_total_spent_hours
752 752
    get :index, :sort => 'total_spent_hours:desc'
753 753
    assert_response :success
754 754
    hours = issues_in_list.map(&:total_spent_hours)
755 755
    assert_equal hours.sort.reverse, hours
756 756
  end
757
  
757

  
758 758
  def test_index_sort_by_total_estimated_hours
759 759
    get :index, :sort => 'total_estimated_hours:desc'
760 760
    assert_response :success
......
959 959
    assert_equal 'application/pdf', response.content_type
960 960
  end
961 961

  
962
  def test_index_with_last_notes_column
963
    get :index, :set_filter => 1, :c => %w(subject last_notes)
964

  
965
    assert_response :success
966
    assert_select 'table.issues thead th', 3 # columns: chekbox + id + subject
967

  
968
    assert_select 'td.last_notes[colspan="3"]', :text => 'Some notes with Redmine links: #2, r2.'
969
    assert_select 'td.last_notes[colspan="3"]', :text => 'A comment with inline image:  and a reference to #1 and r2.'
970

  
971
    get :index, :set_filter => 1, :c => %w(subject last_notes), :format => 'pdf'
972
    assert_response :success
973
    assert_equal 'application/pdf', response.content_type
974
  end
975

  
976
  def test_index_with_last_notes_column_should_display_private_notes_with_permission_only
977
    journal = Journal.create!(:journalized => Issue.find(2), :notes => 'Privates notes', :private_notes => true, :user_id => 1)
978
    @request.session[:user_id] = 2
979

  
980
    get :index, :set_filter => 1, :c => %w(subject last_notes)
981
    assert_response :success
982
    assert_select 'td.last_notes[colspan="3"]', :text => 'Privates notes'
983

  
984
    Role.find(1).remove_permission! :view_private_notes
985

  
986
    get :index, :set_filter => 1, :c => %w(subject last_notes)
987
    assert_response :success
988
    assert_select 'td.last_notes[colspan="3"]', :text => 'A comment with inline image:  and a reference to #1 and r2.'
989
  end
990

  
991
  def test_index_with_description_and_last_notes_columns_should_display_column_name
992
    get :index, :set_filter => 1, :c => %w(subject last_notes description)
993
    assert_response :success
994

  
995
    assert_select 'td.last_notes[colspan="3"] span', :text => 'Last notes'
996
    assert_select 'td.description[colspan="3"] span', :text => 'Description'
997
  end
998

  
962 999
  def test_index_with_parent_column
963 1000
    Issue.delete_all
964 1001
    parent = Issue.generate!
......
1093 1130
  def test_index_should_not_include_new_issue_tab_for_project_without_trackers
1094 1131
    with_settings :new_item_menu_tab => '1' do
1095 1132
      Project.find(1).trackers.clear
1096
  
1133

  
1097 1134
      @request.session[:user_id] = 2
1098 1135
      get :index, :project_id => 1
1099 1136
      assert_select '#main-menu a.new-issue', 0
......
1105 1142
      role = Role.find(1)
1106 1143
      role.remove_permission! :add_issues
1107 1144
      role.add_permission! :copy_issues
1108
  
1145

  
1109 1146
      @request.session[:user_id] = 2
1110 1147
      get :index, :project_id => 1
1111 1148
      assert_select '#main-menu a.new-issue', 0
......
1381 1418

  
1382 1419
  def test_show_should_display_prev_next_links_with_query_and_sort_on_association
1383 1420
    @request.session[:issue_query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => nil}
1384
    
1421

  
1385 1422
    %w(project tracker status priority author assigned_to category fixed_version).each do |assoc_sort|
1386 1423
      @request.session['issues_index_sort'] = assoc_sort
1387 1424

  
......
1614 1651
  end
1615 1652

  
1616 1653
  def test_show_export_to_pdf
1617
    issue = Issue.find(3) 
1654
    issue = Issue.find(3)
1618 1655
    assert issue.relations.select{|r| r.other_issue(issue).visible?}.present?
1619 1656
    get :show, :id => 3, :format => 'pdf'
1620 1657
    assert_response :success
......
2062 2099
    get :new, :project_id => 'invalid'
2063 2100
    assert_response 404
2064 2101
  end
2065
 
2102

  
2066 2103
  def test_new_with_parent_id_should_only_propose_valid_trackers
2067 2104
    @request.session[:user_id] = 2
2068 2105
    t = Tracker.find(3)
......
2611 2648
                              :custom_field_values => {'2' => 'Value for field 2'}}
2612 2649
      end
2613 2650
      assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
2614
  
2651

  
2615 2652
      assert_equal 1, ActionMailer::Base.deliveries.size
2616 2653
    end
2617 2654
  end
......
2885 2922
        assert_select 'option[value="1"][selected=selected]', :text => 'eCookbook'
2886 2923
        assert_select 'option[value="2"]:not([selected])', :text => 'OnlineStore'
2887 2924
      end
2888
      assert_select 'input[name=?][value=?]', 'issue[subject]', orig.subject 
2925
      assert_select 'input[name=?][value=?]', 'issue[subject]', orig.subject
2889 2926
      assert_select 'input[name=copy_from][value="1"]'
2890 2927
    end
2891 2928
  end
......
3180 3217
  def test_get_edit_should_display_the_time_entry_form_with_log_time_permission
3181 3218
    @request.session[:user_id] = 2
3182 3219
    Role.find_by_name('Manager').update_attribute :permissions, [:view_issues, :edit_issues, :log_time]
3183
    
3220

  
3184 3221
    get :edit, :id => 1
3185 3222
    assert_select 'input[name=?]', 'time_entry[hours]'
3186 3223
  end
......
3188 3225
  def test_get_edit_should_not_display_the_time_entry_form_without_log_time_permission
3189 3226
    @request.session[:user_id] = 2
3190 3227
    Role.find_by_name('Manager').remove_permission! :log_time
3191
    
3228

  
3192 3229
    get :edit, :id => 1
3193 3230
    assert_select 'input[name=?]', 'time_entry[hours]', 0
3194 3231
  end
......
3833 3870
    assert_response :redirect
3834 3871
    assert_redirected_to :controller => 'issues', :action => 'show', :id => issue.id
3835 3872
  end
3836
 
3873

  
3837 3874
  def test_put_update_should_redirect_with_previous_and_next_issue_ids_params
3838 3875
    @request.session[:user_id] = 2
3839 3876

  
......
3887 3924

  
3888 3925
      assert_select 'select[name=?]', 'issue[project_id]'
3889 3926
      assert_select 'input[name=?]', 'issue[parent_issue_id]'
3890
  
3927

  
3891 3928
      # Project specific custom field, date type
3892 3929
      field = CustomField.find(9)
3893 3930
      assert !field.is_for_all?
3894 3931
      assert_equal 'date', field.field_format
3895 3932
      assert_select 'input[name=?]', 'issue[custom_field_values][9]'
3896
  
3933

  
3897 3934
      # System wide custom field
3898 3935
      assert CustomField.find(1).is_for_all?
3899 3936
      assert_select 'select[name=?]', 'issue[custom_field_values][1]'
3900
  
3937

  
3901 3938
      # Be sure we don't display inactive IssuePriorities
3902 3939
      assert ! IssuePriority.find(15).active?
3903 3940
      assert_select 'select[name=?]', 'issue[priority_id]' do
......
4084 4121
                                       :issue => {:priority_id => '',
4085 4122
                                                  :assigned_to_id => group.id,
4086 4123
                                                  :custom_field_values => {'2' => ''}}
4087
  
4124

  
4088 4125
      assert_response 302
4089 4126
      assert_equal [group, group], Issue.where(:id => [1, 2]).collect {|i| i.assigned_to}
4090 4127
    end
......
4390 4427
      assert_select 'option[value="2"]'
4391 4428
    end
4392 4429
  end
4393
  
4430

  
4394 4431
  def test_bulk_copy_to_another_project
4395 4432
    @request.session[:user_id] = 2
4396 4433
    assert_difference 'Issue.count', 2 do
......
4443 4480
                    :assigned_to_id => 2)
4444 4481
    ]
4445 4482
    assert_difference 'Issue.count', issues.size do
4446
      post :bulk_update, :ids => issues.map(&:id), :copy => '1', 
4483
      post :bulk_update, :ids => issues.map(&:id), :copy => '1',
4447 4484
           :issue => {
4448 4485
             :project_id => '', :tracker_id => '', :assigned_to_id => '',
4449 4486
             :status_id => '', :start_date => '', :due_date => ''
......
4475 4512
    @request.session[:user_id] = 2
4476 4513
    assert_difference 'Issue.count', 2 do
4477 4514
      assert_no_difference 'Project.find(1).issues.count' do
4478
        post :bulk_update, :ids => [1, 2], :copy => '1', 
4515
        post :bulk_update, :ids => [1, 2], :copy => '1',
4479 4516
             :issue => {
4480 4517
               :project_id => '2', :tracker_id => '', :assigned_to_id => '2',
4481 4518
               :status_id => '1', :start_date => '2009-12-01', :due_date => '2009-12-31'
test/unit/query_test.rb
682 682
    Member.create!(:project_id => 1, :principal => other_group, :role_ids => [1])
683 683
    User.current = user
684 684

  
685
    with_settings :issue_group_assignment => '1' do 
685
    with_settings :issue_group_assignment => '1' do
686 686
      i1 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => user)
687 687
      i2 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => group)
688 688
      i3 = Issue.generate!(:project_id => 1, :tracker_id => 1, :assigned_to => other_group)
689
  
689

  
690 690
      query = IssueQuery.new(:name => '_', :filters => { 'assigned_to_id' => {:operator => '=', :values => ['me']}})
691 691
      result = query.issues
692 692
      assert_equal Issue.visible.where(:assigned_to_id => ([2] + user.reload.group_ids)).sort_by(&:id), result.sort_by(&:id)
693
  
693

  
694 694
      assert result.include?(i1)
695 695
      assert result.include?(i2)
696 696
      assert !result.include?(i3)
......
1107 1107

  
1108 1108
  def test_inline_and_block_columns
1109 1109
    q = IssueQuery.new
1110
    q.column_names = ['subject', 'description', 'tracker']
1110
    q.column_names = ['subject', 'description', 'tracker', 'last_notes']
1111 1111

  
1112 1112
    assert_equal [:id, :subject, :tracker], q.inline_columns.map(&:name)
1113
    assert_equal [:description], q.block_columns.map(&:name)
1113
    assert_equal [:description, :last_notes], q.block_columns.map(&:name)
1114 1114
  end
1115 1115

  
1116 1116
  def test_custom_field_columns_should_be_inline
......
1127 1127
    assert_not_nil issues.first.instance_variable_get("@spent_hours")
1128 1128
  end
1129 1129

  
1130
  def test_query_should_preload_last_notes
1131
    q = IssueQuery.new(:name => '_', :column_names => [:subject, :last_notes])
1132
    assert q.has_column?(:last_notes)
1133
    issues = q.issues
1134
    assert_not_nil issues.first.instance_variable_get("@last_notes")
1135
  end
1136

  
1130 1137
  def test_groupable_columns_should_include_custom_fields
1131 1138
    q = IssueQuery.new
1132 1139
    column = q.groupable_columns.detect {|c| c.name == :cf_1}
(6-6/11)