Project

General

Profile

Feature #2568 ยป 2568-add-description-to-issue-statuses.patch

Takenori TAKAKI, 2023-08-22 09:23

View differences:

app/models/issue_status.rb
31 31
  validates_presence_of :name
32 32
  validates_uniqueness_of :name, :case_sensitive => true
33 33
  validates_length_of :name, :maximum => 30
34
  validates_length_of :description, :maximum => 255
34 35
  validates_inclusion_of :default_done_ratio, :in => 0..100, :allow_nil => true
35 36

  
36 37
  scope :sorted, lambda {order(:position)}
......
38 39

  
39 40
  safe_attributes(
40 41
    'name',
42
    'description',
41 43
    'is_closed',
42 44
    'position',
43 45
    'default_done_ratio')
app/views/issue_statuses/_form.html.erb
2 2

  
3 3
<div class="box tabular">
4 4
<p><%= f.text_field :name, :required => true %></p>
5
<p><%= f.text_area :description, :rows => 4 %></p>
5 6
<% if Issue.use_status_for_done_ratio? %>
6 7
  <p><%= f.select :default_done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }), :include_blank => true, :label => :field_done_ratio %></p>
7 8
<% end %>
app/views/issue_statuses/index.api.rsb
4 4
      api.id status.id
5 5
      api.name status.name
6 6
      api.is_closed status.is_closed
7
      api.description status.description
7 8
    end
8 9
  end
9 10
end
app/views/issue_statuses/index.html.erb
12 12
  <th><%=l(:field_done_ratio)%></th>
13 13
  <% end %>
14 14
  <th><%=l(:field_is_closed)%></th>
15
  <th><%=l(:field_description)%></th>
15 16
  <th></th>
16 17
  <th></th>
17 18
  </tr></thead>
......
23 24
  <td><%= status.default_done_ratio %></td>
24 25
  <% end %>
25 26
  <td><%= checked_image status.is_closed? %></td>
27
  <td class="description"><%= status.description %></td>
26 28
  <td>
27 29
    <% unless WorkflowTransition.where('old_status_id = ? OR new_status_id = ?', status.id, status.id).exists? %>
28 30
      <span class="icon icon-warning">
app/views/issues/_attributes.html.erb
5 5
<% if @issue.safe_attribute?('status_id') && @allowed_statuses.present? %>
6 6
<p>
7 7
  <%= f.select :status_id, (@allowed_statuses.collect {|p| [p.name, p.id]}), {:required => true},
8
                :onchange => "updateIssueFrom('#{escape_javascript(update_issue_form_path(@project, @issue))}', this)" %>
8
    :onchange => "updateIssueFrom('#{escape_javascript(update_issue_form_path(@project, @issue))}', this)",
9
    :title => @issue.status.description %>
10
  <%= content_tag 'a', l(:label_open_issue_status_description), :class => 'icon-only icon-help', :title => l(:label_open_issue_status_description), :onclick => "showModal('issue_statuses_description', '500px'); return false;", :href => '#' if @allowed_statuses.any? {|s| s.description.present? } %>
9 11
  <% if @issue.transition_warning %>
10 12
    <span class="icon-only icon-warning" title="<%= @issue.transition_warning %>"><%= @issue.transition_warning %></span>
11 13
  <% end %>
12 14
</p>
15
<%= render partial: 'issues/issue_status_description', locals: { issue_statuses: @allowed_statuses } %>
13 16
<%= hidden_field_tag 'was_default_status', @issue.status_id, :id => nil if @issue.status == @issue.default_status %>
14 17
<% else %>
15 18
<p><label><%= l(:field_status) %></label> <%= @issue.status %></p>
app/views/issues/_issue_status_description.html.erb
1
<% if issue_statuses.any? {|s| s.description.present? } %>
2
  <div class="modal" id="issue_statuses_description">
3
    <h3 class="title"><%= l(:label_issue_statuses_description) %></h3>
4
      <dl>
5
      <% issue_statuses.each do |issue_status| %>
6
        <% if issue_status.description.present? %>
7
          <dt><%= content_tag 'a', issue_status.name, :onclick => "selectIssueStatus('#{issue_status.id}'); return false;", :href => '#', :title => l(:text_select_apply_issue_status) %></dt>
8
          <dd><%= issue_status.description %></dd>
9
        <% end %>
10
      <% end %>
11
      </dl>
12
  </div>
13
<% end %>
14
<%= javascript_tag do %>
15
  function selectIssueStatus(id) {
16
    var target = $('#issue_status_id');
17
    target.attr("selected", false);
18
    target.find('option[value="' + id + '"]').prop('selected', true);
19
    target.trigger('change');
20
    hideModal('#issue_statuses_description h3');
21
  }
22
<% end %>
config/locales/en.yml
1119 1119
  label_inherited_from_group: "Inherited from group %{name}"
1120 1120
  label_trackers_description: Trackers description
1121 1121
  label_open_trackers_description: View all trackers description
1122
  label_issue_statuses_description: Issue Status description
1123
  label_open_issue_status_description: View all issue statuses description
1122 1124
  label_preferred_body_part_text: Text
1123 1125
  label_preferred_body_part_html: HTML
1124 1126
  label_issue_history_properties: Property changes
......
1314 1316
  text_project_closed: This project is closed and read-only.
1315 1317
  text_turning_multiple_off: "If you disable multiple values, multiple values will be removed in order to preserve only one value per item."
1316 1318
  text_select_apply_tracker: "Select tracker"
1319
  text_select_apply_issue_status: "Select issue status"
1317 1320
  text_avatar_server_config_html: The current avatar server is <a href="%{url}">%{url}</a>. You can configure it in config/configuration.yml.
1318 1321
  text_no_subject: no subject
1319 1322
  text_allowed_queries_to_select: Public (to any users) queries only selectable
db/migrate/20230818020734_add_status_description.rb
1
class AddStatusDescription < ActiveRecord::Migration[6.1]
2
  def up
3
    add_column :issue_statuses, :description, :string, :after => :name
4
  end
5

  
6
  def down
7
    remove_column :issue_statuses, :description
8
  end
9
end
public/stylesheets/application.css
578 578
#issue_tree .issue > td.assigned_to, #relations .issue > td.assigned_to {
579 579
  white-space: nowrap;
580 580
}
581
#trackers_description {display:none;}
582
#trackers_description dt {font-weight: bold; text-decoration: underline;}
583
#trackers_description dd {margin: 0; padding: 0 0 1em 0;}
581
#trackers_description, #issue_statuses_description {display:none;}
582
#trackers_description dt, #issue_statuses_description dt {font-weight: bold; text-decoration: underline;}
583
#trackers_description dd, #issue_statuses_description dd {margin: 0; padding: 0 0 1em 0;}
584 584

  
585 585
#issue-form .assign-to-me-link { padding-left: 5px; }
586 586

  
test/fixtures/issue_statuses.yml
2 2
issue_statuses_001: 
3 3
  id: 1
4 4
  name: New
5
  description: Description for New issue status
5 6
  is_closed: false
6 7
  position: 1
7 8
issue_statuses_002: 
8 9
  id: 2
9 10
  name: Assigned
11
  description: Description for Assigned issue status
10 12
  is_closed: false
11 13
  position: 2
12 14
issue_statuses_003: 
13 15
  id: 3
14 16
  name: Resolved
17
  description: Description for Resolved issue status
15 18
  is_closed: false
16 19
  position: 3
17 20
issue_statuses_004: 
18
  name: Feedback
19 21
  id: 4
22
  name: Feedback
20 23
  is_closed: false
21 24
  position: 4
22 25
issue_statuses_005: 
test/functional/issue_statuses_controller_test.rb
64 64
    get :new
65 65
    assert_response :success
66 66
    assert_select 'input[name=?]', 'issue_status[name]'
67
    assert_select 'textarea[name=?]', 'issue_status[description]'
67 68
  end
68 69

  
69 70
  def test_create
......
72 73
        :create,
73 74
        :params => {
74 75
          :issue_status => {
75
            :name => 'New status'
76
            :name => 'New status',
77
            :description => 'New status description'
76 78
          }
77 79
        }
78 80
      )
......
80 82
    assert_redirected_to :action => 'index'
81 83
    status = IssueStatus.order('id DESC').first
82 84
    assert_equal 'New status', status.name
85
    assert_equal 'New status description', status.description
83 86
  end
84 87

  
85 88
  def test_create_with_failure
......
99 102
    get(:edit, :params => {:id => '3'})
100 103
    assert_response :success
101 104
    assert_select 'input[name=?][value=?]', 'issue_status[name]', 'Resolved'
105
    assert_select 'textarea[name=?]', 'issue_status[description]', 'Description for Resolved issue status'
102 106
  end
103 107

  
104 108
  def test_update
......
107 111
      :params => {
108 112
        :id => '3',
109 113
        :issue_status => {
110
          :name => 'Renamed status'
114
          :name => 'Renamed status',
115
          :description => 'Renamed status description'
111 116
        }
112 117
      }
113 118
    )
114 119
    assert_redirected_to :action => 'index'
115 120
    status = IssueStatus.find(3)
116 121
    assert_equal 'Renamed status', status.name
122
    assert_equal 'Renamed status description', status.description
117 123
  end
118 124

  
119 125
  def test_update_with_failure
test/functional/issues_controller_test.rb
3881 3881
    assert_select 'div#trackers_description', 0
3882 3882
  end
3883 3883

  
3884
  def test_get_new_should_show_issue_status_description
3885
    @request.session[:user_id] = 2
3886
    get :new, :params => {
3887
      :project_id => 1,
3888
      :issue => {
3889
        :status_id => 2
3890
      }
3891
    }
3892
    assert_response :success
3893

  
3894
    assert_select 'form#issue-form' do
3895
      assert_select 'a[title=?]', 'View all issue statuses description', :text => 'View all issue statuses description'
3896
      assert_select 'select[name=?][title=?]', 'issue[status_id]', 'Description for Assigned issue status'
3897
    end
3898

  
3899
    assert_select 'div#issue_statuses_description' do
3900
      assert_select 'h3', :text => 'Issue Status description', :count => 1
3901
      assert_select 'dt', 2
3902
      assert_select 'dt', :text => 'New', :count => 1
3903
      assert_select 'dd', :text => 'Description for New issue status', :count => 1
3904
    end
3905
  end
3906

  
3907
  def test_get_new_should_not_show_issue_status_description
3908
    IssueStatus.update_all(:description => '')
3909

  
3910
    @request.session[:user_id] = 2
3911
    get :new, :params => {
3912
      :project_id => 1,
3913
      :issue => {
3914
        :status_id => 2
3915
      }
3916
    }
3917
    assert_response :success
3918

  
3919
    assert_select 'form#issue-form' do
3920
      assert_select 'a[title=?]', 'View all issue statuses description', 0
3921
      assert_select 'select[name=?][title=?]', 'issue[status_id]', ''
3922
    end
3923

  
3924
    assert_select 'div#issue_statuses_description', 0
3925
  end
3926

  
3884 3927
  def test_get_new_should_show_create_and_follow_button_when_issue_is_subtask_and_back_url_is_present
3885 3928
    @request.session[:user_id] = 2
3886 3929
    get :new, params: {
test/integration/api_test/issue_statuses_test.rb
29 29
    assert_equal 'application/xml', @response.media_type
30 30
    assert_select 'issue_statuses[type=array] issue_status id', :text => '2' do
31 31
      assert_select '~ name', :text => 'Assigned'
32
      assert_select '~ is_closed', :text => 'false'
33
      assert_select '~ description', :text => 'Description for Assigned issue status'
32 34
    end
33 35
  end
34 36
end
test/unit/issue_status_test.rb
151 151
    assert !issue.closed?
152 152
    assert_nil issue.closed_on
153 153
  end
154

  
155
  def test_issue_status_should_have_description
156
    issue_status = IssueStatus.find(1)
157
    assert issue_status.respond_to?(:description)
158
    assert_equal 'Description for New issue status', issue_status.description
159
  end
154 160
end
    (1-1/1)