Project

General

Profile

Feature #44689 » 0001-Use-Open-Color-for-Gantt-charts.patch

Katsuya HIDAKA, 2026-10-28 09:27

View differences:

app/assets/stylesheets/gantt.css
240 240
  inset-inline-start: var(--gantt-today-start);
241 241
  inline-size: 10px;
242 242
  block-size: var(--gantt-content-height);
243
  border-inline-start: 1px dashed red;
243
  border-inline-start: 1px dashed var(--oc-red-7);
244 244
  pointer-events: none;
245 245
}
246 246

  
......
305 305

  
306 306
.gantt-task-late {
307 307
  block-size: 10px;
308
  background: var(--oc-red-5) url(/task_late.png);
309
  border: 1px solid var(--oc-red-5);
308
  background-color: var(--oc-red-4);
309
  border: 1px solid var(--oc-red-4);
310 310
}
311 311

  
312 312
.gantt-task-done {
313 313
  block-size: 10px;
314
  background: var(--oc-green-7) url(/task_done.png);
315
  border: 1px solid var(--oc-green-7);
314
  background-color: var(--oc-green-6);
315
  border: 1px solid var(--oc-green-6);
316 316
}
317 317

  
318 318
.gantt-task-todo {
319 319
  block-size: 10px;
320
  background: var(--oc-gray-5) url(/task_todo.png);
320
  background-color: var(--oc-gray-5);
321 321
  border: 1px solid var(--oc-gray-5);
322 322
}
323 323

  
324 324
.gantt-task-todo.gantt-task-parent {
325
  background: var(--oc-gray-6);
326
  border: 1px solid var(--oc-gray-6);
327
  block-size: 5px;
325
  background-color: var(--oc-gray-6);
326
  border-color: var(--oc-gray-6);
328 327
}
329 328

  
330
.gantt-task-late.gantt-task-parent,
331
.gantt-task-done.gantt-task-parent {
329
.gantt-task-parent:is(.gantt-task-todo, .gantt-task-late, .gantt-task-done) {
332 330
  block-size: 5px;
333 331
}
334 332

  
335
.gantt-task.gantt-task-parent.gantt-task-marker {
336
  position: absolute;
337
  background: url(/task_parent_end.png) no-repeat 0 0;
333
.gantt-task-marker {
334
  background-color: var(--oc-indigo-8);
338 335
  inline-size: 8px;
339
  block-size: 16px;
336
  block-size: 8px;
340 337
  margin-inline-start: -4px;
338
  margin-block-start: 1px;
339
  /* Match the filled area and flat tips of the original 8px marker. */
340
  clip-path: polygon(3.5px 0, 4.5px 0, 8px 3.5px, 8px 4.5px, 4.5px 8px, 3.5px 8px, 0 4.5px, 0 3.5px);
341 341
}
342 342

  
343
.gantt-row[data-gantt-row-type="version"] .gantt-task-late {
344
  background: var(--oc-red-5) url(/milestone_late.png);
345
  border: 1px solid var(--oc-red-5);
346
  block-size: 4px;
347
  margin-block-start: 3px;
343
.gantt-task-parent.gantt-task-marker {
344
  background-color: var(--oc-gray-6);
345
  block-size: 16px;
346
  margin-block-start: 0;
347
  /* Keep the original body's size and align its top with the bar. */
348
  clip-path: polygon(0 0, 100% 0, 100% 6px, 50% 9px, 0 6px);
348 349
}
349 350

  
350
.gantt-row[data-gantt-row-type="version"] .gantt-task-done {
351
  background: var(--oc-green-7) url(/milestone_done.png);
352
  border: 1px solid var(--oc-green-7);
351
.gantt-row[data-gantt-row-type="version"] .gantt-task:is(.gantt-task-todo, .gantt-task-late, .gantt-task-done) {
353 352
  block-size: 4px;
354 353
  margin-block-start: 3px;
355 354
}
356 355

  
357 356
.gantt-row[data-gantt-row-type="version"] .gantt-task-todo {
358
  background: var(--oc-white) url(/milestone_todo.png);
359
  border: 1px solid var(--oc-white);
360
  block-size: 4px;
361
  margin-block-start: 3px;
357
  background-color: var(--oc-gray-5);
358
  border-color: transparent;
359
  background-clip: padding-box;
362 360
}
363 361

  
364 362
.gantt-row[data-gantt-row-type="version"] .gantt-task-marker {
365
  background-image: url(/version_marker.png);
366
  background-repeat: no-repeat;
367
  border: 0;
368
  margin-inline-start: -4px;
369
  margin-block-start: 1px;
363
  background-color: var(--oc-gray-9);
370 364
}
371 365

  
372
.gantt-row[data-gantt-row-type="project"] .gantt-task-late {
373
  background: var(--oc-red-5) url(/milestone_late.png);
374
  border: 1px solid var(--oc-red-5);
375
  block-size: 4px;
376
  margin-block-start: 3px;
377
}
378

  
379
.gantt-row[data-gantt-row-type="project"] .gantt-task-done {
380
  background: var(--oc-green-7) url(/milestone_done.png);
381
  border: 1px solid var(--oc-green-7);
366
.gantt-row[data-gantt-row-type="project"] .gantt-task:is(.gantt-task-todo, .gantt-task-late, .gantt-task-done) {
382 367
  block-size: 4px;
383 368
  margin-block-start: 3px;
384 369
}
385 370

  
386 371
.gantt-row[data-gantt-row-type="project"] .gantt-task-todo {
387
  background: var(--oc-white) url(/milestone_todo.png);
388
  border: 1px solid var(--oc-white);
389
  block-size: 4px;
390
  margin-block-start: 3px;
391
}
392

  
393
.gantt-row[data-gantt-row-type="project"] .gantt-task-marker {
394
  background-image: url(/project_marker.png);
395
  background-repeat: no-repeat;
396
  border: 0;
397
  margin-inline-start: -4px;
398
  margin-block-start: 1px;
399
}
400

  
401
/* RTL adjustment (disabled while Gantt is forced LTR).  Enable when RTL is supported.
402
  [dir="rtl"] .gantt-task-marker {
403
  background-position: right;
372
  background-color: var(--oc-gray-5);
373
  border-color: transparent;
374
  background-clip: padding-box;
404 375
}
405
*/
406 376

  
407 377
.version-behind-schedule a,
408 378
.issue-behind-schedule a {
lib/redmine/helpers/gantt.rb
36 36
        },
37 37
        IssueRelation::TYPE_PRECEDES => {
38 38
          :landscape_margin => 20,
39
          :color => '#228be6' # oc-blue-6
39
          :color => '#1c7ed6' # oc-blue-7
40 40
        }
41 41
      }.freeze
42 42

  
......
496 496
          @months.times do
497 497
            width = ((month_f >> 1) - month_f) * zoom
498 498
            gc.fill('white')
499
            gc.stroke('grey')
499
            gc.stroke('#adb5bd') # oc-gray-5
500 500
            gc.strokewidth(1)
501 501
            gc.draw('rectangle %d,%d %d,%d' % [
502 502
              left, 0, left + width, height
......
522 522
              week_f = @date_from + (7 - @date_from.cwday + 1)
523 523
              width = (7 - @date_from.cwday + 1) * zoom
524 524
              gc.fill('white')
525
              gc.stroke('grey')
525
              gc.stroke('#adb5bd') # oc-gray-5
526 526
              gc.strokewidth(1)
527 527
              gc.draw('rectangle %d,%d %d,%d' % [
528 528
                left, header_height, left + width, 2 * header_height + g_height - 1
......
532 532
            while week_f <= date_to
533 533
              width = (week_f + 6 <= date_to) ? 7 * zoom : (date_to - week_f + 1) * zoom
534 534
              gc.fill('white')
535
              gc.stroke('grey')
535
              gc.stroke('#adb5bd') # oc-gray-5
536 536
              gc.strokewidth(1)
537 537
              gc.draw('rectangle %d,%d %d,%d' % [
538 538
                left.round, header_height, left.round + width, 2 * header_height + g_height - 1
......
553 553
            height = g_height + header_height - 1
554 554
            (@date_from..date_to).each do |g_date|
555 555
              width =  zoom
556
              gc.fill(non_working_day?(g_date) ? '#eee' : 'white')
557
              gc.stroke('#ddd')
556
              gc.fill(non_working_day?(g_date) ? '#f1f3f5' : 'white') # oc-gray-1
557
              gc.stroke('#dee2e6') # oc-gray-3
558 558
              gc.strokewidth(1)
559 559
              gc.draw('rectangle %d,%d %d,%d' % [
560 560
                left, 2 * header_height, left + width, 2 * header_height + g_height - 1
......
564 564
          end
565 565
          # border
566 566
          gc.fill('transparent')
567
          gc.stroke('grey')
567
          gc.stroke('#adb5bd') # oc-gray-5
568 568
          gc.strokewidth(1)
569 569
          gc.draw('rectangle %d,%d %d,%d' % [
570 570
            0, 0, subject_width + g_width, headers_height
......
580 580
                :subject_width => subject_width, :format => :image)
581 581
          # today red line
582 582
          if User.current.today.between?(@date_from, date_to)
583
            gc.stroke('red')
583
            gc.stroke('#f03e3e') # oc-red-7
584 584
            x = (User.current.today - @date_from + 1) * zoom + subject_width
585 585
            gc.draw('line %g,%g %g,%g' % [
586 586
              x, headers_height, x, headers_height + g_height - 1
......
673 673
            width = zoom
674 674
            pdf.SetY(y_start + header_height * 2)
675 675
            pdf.SetX(left)
676
            pdf.SetTextColor(non_working_day?(g_date) ? 150 : 0)
676
            if non_working_day?(g_date)
677
              pdf.SetTextColor(134, 142, 150) # oc-gray-6
678
            else
679
              pdf.SetTextColor(0)
680
            end
677 681
            pdf.RDMCell(width, height, day_num.day.to_s, "LTR", 0, "C")
678 682
            left = left + width
679 683
            day_num = day_num + 1
......
688 692
            width = zoom
689 693
            pdf.SetY(y_start + header_height * (show_day_num ? 3 : 2))
690 694
            pdf.SetX(left)
691
            pdf.SetTextColor(non_working_day?(g_date) ? 150 : 0)
695
            if non_working_day?(g_date)
696
              pdf.SetTextColor(134, 142, 150) # oc-gray-6
697
            else
698
              pdf.SetTextColor(0)
699
            end
692 700
            pdf.RDMCell(width, height, day_name(g_date.cwday).first, "LTR", 0, "C")
693 701
            left = left + width
694 702
          end
......
1033 1041
          width = [1, coords[:bar_end] - coords[:bar_start]].max
1034 1042
          params[:pdf].SetY(params[:top] + 1.5)
1035 1043
          params[:pdf].SetX(params[:subject_width] + coords[:bar_start])
1036
          params[:pdf].SetFillColor(200, 200, 200)
1044
          params[:pdf].SetFillColor(206, 212, 218) # oc-gray-4
1037 1045
          params[:pdf].RDMCell(width, height, "", 0, 0, "", 1)
1038 1046
          if coords[:bar_late_end]
1039 1047
            width = [1, coords[:bar_late_end] - coords[:bar_start]].max
1040 1048
            params[:pdf].SetY(params[:top] + 1.5)
1041 1049
            params[:pdf].SetX(params[:subject_width] + coords[:bar_start])
1042
            params[:pdf].SetFillColor(255, 100, 100)
1050
            params[:pdf].SetFillColor(255, 107, 107) # oc-red-5
1043 1051
            params[:pdf].RDMCell(width, height, "", 0, 0, "", 1)
1044 1052
          end
1045 1053
          if coords[:bar_progress_end]
1046 1054
            width = [1, coords[:bar_progress_end] - coords[:bar_start]].max
1047 1055
            params[:pdf].SetY(params[:top] + 1.5)
1048 1056
            params[:pdf].SetX(params[:subject_width] + coords[:bar_start])
1049
            params[:pdf].SetFillColor(90, 200, 90)
1057
            params[:pdf].SetFillColor(81, 207, 102) # oc-green-5
1050 1058
            params[:pdf].RDMCell(width, height, "", 0, 0, "", 1)
1051 1059
          end
1052 1060
        end
......
1055 1063
          if coords[:start]
1056 1064
            params[:pdf].SetY(params[:top] + 1)
1057 1065
            params[:pdf].SetX(params[:subject_width] + coords[:start] - 1)
1058
            params[:pdf].SetFillColor(50, 50, 200)
1066
            params[:pdf].SetFillColor(54, 79, 199) # oc-indigo-9
1059 1067
            params[:pdf].RDMCell(2, 2, "", 0, 0, "", 1)
1060 1068
          end
1061 1069
          if coords[:end]
1062 1070
            params[:pdf].SetY(params[:top] + 1)
1063 1071
            params[:pdf].SetX(params[:subject_width] + coords[:end] - 1)
1064
            params[:pdf].SetFillColor(50, 50, 200)
1072
            params[:pdf].SetFillColor(54, 79, 199) # oc-indigo-9
1065 1073
            params[:pdf].RDMCell(2, 2, "", 0, 0, "", 1)
1066 1074
          end
1067 1075
        end
......
1079 1087
        height /= 2 if markers
1080 1088
        # Renders the task bar, with progress and late
1081 1089
        if coords[:bar_start] && coords[:bar_end]
1082
          params[:image].fill('#aaa')
1090
          params[:image].fill('#adb5bd') # oc-gray-5
1083 1091
          params[:image].draw('rectangle %d,%d %d,%d' % [
1084 1092
            params[:subject_width] + coords[:bar_start],
1085 1093
            params[:top],
......
1087 1095
            params[:top] - height
1088 1096
          ])
1089 1097
          if coords[:bar_late_end]
1090
            params[:image].fill('#f66')
1098
            params[:image].fill('#ff6b6b') # oc-red-5
1091 1099
            params[:image].draw('rectangle %d,%d %d,%d' % [
1092 1100
              params[:subject_width] + coords[:bar_start],
1093 1101
              params[:top],
......
1096 1104
            ])
1097 1105
          end
1098 1106
          if coords[:bar_progress_end]
1099
            params[:image].fill('#00c600')
1107
            params[:image].fill('#40c057') # oc-green-6
1100 1108
            params[:image].draw('rectangle %d,%d %d,%d' % [
1101 1109
              params[:subject_width] + coords[:bar_start],
1102 1110
              params[:top],
......
1110 1118
          if coords[:start]
1111 1119
            x = params[:subject_width] + coords[:start]
1112 1120
            y = params[:top] - height / 2
1113
            params[:image].fill('blue')
1121
            params[:image].fill('#364fc7') # oc-indigo-9
1114 1122
            params[:image].draw('polygon %d,%d %d,%d %d,%d %d,%d' % [
1115 1123
              x - 4, y,
1116 1124
              x, y - 4,
......
1121 1129
          if coords[:end]
1122 1130
            x = params[:subject_width] + coords[:end]
1123 1131
            y = params[:top] - height / 2
1124
            params[:image].fill('blue')
1132
            params[:image].fill('#364fc7') # oc-indigo-9
1125 1133
            params[:image].draw('polygon %d,%d %d,%d %d,%d %d,%d' % [
1126 1134
              x - 4, y,
1127 1135
              x, y - 4,
(3-3/3)