Project

General

Profile

Feature #28471 » 0001-Include-only-visible-issues-in-subtasks-stats.patch

Marius BĂLTEANU, 2020-12-06 23:01

View differences:

app/helpers/issues_helper.rb
143 143
    s.html_safe
144 144
  end
145 145

  
146
  # Renders descendants stats (total descendants (open - closed)) with query links
147
  def render_descendants_stats(issue)
148
    # Get issue descendants grouped by status type (open/closed) using a single query
149
    subtasks_grouped = issue.descendants.visible.joins(:status).select(:is_closed, :id).group(:is_closed).reorder(:is_closed).count(:id)
150
    # Cast keys to boolean in order to have consistent results between database types
151
    subtasks_grouped.transform_keys! {|k| ActiveModel::Type::Boolean.new.cast(k)}
152

  
153
    open_subtasks = subtasks_grouped[false].to_i
154
    closed_subtasks = subtasks_grouped[true].to_i
155
    all_subtasks = open_subtasks + closed_subtasks
156

  
157
    return if all_subtasks == 0
158

  
159
    all_block = content_tag(
160
        'span',
161
        link_to(all_subtasks, issues_path(parent_id: "~#{issue.id}", set_filter: true, status_id: '*')),
162
        class: 'badge badge-issues-count'
163
      )
164

  
165
    closed_block = content_tag(
166
        'span',
167
        link_to_if(
168
          closed_subtasks > 0,
169
          l(:label_x_closed_issues_abbr, count: closed_subtasks),
170
          issues_path(parent_id: "~#{issue.id}", set_filter: true, status_id: 'c')
171
        ),
172
        class: 'closed'
173
      )
174

  
175
    open_block = content_tag(
176
        'span',
177
        link_to_if(
178
          open_subtasks > 0,
179
          l(:label_x_open_issues_abbr, :count => open_subtasks),
180
          issues_path(:parent_id => "~#{issue.id}", :set_filter => true, :status_id => 'o')
181
        ),
182
        class: 'open'
183
      )
184

  
185
    content_tag(
186
        "span",
187
        "#{all_block} (#{open_block} — #{closed_block})".html_safe,
188
        :class => 'issues-stat'
189
      )
190
  end
191

  
146 192
  # Renders the list of related issues on the issue details view
147 193
  def render_issue_relations(issue, relations)
148 194
    manage_relations = User.current.allowed_to?(:manage_issue_relations, issue.project)
app/views/issues/show.html.erb
109 109
  <%= link_to_new_subtask(@issue) if User.current.allowed_to?(:manage_subtasks, @project) %>
110 110
</div>
111 111
<p>
112
<strong><%=l(:label_subtask_plural)%></strong>
113
<% if !@issue.leaf? %>
114
  (<%= link_to(l(:label_x_issues, :count => @issue.descendants.count),
115
                  issues_path(:parent_id => "~#{@issue.id}", :set_filter => true, :status_id => '*')) %>
116
  : <%= link_to_if( @issue.descendants.select(&:closed?).count > 0,
117
                  l(:label_x_closed_issues_abbr, :count => @issue.descendants.select(&:closed?).count ),
118
                  issues_path(:parent_id => "~#{@issue.id}", :set_filter => true, :status_id => 'c')) %>
119
  &#8212;
120
  <%= link_to_if( @issue.descendants.open.count > 0,
121
                 l(:label_x_open_issues_abbr, :count => @issue.descendants.open.count ),
122
                 issues_path(:parent_id => "~#{@issue.id}", :set_filter => true, :status_id => 'o')) %>)
123
<% end %>
112
  <strong><%=l(:label_subtask_plural)%></strong>
113
  <%= render_descendants_stats(@issue) unless @issue.leaf? %>
124 114
</p>
125 115
<%= form_tag({}, :data => {:cm_url => issues_context_menu_path}) do %>
126 116
<%= render_descendants_tree(@issue) unless @issue.leaf? %>
public/stylesheets/application.css
540 540
#issue_tree td.checkbox, #relations td.checkbox {display:none;}
541 541
#issue_tree td.subject, #relations td.subject {width: 50%;}
542 542
#issue_tree td.buttons, #relations td.buttons {padding:0;}
543
#issue_tree .issues-stat {font-size: 80%}
544
#issue_tree .issues-stat .badge {bottom: initial;}
543 545

  
544 546
#trackers_description {display:none;}
545 547
#trackers_description dt {font-weight: bold; text-decoration: underline;}
......
1469 1471
  color: #1D781D;
1470 1472
  border: 1px solid #1D781D;
1471 1473
}
1474
.badge-issues-count {
1475
  background: #EEEEEE;
1476
}
1477

  
1472 1478
/***** Tooltips *****/
1473 1479
.ui-tooltip {
1474 1480
  background: #000;
test/functional/issues_controller_test.rb
2299 2299
    end
2300 2300
  end
2301 2301

  
2302
  def test_show_should_show_subtasks_stats
2303
    @request.session[:user_id] = 1
2304
    child1 = Issue.generate!(parent_issue_id: 1, subject: 'Open child issue')
2305
    Issue.generate!(parent_issue_id: 1, subject: 'Closed child issue', status_id: 5)
2306
    Issue.generate!(parent_issue_id: child1.id, subject: 'Open child of child')
2307
    # Issue not visible for anonymous
2308
    Issue.generate!(parent_issue_id: 1, subject: 'Private child', project_id: 5)
2309

  
2310
    get(:show, params: {:id => 1})
2311
    assert_response :success
2312

  
2313
    assert_select 'div#issue_tree span.issues-stat' do
2314
      assert_select 'span.badge', text: '4'
2315
      assert_select 'span.open a[href=?]', "/issues?parent_id=~1&set_filter=true&status_id=o", text: '3 open'
2316
      assert_select 'span.closed a[href=?]', "/issues?parent_id=~1&set_filter=true&status_id=c", text: '1 closed'
2317
    end
2318
  end
2319

  
2320
  def test_show_subtasks_stats_should_not_link_if_issue_has_zero_open_or_closed_subtasks
2321
    child1 = Issue.generate!(parent_issue_id: 1, subject: 'Open child issue')
2322

  
2323
    get(:show, params: {:id => 1})
2324
    assert_response :success
2325

  
2326
    assert_select 'div#issue_tree span.issues-stat' do
2327
      assert_select 'span.open a[href=?]', "/issues?parent_id=~1&set_filter=true&status_id=o", text: '1 open'
2328
      assert_select 'span.closed', text: '0 closed'
2329
      assert_select 'span.closed a', 0
2330
    end
2331
  end
2332

  
2333
  def test_show_should_not_show_subtasks_stats_if_subtasks_are_not_visible
2334
    # Issue not visible for anonymous
2335
    Issue.generate!(parent_issue_id: 1, subject: 'Private child', project_id: 5)
2336

  
2337
    get(:show, params: {:id => 1})
2338
    assert_response :success
2339

  
2340
    assert_select 'div#issue_tree span.issues-stat', 0
2341
  end
2342

  
2302 2343
  def test_show_should_list_parents
2303 2344
    issue = Issue.
2304 2345
              create!(
(8-8/10)