Project

General

Profile

Feature #31589 » 0001-Show-an-warning-with-the-reason-for-why-an-issue-can.patch

Marius BĂLTEANU, 2020-01-08 08:35

View differences:

app/models/issue.rb
56 56

  
57 57
  DONE_RATIO_OPTIONS = %w(issue_field issue_status)
58 58

  
59
  attr_reader :not_closable_reason
59 60
  attr_writer :deleted_attachment_ids
60 61
  delegate :notes, :notes=, :private_notes, :private_notes=, :to => :current_journal, :allow_nil => true
61 62

  
......
969 970
    !relations_to.detect {|ir| ir.relation_type == 'blocks' && !ir.issue_from.closed?}.nil?
970 971
  end
971 972

  
973
  # Returns true if this issue can be closed and if not, returns false and populates the reason
974
  def closable?
975
    if descendants.open.any?
976
      @not_closable_reason = l(:notice_issue_not_closable_by_open_tasks)
977
      return false
978
    end
979
    if blocked?
980
      @not_closable_reason = l(:notice_issue_not_closable_by_blocking_issue)
981
      return false
982
    end
983
    return true
984
  end
985

  
972 986
  # Returns the default status of the issue based on its tracker
973 987
  # Returns nil if tracker is nil
974 988
  def default_status
......
1008 1022
    statuses << default_status if include_default || (new_record? && statuses.empty?)
1009 1023

  
1010 1024
    statuses = statuses.compact.uniq.sort
1011
    if blocked? || descendants.open.any?
1025
    unless closable?
1012 1026
      # cannot close a blocked issue or a parent with open subtasks
1013 1027
      statuses.reject!(&:is_closed?)
1014 1028
    end
app/views/issues/_attributes.html.erb
3 3
<div class="splitcontent">
4 4
<div class="splitcontentleft">
5 5
<% if @issue.safe_attribute?('status_id') && @allowed_statuses.present? %>
6
<p><%= f.select :status_id, (@allowed_statuses.collect {|p| [p.name, p.id]}), {:required => true},
7
                :onchange => "updateIssueFrom('#{escape_javascript(update_issue_form_path(@project, @issue))}', this)" %></p>
6
<p>
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)" %>
9
  <% unless @issue.closable? %>
10
    <span class="icon-only icon-warning" title="<%= @issue.not_closable_reason %>"><%= @issue.not_closable_reason %></span>
11
  <% end %>
12
</p>
8 13
<%= hidden_field_tag 'was_default_status', @issue.status_id, :id => nil if @issue.status == @issue.default_status %>
9 14
<% else %>
10 15
<p><label><%= l(:field_status) %></label> <%= @issue.status %></p>
config/locales/en.yml
191 191
  notice_new_password_must_be_different: The new password must be different from the current password
192 192
  notice_import_finished: "%{count} items have been imported"
193 193
  notice_import_finished_with_errors: "%{count} out of %{total} items could not be imported"
194
  notice_issue_not_closable_by_open_tasks: "This issue cannot be closed because it has open subtasks."
195
  notice_issue_not_closable_by_blocking_issue: "This issue cannot be closed because it is blocked by another issue."
194 196

  
195 197
  error_can_t_load_default_data: "Default configuration could not be loaded: %{value}"
196 198
  error_scm_not_found: "The entry or revision was not found in the repository."
test/functional/issues_controller_test.rb
5196 5196
    assert_select 'select[name=?]', 'issue[priority_id]' do
5197 5197
      assert_select 'option[value="15"]', 0
5198 5198
    end
5199
    assert_select 'span.icon-warning', 0
5199 5200
  end
5200 5201

  
5201 5202
  def test_edit_should_hide_project_if_user_is_not_allowed_to_change_project
......
5307 5308
    end
5308 5309
  end
5309 5310

  
5311
  def test_get_edit_for_non_closable_issue_should_show_the_reason
5312
    @request.session[:user_id] = 2
5313
    get(
5314
      :edit,
5315
      :params => {
5316
        :id => 9,
5317
      }
5318
    )
5319

  
5320
    assert_response :success
5321
    reason = l(:notice_issue_not_closable_by_blocking_issue)
5322
    assert_select 'span.icon-warning[title=?]', reason, :text => reason
5323
  end
5324

  
5310 5325
  def test_update_form_for_existing_issue
5311 5326
    @request.session[:user_id] = 2
5312 5327
    patch(
test/unit/issue_test.rb
2104 2104
    child = Issue.generate!(:parent_issue_id => parent.id)
2105 2105

  
2106 2106
    allowed_statuses = parent.reload.new_statuses_allowed_to(users(:users_002))
2107

  
2108
    assert !parent.closable?
2109
    assert_equal l(:notice_issue_not_closable_by_open_tasks), parent.not_closable_reason
2110

  
2107 2111
    assert allowed_statuses.any?
2108 2112
    assert_equal [], allowed_statuses.select(&:is_closed?)
2109 2113
  end
......
2113 2117
    child = Issue.generate!(:parent_issue_id => parent.id, :status_id => 5)
2114 2118

  
2115 2119
    allowed_statuses = parent.reload.new_statuses_allowed_to(users(:users_002))
2120

  
2121
    assert parent.closable?
2122
    assert_nil parent.not_closable_reason
2116 2123
    assert allowed_statuses.any?
2117 2124
    assert allowed_statuses.select(&:is_closed?).any?
2118 2125
  end
......
3244 3251
    User.current = user_in_asia
3245 3252
    assert issue.overdue?
3246 3253
  end
3254

  
3255
  def test_closable
3256
    issue10 = Issue.find(10)
3257
    assert issue10.closable?
3258
    assert_nil issue10.not_closable_reason
3259

  
3260
    # Issue blocked by another issue
3261
    issue9 = Issue.find(9)
3262
    assert !issue9.closable?
3263
    assert_equal l(:notice_issue_not_closable_by_blocking_issue), issue9.not_closable_reason
3264
  end
3247 3265
end
(3-3/4)