issue-burnup-chart-in-the-version-detail.patch

Takenori TAKAKI, 2019-06-18 05:37

Download (7.72 KB)

View differences:

app/helpers/versions_helper.rb
73 73
  def status_by_options_for_select(value)
74 74
    options_for_select(STATUS_BY_CRITERIAS.collect {|criteria| [l("field_#{criteria}".to_sym), criteria]}, value)
75 75
  end
76

  
77
  def version_burnup_chart_data(version)
78
    return nil if version.visible_fixed_issues.empty?
79
    chart_start_date = (version.start_date || version.created_on).to_date
80
    chart_end_date = [version.due_date, version.visible_fixed_issues.maximum(:due_date), version.visible_fixed_issues.maximum(:updated_on)].compact.max.to_date
81
    line_end_date = [User.current.today, chart_end_date].min
82
    step_size = ((chart_start_date..chart_end_date).count.to_f / 90).ceil
83
    return nil if step_size < 1
84
    reported = line_end_date.step(chart_start_date, -step_size).collect{|d| {:t => d.to_s, :y => version.visible_fixed_issues.where("#{Issue.table_name}.created_on<=?", d.end_of_day).count}}
85
    closed = line_end_date.step(chart_start_date, -step_size).collect{|d| {:t => d.to_s, :y => version.visible_fixed_issues.open(false).where("#{Issue.table_name}.closed_on<=?", d.end_of_day).count}}
86
    chart_data = {
87
      :labels => chart_end_date.step(chart_start_date, -step_size).collect{|d|d.to_s},
88
      :datasets => [
89
        {:label => l(:label_reported_issues), :data => reported,
90
         :borderColor => "rgba(128, 128, 128, 1)", :backgroundColor => "rgba(128, 128, 128, 0.1)", :pointBackgroundColor => "rgba(128, 128, 128, 1)",
91
         :lineTension => 0, :borderWidth => 2},
92
        {:label => l(:label_closed_issues), :data => closed,
93
         :borderColor => "rgba(186, 224, 186, 1)", :backgroundColor => "rgba(186, 224, 186, 0.1)", :pointBackgroundColor => "rgba(186, 224, 186, 1)",
94
         :lineTension => 0, :borderWidth => 2}
95
      ]
96
    }
97
    return chart_data
98
  end
76 99
end
app/views/versions/show.html.erb
51 51
  <% end %>
52 52
  </table>
53 53
<% end %>
54
<div class="version-report-graph">
55
  <canvas id="version_chart"></canvas>
56
</div>
54 57
<%= context_menu %>
55 58
<% end %>
56 59
</div>
......
58 61
<%= call_hook :view_versions_show_bottom, :version => @version %>
59 62

  
60 63
<% html_title @version.name %>
64
<% if chart_data = version_burnup_chart_data(@version) %>
65
  <%= javascript_tag do %>
66
  function renderChart(canvas_id, title, chartData){
67
    new Chart($(canvas_id), {
68
      type: 'line',
69
      data: chartData,
70
      options: {
71
        responsive: true,
72
        legend: {
73
          position: 'right',
74
          labels: { boxWidth: 20, fontSize: 10, padding: 10 }
75
        },
76
        title: { display: true, text: title },
77
        tooltips: {
78
          callbacks: {
79
            title: function(tooltipItem, data) { return '' }
80
          }
81
        },
82
        scales: {
83
          xAxes: [{
84
            type: "time",
85
            time: { unit: "day", displayFormats: { day: 'YYYY-MM-DD' } },
86
            gridLines: { borderDash: [6, 4] },
87
            ticks: { source: 'labels', autoSkip: true }
88
          }],
89
          yAxes: [{
90
            gridLines: { borderDash: [6, 4] },
91
            ticks: { min: 0, max: <%= @version.fixed_issues.count + 1 %>, stepSize: 1 }
92
          }]
93
        }
94
      }
95
    });
96
  }
97
  $(document).ready(function(){
98
    var chartData = <%= chart_data.to_json.html_safe %>;
99
    renderChart("#version_chart", "Issues burnup", chartData);
100
  });
101
  <% end %>
102
  <% content_for :header_tags do %>
103
    <%= javascript_include_tag "Chart.bundle.min" %>
104
  <% end %>
105
<% end %>
public/stylesheets/application.css
585 585
div#roadmap .wiki h2 { font-size: 110%; }
586 586
div#roadmap h2, div#roadmap h3 { display: inline; padding-right: 0;}
587 587
body.controller-versions.action-show div#roadmap .related-issues {width:70%;}
588
body.controller-versions.action-show div#roadmap .version-report-graph { width: 70%; margin: 2em 0 }
588 589

  
589 590
div#version-summary { float:right; width:28%; margin-left: 16px; margin-bottom: 16px; background-color: #fff; }
590 591
div#version-summary fieldset { margin-bottom: 1em; }
public/stylesheets/responsive.css
679 679
  .version-overview table.progress {width:75%;}
680 680
  div#version-summary {float:none; width:100%; margin-left:0;}
681 681
  body.controller-versions.action-show div#roadmap .related-issues {width:100%;}
682
  body.controller-versions.action-show div#roadmap .version-report-graph {width:100%;}
682 683

  
683 684
  /* History and Changeset */
684 685
  div#issue-changesets {
test/helpers/version_helper_test.rb
53 53
    version.project = Project.find(5)
54 54
    assert_match /^\/issues\?/, version_filtered_issues_path(version)
55 55
  end
56

  
57
  def test_version_burnup_chart_data_should_return_chart_data
58
    User.any_instance.stubs(:today).returns(3.days.after.to_date)
59
    version = Version.create!(:project => Project.find(1), :name => 'test', :due_date => 5.days.after)
60
    issue = Issue.create!(:project => version.project, :fixed_version => version,
61
                          :tracker => version.project.trackers.first, :subject => 'text', :author => User.current,
62
                          :start_date => 1.days.after)
63
    chart_data = {
64
      :labels => [5.days.after.to_date.to_s, 4.days.after.to_date.to_s, 3.days.after.to_date.to_s, 2.days.after.to_date.to_s, 1.days.after.to_date.to_s],
65
      :datasets => [
66
        {:label => l(:label_reported_issues),
67
         :data => [{:t => 3.days.after.to_date.to_s, :y => 1}, {:t => 2.days.after.to_date.to_s, :y => 1}, {:t => 1.days.after.to_date.to_s, :y => 1}],
68
         :borderColor => "rgba(128, 128, 128, 1)", :backgroundColor => "rgba(128, 128, 128, 0.1)", :pointBackgroundColor => "rgba(128, 128, 128, 1)",
69
         :lineTension => 0, :borderWidth => 2},
70
        {:label => l(:label_closed_issues),
71
         :data => [{:t => 3.days.after.to_date.to_s, :y => 0}, {:t => 2.days.after.to_date.to_s, :y => 0}, {:t => 1.days.after.to_date.to_s, :y => 0}],
72
         :borderColor => "rgba(186, 224, 186, 1)", :backgroundColor => "rgba(186, 224, 186, 0.1)", :pointBackgroundColor => "rgba(186, 224, 186, 1)",
73
         :lineTension => 0, :borderWidth => 2}
74
      ]
75
    }
76
    assert_equal chart_data, version_burnup_chart_data(version)
77
  end
78

  
79
  def test_version_burnup_chart_data_should_return_nil_when_visible_fixed_issues_empty
80
    version = Version.create!(:project => Project.find(1), :name => 'test')
81
    version.visible_fixed_issues.destroy_all
82
    assert_empty version.visible_fixed_issues
83
    assert_nil version_burnup_chart_data(version)
84
  end
85

  
86
  def test_version_burnup_chart_data_should_return_nil_when_order_of_start_date_and_due_date_is_reversed
87
    version = Version.create!(:project => Project.find(1), :name => 'test', :due_date => 10.days.after)
88
    issue = Issue.create!(:project => version.project, :fixed_version => version,
89
                          :tracker => version.project.trackers.first, :subject => 'text', :author => User.current,
90
                          :start_date => 11.days.after)
91
    assert_nil version_burnup_chart_data(version)
92
  end
56 93
end