Project

General

Profile

Patch #23417 » make_id_column_configurable_v2.patch

Marius BĂLTEANU, 2016-07-28 17:47

View differences:

app/models/issue_query.rb
21 21
  self.view_permission = :view_issues
22 22

  
23 23
  self.available_columns = [
24
    QueryColumn.new(:id, :sortable => "#{Issue.table_name}.id", :default_order => 'desc', :caption => '#', :frozen => true),
24
    QueryColumn.new(:id, :sortable => "#{Issue.table_name}.id", :default_order => 'desc', :caption => '#'),
25 25
    QueryColumn.new(:project, :sortable => "#{Project.table_name}.name", :groupable => true),
26 26
    QueryColumn.new(:tracker, :sortable => "#{Tracker.table_name}.position", :groupable => true),
27 27
    QueryColumn.new(:parent, :sortable => ["#{Issue.table_name}.root_id", "#{Issue.table_name}.lft ASC"], :default_order => 'desc', :caption => :field_parent_issue),
config/settings.yml
191 191
issue_list_default_columns:
192 192
  serialized: true
193 193
  default:
194
  - id
194 195
  - tracker
195 196
  - status
196 197
  - priority
db/migrate/20160712091212_add_id_to_default_issue_list_columns.rb
1
class AddIdToDefaultIssueListColumns < ActiveRecord::Migration
2
  def self.up
3
    columns = Setting.issue_list_default_columns
4
    return if columns.include?("id")
5

  
6
    columns.unshift "id"
7
    Setting.set_from_params("issue_list_default_columns", columns)
8
  end
9
  def down
10
    columns = Setting.issue_list_default_columns
11
    return unless columns.include?("id")
12

  
13
    columns -= ["id"]
14
    Setting.set_from_params("issue_list_default_columns", columns)
15
  end
16
end
plugins/README
1
Put your Redmine plugins here.
test/functional/issues_controller_test.rb
217 217
      :f => [filter_name],
218 218
      :op => {filter_name => '='},
219 219
      :v => {filter_name => ['Foo']},
220
      :c => ['project']
220
      :c => ['id', 'project']
221 221
    assert_response :success
222 222

  
223 223
    assert_equal [3, 5], issues_in_list.map(&:project_id).uniq.sort
......
455 455
    assert_response :success
456 456

  
457 457
    assert_equal 'text/csv; header=present', @response.content_type
458
    assert response.body.starts_with?("#,")
458
    assert response.body.starts_with?("Project,")
459 459
    lines = response.body.chomp.split("\n")
460
    # default columns + id and project
461
    assert_equal Setting.issue_list_default_columns.size + 2, lines[0].split(',').size
460
    # default columns + project
461
    assert_equal Setting.issue_list_default_columns.size + 1, lines[0].split(',').size
462 462
  end
463 463

  
464 464
  def test_index_csv_with_project
......
495 495
    issue = Issue.create!(:project_id => 1, :tracker_id => 1, :subject => 'test_index_csv_with_spent_time_column', :author_id => 2)
496 496
    TimeEntry.create!(:project => issue.project, :issue => issue, :hours => 7.33, :user => User.find(2), :spent_on => Date.today)
497 497

  
498
    get :index, :format => 'csv', :set_filter => '1', :c => %w(subject spent_hours)
498
    get :index, :format => 'csv', :set_filter => '1', :c => %w(id subject spent_hours)
499 499
    assert_response :success
500 500
    assert_equal 'text/csv; header=present', @response.content_type
501 501
    lines = @response.body.chomp.split("\n")
......
549 549
    child = Issue.generate!(:parent_issue_id => parent.id)
550 550

  
551 551
    with_settings :default_language => 'en' do
552
      get :index, :format => 'csv', :c => %w(parent)
552
      get :index, :format => 'csv', :c => %w(id parent)
553 553
    end
554 554
    lines = response.body.split("\n")
555 555
    assert_include "#{child.id},#{parent.id}", lines
......
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
                  :c => ['status', 'subject'],
586
                  :c => ['id', 'status', 'subject'],
587 587
                  :format => 'csv',
588 588
                  :set_filter => 1
589 589
      assert_equal 'text/csv; header=present', @response.content_type
......
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
                  :c => ['estimated_hours', 'subject'],
609
                  :c => ['id', 'estimated_hours', 'subject'],
610 610
                  :format => 'csv',
611 611
                  :set_filter => 1
612 612
      assert_equal 'text/csv; header=present', @response.content_type
......
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
                  :c => ['estimated_hours', 'subject'],
626
                  :c => ['id', 'estimated_hours', 'subject'],
627 627
                  :format => 'csv',
628 628
                  :set_filter => 1
629 629
      assert_equal 'text/csv; header=present', @response.content_type
......
694 694
    Setting.issue_list_default_columns = %w(subject author)
695 695
    get :index, :sort => 'tracker'
696 696
  end
697
  
697

  
698 698
  def test_index_sort_by_assigned_to
699 699
    get :index, :sort => 'assigned_to'
700 700
    assert_response :success
701
    
701

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

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

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

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

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

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

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

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

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

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

  
756 756
  def test_index_sort_by_total_estimated_hours
757 757
    get :index, :sort => 'total_estimated_hours:desc'
758 758
    assert_response :success
......
767 767
    CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
768 768
    CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
769 769

  
770
    get :index, :project_id => 1, :set_filter => 1, :sort => "cf_#{cf.id},id"
770
    get :index, :project_id => 1, :c => ["id"], :set_filter => 1, :sort => "cf_#{cf.id},id"
771 771
    assert_response :success
772 772

  
773 773
    assert_equal [2, 3, 1], issues_in_list.select {|issue| issue.custom_field_value(cf).present?}.map(&:id)
......
778 778
    get :index, :set_filter => 1, :c => columns
779 779
    assert_response :success
780 780

  
781
    # query should use specified columns + id and checkbox
782
    assert_select 'table.issues thead th', columns.size + 2
781
    # query should use specified columns + checkbox
782
    assert_select 'table.issues thead th', columns.size + 1
783 783

  
784 784
    # columns should be stored in session
785 785
    assert_kind_of Hash, session[:issue_query]
......
799 799
    get :index, :set_filter => 1
800 800

  
801 801
    # query should use specified columns
802
    assert_equal ["#", "Project", "Tracker", "Subject", "Assignee"], columns_in_issues_list
802
    assert_equal ["Project", "Tracker", "Subject", "Assignee"], columns_in_issues_list
803 803
  end
804 804

  
805 805
  def test_index_without_project_and_explicit_default_columns_should_not_add_project_column
......
816 816
    with_settings :issue_list_default_columns => columns do
817 817
      get :index, :project_id => 1, :set_filter => 1
818 818

  
819
      assert_equal ["#", "Assignee", "Subject", "Status", "Tracker"], columns_in_issues_list
819
      assert_equal ["Assignee", "Subject", "Status", "Tracker"], columns_in_issues_list
820 820
    end
821 821
  end
822 822

  
823 823
  def test_index_with_custom_field_column
824
    columns = %w(tracker subject cf_2)
824
    columns = %w(id tracker subject cf_2)
825 825
    get :index, :set_filter => 1, :c => columns
826 826
    assert_response :success
827 827

  
......
915 915
    IssueRelation.create!(:relation_type => "blocks", :issue_from => Issue.find(1), :issue_to => Issue.find(11))
916 916
    IssueRelation.create!(:relation_type => "blocks", :issue_from => Issue.find(12), :issue_to => Issue.find(2))
917 917

  
918
    get :index, :set_filter => 1, :c => %w(subject relations)
918
    get :index, :set_filter => 1, :c => %w(id subject relations)
919 919
    assert_response :success
920 920
    assert_select "tr#issue-1 td.relations" do
921 921
      assert_select "span", 3
......
931 931
      assert_select "span", 0
932 932
    end
933 933

  
934
    get :index, :set_filter => 1, :c => %w(relations), :format => 'csv'
934
    get :index, :set_filter => 1, :c => %w(id relations), :format => 'csv'
935 935
    assert_response :success
936 936
    assert_equal 'text/csv; header=present', response.content_type
937 937
    lines = response.body.chomp.split("\n")
......
939 939
    assert_include '2,Blocked by #12', lines
940 940
    assert_include '3,""', lines
941 941

  
942
    get :index, :set_filter => 1, :c => %w(subject relations), :format => 'pdf'
942
    get :index, :set_filter => 1, :c => %w(id subject relations), :format => 'pdf'
943 943
    assert_response :success
944 944
    assert_equal 'application/pdf', response.content_type
945 945
  end
......
947 947
  def test_index_with_description_column
948 948
    get :index, :set_filter => 1, :c => %w(subject description)
949 949

  
950
    assert_select 'table.issues thead th', 3 # columns: chekbox + id + subject
951
    assert_select 'td.description[colspan="3"]', :text => 'Unable to print recipes'
950
    assert_select 'table.issues thead th', 2 # columns: chekbox subject
951
    assert_select 'td.description[colspan="2"]', :text => 'Unable to print recipes'
952 952

  
953 953
    get :index, :set_filter => 1, :c => %w(subject description), :format => 'pdf'
954 954
    assert_response :success
......
1089 1089
  def test_index_should_not_include_new_issue_tab_for_project_without_trackers
1090 1090
    with_settings :new_item_menu_tab => '1' do
1091 1091
      Project.find(1).trackers.clear
1092
  
1092

  
1093 1093
      @request.session[:user_id] = 2
1094 1094
      get :index, :project_id => 1
1095 1095
      assert_select '#main-menu a.new-issue', 0
......
1101 1101
      role = Role.find(1)
1102 1102
      role.remove_permission! :add_issues
1103 1103
      role.add_permission! :copy_issues
1104
  
1104

  
1105 1105
      @request.session[:user_id] = 2
1106 1106
      get :index, :project_id => 1
1107 1107
      assert_select '#main-menu a.new-issue', 0
......
1377 1377

  
1378 1378
  def test_show_should_display_prev_next_links_with_query_and_sort_on_association
1379 1379
    @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => nil}
1380
    
1380

  
1381 1381
    %w(project tracker status priority author assigned_to category fixed_version).each do |assoc_sort|
1382 1382
      @request.session['issues_index_sort'] = assoc_sort
1383 1383

  
......
1610 1610
  end
1611 1611

  
1612 1612
  def test_show_export_to_pdf
1613
    issue = Issue.find(3) 
1613
    issue = Issue.find(3)
1614 1614
    assert issue.relations.select{|r| r.other_issue(issue).visible?}.present?
1615 1615
    get :show, :id => 3, :format => 'pdf'
1616 1616
    assert_response :success
......
2021 2021
    get :new, :project_id => 'invalid'
2022 2022
    assert_response 404
2023 2023
  end
2024
 
2024

  
2025 2025
  def test_new_with_parent_id_should_only_propose_valid_trackers
2026 2026
    @request.session[:user_id] = 2
2027 2027
    t = Tracker.find(3)
......
2570 2570
                              :custom_field_values => {'2' => 'Value for field 2'}}
2571 2571
      end
2572 2572
      assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
2573
  
2573

  
2574 2574
      assert_equal 1, ActionMailer::Base.deliveries.size
2575 2575
    end
2576 2576
  end
......
2844 2844
        assert_select 'option[value="1"][selected=selected]', :text => 'eCookbook'
2845 2845
        assert_select 'option[value="2"]:not([selected])', :text => 'OnlineStore'
2846 2846
      end
2847
      assert_select 'input[name=?][value=?]', 'issue[subject]', orig.subject 
2847
      assert_select 'input[name=?][value=?]', 'issue[subject]', orig.subject
2848 2848
      assert_select 'input[name=copy_from][value="1"]'
2849 2849
    end
2850 2850
  end
......
3119 3119
  def test_get_edit_should_display_the_time_entry_form_with_log_time_permission
3120 3120
    @request.session[:user_id] = 2
3121 3121
    Role.find_by_name('Manager').update_attribute :permissions, [:view_issues, :edit_issues, :log_time]
3122
    
3122

  
3123 3123
    get :edit, :id => 1
3124 3124
    assert_select 'input[name=?]', 'time_entry[hours]'
3125 3125
  end
......
3127 3127
  def test_get_edit_should_not_display_the_time_entry_form_without_log_time_permission
3128 3128
    @request.session[:user_id] = 2
3129 3129
    Role.find_by_name('Manager').remove_permission! :log_time
3130
    
3130

  
3131 3131
    get :edit, :id => 1
3132 3132
    assert_select 'input[name=?]', 'time_entry[hours]', 0
3133 3133
  end
......
3772 3772
    assert_response :redirect
3773 3773
    assert_redirected_to :controller => 'issues', :action => 'show', :id => issue.id
3774 3774
  end
3775
 
3775

  
3776 3776
  def test_put_update_should_redirect_with_previous_and_next_issue_ids_params
3777 3777
    @request.session[:user_id] = 2
3778 3778

  
......
3826 3826

  
3827 3827
      assert_select 'select[name=?]', 'issue[project_id]'
3828 3828
      assert_select 'input[name=?]', 'issue[parent_issue_id]'
3829
  
3829

  
3830 3830
      # Project specific custom field, date type
3831 3831
      field = CustomField.find(9)
3832 3832
      assert !field.is_for_all?
3833 3833
      assert_equal 'date', field.field_format
3834 3834
      assert_select 'input[name=?]', 'issue[custom_field_values][9]'
3835
  
3835

  
3836 3836
      # System wide custom field
3837 3837
      assert CustomField.find(1).is_for_all?
3838 3838
      assert_select 'select[name=?]', 'issue[custom_field_values][1]'
3839
  
3839

  
3840 3840
      # Be sure we don't display inactive IssuePriorities
3841 3841
      assert ! IssuePriority.find(15).active?
3842 3842
      assert_select 'select[name=?]', 'issue[priority_id]' do
......
4009 4009
                                       :issue => {:priority_id => '',
4010 4010
                                                  :assigned_to_id => group.id,
4011 4011
                                                  :custom_field_values => {'2' => ''}}
4012
  
4012

  
4013 4013
      assert_response 302
4014 4014
      assert_equal [group, group], Issue.where(:id => [1, 2]).collect {|i| i.assigned_to}
4015 4015
    end
......
4315 4315
      assert_select 'option[value="2"]'
4316 4316
    end
4317 4317
  end
4318
  
4318

  
4319 4319
  def test_bulk_copy_to_another_project
4320 4320
    @request.session[:user_id] = 2
4321 4321
    assert_difference 'Issue.count', 2 do
......
4368 4368
                    :assigned_to_id => 3)
4369 4369
    ]
4370 4370
    assert_difference 'Issue.count', issues.size do
4371
      post :bulk_update, :ids => issues.map(&:id), :copy => '1', 
4371
      post :bulk_update, :ids => issues.map(&:id), :copy => '1',
4372 4372
           :issue => {
4373 4373
             :project_id => '', :tracker_id => '', :assigned_to_id => '',
4374 4374
             :status_id => '', :start_date => '', :due_date => ''
......
4396 4396
    @request.session[:user_id] = 2
4397 4397
    assert_difference 'Issue.count', 2 do
4398 4398
      assert_no_difference 'Project.find(1).issues.count' do
4399
        post :bulk_update, :ids => [1, 2], :copy => '1', 
4399
        post :bulk_update, :ids => [1, 2], :copy => '1',
4400 4400
             :issue => {
4401 4401
               :project_id => '2', :tracker_id => '', :assigned_to_id => '2',
4402 4402
               :status_id => '1', :start_date => '2009-12-01', :due_date => '2009-12-31'
test/functional/issues_custom_fields_visibility_test.rb
206 206
    Issue.generate!(:project => p1, :tracker_id => 1, :custom_field_values => {@field2.id => 'ValueC'})
207 207

  
208 208
    @request.session[:user_id] = user.id
209
    get :index, :c => ["subject", "cf_#{@field2.id}"]
209
    get :index, :c => ["id", "subject", "cf_#{@field2.id}"]
210 210
    assert_select 'td', :text => 'ValueA'
211 211
    assert_select 'td', :text => 'ValueB', :count => 0
212 212
    assert_select 'td', :text => 'ValueC'
test/functional/queries_controller_test.rb
122 122
         :operators => {"assigned_to_id" => "=", "status_id" => "o"},
123 123
         :values => { "assigned_to_id" => ["me"], "status_id" => ["1"]},
124 124
         :query => {"name" => "test_new_global_private_query", "visibility" => "0"},
125
         :c => ["", "tracker", "subject", "priority", "category"]
125
         :c => ["", "id", "tracker", "subject", "priority", "category"]
126 126

  
127 127
    q = Query.find_by_name('test_new_global_private_query')
128 128
    assert_redirected_to :controller => 'issues', :action => 'index', :project_id => nil, :query_id => q
test/unit/query_test.rb
943 943
  def test_filter_on_parent
944 944
    Issue.delete_all
945 945
    parent = Issue.generate_with_descendants!
946
    
946

  
947 947

  
948 948
    query = IssueQuery.new(:name => '_')
949 949
    query.filters = {"parent_id" => {:operator => '=', :values => [parent.id.to_s]}}
......
973 973
    parent = Issue.generate_with_descendants!
974 974
    child, leaf = parent.children.sort_by(&:id)
975 975
    grandchild = child.children.first
976
    
976

  
977 977

  
978 978
    query = IssueQuery.new(:name => '_')
979 979
    query.filters = {"child_id" => {:operator => '=', :values => [grandchild.id.to_s]}}
......
1037 1037

  
1038 1038
  def test_set_column_names
1039 1039
    q = IssueQuery.new
1040
    q.column_names = ['tracker', :subject, '', 'unknonw_column']
1040
    q.column_names = ['id', 'tracker', :subject, '', 'unknonw_column']
1041 1041
    assert_equal [:id, :tracker, :subject], q.columns.collect {|c| c.name}
1042 1042
  end
1043 1043

  
......
1063 1063

  
1064 1064
  def test_inline_and_block_columns
1065 1065
    q = IssueQuery.new
1066
    q.column_names = ['subject', 'description', 'tracker']
1066
    q.column_names = ['id', 'subject', 'description', 'tracker']
1067 1067

  
1068 1068
    assert_equal [:id, :subject, :tracker], q.inline_columns.map(&:name)
1069 1069
    assert_equal [:description], q.block_columns.map(&:name)
(3-3/5)