jirametrics 2.29.2 → 2.30

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4b85b61821add760ea7d427236007207fa161d5e2f80c04f99b8dda1c9bc6118
4
- data.tar.gz: 6afeded710d46ba016e28500ff771a8c6c16f99f68ae40d7cc4435a193261958
3
+ metadata.gz: a1f64f63f13e8cb59d3b18fb1e1ad90f77ca06d0e2f59a75ff7b7bae4db1870f
4
+ data.tar.gz: 9b7d6b8759102d7590e86c114d2ac8b1b2e7c4cc9f45a168002752196a6bf797
5
5
  SHA512:
6
- metadata.gz: 7fb8fd29609fb8a4f5a13c0dee6167322d91072ef7dbd438455f2cb24181aad6e5a62d226eef6e6f4787173b8ce0cd756535c6eccf94587f2675c5a3509d81c8
7
- data.tar.gz: 5875777fcb72109e91646e0346cf7a6b192061fe752dc818533225421cf82d5182ddd8d644c57a183d6b3fb938aff341c5849b43116c1728048d2f75e5bab9b9
6
+ metadata.gz: 8ec0bee468f8c34c001ea9151b0d78b1018d246cc86f9c2588a70ee55e3940b6263f69032884ec5c2dc596d3182909829f6ee63fe51b6c65444ce667bf70a6ca
7
+ data.tar.gz: 9b9f5337d0fc671639f9f651977cb2ecc60b2d27105cdce1b75a2a4188c093c111ba29ed880adccb515d548b8bd9209b4cf703482a0ede4ccea6b182212a3a57
@@ -1,6 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ChartBase
4
+ # Okabe-Ito palette — perceptually distinct under the most common forms of colour blindness.
5
+ # Ordered from most- to least-commonly useful for chart series.
6
+ OKABE_ITO_PALETTE = %w[
7
+ #0072B2
8
+ #E69F00
9
+ #009E73
10
+ #56B4E9
11
+ #D55E00
12
+ #CC79A7
13
+ #F0E442
14
+ ].freeze
4
15
  attr_accessor :timezone_offset, :board_id, :all_boards, :date_range,
5
16
  :time_range, :data_quality, :holiday_dates, :settings, :issues, :file_system,
6
17
  :atlassian_document_format, :x_axis_title, :y_axis_title, :fix_versions
@@ -328,7 +339,8 @@ class ChartBase
328
339
  end
329
340
 
330
341
  def random_color
331
- "##{Random.bytes(3).unpack1('H*')}"
342
+ @palette_index = (@palette_index || -1) + 1
343
+ OKABE_ITO_PALETTE[@palette_index % OKABE_ITO_PALETTE.size]
332
344
  end
333
345
 
334
346
  def canvas width:, height:, responsive: true
@@ -25,7 +25,7 @@ class DownloaderForDataCenter < Downloader
25
25
  keys_to_request = @issue_keys_pending_download[0..99]
26
26
  @issue_keys_pending_download.reject! { |key| keys_to_request.include? key }
27
27
  jql = "key in (#{keys_to_request.join(', ')})"
28
- jira_search_by_jql(jql: jql, initial_query: false, board: board, path: path)
28
+ jira_search_by_jql(jql: jql, initial_query: true, board: board, path: path)
29
29
  end
30
30
  end
31
31
 
@@ -10,6 +10,7 @@ class Exporter
10
10
  logfile_name = 'jirametrics.log'
11
11
  logfile = File.open(logfile_name, 'w')
12
12
  rescue Errno::EACCES
13
+ # FileSystem can't be used here — it hasn't been created yet (it depends on this logfile).
13
14
  warn "Error: Cannot write to #{File.expand_path(logfile_name)}. " \
14
15
  'Please ensure the current directory is writable.'
15
16
  exit 1
@@ -72,18 +73,23 @@ class Exporter
72
73
 
73
74
  def info key, name_filter:
74
75
  selected = []
76
+ file_system.log_only = true
75
77
  each_project_config(name_filter: name_filter) do |project|
76
78
  project.evaluate_next_level
77
79
 
78
80
  project.run load_only: true
79
81
  project.issues.each do |issue|
80
82
  selected << [project, issue] if key == issue.key
83
+ issue.subtasks.each do |subtask|
84
+ selected << [project, subtask] if key == subtask.key
85
+ end
81
86
  end
82
87
  rescue => e # rubocop:disable Style/RescueStandardError
83
88
  # This happens when we're attempting to load an aggregated project because it hasn't been
84
89
  # properly initialized. Since we don't care about aggregated projects, we just ignore it.
85
90
  raise unless e.message.start_with? 'This is an aggregated project and issues should have been included'
86
91
  end
92
+ file_system.log_only = false
87
93
 
88
94
  if selected.empty?
89
95
  file_system.log "No issues found to match #{key.inspect}"
@@ -65,22 +65,20 @@ class FileConfig
65
65
  # most common usecase - the Team Dashboard from FocusedObjective.com. The rule for that one
66
66
  # is that all empty values in the first column should be at the bottom.
67
67
  def sort_output all_lines
68
- all_lines.sort do |a, b|
69
- result = nil
70
- if a[0] == b[0]
71
- result = a[1..] <=> b[1..]
68
+ all_lines.each_with_index.sort do |(a, a_idx), (b, b_idx)|
69
+ result = if a[0] == b[0]
70
+ a[1..] <=> b[1..]
72
71
  elsif a[0].nil?
73
- result = 1
72
+ 1
74
73
  elsif b[0].nil?
75
- result = -1
74
+ -1
76
75
  else
77
- result = a[0] <=> b[0]
76
+ a[0] <=> b[0]
78
77
  end
79
78
 
80
- # This will only happen if one of the objects isn't comparable. Seen in production.
81
- result = -1 if result.nil?
82
- result
83
- end
79
+ # When objects aren't comparable, preserve original order for a stable sort.
80
+ result.nil? || result.zero? ? a_idx <=> b_idx : result
81
+ end.map(&:first)
84
82
  end
85
83
 
86
84
  def columns &block
@@ -7,47 +7,47 @@
7
7
  --cycletime-scatterplot-overall-trendline-color: gray;
8
8
 
9
9
  --non-working-days-color: #F0F0F0;
10
- --expedited-color: red;
11
- --blocked-color: #FF7400;
12
- --stalled-color: orange;
10
+ --expedited-color: #D55E00; /* Okabe-Ito vermilion */
11
+ --blocked-color: #D55E00; /* Okabe-Ito vermilion */
12
+ --stalled-color: #E69F00; /* Okabe-Ito orange */
13
13
  --dead-color: black;
14
14
 
15
- --type-story-color: #4bc14b;
16
- --type-task-color: blue;
17
- --type-bug-color: orange;
18
- --type-spike-color: #9400D3;
15
+ --type-story-color: #009E73; /* Okabe-Ito bluish green */
16
+ --type-task-color: #0072B2; /* Okabe-Ito blue */
17
+ --type-bug-color: #D55E00; /* Okabe-Ito vermilion */
18
+ --type-spike-color: #CC79A7; /* Okabe-Ito reddish purple */
19
19
 
20
20
  --status-category-todo-color: gray;
21
- --status-category-inprogress-color: #2663ff;
22
- --status-category-done-color: #00ff00;
21
+ --status-category-inprogress-color: #0072B2; /* Okabe-Ito blue */
22
+ --status-category-done-color: #009E73; /* Okabe-Ito bluish green */
23
23
  --status-category-unknown-color: black;
24
24
 
25
- --aging-work-bar-chart-percentage-line-color: red;
25
+ --aging-work-bar-chart-percentage-line-color: #D55E00; /* Okabe-Ito vermilion */
26
26
  --aging-work-bar-chart-separator-color: white;
27
27
 
28
28
  --throughput_chart_total_line_color: gray;
29
-
29
+
30
30
  --aging-work-in-progress-chart-shading-color: lightgray;
31
- --aging-work-in-progress-chart-shading-50-color: #2E8BC0; // green;
32
- --aging-work-in-progress-chart-shading-85-color: #ADD8E6; // yellow;
33
- --aging-work-in-progress-chart-shading-98-color: #FF8A8A; // orange;
34
- --aging-work-in-progress-chart-shading-100-color: #FF2E2E; // red;
35
-
31
+ --aging-work-in-progress-chart-shading-50-color: #56B4E9; /* Okabe-Ito sky blue */
32
+ --aging-work-in-progress-chart-shading-85-color: #F0E442; /* Okabe-Ito yellow */
33
+ --aging-work-in-progress-chart-shading-98-color: #E69F00; /* Okabe-Ito orange */
34
+ --aging-work-in-progress-chart-shading-100-color: #D55E00; /* Okabe-Ito vermilion */
35
+
36
36
  --aging-work-in-progress-by-age-trend-line-color: gray;
37
-
38
- --aging-work-table-date-in-jeopardy: yellow;
39
- --aging-work-table-date-overdue: red;
37
+
38
+ --aging-work-table-date-in-jeopardy: #F0E442; /* Okabe-Ito yellow */
39
+ --aging-work-table-date-overdue: #D55E00; /* Okabe-Ito vermilion */
40
40
 
41
41
  --hierarchy-table-inactive-item-text-color: gray;
42
42
 
43
- --wip-chart-completed-color: #00ff00;
44
- --wip-chart-completed-but-not-started-color: #99FF99;
45
- --wip-chart-duration-less-than-day-color: #ffef41;
46
- --wip-chart-duration-week-or-less-color: #dcc900;
47
- --wip-chart-duration-two-weeks-or-less-color: #dfa000;
48
- --wip-chart-duration-four-weeks-or-less-color: #eb7200;
49
- --wip-chart-duration-more-than-four-weeks-color: #e70000;
50
- --wip-chart-active-color: #326cff;
43
+ --wip-chart-completed-color: #009E73; /* Okabe-Ito bluish green */
44
+ --wip-chart-completed-but-not-started-color: #92D9C0; /* light bluish green */
45
+ --wip-chart-duration-less-than-day-color: #56B4E9; /* Okabe-Ito sky blue */
46
+ --wip-chart-duration-week-or-less-color: #F0E442; /* Okabe-Ito yellow */
47
+ --wip-chart-duration-two-weeks-or-less-color: #E69F00; /* Okabe-Ito orange */
48
+ --wip-chart-duration-four-weeks-or-less-color: #D55E00; /* Okabe-Ito vermilion */
49
+ --wip-chart-duration-more-than-four-weeks-color: #CC79A7; /* Okabe-Ito reddish purple */
50
+ --wip-chart-active-color: #0072B2; /* Okabe-Ito blue */
51
51
  --wip-chart-border-color: gray;
52
52
 
53
53
  --wip-by-column-chart-bar-fill-color: #0072B2; /* Okabe-Ito blue */
@@ -55,28 +55,30 @@
55
55
  --wip-by-column-chart-limit-line-color: #D55E00; /* Okabe-Ito vermilion */
56
56
  --wip-by-column-chart-recommendation-color: #009E73; /* Okabe-Ito bluish green */
57
57
 
58
- --estimate-accuracy-chart-completed-fill-color: #00ff00;
59
- --estimate-accuracy-chart-completed-border-color: green;
60
- --estimate-accuracy-chart-active-fill-color: #FFCCCB;
61
- --estimate-accuracy-chart-active-border-color: red;
58
+ --estimate-accuracy-chart-completed-fill-color: #92D9C0; /* light bluish green */
59
+ --estimate-accuracy-chart-completed-border-color: #009E73; /* Okabe-Ito bluish green */
60
+ --estimate-accuracy-chart-active-fill-color: #F4C6AD; /* light vermilion */
61
+ --estimate-accuracy-chart-active-border-color: #D55E00; /* Okabe-Ito vermilion */
62
62
 
63
63
  --expedited-chart-no-longer-expedited: gray;
64
- --expedited-chart-dot-issue-started-color: orange;
65
- --expedited-chart-dot-issue-stopped-color: green;
66
- --expedited-chart-dot-expedite-started-color: red;
67
- --expedited-chart-dot-expedite-stopped-color: green;
64
+ --expedited-chart-dot-issue-started-color: #E69F00; /* Okabe-Ito orange */
65
+ --expedited-chart-dot-issue-stopped-color: #009E73; /* Okabe-Ito bluish green */
66
+ --expedited-chart-dot-expedite-started-color: #D55E00; /* Okabe-Ito vermilion */
67
+ --expedited-chart-dot-expedite-stopped-color: #009E73; /* Okabe-Ito bluish green */
68
68
 
69
- --sprint-burndown-sprint-color-1: blue;
70
- --sprint-burndown-sprint-color-2: orange;
71
- --sprint-burndown-sprint-color-3: green;
72
- --sprint-burndown-sprint-color-4: red;
73
- --sprint-burndown-sprint-color-5: brown;
69
+ --sprint-burndown-sprint-color-1: #0072B2; /* Okabe-Ito blue */
70
+ --sprint-burndown-sprint-color-2: #E69F00; /* Okabe-Ito orange */
71
+ --sprint-burndown-sprint-color-3: #009E73; /* Okabe-Ito bluish green */
72
+ --sprint-burndown-sprint-color-4: #D55E00; /* Okabe-Ito vermilion */
73
+ --sprint-burndown-sprint-color-5: #CC79A7; /* Okabe-Ito reddish purple */
74
+ --sprint-burndown-sprint-color-6: #56B4E9; /* Okabe-Ito sky blue */
75
+ --sprint-burndown-sprint-color-7: #F0E442; /* Okabe-Ito yellow */
74
76
 
75
- --sprint-color: lightblue;
77
+ --sprint-color: #56B4E9; /* Okabe-Ito sky blue */
76
78
 
77
79
  --daily-view-selected-issue-background: lightgray;
78
- --daily-view-issue-border: green;
79
- --daily-view-selected-issue-border: red;
80
+ --daily-view-issue-border: #009E73; /* Okabe-Ito bluish green */
81
+ --daily-view-selected-issue-border: #D55E00; /* Okabe-Ito vermilion */
80
82
 
81
83
  /* The first five are the standard priorities that Jira creates by default. */
82
84
  --priority-color-highest: #dc2626; /* red-600 - urgent red */
@@ -226,29 +228,39 @@ div.child_issue {
226
228
  html[data-theme="dark"] {
227
229
  --warning-banner: #9F2B00;
228
230
  --non-working-days-color: #2f2f2f;
229
- --type-story-color: #6fb86f;
230
- --type-task-color: #0021b3;
231
- --type-bug-color: #bb5603;
231
+ --type-story-color: #2DCB9A; /* lighter bluish green for dark bg */
232
+ --type-task-color: #56B4E9; /* sky blue for dark bg */
233
+ --type-bug-color: #E69F00; /* orange instead of vermilion for dark bg */
232
234
  --body-background: #343434;
233
235
  --default-text-color: #aaa;
234
236
  --grid-line-color: #424242;
235
- --expedited-color: #b90000;
236
- --blocked-color: #c75b02;
237
- --stalled-color: #ae7202;
238
- --wip-chart-active-color: #2551c1;
239
- --status-category-inprogress-color: #1c49bb;
237
+ --expedited-color: #E69F00; /* Okabe-Ito orange for dark bg */
238
+ --blocked-color: #E69F00; /* Okabe-Ito orange for dark bg */
239
+ --stalled-color: #F0E442; /* Okabe-Ito yellow — distinct from blocked */
240
+ --wip-chart-active-color: #56B4E9; /* sky blue for dark bg */
241
+ --status-category-inprogress-color: #56B4E9; /* sky blue for dark bg */
242
+ --status-category-done-color: #2DCB9A; /* lighter bluish green for dark bg */
240
243
  --hierarchy-table-inactive-item-text-color: #939393;
241
244
  --wip-by-column-chart-bar-fill-color: #56B4E9; /* Okabe-Ito sky blue */
242
245
  --wip-by-column-chart-bar-text-color: #000000;
243
246
  --wip-by-column-chart-limit-line-color: #E69F00; /* Okabe-Ito orange */
244
247
  --wip-by-column-chart-recommendation-color: #2DCB9A; /* lighter bluish green for dark bg */
245
- --wip-chart-completed-color: #03cb03;
246
- --wip-chart-duration-less-than-day-color: #d2d988;
247
- --wip-chart-duration-week-or-less-color: #dfcd00;
248
- --wip-chart-duration-two-weeks-or-less-color: #cf9400;
249
- --wip-chart-duration-four-weeks-or-less-color: #c25e00;
250
- --wip-chart-duration-more-than-four-weeks-color: #8e0000;
248
+ --wip-chart-completed-color: #2DCB9A; /* lighter bluish green */
249
+ --wip-chart-duration-more-than-four-weeks-color: #DE9AC4; /* lighter reddish purple */
250
+ --estimate-accuracy-chart-completed-border-color: #2DCB9A;
251
+ --estimate-accuracy-chart-active-border-color: #E69F00;
252
+ --expedited-chart-dot-issue-stopped-color: #2DCB9A;
253
+ --expedited-chart-dot-expedite-started-color: #E69F00;
254
+ --expedited-chart-dot-expedite-stopped-color: #2DCB9A;
255
+ --sprint-burndown-sprint-color-1: #56B4E9; /* sky blue */
256
+ --sprint-burndown-sprint-color-3: #2DCB9A; /* lighter bluish green */
257
+ --sprint-burndown-sprint-color-4: #CC79A7; /* reddish purple (vermilion → orange conflicts with color-2) */
258
+ --sprint-burndown-sprint-color-5: #F0E442; /* yellow */
259
+ --sprint-burndown-sprint-color-6: #D55E00; /* vermilion (sky blue conflicts with color-1) */
260
+ --sprint-burndown-sprint-color-7: #92D9C0; /* light teal (yellow conflicts with color-5) */
251
261
  --daily-view-selected-issue-background: #474747;
262
+ --daily-view-issue-border: #2DCB9A;
263
+ --daily-view-selected-issue-border: #E69F00;
252
264
  --priority-color-highest: #ef4444;
253
265
  --priority-color-high: #f97316;
254
266
  --priority-color-low: #06b6d4;
@@ -271,29 +283,33 @@ html[data-theme="dark"] {
271
283
  html[data-theme="light"] {
272
284
  --warning-banner: yellow;
273
285
  --non-working-days-color: #F0F0F0;
274
- --type-story-color: #4bc14b;
275
- --type-task-color: blue;
276
- --type-bug-color: orange;
286
+ --type-story-color: #009E73; /* Okabe-Ito bluish green */
287
+ --type-task-color: #0072B2; /* Okabe-Ito blue */
288
+ --type-bug-color: #D55E00; /* Okabe-Ito vermilion */
277
289
  --body-background: white;
278
290
  --default-text-color: black;
279
291
  --grid-line-color: lightgray;
280
- --expedited-color: red;
281
- --blocked-color: #FF7400;
282
- --stalled-color: orange;
283
- --wip-chart-active-color: #326cff;
284
- --status-category-inprogress-color: #2663ff;
292
+ --expedited-color: #D55E00; /* Okabe-Ito vermilion */
293
+ --blocked-color: #D55E00; /* Okabe-Ito vermilion */
294
+ --stalled-color: #E69F00; /* Okabe-Ito orange */
295
+ --wip-chart-active-color: #0072B2; /* Okabe-Ito blue */
296
+ --status-category-inprogress-color: #0072B2; /* Okabe-Ito blue */
297
+ --status-category-done-color: #009E73; /* Okabe-Ito bluish green */
285
298
  --hierarchy-table-inactive-item-text-color: gray;
286
299
  --wip-by-column-chart-bar-fill-color: #0072B2;
287
300
  --wip-by-column-chart-bar-text-color: #ffffff;
288
301
  --wip-by-column-chart-limit-line-color: #D55E00;
289
302
  --wip-by-column-chart-recommendation-color: #009E73;
290
- --wip-chart-completed-color: #00ff00;
291
- --wip-chart-duration-less-than-day-color: #ffef41;
292
- --wip-chart-duration-week-or-less-color: #dcc900;
293
- --wip-chart-duration-two-weeks-or-less-color: #dfa000;
294
- --wip-chart-duration-four-weeks-or-less-color: #eb7200;
295
- --wip-chart-duration-more-than-four-weeks-color: #e70000;
303
+ --wip-chart-completed-color: #009E73; /* Okabe-Ito bluish green */
304
+ --wip-chart-completed-but-not-started-color: #92D9C0;
305
+ --wip-chart-duration-less-than-day-color: #56B4E9;
306
+ --wip-chart-duration-week-or-less-color: #F0E442;
307
+ --wip-chart-duration-two-weeks-or-less-color: #E69F00;
308
+ --wip-chart-duration-four-weeks-or-less-color: #D55E00;
309
+ --wip-chart-duration-more-than-four-weeks-color: #CC79A7;
296
310
  --daily-view-selected-issue-background: lightgray;
311
+ --daily-view-issue-border: #009E73;
312
+ --daily-view-selected-issue-border: #D55E00;
297
313
  --priority-color-highest: #dc2626;
298
314
  --priority-color-high: #ea580c;
299
315
  --priority-color-low: #0891b2;
@@ -349,21 +365,22 @@ html[data-theme="light"] {
349
365
  --warning-banner: #9F2B00;
350
366
 
351
367
  --non-working-days-color: #2f2f2f;
352
- --type-story-color: #6fb86f;
353
- --type-task-color: #0021b3;
354
- --type-bug-color: #bb5603;
368
+ --type-story-color: #2DCB9A; /* lighter bluish green for dark bg */
369
+ --type-task-color: #56B4E9; /* sky blue for dark bg */
370
+ --type-bug-color: #E69F00; /* orange instead of vermilion for dark bg */
355
371
 
356
372
  --body-background: #343434;
357
373
  --default-text-color: #aaa;
358
374
  --grid-line-color: #424242;
359
375
 
360
- --expedited-color: #b90000;
361
- --blocked-color: #c75b02;
362
- --stalled-color: #ae7202;
376
+ --expedited-color: #E69F00; /* Okabe-Ito orange for dark bg */
377
+ --blocked-color: #E69F00; /* Okabe-Ito orange for dark bg */
378
+ --stalled-color: #F0E442; /* Okabe-Ito yellow — distinct from blocked */
363
379
  --dead-color: black;
364
- --wip-chart-active-color: #2551c1;
380
+ --wip-chart-active-color: #56B4E9; /* sky blue for dark bg */
365
381
 
366
- --status-category-inprogress-color: #1c49bb;
382
+ --status-category-inprogress-color: #56B4E9; /* sky blue for dark bg */
383
+ --status-category-done-color: #2DCB9A; /* lighter bluish green for dark bg */
367
384
 
368
385
  --wip-by-column-chart-bar-fill-color: #56B4E9;
369
386
  --wip-by-column-chart-bar-text-color: #000000;
@@ -374,21 +391,37 @@ html[data-theme="light"] {
374
391
 
375
392
  --hierarchy-table-inactive-item-text-color: #939393;
376
393
 
377
- --wip-chart-completed-color: #03cb03;
378
- --wip-chart-completed-but-not-started-color: #99FF99;
379
- --wip-chart-duration-less-than-day-color: #d2d988;
380
- --wip-chart-duration-week-or-less-color: #dfcd00;
381
- --wip-chart-duration-two-weeks-or-less-color: #cf9400;
382
- --wip-chart-duration-four-weeks-or-less-color: #c25e00;
383
- --wip-chart-duration-more-than-four-weeks-color: #8e0000;
394
+ --wip-chart-completed-color: #2DCB9A; /* lighter bluish green */
395
+ --wip-chart-completed-but-not-started-color: #92D9C0;
396
+ --wip-chart-duration-less-than-day-color: #56B4E9;
397
+ --wip-chart-duration-week-or-less-color: #F0E442;
398
+ --wip-chart-duration-two-weeks-or-less-color: #E69F00;
399
+ --wip-chart-duration-four-weeks-or-less-color: #D55E00;
400
+ --wip-chart-duration-more-than-four-weeks-color: #DE9AC4; /* lighter reddish purple */
401
+
402
+ --estimate-accuracy-chart-completed-border-color: #2DCB9A;
403
+ --estimate-accuracy-chart-active-border-color: #E69F00;
404
+
405
+ --expedited-chart-dot-issue-stopped-color: #2DCB9A;
406
+ --expedited-chart-dot-expedite-started-color: #E69F00;
407
+ --expedited-chart-dot-expedite-stopped-color: #2DCB9A;
408
+
409
+ --sprint-burndown-sprint-color-1: #56B4E9; /* sky blue */
410
+ --sprint-burndown-sprint-color-3: #2DCB9A; /* lighter bluish green */
411
+ --sprint-burndown-sprint-color-4: #CC79A7; /* reddish purple (vermilion → orange conflicts with color-2) */
412
+ --sprint-burndown-sprint-color-5: #F0E442; /* yellow */
413
+ --sprint-burndown-sprint-color-6: #D55E00; /* vermilion (sky blue conflicts with color-1) */
414
+ --sprint-burndown-sprint-color-7: #92D9C0; /* light teal (yellow conflicts with color-5) */
384
415
 
385
416
  --daily-view-selected-issue-background: #474747;
417
+ --daily-view-issue-border: #2DCB9A;
418
+ --daily-view-selected-issue-border: #E69F00;
386
419
 
387
420
  --priority-color-highest: #ef4444; /* red-500 - bright urgent red */
388
421
  --priority-color-high: #f97316; /* orange-500 - bright orange */
389
422
  --priority-color-medium: #9ca3af; /* gray-400 - neutral light gray */
390
423
  --priority-color-low: #06b6d4; /* cyan-500 - bright calm blue */
391
- --priority-color-lowest: #94a3b8; /* slate-400 - muted light slate */
424
+ --priority-color-lowest: #94a3b8; /* slate-400 - muted light slate */
392
425
  }
393
426
 
394
427
  a[href] {
@@ -424,4 +457,4 @@ html[data-theme="light"] {
424
457
  }
425
458
  }
426
459
 
427
- }
460
+ }
@@ -0,0 +1,174 @@
1
+ /* Legacy color scheme for jirametrics
2
+ *
3
+ * The default colors were updated to improve accessibility for people with
4
+ * color vision deficiencies. If you prefer the original colors, add this to
5
+ * your project config:
6
+ *
7
+ * setting['include_css'] = './legacy_colors.css'
8
+ *
9
+ * and copy this file to the same directory as your config file.
10
+ */
11
+
12
+ /* Light mode */
13
+ :root,
14
+ html[data-theme="light"] {
15
+ --body-background: white;
16
+ --default-text-color: black;
17
+ --grid-line-color: lightgray;
18
+ --warning-banner: yellow;
19
+
20
+ --cycletime-scatterplot-overall-trendline-color: gray;
21
+
22
+ --non-working-days-color: #F0F0F0;
23
+ --expedited-color: red;
24
+ --blocked-color: #FF7400;
25
+ --stalled-color: orange;
26
+ --dead-color: black;
27
+
28
+ --type-story-color: #4bc14b;
29
+ --type-task-color: blue;
30
+ --type-bug-color: orange;
31
+ --type-spike-color: #9400D3;
32
+
33
+ --status-category-todo-color: gray;
34
+ --status-category-inprogress-color: #2663ff;
35
+ --status-category-done-color: #00ff00;
36
+ --status-category-unknown-color: black;
37
+
38
+ --aging-work-bar-chart-percentage-line-color: red;
39
+ --aging-work-bar-chart-separator-color: white;
40
+
41
+ --throughput_chart_total_line_color: gray;
42
+
43
+ --aging-work-in-progress-chart-shading-color: lightgray;
44
+ --aging-work-in-progress-chart-shading-50-color: #2E8BC0;
45
+ --aging-work-in-progress-chart-shading-85-color: #ADD8E6;
46
+ --aging-work-in-progress-chart-shading-98-color: #FF8A8A;
47
+ --aging-work-in-progress-chart-shading-100-color: #FF2E2E;
48
+
49
+ --aging-work-in-progress-by-age-trend-line-color: gray;
50
+
51
+ --aging-work-table-date-in-jeopardy: yellow;
52
+ --aging-work-table-date-overdue: red;
53
+
54
+ --hierarchy-table-inactive-item-text-color: gray;
55
+
56
+ --wip-chart-completed-color: #00ff00;
57
+ --wip-chart-completed-but-not-started-color: #99FF99;
58
+ --wip-chart-duration-less-than-day-color: #ffef41;
59
+ --wip-chart-duration-week-or-less-color: #dcc900;
60
+ --wip-chart-duration-two-weeks-or-less-color: #dfa000;
61
+ --wip-chart-duration-four-weeks-or-less-color: #eb7200;
62
+ --wip-chart-duration-more-than-four-weeks-color: #e70000;
63
+ --wip-chart-active-color: #326cff;
64
+ --wip-chart-border-color: gray;
65
+
66
+ --wip-by-column-chart-bar-fill-color: #0072B2;
67
+ --wip-by-column-chart-bar-text-color: #ffffff;
68
+ --wip-by-column-chart-limit-line-color: #D55E00;
69
+ --wip-by-column-chart-recommendation-color: #009E73;
70
+
71
+ --estimate-accuracy-chart-completed-fill-color: #00ff00;
72
+ --estimate-accuracy-chart-completed-border-color: green;
73
+ --estimate-accuracy-chart-active-fill-color: #FFCCCB;
74
+ --estimate-accuracy-chart-active-border-color: red;
75
+
76
+ --expedited-chart-no-longer-expedited: gray;
77
+ --expedited-chart-dot-issue-started-color: orange;
78
+ --expedited-chart-dot-issue-stopped-color: green;
79
+ --expedited-chart-dot-expedite-started-color: red;
80
+ --expedited-chart-dot-expedite-stopped-color: green;
81
+
82
+ --sprint-burndown-sprint-color-1: blue;
83
+ --sprint-burndown-sprint-color-2: orange;
84
+ --sprint-burndown-sprint-color-3: green;
85
+ --sprint-burndown-sprint-color-4: red;
86
+ --sprint-burndown-sprint-color-5: brown;
87
+ --sprint-burndown-sprint-color-6: blue; /* wraps back to color-1 (legacy had only 5) */
88
+ --sprint-burndown-sprint-color-7: orange; /* wraps back to color-2 (legacy had only 5) */
89
+
90
+ --sprint-color: lightblue;
91
+
92
+ --daily-view-selected-issue-background: lightgray;
93
+ --daily-view-issue-border: green;
94
+ --daily-view-selected-issue-border: red;
95
+
96
+ --priority-color-highest: #dc2626;
97
+ --priority-color-high: #ea580c;
98
+ --priority-color-medium: #9ca3af;
99
+ --priority-color-low: #0891b2;
100
+ --priority-color-lowest: #64748b;
101
+ --priority-color-notset: gray;
102
+ --priority-color-critical: red;
103
+ }
104
+
105
+ /* Dark mode */
106
+ html[data-theme="dark"] {
107
+ --warning-banner: #9F2B00;
108
+ --non-working-days-color: #2f2f2f;
109
+ --type-story-color: #6fb86f;
110
+ --type-task-color: #0021b3;
111
+ --type-bug-color: #bb5603;
112
+ --body-background: #343434;
113
+ --default-text-color: #aaa;
114
+ --grid-line-color: #424242;
115
+ --expedited-color: #b90000;
116
+ --blocked-color: #c75b02;
117
+ --stalled-color: #ae7202;
118
+ --wip-chart-active-color: #2551c1;
119
+ --status-category-inprogress-color: #1c49bb;
120
+ --hierarchy-table-inactive-item-text-color: #939393;
121
+ --wip-by-column-chart-bar-fill-color: #56B4E9;
122
+ --wip-by-column-chart-bar-text-color: #000000;
123
+ --wip-by-column-chart-limit-line-color: #E69F00;
124
+ --wip-by-column-chart-recommendation-color: #2DCB9A;
125
+ --wip-chart-completed-color: #03cb03;
126
+ --wip-chart-duration-less-than-day-color: #d2d988;
127
+ --wip-chart-duration-week-or-less-color: #dfcd00;
128
+ --wip-chart-duration-two-weeks-or-less-color: #cf9400;
129
+ --wip-chart-duration-four-weeks-or-less-color: #c25e00;
130
+ --wip-chart-duration-more-than-four-weeks-color: #8e0000;
131
+ --daily-view-selected-issue-background: #474747;
132
+ --priority-color-highest: #ef4444;
133
+ --priority-color-high: #f97316;
134
+ --priority-color-low: #06b6d4;
135
+ --priority-color-lowest: #94a3b8;
136
+ }
137
+
138
+ @media screen and (prefers-color-scheme: dark) {
139
+ :root {
140
+ --warning-banner: #9F2B00;
141
+ --non-working-days-color: #2f2f2f;
142
+ --type-story-color: #6fb86f;
143
+ --type-task-color: #0021b3;
144
+ --type-bug-color: #bb5603;
145
+ --body-background: #343434;
146
+ --default-text-color: #aaa;
147
+ --grid-line-color: #424242;
148
+ --expedited-color: #b90000;
149
+ --blocked-color: #c75b02;
150
+ --stalled-color: #ae7202;
151
+ --dead-color: black;
152
+ --wip-chart-active-color: #2551c1;
153
+ --status-category-inprogress-color: #1c49bb;
154
+ --cycletime-scatterplot-overall-trendline-color: gray;
155
+ --hierarchy-table-inactive-item-text-color: #939393;
156
+ --wip-by-column-chart-bar-fill-color: #56B4E9;
157
+ --wip-by-column-chart-bar-text-color: #000000;
158
+ --wip-by-column-chart-limit-line-color: #E69F00;
159
+ --wip-by-column-chart-recommendation-color: #2DCB9A;
160
+ --wip-chart-completed-color: #03cb03;
161
+ --wip-chart-completed-but-not-started-color: #99FF99;
162
+ --wip-chart-duration-less-than-day-color: #d2d988;
163
+ --wip-chart-duration-week-or-less-color: #dfcd00;
164
+ --wip-chart-duration-two-weeks-or-less-color: #cf9400;
165
+ --wip-chart-duration-four-weeks-or-less-color: #c25e00;
166
+ --wip-chart-duration-more-than-four-weeks-color: #8e0000;
167
+ --daily-view-selected-issue-background: #474747;
168
+ --priority-color-highest: #ef4444;
169
+ --priority-color-high: #f97316;
170
+ --priority-color-medium: #9ca3af;
171
+ --priority-color-low: #06b6d4;
172
+ --priority-color-lowest: #94a3b8;
173
+ }
174
+ }
@@ -119,7 +119,8 @@ class HtmlReportConfig < HtmlGenerator
119
119
  end
120
120
 
121
121
  def random_color
122
- "##{Random.bytes(3).unpack1('H*')}"
122
+ @palette_index = (@palette_index || -1) + 1
123
+ ChartBase::OKABE_ITO_PALETTE[@palette_index % ChartBase::OKABE_ITO_PALETTE.size]
123
124
  end
124
125
 
125
126
  def html string, type: :body
@@ -905,11 +905,20 @@ class Issue
905
905
 
906
906
  history['items']&.each do |item|
907
907
  if item['field'] == 'status' && item['to'].nil?
908
- board.project_config.file_system.log(
908
+ to_name = item['toString']
909
+ matches = board.possible_statuses.find_all_by_name(to_name)
910
+ guessed_id, id_note = if matches.length == 1
911
+ [matches.first.id.to_s, "Guessed id #{matches.first.id} from status name."]
912
+ elsif matches.length > 1
913
+ ['0', "Multiple statuses named #{to_name.inspect} exist (ids: #{matches.map(&:id).join(', ')}); cannot disambiguate. Using id 0."]
914
+ else
915
+ ['0', "No known status named #{to_name.inspect}. Using id 0."]
916
+ end
917
+ board.project_config.file_system.warning(
909
918
  "Issue #{key} has a status change without a 'to' id " \
910
- "(from #{item['fromString'].inspect} to #{item['toString'].inspect}). Using id 0."
919
+ "(from #{item['fromString'].inspect} to #{to_name.inspect}). #{id_note}"
911
920
  )
912
- item = item.merge('to' => '0')
921
+ item = item.merge('to' => guessed_id)
913
922
  end
914
923
 
915
924
  @changes << ChangeItem.new(raw: item, time: created, author_raw: history['author'])
@@ -9,6 +9,10 @@ class JiraGateway
9
9
  attr_accessor :ignore_ssl_errors
10
10
  attr_reader :jira_url, :settings, :file_system
11
11
 
12
+ RETRYABLE_EXIT_CODES = [7, 28, 35, 56].freeze
13
+ MAX_RETRIES = 3
14
+ RETRY_DELAY_SECONDS = 5
15
+
12
16
  def initialize file_system:, jira_config:, settings:
13
17
  @file_system = file_system
14
18
  load_jira_config(jira_config)
@@ -26,8 +30,23 @@ class JiraGateway
26
30
  log_entry = sanitize_message log_entry
27
31
  @file_system.log log_entry
28
32
 
29
- stdout, stderr, status = capture3(command, stdin_data: stdin_data)
30
- unless status.success?
33
+ retries = 0
34
+ loop do
35
+ stdout, stderr, status = capture3(command, stdin_data: stdin_data)
36
+
37
+ if status.success?
38
+ @file_system.log "Returned (stderr): #{stderr.inspect}" unless stderr == ''
39
+ raise 'no response from curl on stdout' if stdout == ''
40
+ return parse_response(command: command, result: stdout)
41
+ end
42
+
43
+ if RETRYABLE_EXIT_CODES.include?(status.exitstatus) && retries < MAX_RETRIES
44
+ retries += 1
45
+ @file_system.log "Transient network error (exit #{status.exitstatus}), retrying in #{RETRY_DELAY_SECONDS}s (attempt #{retries}/#{MAX_RETRIES})..."
46
+ sleep_between_retries
47
+ next
48
+ end
49
+
31
50
  @file_system.error "Failed call with exit status #{status.exitstatus}!"
32
51
  @file_system.error "Returned (stdout): #{stdout.inspect}"
33
52
  @file_system.error "Returned (stderr): #{stderr.inspect}"
@@ -37,11 +56,6 @@ class JiraGateway
37
56
  raise "Failed call with exit status #{status.exitstatus}. " \
38
57
  "See #{@file_system.logfile_name} for details"
39
58
  end
40
-
41
- @file_system.log "Returned (stderr): #{stderr.inspect}" unless stderr == ''
42
- raise 'no response from curl on stdout' if stdout == ''
43
-
44
- parse_response(command: command, result: stdout)
45
59
  end
46
60
 
47
61
  def capture3 command, stdin_data:
@@ -49,6 +63,11 @@ class JiraGateway
49
63
  Open3.capture3(command, stdin_data: stdin_data)
50
64
  end
51
65
 
66
+ def sleep_between_retries
67
+ # In its own method so we can mock it out in tests
68
+ sleep RETRY_DELAY_SECONDS
69
+ end
70
+
52
71
  def call_url relative_url:
53
72
  command = make_curl_command url: "#{@jira_url}#{relative_url}"
54
73
  exec_and_parse_response command: command, stdin_data: nil
@@ -66,7 +66,7 @@ class SprintBurndown < ChartBase
66
66
  result = +''
67
67
  result << render_top_text(binding)
68
68
 
69
- possible_colours = (1..5).collect { |i| CssVariable["--sprint-burndown-sprint-color-#{i}"] }
69
+ possible_colours = (1..ChartBase::OKABE_ITO_PALETTE.size).collect { |i| CssVariable["--sprint-burndown-sprint-color-#{i}"] }
70
70
  charts_to_generate = []
71
71
  charts_to_generate << [:data_set_by_story_points, 'Story Points'] if @use_story_points
72
72
  charts_to_generate << [:data_set_by_story_counts, 'Story Count'] if @use_story_counts
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jirametrics
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.29.2
4
+ version: '2.30'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Bowler
@@ -150,6 +150,7 @@ files:
150
150
  - lib/jirametrics/html/index.css
151
151
  - lib/jirametrics/html/index.erb
152
152
  - lib/jirametrics/html/index.js
153
+ - lib/jirametrics/html/legacy_colors.css
153
154
  - lib/jirametrics/html/sprint_burndown.erb
154
155
  - lib/jirametrics/html/throughput_chart.erb
155
156
  - lib/jirametrics/html/time_based_histogram.erb