Project

General

Profile

Patch #21705 » option_to_show_issue_custom_fields_on_full_width.patch

Marius BĂLTEANU, 2016-12-29 16:01

View differences:

app/helpers/issues_helper.rb
239 239
    r.to_html
240 240
  end
241 241

  
242
  def render_custom_fields_rows(issue)
243
    values = issue.visible_custom_field_values
242
  def render_half_width_custom_fields_rows(issue)
243
    values = issue.visible_custom_field_values.select{|cf| cf.custom_field.full_width_layout == false}
244 244
    return if values.empty?
245 245
    half = (values.size / 2.0).ceil
246 246
    issue_fields_rows do |rows|
......
252 252
    end
253 253
  end
254 254

  
255
  def render_full_width_custom_fields_rows(issue)
256
    values = issue.visible_custom_field_values.select{|cf| cf.custom_field.full_width_layout == true}
257
    return if values.empty?
258

  
259
    s = ''
260
    values.each_with_index do |value, i|
261
      if value.custom_field.text_formatting == 'full'
262
        attr_value = content_tag('div', show_value(value), class: 'wiki')
263
      else
264
        attr_value = show_value(value)
265
      end
266
      content =
267
          content_tag('hr') +
268
          content_tag('p', content_tag('strong', custom_field_name_tag(value.custom_field) )) +
269
          content_tag('div', attr_value, class: 'value')
270
      s << content_tag('div', content, class: "cf_#{value.custom_field.id} attribute")
271
    end
272
    s.html_safe
273
  end
274

  
255 275
  # Returns the path for updating the issue form
256 276
  # with project as the current project
257 277
  def update_issue_form_path(project, issue)
app/models/custom_field.rb
89 89
    'edit_tag_style',
90 90
    'user_role',
91 91
    'version_status',
92
    'extensions_allowed'
92
    'extensions_allowed',
93
    'full_width_layout'
93 94

  
94 95
  def format
95 96
    @format ||= Redmine::FieldFormat.find(field_format)
app/views/custom_fields/formats/_text.html.erb
1 1
<%= render :partial => 'custom_fields/formats/regexp', :locals => {:f => f, :custom_field => custom_field} %>
2 2
<p><%= f.check_box :text_formatting, {:label => :setting_text_formatting}, 'full', '' %></p>
3
<% if @custom_field.class.name == "IssueCustomField" %>
4
<p><%= f.check_box :full_width_layout, {:label => :setting_full_width_layout} %></p>
5
<% end %>
3 6
<p><%= f.text_area(:default_value, :rows => 5) %></p>
app/views/issues/_form_custom_fields.html.erb
1 1
<% custom_field_values = @issue.editable_custom_field_values %>
2
<% custom_field_values_half_width = custom_field_values.select{ |cf| cf.custom_field.full_width_layout == false } %>
3
<% custom_field_values_full_width = custom_field_values.select{ |cf| cf.custom_field.full_width_layout == true } %>
2 4
<% if custom_field_values.present? %>
3 5
<div class="splitcontent">
4 6
<div class="splitcontentleft">
5 7
<% i = 0 %>
6
<% split_on = (custom_field_values.size / 2.0).ceil - 1 %>
7
<% custom_field_values.each do |value| %>
8
<% split_on = (custom_field_values_half_width.size / 2.0).ceil - 1 %>
9
<% custom_field_values_half_width.each do |value| %>
8 10
  <p><%= custom_field_tag_with_label :issue, value, :required => @issue.required_attribute?(value.custom_field_id) %></p>
9 11
<% if i == split_on -%>
10 12
</div><div class="splitcontentright">
......
12 14
<% i += 1 -%>
13 15
<% end -%>
14 16
</div>
17
<% custom_field_values_full_width.each do |value| %>
18
  <p><%= custom_field_tag_with_label :issue, value, :required => @issue.required_attribute?(value.custom_field_id) %></p>
19
<% end %>
15 20
</div>
16 21
<% end %>
app/views/issues/show.html.erb
66 66
    end
67 67
  end
68 68
end %>
69
<%= render_custom_fields_rows(@issue) %>
69
<%= render_half_width_custom_fields_rows(@issue) %>
70 70
<%= call_hook(:view_issues_show_details_bottom, :issue => @issue) %>
71 71
</div>
72 72

  
......
87 87
<%= link_to_attachments @issue, :thumbnails => true %>
88 88
<% end -%>
89 89

  
90
<%= render_full_width_custom_fields_rows(@issue) %>
91

  
90 92
<%= call_hook(:view_issues_show_description_bottom, :issue => @issue) %>
91 93

  
92 94
<% if !@issue.leaf? || User.current.allowed_to?(:manage_subtasks, @project) %>
config/locales/en.yml
453 453
  setting_attachment_extensions_denied: Disallowed extensions
454 454
  setting_new_item_menu_tab: Project menu tab for creating new objects
455 455
  setting_commit_logs_formatting: Apply text formatting to commit messages
456
  setting_full_width_layout: Full width layout
456 457

  
457 458
  permission_add_project: Create project
458 459
  permission_add_subprojects: Create subprojects
db/migrate/20161228180443_add_custom_fields_full_width_layout.rb
1
class AddCustomFieldsFullWidthLayout < ActiveRecord::Migration
2
  def self.up
3
    add_column :custom_fields, :full_width_layout, :boolean, :default => false
4
  end
5

  
6
  def self.down
7
    remove_column :custom_fields, :full_width_layout
8
  end
9
end
public/stylesheets/application.css
457 457
div.issue span.private, div.journal span.private { position:relative; bottom: 2px; text-transform: uppercase; background: #d22; color: #fff; font-weight:bold; padding: 0px 2px 0px 2px; font-size: 60%; margin-right: 2px; border-radius: 2px;}
458 458
div.issue .next-prev-links {color:#999;}
459 459
div.issue .attributes {margin-top: 2em;}
460
div.issue .attribute {padding-left:180px; clear:left; min-height: 1.8em;}
461
div.issue .attribute .label {width: 170px; margin-left:-180px; font-weight:bold; float:left; overflow:hidden; text-overflow: ellipsis;}
460
div.issue .attributes .attribute {padding-left:180px; clear:left; min-height: 1.8em;}
461
div.issue .attributes .attribute .label {width: 170px; margin-left:-180px; font-weight:bold; float:left;}
462 462
div.issue .attribute .value {overflow:hidden; text-overflow: ellipsis;}
463 463
div.issue.overdue .due-date .value { color: #c22; }
464 464

  
test/functional/custom_fields_controller_test.rb
126 126
    assert_select '[name=?]', 'custom_field[default_value]', 0
127 127
  end
128 128

  
129
  def test_setting_full_width_layout_shoul_be_present_only_for_long_text_issue_custom_field
130
    get :new, :type => 'IssueCustomField', :custom_field => {:field_format => 'text'}
131
    assert_response :success
132
    assert_select '[name=?]', 'custom_field[full_width_layout]'
133

  
134
    get :new, :type => 'IssueCustomField', :custom_field => {:field_format => 'list'}
135
    assert_response :success
136
    assert_select '[name=?]', 'custom_field[full_width_layout]', 0
137

  
138
    get :new, :type => 'TimeEntryCustomField', :custom_field => {:field_format => 'text'}
139
    assert_response :success
140
    assert_select '[name=?]', 'custom_field[full_width_layout]', 0
141
  end
142

  
129 143
  def test_new_js
130 144
    xhr :get, :new, :type => 'IssueCustomField', :custom_field => {:field_format => 'list'}, :format => 'js'
131 145
    assert_response :success
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
......
1093 1093
  def test_index_should_not_include_new_issue_tab_for_project_without_trackers
1094 1094
    with_settings :new_item_menu_tab => '1' do
1095 1095
      Project.find(1).trackers.clear
1096
  
1096

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

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

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

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

  
......
1575 1575
    assert_select ".cf_1 .value", :text => 'MySQL, Oracle'
1576 1576
  end
1577 1577

  
1578
  def test_show_with_full_width_layout_custom_field_should_show_field_under_description
1579
    field = IssueCustomField.create!(:name => 'Long text', :field_format => 'text', :full_width_layout => true,
1580
      :tracker_ids => [1], :is_for_all => true)
1581
    issue = Issue.find(1)
1582
    issue.custom_field_values = {field.id => 'This is a long text'}
1583
    issue.save!
1584

  
1585
    get :show, :id => 1
1586
    assert_response :success
1587

  
1588
    # long text custom field should not be render in the attributes div
1589
    assert_select "div.attributes div.attribute.cf_#{field.id} p strong", 0, :text => 'Long text'
1590
    assert_select "div.attributes div.attribute.cf_#{field.id} div.value", 0, :text => 'This is a long text'
1591

  
1592
    # long text custom field should be render under description field
1593
    assert_select "div.description ~ div.attribute.cf_#{field.id} p strong", :text => 'Long text'
1594
    assert_select "div.description ~ div.attribute.cf_#{field.id} div.value", :text => 'This is a long text'
1595
  end
1596

  
1578 1597
  def test_show_with_multi_user_custom_field
1579 1598
    field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
1580 1599
      :tracker_ids => [1], :is_for_all => true)
......
1614 1633
  end
1615 1634

  
1616 1635
  def test_show_export_to_pdf
1617
    issue = Issue.find(3) 
1636
    issue = Issue.find(3)
1618 1637
    assert issue.relations.select{|r| r.other_issue(issue).visible?}.present?
1619 1638
    get :show, :id => 3, :format => 'pdf'
1620 1639
    assert_response :success
......
2062 2081
    get :new, :project_id => 'invalid'
2063 2082
    assert_response 404
2064 2083
  end
2065
 
2084

  
2066 2085
  def test_new_with_parent_id_should_only_propose_valid_trackers
2067 2086
    @request.session[:user_id] = 2
2068 2087
    t = Tracker.find(3)
......
2611 2630
                              :custom_field_values => {'2' => 'Value for field 2'}}
2612 2631
      end
2613 2632
      assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
2614
  
2633

  
2615 2634
      assert_equal 1, ActionMailer::Base.deliveries.size
2616 2635
    end
2617 2636
  end
......
2885 2904
        assert_select 'option[value="1"][selected=selected]', :text => 'eCookbook'
2886 2905
        assert_select 'option[value="2"]:not([selected])', :text => 'OnlineStore'
2887 2906
      end
2888
      assert_select 'input[name=?][value=?]', 'issue[subject]', orig.subject 
2907
      assert_select 'input[name=?][value=?]', 'issue[subject]', orig.subject
2889 2908
      assert_select 'input[name=copy_from][value="1"]'
2890 2909
    end
2891 2910
  end
......
3180 3199
  def test_get_edit_should_display_the_time_entry_form_with_log_time_permission
3181 3200
    @request.session[:user_id] = 2
3182 3201
    Role.find_by_name('Manager').update_attribute :permissions, [:view_issues, :edit_issues, :log_time]
3183
    
3202

  
3184 3203
    get :edit, :id => 1
3185 3204
    assert_select 'input[name=?]', 'time_entry[hours]'
3186 3205
  end
......
3188 3207
  def test_get_edit_should_not_display_the_time_entry_form_without_log_time_permission
3189 3208
    @request.session[:user_id] = 2
3190 3209
    Role.find_by_name('Manager').remove_permission! :log_time
3191
    
3210

  
3192 3211
    get :edit, :id => 1
3193 3212
    assert_select 'input[name=?]', 'time_entry[hours]', 0
3194 3213
  end
......
3833 3852
    assert_response :redirect
3834 3853
    assert_redirected_to :controller => 'issues', :action => 'show', :id => issue.id
3835 3854
  end
3836
 
3855

  
3837 3856
  def test_put_update_should_redirect_with_previous_and_next_issue_ids_params
3838 3857
    @request.session[:user_id] = 2
3839 3858

  
......
3887 3906

  
3888 3907
      assert_select 'select[name=?]', 'issue[project_id]'
3889 3908
      assert_select 'input[name=?]', 'issue[parent_issue_id]'
3890
  
3909

  
3891 3910
      # Project specific custom field, date type
3892 3911
      field = CustomField.find(9)
3893 3912
      assert !field.is_for_all?
3894 3913
      assert_equal 'date', field.field_format
3895 3914
      assert_select 'input[name=?]', 'issue[custom_field_values][9]'
3896
  
3915

  
3897 3916
      # System wide custom field
3898 3917
      assert CustomField.find(1).is_for_all?
3899 3918
      assert_select 'select[name=?]', 'issue[custom_field_values][1]'
3900
  
3919

  
3901 3920
      # Be sure we don't display inactive IssuePriorities
3902 3921
      assert ! IssuePriority.find(15).active?
3903 3922
      assert_select 'select[name=?]', 'issue[priority_id]' do
......
4084 4103
                                       :issue => {:priority_id => '',
4085 4104
                                                  :assigned_to_id => group.id,
4086 4105
                                                  :custom_field_values => {'2' => ''}}
4087
  
4106

  
4088 4107
      assert_response 302
4089 4108
      assert_equal [group, group], Issue.where(:id => [1, 2]).collect {|i| i.assigned_to}
4090 4109
    end
......
4390 4409
      assert_select 'option[value="2"]'
4391 4410
    end
4392 4411
  end
4393
  
4412

  
4394 4413
  def test_bulk_copy_to_another_project
4395 4414
    @request.session[:user_id] = 2
4396 4415
    assert_difference 'Issue.count', 2 do
......
4443 4462
                    :assigned_to_id => 2)
4444 4463
    ]
4445 4464
    assert_difference 'Issue.count', issues.size do
4446
      post :bulk_update, :ids => issues.map(&:id), :copy => '1', 
4465
      post :bulk_update, :ids => issues.map(&:id), :copy => '1',
4447 4466
           :issue => {
4448 4467
             :project_id => '', :tracker_id => '', :assigned_to_id => '',
4449 4468
             :status_id => '', :start_date => '', :due_date => ''
......
4475 4494
    @request.session[:user_id] = 2
4476 4495
    assert_difference 'Issue.count', 2 do
4477 4496
      assert_no_difference 'Project.find(1).issues.count' do
4478
        post :bulk_update, :ids => [1, 2], :copy => '1', 
4497
        post :bulk_update, :ids => [1, 2], :copy => '1',
4479 4498
             :issue => {
4480 4499
               :project_id => '2', :tracker_id => '', :assigned_to_id => '2',
4481 4500
               :status_id => '1', :start_date => '2009-12-01', :due_date => '2009-12-31'
(5-5/8)