jirametrics 2.0 → 2.11

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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/lib/jirametrics/aggregate_config.rb +19 -26
  3. data/lib/jirametrics/aging_work_bar_chart.rb +79 -54
  4. data/lib/jirametrics/aging_work_in_progress_chart.rb +106 -40
  5. data/lib/jirametrics/aging_work_table.rb +78 -43
  6. data/lib/jirametrics/anonymizer.rb +6 -5
  7. data/lib/jirametrics/blocked_stalled_change.rb +24 -4
  8. data/lib/jirametrics/board.rb +44 -15
  9. data/lib/jirametrics/board_config.rb +8 -4
  10. data/lib/jirametrics/board_movement_calculator.rb +147 -0
  11. data/lib/jirametrics/change_item.rb +31 -10
  12. data/lib/jirametrics/chart_base.rb +102 -61
  13. data/lib/jirametrics/columns_config.rb +4 -0
  14. data/lib/jirametrics/css_variable.rb +33 -0
  15. data/lib/jirametrics/cycletime_config.rb +59 -8
  16. data/lib/jirametrics/cycletime_histogram.rb +69 -4
  17. data/lib/jirametrics/cycletime_scatterplot.rb +11 -15
  18. data/lib/jirametrics/daily_wip_by_age_chart.rb +44 -20
  19. data/lib/jirametrics/daily_wip_by_blocked_stalled_chart.rb +37 -35
  20. data/lib/jirametrics/daily_wip_by_parent_chart.rb +38 -0
  21. data/lib/jirametrics/daily_wip_chart.rb +61 -14
  22. data/lib/jirametrics/data_quality_report.rb +222 -41
  23. data/lib/jirametrics/dependency_chart.rb +54 -23
  24. data/lib/jirametrics/download_config.rb +12 -0
  25. data/lib/jirametrics/downloader.rb +76 -57
  26. data/lib/jirametrics/{story_point_accuracy_chart.rb → estimate_accuracy_chart.rb} +48 -33
  27. data/lib/jirametrics/examples/aggregated_project.rb +22 -39
  28. data/lib/jirametrics/examples/standard_project.rb +25 -49
  29. data/lib/jirametrics/expedited_chart.rb +28 -25
  30. data/lib/jirametrics/exporter.rb +59 -32
  31. data/lib/jirametrics/file_config.rb +34 -13
  32. data/lib/jirametrics/file_system.rb +48 -3
  33. data/lib/jirametrics/flow_efficiency_scatterplot.rb +111 -0
  34. data/lib/jirametrics/groupable_issue_chart.rb +2 -6
  35. data/lib/jirametrics/grouping_rules.rb +7 -1
  36. data/lib/jirametrics/hierarchy_table.rb +4 -4
  37. data/lib/jirametrics/html/aging_work_bar_chart.erb +13 -16
  38. data/lib/jirametrics/html/aging_work_in_progress_chart.erb +28 -5
  39. data/lib/jirametrics/html/aging_work_table.erb +19 -25
  40. data/lib/jirametrics/html/cycletime_histogram.erb +83 -3
  41. data/lib/jirametrics/html/cycletime_scatterplot.erb +9 -12
  42. data/lib/jirametrics/html/daily_wip_chart.erb +17 -13
  43. data/lib/jirametrics/html/{story_point_accuracy_chart.erb → estimate_accuracy_chart.erb} +9 -4
  44. data/lib/jirametrics/html/expedited_chart.erb +10 -13
  45. data/lib/jirametrics/html/flow_efficiency_scatterplot.erb +85 -0
  46. data/lib/jirametrics/html/hierarchy_table.erb +2 -2
  47. data/lib/jirametrics/html/index.css +209 -0
  48. data/lib/jirametrics/html/index.erb +16 -39
  49. data/lib/jirametrics/html/sprint_burndown.erb +10 -14
  50. data/lib/jirametrics/html/throughput_chart.erb +10 -13
  51. data/lib/jirametrics/html_report_config.rb +108 -86
  52. data/lib/jirametrics/issue.rb +357 -96
  53. data/lib/jirametrics/jira_gateway.rb +29 -11
  54. data/lib/jirametrics/project_config.rb +256 -144
  55. data/lib/jirametrics/rules.rb +2 -2
  56. data/lib/jirametrics/self_or_issue_dispatcher.rb +2 -0
  57. data/lib/jirametrics/settings.json +10 -0
  58. data/lib/jirametrics/sprint_burndown.rb +24 -7
  59. data/lib/jirametrics/status.rb +84 -19
  60. data/lib/jirametrics/status_collection.rb +80 -39
  61. data/lib/jirametrics/throughput_chart.rb +12 -4
  62. data/lib/jirametrics/value_equality.rb +2 -2
  63. data/lib/jirametrics.rb +25 -7
  64. metadata +16 -17
  65. data/lib/jirametrics/discard_changes_before.rb +0 -37
  66. data/lib/jirametrics/experimental/generator.rb +0 -210
  67. data/lib/jirametrics/experimental/info.rb +0 -77
  68. data/lib/jirametrics/html/data_quality_report.erb +0 -126
@@ -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: [<%= column_headings.collect(&:inspect).join(',') %>],
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
- return "85% of the issues, leave this column in "+context.dataset.data[context.dataIndex]+" days";
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,37 @@
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>Age (days)</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>
24
7
  <th>Issue</th>
25
8
  <th>Status</th>
9
+ <th>Forecast</th>
26
10
  <th>Fix versions</th>
27
- <% if any_scrum_boards? %>
11
+ <% if any_scrum_boards %>
28
12
  <th>Sprints</th>
29
13
  <% end %>
30
14
  <th><%= aggregated_project? ? 'Board' : 'Who' %></th>
31
15
  </tr>
32
16
  </thead>
33
17
  <tbody>
18
+ <% show_age_cutoff_bar_at = age_cutoff %>
34
19
  <% aging_issues.each do |issue| %>
20
+ <% issue_age = issue.board.cycletime.age(issue, today: @today) %>
21
+ <% if show_age_cutoff_bar_at && issue_age&.<(show_age_cutoff_bar_at) %>
22
+ <tr><th colspan=100 style="text-align: left; padding-top: 1em;">
23
+ The items below are less than <%= label_days age_cutoff %> old, and are only on this report
24
+ because they're either expedited or blocked.
25
+ </th></tr>
26
+ <% show_age_cutoff_bar_at = nil %>
27
+ <% end %>
35
28
  <tr>
36
- <td style="text-align: right;"><%= issue.board.cycletime.age(issue, today: @today) || 'Not started' %></td>
29
+ <td style="text-align: right;"><%= issue_age || 'Not started' %></td>
37
30
  <td><%= expedited_text(issue) %></td>
38
31
  <td><%= blocked_text(issue) %></td>
39
32
  <td>
40
33
  <% parent_hierarchy(issue).each_with_index do |parent, index| %>
41
- <% color = (parent == issue ? 'black' : 'gray') %>
34
+ <% color = parent != issue ? "var(--hierarchy-table-inactive-item-text-color)" : 'var(--default-text-color)' %>
42
35
  <div style="padding-left: <%= index %>em; color: <%= color %>">
43
36
  <span style="white-space: nowrap;">
44
37
  <img src="<%= parent.type_icon_url %>" title="<%= parent.type %>"/>
@@ -48,9 +41,10 @@
48
41
  </div>
49
42
  <% end %>
50
43
  </td>
51
- <td><%= format_status issue.status.name, board: issue.board %><%= unmapped_status_text(issue) unless current_status_visible? issue %></td>
44
+ <td><%= format_status issue.status, board: issue.board %></td>
45
+ <td><%= dates_text(issue) %></td>
52
46
  <td><%= fix_versions_text(issue) %></td>
53
- <% if any_scrum_boards? %>
47
+ <% if any_scrum_boards %>
54
48
  <td><%= sprints_text(issue) %></td>
55
49
  <% end %>
56
50
  <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
- <% holidays.each_with_index do |range, index| %>
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: '<%= color %>',
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
- <% holidays.each_with_index do |range, index| %>
49
- holiday<%= index %>: {
50
- drawTime: 'beforeDraw',
51
- type: 'box',
52
- xMin: '<%= range.begin %>T00:00:00',
53
- xMax: '<%= range.end %>T23:59:59',
54
- backgroundColor: '#F0F0F0',
55
- borderColor: '#F0F0F0'
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
- <% holidays.each_with_index do |range, index| %>
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? ? 'gray' : 'black') %>
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.name, board: issue.board %></td>
25
+ <td><%= format_status issue.status, board: issue.board %></td>
26
26
  </tr>
27
27
  <% end %>
28
28
  </tbody>