jirametrics 2.0 → 2.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/jirametrics/aggregate_config.rb +19 -26
- data/lib/jirametrics/aging_work_bar_chart.rb +79 -54
- data/lib/jirametrics/aging_work_in_progress_chart.rb +106 -40
- data/lib/jirametrics/aging_work_table.rb +84 -54
- data/lib/jirametrics/anonymizer.rb +6 -5
- data/lib/jirametrics/blocked_stalled_change.rb +24 -4
- data/lib/jirametrics/board.rb +51 -23
- data/lib/jirametrics/board_config.rb +9 -4
- data/lib/jirametrics/board_movement_calculator.rb +155 -0
- data/lib/jirametrics/change_item.rb +56 -21
- data/lib/jirametrics/chart_base.rb +101 -61
- data/lib/jirametrics/columns_config.rb +4 -0
- data/lib/jirametrics/css_variable.rb +33 -0
- data/lib/jirametrics/cycletime_config.rb +59 -8
- data/lib/jirametrics/cycletime_histogram.rb +69 -4
- data/lib/jirametrics/cycletime_scatterplot.rb +11 -15
- data/lib/jirametrics/daily_view.rb +277 -0
- data/lib/jirametrics/daily_wip_by_age_chart.rb +44 -20
- data/lib/jirametrics/daily_wip_by_blocked_stalled_chart.rb +37 -35
- data/lib/jirametrics/daily_wip_by_parent_chart.rb +38 -0
- data/lib/jirametrics/daily_wip_chart.rb +61 -14
- data/lib/jirametrics/data_quality_report.rb +222 -41
- data/lib/jirametrics/dependency_chart.rb +54 -23
- data/lib/jirametrics/download_config.rb +12 -0
- data/lib/jirametrics/downloader.rb +86 -56
- data/lib/jirametrics/estimate_accuracy_chart.rb +173 -0
- data/lib/jirametrics/estimation_configuration.rb +25 -0
- data/lib/jirametrics/examples/aggregated_project.rb +22 -39
- data/lib/jirametrics/examples/standard_project.rb +26 -48
- data/lib/jirametrics/expedited_chart.rb +28 -25
- data/lib/jirametrics/exporter.rb +59 -32
- data/lib/jirametrics/file_config.rb +35 -14
- data/lib/jirametrics/file_system.rb +48 -3
- data/lib/jirametrics/flow_efficiency_scatterplot.rb +111 -0
- data/lib/jirametrics/groupable_issue_chart.rb +2 -6
- data/lib/jirametrics/grouping_rules.rb +7 -1
- data/lib/jirametrics/hierarchy_table.rb +4 -4
- data/lib/jirametrics/html/aging_work_bar_chart.erb +13 -16
- data/lib/jirametrics/html/aging_work_in_progress_chart.erb +28 -5
- data/lib/jirametrics/html/aging_work_table.erb +21 -25
- data/lib/jirametrics/html/cycletime_histogram.erb +83 -3
- data/lib/jirametrics/html/cycletime_scatterplot.erb +9 -12
- data/lib/jirametrics/html/daily_wip_chart.erb +17 -13
- data/lib/jirametrics/html/{story_point_accuracy_chart.erb → estimate_accuracy_chart.erb} +9 -4
- data/lib/jirametrics/html/expedited_chart.erb +10 -13
- data/lib/jirametrics/html/flow_efficiency_scatterplot.erb +85 -0
- data/lib/jirametrics/html/hierarchy_table.erb +2 -2
- data/lib/jirametrics/html/index.css +280 -0
- data/lib/jirametrics/html/index.erb +33 -39
- data/lib/jirametrics/html/sprint_burndown.erb +10 -14
- data/lib/jirametrics/html/throughput_chart.erb +10 -13
- data/lib/jirametrics/html_report_config.rb +110 -86
- data/lib/jirametrics/issue.rb +390 -109
- data/lib/jirametrics/issue_collection.rb +33 -0
- data/lib/jirametrics/jira_gateway.rb +33 -12
- data/lib/jirametrics/project_config.rb +276 -147
- data/lib/jirametrics/rules.rb +2 -2
- data/lib/jirametrics/self_or_issue_dispatcher.rb +2 -0
- data/lib/jirametrics/settings.json +11 -0
- data/lib/jirametrics/sprint.rb +1 -0
- data/lib/jirametrics/sprint_burndown.rb +59 -40
- data/lib/jirametrics/sprint_issue_change_data.rb +3 -3
- data/lib/jirametrics/status.rb +84 -19
- data/lib/jirametrics/status_collection.rb +86 -39
- data/lib/jirametrics/throughput_chart.rb +12 -4
- data/lib/jirametrics/user.rb +12 -0
- data/lib/jirametrics/value_equality.rb +2 -2
- data/lib/jirametrics.rb +29 -7
- metadata +20 -17
- data/lib/jirametrics/discard_changes_before.rb +0 -37
- data/lib/jirametrics/experimental/generator.rb +0 -210
- data/lib/jirametrics/experimental/info.rb +0 -77
- data/lib/jirametrics/html/data_quality_report.erb +0 -126
- data/lib/jirametrics/story_point_accuracy_chart.rb +0 -134
|
@@ -5,12 +5,8 @@ require 'jirametrics/grouping_rules'
|
|
|
5
5
|
|
|
6
6
|
module GroupableIssueChart
|
|
7
7
|
def init_configuration_block user_provided_block, &default_block
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
return if @group_by_block
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
instance_eval(&default_block)
|
|
8
|
+
instance_eval(&user_provided_block)
|
|
9
|
+
instance_eval(&default_block) unless @group_by_block
|
|
14
10
|
end
|
|
15
11
|
|
|
16
12
|
def grouping_rules &block
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class GroupingRules < Rules
|
|
4
|
-
attr_accessor :label
|
|
4
|
+
attr_accessor :label
|
|
5
|
+
attr_reader :color
|
|
5
6
|
|
|
6
7
|
def eql? other
|
|
7
8
|
other.label == @label && other.color == @color
|
|
@@ -10,4 +11,9 @@ class GroupingRules < Rules
|
|
|
10
11
|
def group
|
|
11
12
|
[@label, @color]
|
|
12
13
|
end
|
|
14
|
+
|
|
15
|
+
def color= color
|
|
16
|
+
color = CssVariable[color] unless color.is_a?(CssVariable)
|
|
17
|
+
@color = color
|
|
18
|
+
end
|
|
13
19
|
end
|
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
require 'jirametrics/chart_base'
|
|
4
4
|
|
|
5
5
|
class HierarchyTable < ChartBase
|
|
6
|
-
def initialize block
|
|
6
|
+
def initialize block
|
|
7
7
|
super()
|
|
8
8
|
|
|
9
9
|
header_text 'Hierarchy Table'
|
|
10
|
-
description_text
|
|
11
|
-
<p>
|
|
10
|
+
description_text <<~HTML
|
|
11
|
+
<p>Shows all issues through this time period and the full hierarchy of their parents.</p>
|
|
12
12
|
HTML
|
|
13
13
|
|
|
14
|
-
instance_eval(&block)
|
|
14
|
+
instance_eval(&block)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def run
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<div>
|
|
1
|
+
<div class="chart">
|
|
2
2
|
<canvas id="<%= chart_id %>" width="<%= canvas_width %>" height="<%= canvas_height %>"></canvas>
|
|
3
3
|
</div>
|
|
4
4
|
<script>
|
|
@@ -19,36 +19,33 @@ new Chart(document.getElementById('<%= chart_id %>').getContext('2d'),
|
|
|
19
19
|
stacked: false,
|
|
20
20
|
title: {
|
|
21
21
|
display: false
|
|
22
|
-
}
|
|
22
|
+
},
|
|
23
|
+
grid: {
|
|
24
|
+
color: <%= CssVariable['--grid-line-color'].to_json %>
|
|
25
|
+
},
|
|
23
26
|
},
|
|
24
27
|
y: {
|
|
25
28
|
stacked: true,
|
|
26
29
|
position: 'right',
|
|
27
30
|
ticks: {
|
|
28
31
|
display: true
|
|
29
|
-
}
|
|
32
|
+
},
|
|
33
|
+
grid: {
|
|
34
|
+
color: <%= CssVariable['--grid-line-color'].to_json %>
|
|
35
|
+
},
|
|
30
36
|
}
|
|
31
37
|
},
|
|
32
38
|
plugins: {
|
|
33
39
|
annotation: {
|
|
34
40
|
annotations: {
|
|
35
|
-
|
|
36
|
-
holiday<%= index %>: {
|
|
37
|
-
drawTime: 'beforeDraw',
|
|
38
|
-
type: 'box',
|
|
39
|
-
xMin: '<%= range.begin %>T00:00:00',
|
|
40
|
-
xMax: '<%= range.end %>T23:59:59',
|
|
41
|
-
backgroundColor: '#F0F0F0',
|
|
42
|
-
borderColor: '#F0F0F0'
|
|
43
|
-
},
|
|
44
|
-
<% end %>
|
|
41
|
+
<%= working_days_annotation %>
|
|
45
42
|
|
|
46
43
|
<% if percentage_line_x %>
|
|
47
44
|
line: {
|
|
48
45
|
type: 'line',
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
borderColor: '
|
|
46
|
+
scaleID: 'x',
|
|
47
|
+
value: '<%= percentage_line_x %>',
|
|
48
|
+
borderColor: <%= CssVariable.new('--aging-work-bar-chart-percentage-line-color').to_json %>,
|
|
52
49
|
borderWidth: 1,
|
|
53
50
|
drawTime: 'afterDraw'
|
|
54
51
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<div>
|
|
1
|
+
<div class="chart">
|
|
2
2
|
<canvas id="<%= chart_id %>" width="<%= canvas_width %>" height="<%= canvas_height %>"></canvas>
|
|
3
3
|
</div>
|
|
4
4
|
<script>
|
|
@@ -6,7 +6,7 @@ new Chart(document.getElementById(<%= chart_id.inspect %>).getContext('2d'),
|
|
|
6
6
|
{
|
|
7
7
|
type: 'bar',
|
|
8
8
|
data: {
|
|
9
|
-
labels: [<%=
|
|
9
|
+
labels: [<%= @board_columns.collect { |c| c.name.inspect }.join(',') %>],
|
|
10
10
|
datasets: <%= JSON.generate(data_sets) %>
|
|
11
11
|
},
|
|
12
12
|
options: {
|
|
@@ -20,7 +20,12 @@ new Chart(document.getElementById(<%= chart_id.inspect %>).getContext('2d'),
|
|
|
20
20
|
scaleLabel: {
|
|
21
21
|
display: true,
|
|
22
22
|
labelString: 'Date Completed'
|
|
23
|
-
}
|
|
23
|
+
},
|
|
24
|
+
grid: {
|
|
25
|
+
color: <%= CssVariable['--grid-line-color'].to_json %>,
|
|
26
|
+
z: 1 // draw the grid lines on top of the bars
|
|
27
|
+
},
|
|
28
|
+
stacked: true
|
|
24
29
|
},
|
|
25
30
|
y: {
|
|
26
31
|
scaleLabel: {
|
|
@@ -31,6 +36,12 @@ new Chart(document.getElementById(<%= chart_id.inspect %>).getContext('2d'),
|
|
|
31
36
|
display: true,
|
|
32
37
|
text: 'Age in days'
|
|
33
38
|
},
|
|
39
|
+
grid: {
|
|
40
|
+
color: <%= CssVariable['--grid-line-color'].to_json %>,
|
|
41
|
+
z: 1 // draw the grid lines on top of the bars
|
|
42
|
+
},
|
|
43
|
+
stacked: true,
|
|
44
|
+
max: <%= (@max_age * 1.1).to_i %>
|
|
34
45
|
}
|
|
35
46
|
},
|
|
36
47
|
plugins: {
|
|
@@ -38,14 +49,26 @@ new Chart(document.getElementById(<%= chart_id.inspect %>).getContext('2d'),
|
|
|
38
49
|
callbacks: {
|
|
39
50
|
label: function(context) {
|
|
40
51
|
if( typeof(context.dataset.data[context.dataIndex]) == "number" ) {
|
|
41
|
-
|
|
52
|
+
let full_data = <%= @bar_data.inspect %>;
|
|
53
|
+
let columnIndex = context.dataIndex;
|
|
54
|
+
let rowIndex = context.datasetIndex - <%= @row_index_offset %>;
|
|
55
|
+
return context.dataset.label + " of completed work items left this column in " +full_data[rowIndex][columnIndex] + " days or less";
|
|
42
56
|
}
|
|
43
57
|
else {
|
|
44
|
-
return context.dataset.data[context.dataIndex].title
|
|
58
|
+
return context.dataset.data[context.dataIndex].title;
|
|
45
59
|
}
|
|
46
60
|
}
|
|
47
61
|
}
|
|
62
|
+
},
|
|
63
|
+
legend: {
|
|
64
|
+
labels: {
|
|
65
|
+
filter: function(item, chart) {
|
|
66
|
+
// Logic to remove a particular legend item goes here
|
|
67
|
+
return !item.text.includes('%');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
48
70
|
}
|
|
71
|
+
|
|
49
72
|
}
|
|
50
73
|
}
|
|
51
74
|
});
|
|
@@ -1,44 +1,39 @@
|
|
|
1
|
-
<h1>Aging Work Table</h1>
|
|
2
|
-
<p>
|
|
3
|
-
This chart shows all active (started but not completed) work, ordered from oldest at the top to
|
|
4
|
-
newest at the bottom.
|
|
5
|
-
</p>
|
|
6
|
-
<p>
|
|
7
|
-
If there are expedited items that haven't yet started then they're at the bottom of the table. By the
|
|
8
|
-
very definition of expedited, if we haven't started them already, we'd better get on that.
|
|
9
|
-
</p>
|
|
10
|
-
<p>
|
|
11
|
-
<% if age_cutoff > 0 %>
|
|
12
|
-
Items less than <%= label_days age_cutoff %> old have been excluded from this chart to provide more
|
|
13
|
-
focus on the older items. The exception are items that are either expedited or blocked - these are
|
|
14
|
-
shown no matter how old they are.
|
|
15
|
-
<% end %>
|
|
16
|
-
</p>
|
|
17
|
-
|
|
18
1
|
<table class='standard'>
|
|
19
2
|
<thead>
|
|
20
3
|
<tr>
|
|
21
|
-
<th
|
|
22
|
-
<th>E</th>
|
|
23
|
-
<th>B</th>
|
|
4
|
+
<th title="Age in days">Age</th>
|
|
5
|
+
<th title="Expedited">E</th>
|
|
6
|
+
<th title="Blocked / Stalled">B/S</th>
|
|
7
|
+
<th title="Priority">P</th>
|
|
24
8
|
<th>Issue</th>
|
|
25
9
|
<th>Status</th>
|
|
10
|
+
<th>Forecast</th>
|
|
26
11
|
<th>Fix versions</th>
|
|
27
|
-
<% if any_scrum_boards
|
|
12
|
+
<% if any_scrum_boards %>
|
|
28
13
|
<th>Sprints</th>
|
|
29
14
|
<% end %>
|
|
30
15
|
<th><%= aggregated_project? ? 'Board' : 'Who' %></th>
|
|
31
16
|
</tr>
|
|
32
17
|
</thead>
|
|
33
18
|
<tbody>
|
|
19
|
+
<% show_age_cutoff_bar_at = age_cutoff %>
|
|
34
20
|
<% aging_issues.each do |issue| %>
|
|
21
|
+
<% issue_age = issue.board.cycletime.age(issue, today: @today) %>
|
|
22
|
+
<% if show_age_cutoff_bar_at && issue_age&.<(show_age_cutoff_bar_at) %>
|
|
23
|
+
<tr><th colspan=100 style="text-align: left; padding-top: 1em;">
|
|
24
|
+
The items below are less than <%= label_days age_cutoff %> old, and are only on this report
|
|
25
|
+
because they're either expedited or blocked.
|
|
26
|
+
</th></tr>
|
|
27
|
+
<% show_age_cutoff_bar_at = nil %>
|
|
28
|
+
<% end %>
|
|
35
29
|
<tr>
|
|
36
|
-
<td style="text-align: right;"><%=
|
|
30
|
+
<td style="text-align: right;"><%= issue_age || 'Not started' %></td>
|
|
37
31
|
<td><%= expedited_text(issue) %></td>
|
|
38
32
|
<td><%= blocked_text(issue) %></td>
|
|
33
|
+
<td><%= priority_text(issue) %></td>
|
|
39
34
|
<td>
|
|
40
35
|
<% parent_hierarchy(issue).each_with_index do |parent, index| %>
|
|
41
|
-
<% color =
|
|
36
|
+
<% color = parent != issue ? "var(--hierarchy-table-inactive-item-text-color)" : 'var(--default-text-color)' %>
|
|
42
37
|
<div style="padding-left: <%= index %>em; color: <%= color %>">
|
|
43
38
|
<span style="white-space: nowrap;">
|
|
44
39
|
<img src="<%= parent.type_icon_url %>" title="<%= parent.type %>"/>
|
|
@@ -48,9 +43,10 @@
|
|
|
48
43
|
</div>
|
|
49
44
|
<% end %>
|
|
50
45
|
</td>
|
|
51
|
-
<td><%= format_status issue.status
|
|
46
|
+
<td><%= format_status issue.status, board: issue.board %></td>
|
|
47
|
+
<td><%= dates_text(issue) %></td>
|
|
52
48
|
<td><%= fix_versions_text(issue) %></td>
|
|
53
|
-
<% if any_scrum_boards
|
|
49
|
+
<% if any_scrum_boards %>
|
|
54
50
|
<td><%= sprints_text(issue) %></td>
|
|
55
51
|
<% end %>
|
|
56
52
|
<td><%= aggregated_project? ? issue.board.name : issue.assigned_to %></td>
|
|
@@ -1,6 +1,57 @@
|
|
|
1
|
-
<div>
|
|
1
|
+
<div class="chart">
|
|
2
2
|
<canvas id="<%= chart_id %>" width="<%= canvas_width %>" height="<%= canvas_height %>"></canvas>
|
|
3
3
|
</div>
|
|
4
|
+
<%
|
|
5
|
+
if show_stats
|
|
6
|
+
link_id = next_id
|
|
7
|
+
issues_id = next_id
|
|
8
|
+
%>
|
|
9
|
+
[<a id='<%= link_id %>' href="#" onclick='expand_collapse("<%= link_id %>", "<%= issues_id %>"); return false;'>Show details</a>]
|
|
10
|
+
<div id="<%= issues_id %>" style="display: none;">
|
|
11
|
+
<div>
|
|
12
|
+
<table class="standard">
|
|
13
|
+
<tr>
|
|
14
|
+
<th>Issue Type</th>
|
|
15
|
+
<th>Min</th>
|
|
16
|
+
<th>Max</th>
|
|
17
|
+
<th>Avg</th>
|
|
18
|
+
<th>Mode</th>
|
|
19
|
+
<% percentiles.each do |p| %>
|
|
20
|
+
<th><%= p %>th</th>
|
|
21
|
+
<% end %>
|
|
22
|
+
</tr>
|
|
23
|
+
<% the_stats.each do |k, v| %>
|
|
24
|
+
<tr>
|
|
25
|
+
<td><%= k %></td>
|
|
26
|
+
<td style="text-align: right;"><%= v[:min] %></td>
|
|
27
|
+
<td style="text-align: right;"><%= v[:max] %></td>
|
|
28
|
+
<td style="text-align: right;"><%= sprintf('%.2f', v[:average]) %></td>
|
|
29
|
+
<td><%= v[:mode].join(', ') %></td>
|
|
30
|
+
<% percentiles.each do |p| %>
|
|
31
|
+
<td style="text-align: right;"><%= v[:percentiles][p] %></td>
|
|
32
|
+
<% end %>
|
|
33
|
+
</tr>
|
|
34
|
+
<% end %>
|
|
35
|
+
</table>
|
|
36
|
+
</div>
|
|
37
|
+
<div>
|
|
38
|
+
<p>These statistics help understand the <i>"shape"</i> of the cycletime histogram distribution, to help us with predictions.</p>
|
|
39
|
+
<ul>
|
|
40
|
+
<li><b>Min & Max:</b> the observed spread for the data set. Useful to judge how wide the variation is. </li>
|
|
41
|
+
<li><b>Average:</b> the arithmetic mean of the data set. Useful as a <i>"typical representative"</i> of the complete set.</li>
|
|
42
|
+
<li><b>Mode:</b> the most repeated value(s) in the data set. This is the value we're most likely to remember. </li>
|
|
43
|
+
<li><b>Percentiles:</b> they partition the data set. If X is the Nth percentile, it means that N% of cycletime values are X or less. Typical percentiles of interest are:</li>
|
|
44
|
+
<ul>
|
|
45
|
+
<li><b>50%</b>: also known as the <b>Median</b>. Useful to establish short feedback loops, to monitor that it's not drifting to the right.</li>
|
|
46
|
+
<li><b>85%</b>: useful to establish service level expectations, accounting for rare events..</li>
|
|
47
|
+
<li><b>98% (or higher)</b>: useful to gauge worst case expectations..</li>
|
|
48
|
+
</ul>
|
|
49
|
+
</ul>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
<%
|
|
53
|
+
end
|
|
54
|
+
%>
|
|
4
55
|
<script>
|
|
5
56
|
new Chart(document.getElementById('<%= chart_id %>').getContext('2d'),
|
|
6
57
|
{
|
|
@@ -17,17 +68,46 @@ new Chart(document.getElementById('<%= chart_id %>').getContext('2d'),
|
|
|
17
68
|
title: {
|
|
18
69
|
display: true,
|
|
19
70
|
text: 'Cycletime in days'
|
|
20
|
-
}
|
|
71
|
+
},
|
|
72
|
+
grid: {
|
|
73
|
+
color: <%= CssVariable['--grid-line-color'].to_json %>
|
|
74
|
+
},
|
|
75
|
+
min: 0,
|
|
76
|
+
offset: false, // Gets rid of the ugly padding on left.
|
|
21
77
|
},
|
|
22
78
|
y: {
|
|
23
79
|
stacked: true,
|
|
24
80
|
title: {
|
|
25
81
|
display: true,
|
|
26
82
|
text: 'Number of items that had that cycletime'
|
|
27
|
-
}
|
|
83
|
+
},
|
|
84
|
+
grid: {
|
|
85
|
+
color: <%= CssVariable['--grid-line-color'].to_json %>
|
|
86
|
+
},
|
|
28
87
|
}
|
|
29
88
|
},
|
|
30
89
|
plugins: {
|
|
90
|
+
annotation: {
|
|
91
|
+
annotations: {
|
|
92
|
+
<%
|
|
93
|
+
results = the_stats[:all][:percentiles]
|
|
94
|
+
results.each do |percentile, value|
|
|
95
|
+
%>
|
|
96
|
+
percentile<%= percentile.to_s %>: {
|
|
97
|
+
type: 'line',
|
|
98
|
+
scaleID: 'x',
|
|
99
|
+
value: <%= value %>,
|
|
100
|
+
borderWidth: 1,
|
|
101
|
+
drawTime: 'beforeDatasetsDraw',
|
|
102
|
+
label: {
|
|
103
|
+
enabled: true,
|
|
104
|
+
content: '<%= "#{percentile}%" %>',
|
|
105
|
+
position: 'start',
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
<% end %>
|
|
109
|
+
},
|
|
110
|
+
},
|
|
31
111
|
tooltip: {
|
|
32
112
|
callbacks: {
|
|
33
113
|
label: function(context) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<div>
|
|
1
|
+
<div class="chart">
|
|
2
2
|
<canvas id="<%= chart_id %>" width="<%= canvas_width %>" height="<%= canvas_height %>"></canvas>
|
|
3
3
|
</div>
|
|
4
4
|
<script>
|
|
@@ -20,6 +20,9 @@ new Chart(document.getElementById('<%= chart_id %>').getContext('2d'), {
|
|
|
20
20
|
display: true,
|
|
21
21
|
labelString: 'Date Completed'
|
|
22
22
|
},
|
|
23
|
+
grid: {
|
|
24
|
+
color: <%= CssVariable['--grid-line-color'].to_json %>
|
|
25
|
+
},
|
|
23
26
|
min: "<%= date_range.begin.to_s %>",
|
|
24
27
|
max: "<%= (date_range.end + 1).to_s %>"
|
|
25
28
|
},
|
|
@@ -34,6 +37,9 @@ new Chart(document.getElementById('<%= chart_id %>').getContext('2d'), {
|
|
|
34
37
|
display: true,
|
|
35
38
|
text: 'Cycle time in days'
|
|
36
39
|
},
|
|
40
|
+
grid: {
|
|
41
|
+
color: <%= CssVariable['--grid-line-color'].to_json %>
|
|
42
|
+
},
|
|
37
43
|
}
|
|
38
44
|
},
|
|
39
45
|
plugins: {
|
|
@@ -47,16 +53,7 @@ new Chart(document.getElementById('<%= chart_id %>').getContext('2d'), {
|
|
|
47
53
|
autocolors: false,
|
|
48
54
|
annotation: {
|
|
49
55
|
annotations: {
|
|
50
|
-
|
|
51
|
-
holiday<%= index %>: {
|
|
52
|
-
drawTime: 'beforeDraw',
|
|
53
|
-
type: 'box',
|
|
54
|
-
xMin: '<%= range.begin %>T00:00:00',
|
|
55
|
-
xMax: '<%= range.end %>T23:59:59',
|
|
56
|
-
backgroundColor: '#F0F0F0',
|
|
57
|
-
borderColor: '#F0F0F0'
|
|
58
|
-
},
|
|
59
|
-
<% end %>
|
|
56
|
+
<%= working_days_annotation %>
|
|
60
57
|
|
|
61
58
|
<% @percentage_lines.each_with_index do |args, index| %>
|
|
62
59
|
<% percent, color = args %>
|
|
@@ -64,7 +61,7 @@ new Chart(document.getElementById('<%= chart_id %>').getContext('2d'), {
|
|
|
64
61
|
type: 'line',
|
|
65
62
|
yMin: <%= percent %>,
|
|
66
63
|
yMax: <%= percent %>,
|
|
67
|
-
borderColor:
|
|
64
|
+
borderColor: <%= color.to_json %>,
|
|
68
65
|
borderWidth: 1,
|
|
69
66
|
drawTime: 'beforeDraw'
|
|
70
67
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<div>
|
|
1
|
+
<div class="chart">
|
|
2
2
|
<canvas id="<%= chart_id %>" width="<%= canvas_width %>" height="<%= canvas_height %>"></canvas>
|
|
3
3
|
</div>
|
|
4
4
|
<script>
|
|
@@ -20,7 +20,10 @@ new Chart(document.getElementById('<%= chart_id %>').getContext('2d'),
|
|
|
20
20
|
time: {
|
|
21
21
|
unit: 'day'
|
|
22
22
|
},
|
|
23
|
-
stacked: true
|
|
23
|
+
stacked: true,
|
|
24
|
+
grid: {
|
|
25
|
+
color: <%= CssVariable['--grid-line-color'].to_json %>
|
|
26
|
+
},
|
|
24
27
|
},
|
|
25
28
|
y: {
|
|
26
29
|
stacked: true,
|
|
@@ -32,7 +35,9 @@ new Chart(document.getElementById('<%= chart_id %>').getContext('2d'),
|
|
|
32
35
|
display: true,
|
|
33
36
|
text: 'Count of items'
|
|
34
37
|
},
|
|
35
|
-
|
|
38
|
+
grid: {
|
|
39
|
+
color: <%= CssVariable['--grid-line-color'].to_json %>
|
|
40
|
+
},
|
|
36
41
|
}
|
|
37
42
|
},
|
|
38
43
|
plugins: {
|
|
@@ -45,16 +50,15 @@ new Chart(document.getElementById('<%= chart_id %>').getContext('2d'),
|
|
|
45
50
|
},
|
|
46
51
|
annotation: {
|
|
47
52
|
annotations: {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
<% end %>
|
|
53
|
+
<%= working_days_annotation %>
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
legend: {
|
|
57
|
+
labels: {
|
|
58
|
+
filter: function(item, chart) {
|
|
59
|
+
// Logic to remove a particular legend item goes here
|
|
60
|
+
return !item.text.includes('Trendline');
|
|
61
|
+
}
|
|
58
62
|
}
|
|
59
63
|
}
|
|
60
64
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<div>
|
|
1
|
+
<div class="chart">
|
|
2
2
|
<canvas id="<%= chart_id %>" width="<%= canvas_width %>" height="<%= canvas_height %>"></canvas>
|
|
3
3
|
</div>
|
|
4
4
|
<script>
|
|
@@ -24,8 +24,10 @@ new Chart(document.getElementById('<%= chart_id %>').getContext('2d'), {
|
|
|
24
24
|
display: true,
|
|
25
25
|
text: "Cycletime (days)"
|
|
26
26
|
},
|
|
27
|
-
min: 0
|
|
28
|
-
|
|
27
|
+
min: 0,
|
|
28
|
+
grid: {
|
|
29
|
+
color: <%= CssVariable['--grid-line-color'].to_json %>
|
|
30
|
+
},
|
|
29
31
|
},
|
|
30
32
|
y: {
|
|
31
33
|
type: "<%= @y_axis_type %>",
|
|
@@ -40,7 +42,10 @@ new Chart(document.getElementById('<%= chart_id %>').getContext('2d'), {
|
|
|
40
42
|
display: true,
|
|
41
43
|
text: "<%= @y_axis_label %>"
|
|
42
44
|
},
|
|
43
|
-
min: 0.0
|
|
45
|
+
min: 0.0,
|
|
46
|
+
grid: {
|
|
47
|
+
color: <%= CssVariable['--grid-line-color'].to_json %>
|
|
48
|
+
},
|
|
44
49
|
}
|
|
45
50
|
},
|
|
46
51
|
plugins: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<div>
|
|
1
|
+
<div class="chart">
|
|
2
2
|
<canvas id="<%= chart_id %>" width="<%= canvas_width %>" height="<%= canvas_height %>"></canvas>
|
|
3
3
|
</div>
|
|
4
4
|
<script>
|
|
@@ -24,7 +24,10 @@ new Chart(document.getElementById('<%= chart_id %>').getContext('2d'), {
|
|
|
24
24
|
labelString: 'Date Completed'
|
|
25
25
|
},
|
|
26
26
|
min: "<%= date_range.begin.to_s %>",
|
|
27
|
-
max: "<%= date_range.end.to_s %>"
|
|
27
|
+
max: "<%= date_range.end.to_s %>",
|
|
28
|
+
grid: {
|
|
29
|
+
color: <%= CssVariable['--grid-line-color'].to_json %>
|
|
30
|
+
},
|
|
28
31
|
},
|
|
29
32
|
y: {
|
|
30
33
|
scaleLabel: {
|
|
@@ -35,7 +38,10 @@ new Chart(document.getElementById('<%= chart_id %>').getContext('2d'), {
|
|
|
35
38
|
display: true,
|
|
36
39
|
text: 'Age in days'
|
|
37
40
|
},
|
|
38
|
-
min: 0
|
|
41
|
+
min: 0,
|
|
42
|
+
grid: {
|
|
43
|
+
color: <%= CssVariable['--grid-line-color'].to_json %>
|
|
44
|
+
},
|
|
39
45
|
}
|
|
40
46
|
},
|
|
41
47
|
plugins: {
|
|
@@ -49,16 +55,7 @@ new Chart(document.getElementById('<%= chart_id %>').getContext('2d'), {
|
|
|
49
55
|
autocolors: false,
|
|
50
56
|
annotation: {
|
|
51
57
|
annotations: {
|
|
52
|
-
|
|
53
|
-
holiday<%= index %>: {
|
|
54
|
-
drawTime: 'beforeDraw',
|
|
55
|
-
type: 'box',
|
|
56
|
-
xMin: '<%= range.begin %>T00:00:00',
|
|
57
|
-
xMax: '<%= range.end %>T23:59:59',
|
|
58
|
-
backgroundColor: '#F0F0F0',
|
|
59
|
-
borderColor: '#F0F0F0'
|
|
60
|
-
},
|
|
61
|
-
<% end %>
|
|
58
|
+
<%= working_days_annotation %>
|
|
62
59
|
}
|
|
63
60
|
}
|
|
64
61
|
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<div class="chart">
|
|
2
|
+
<canvas id="<%= chart_id %>" width="<%= canvas_width %>" height="<%= canvas_height %>"></canvas>
|
|
3
|
+
</div>
|
|
4
|
+
<script>
|
|
5
|
+
new Chart(document.getElementById('<%= chart_id %>').getContext('2d'), {
|
|
6
|
+
type: 'scatter',
|
|
7
|
+
data: {
|
|
8
|
+
datasets: <%= JSON.generate(data_sets) %>
|
|
9
|
+
},
|
|
10
|
+
options: {
|
|
11
|
+
title: {
|
|
12
|
+
display: true,
|
|
13
|
+
text: "Cycletime Scatterplot"
|
|
14
|
+
},
|
|
15
|
+
responsive: <%= canvas_responsive? %>, // If responsive is true then it fills the screen
|
|
16
|
+
scales: {
|
|
17
|
+
x: {
|
|
18
|
+
scaleLabel: {
|
|
19
|
+
display: true,
|
|
20
|
+
labelString: 'Days'
|
|
21
|
+
},
|
|
22
|
+
title: {
|
|
23
|
+
display: true,
|
|
24
|
+
text: 'Total time (days)'
|
|
25
|
+
},
|
|
26
|
+
grid: {
|
|
27
|
+
color: <%= CssVariable['--grid-line-color'].to_json %>
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
},
|
|
31
|
+
y: {
|
|
32
|
+
scaleLabel: {
|
|
33
|
+
display: true,
|
|
34
|
+
labelString: 'Percentage',
|
|
35
|
+
min: 0,
|
|
36
|
+
max: <%= @highest_cycletime %>
|
|
37
|
+
},
|
|
38
|
+
title: {
|
|
39
|
+
display: true,
|
|
40
|
+
text: 'Time adding value (days)'
|
|
41
|
+
},
|
|
42
|
+
grid: {
|
|
43
|
+
color: <%= CssVariable['--grid-line-color'].to_json %>
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
plugins: {
|
|
48
|
+
tooltip: {
|
|
49
|
+
callbacks: {
|
|
50
|
+
label: function(context) {
|
|
51
|
+
return context.dataset.data[context.dataIndex].title
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
autocolors: false,
|
|
56
|
+
legend: {
|
|
57
|
+
onClick: (evt, legendItem, legend) => {
|
|
58
|
+
// Find the datasetMeta that corresponds to the item clicked
|
|
59
|
+
var i = 0
|
|
60
|
+
while(legendItem.text != legend.chart.getDatasetMeta(i).label) {
|
|
61
|
+
i++;
|
|
62
|
+
}
|
|
63
|
+
nextVisibility = !!legend.chart.getDatasetMeta(i).hidden;
|
|
64
|
+
|
|
65
|
+
// Hide/show the 85% line for that dataset
|
|
66
|
+
legend.chart.options.plugins.annotation.annotations["line"+(i/2)].display = nextVisibility;
|
|
67
|
+
|
|
68
|
+
// Hide/show the trendline for this dataset, if they were enabled. The trendline is always
|
|
69
|
+
// there but not always visible.
|
|
70
|
+
legend.chart.setDatasetVisibility(i+1, <%= !!@show_trend_lines %> && nextVisibility);
|
|
71
|
+
|
|
72
|
+
// Still run the default behaviour
|
|
73
|
+
Chart.defaults.plugins.legend.onClick(evt, legendItem, legend);
|
|
74
|
+
},
|
|
75
|
+
labels: {
|
|
76
|
+
filter: function(item, chart) {
|
|
77
|
+
// Logic to remove a particular legend item goes here
|
|
78
|
+
return !item.text.includes('Trendline');
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
</script>
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
<tr>
|
|
15
15
|
<td style="text-align: right;"><%= issue.board.cycletime.age(issue, today: @today) || 'Not started' %></td>
|
|
16
16
|
<td>
|
|
17
|
-
<% color = (node.children?
|
|
17
|
+
<% color = "var(--hierarchy-table-#{ 'in' if node.children? }active-item-text-color)" %>
|
|
18
18
|
<span style="padding-left: <%= depth - 1 %>em;" />
|
|
19
19
|
<span style="white-space: nowrap;">
|
|
20
20
|
<img src="<%= issue.type_icon_url %>" title="<%= issue.type %>"/>
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
</span>
|
|
23
23
|
</td>
|
|
24
24
|
<td><span style="color: <%= color %>; font-style: italic;"><%= issue.summary[0..80] %></span></td>
|
|
25
|
-
<td><%= format_status issue.status
|
|
25
|
+
<td><%= format_status issue.status, board: issue.board %></td>
|
|
26
26
|
</tr>
|
|
27
27
|
<% end %>
|
|
28
28
|
</tbody>
|