Feature #31581 » issue-burnup-chart-in-the-version-detail.patch
| 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 |