solid_queue_monitor 0.4.0 → 0.6.0
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/README.md +11 -4
- data/app/controllers/solid_queue_monitor/application_controller.rb +11 -2
- data/app/controllers/solid_queue_monitor/base_controller.rb +15 -7
- data/app/controllers/solid_queue_monitor/overview_controller.rb +11 -0
- data/app/controllers/solid_queue_monitor/queues_controller.rb +18 -1
- data/app/presenters/solid_queue_monitor/queues_presenter.rb +45 -6
- data/app/services/solid_queue_monitor/chart_data_service.rb +100 -0
- data/app/services/solid_queue_monitor/chart_presenter.rb +239 -0
- data/app/services/solid_queue_monitor/html_generator.rb +168 -8
- data/app/services/solid_queue_monitor/queue_pause_service.rb +34 -0
- data/app/services/solid_queue_monitor/stylesheet_generator.rb +425 -33
- data/config/database.yml +3 -0
- data/config/routes.rb +9 -1
- data/lib/solid_queue_monitor/engine.rb +5 -0
- data/lib/solid_queue_monitor/version.rb +1 -1
- metadata +5 -1
|
@@ -8,9 +8,35 @@ module SolidQueueMonitor
|
|
|
8
8
|
--primary-color: #3b82f6;
|
|
9
9
|
--success-color: #10b981;
|
|
10
10
|
--error-color: #ef4444;
|
|
11
|
+
--warning-color: #f59e0b;
|
|
11
12
|
--text-color: #1f2937;
|
|
13
|
+
--text-muted: #6b7280;
|
|
12
14
|
--border-color: #e5e7eb;
|
|
13
15
|
--background-color: #f9fafb;
|
|
16
|
+
--card-background: #ffffff;
|
|
17
|
+
--card-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
|
18
|
+
--input-background: #ffffff;
|
|
19
|
+
--input-border: #d1d5db;
|
|
20
|
+
--hover-background: #f3f4f6;
|
|
21
|
+
--code-background: #f5f5f5;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* Dark theme */
|
|
25
|
+
.solid_queue_monitor.dark-theme {
|
|
26
|
+
--primary-color: #60a5fa;
|
|
27
|
+
--success-color: #34d399;
|
|
28
|
+
--error-color: #f87171;
|
|
29
|
+
--warning-color: #fbbf24;
|
|
30
|
+
--text-color: #f9fafb;
|
|
31
|
+
--text-muted: #9ca3af;
|
|
32
|
+
--border-color: #2d2d2d;
|
|
33
|
+
--background-color: #000000;
|
|
34
|
+
--card-background: #121212;
|
|
35
|
+
--card-shadow: 0 1px 3px rgba(0,0,0,0.5);
|
|
36
|
+
--input-background: #1e1e1e;
|
|
37
|
+
--input-border: #3d3d3d;
|
|
38
|
+
--hover-background: #1e1e1e;
|
|
39
|
+
--code-background: #1e1e1e;
|
|
14
40
|
}
|
|
15
41
|
|
|
16
42
|
.solid_queue_monitor * { box-sizing: border-box; margin: 0; padding: 0; }
|
|
@@ -23,7 +49,8 @@ module SolidQueueMonitor
|
|
|
23
49
|
}
|
|
24
50
|
|
|
25
51
|
.solid_queue_monitor .container {
|
|
26
|
-
|
|
52
|
+
width: 95%;
|
|
53
|
+
max-width: 1800px;
|
|
27
54
|
margin: 0 auto;
|
|
28
55
|
padding: 2rem;
|
|
29
56
|
}
|
|
@@ -52,8 +79,8 @@ module SolidQueueMonitor
|
|
|
52
79
|
color: var(--text-color);
|
|
53
80
|
padding: 0.5rem 1rem;
|
|
54
81
|
border-radius: 0.375rem;
|
|
55
|
-
background:
|
|
56
|
-
box-shadow:
|
|
82
|
+
background: var(--card-background);
|
|
83
|
+
box-shadow: var(--card-shadow);
|
|
57
84
|
transition: all 0.2s;
|
|
58
85
|
}
|
|
59
86
|
|
|
@@ -89,15 +116,15 @@ module SolidQueueMonitor
|
|
|
89
116
|
.solid_queue_monitor .stat-card {
|
|
90
117
|
flex: 1 1 0;
|
|
91
118
|
min-width: 150px;
|
|
92
|
-
background:
|
|
119
|
+
background: var(--card-background);
|
|
93
120
|
padding: 1.5rem 1rem;
|
|
94
121
|
border-radius: 0.5rem;
|
|
95
|
-
box-shadow:
|
|
122
|
+
box-shadow: var(--card-shadow);
|
|
96
123
|
text-align: center;
|
|
97
124
|
}
|
|
98
125
|
|
|
99
126
|
.solid_queue_monitor .stat-card h3 {
|
|
100
|
-
color:
|
|
127
|
+
color: var(--text-muted);
|
|
101
128
|
font-size: 0.875rem;
|
|
102
129
|
text-transform: uppercase;
|
|
103
130
|
letter-spacing: 0.05em;
|
|
@@ -137,11 +164,12 @@ module SolidQueueMonitor
|
|
|
137
164
|
}
|
|
138
165
|
|
|
139
166
|
.solid_queue_monitor th {
|
|
140
|
-
background: var(--background
|
|
167
|
+
background: var(--hover-background);
|
|
141
168
|
font-weight: 500;
|
|
142
169
|
font-size: 0.875rem;
|
|
143
170
|
text-transform: uppercase;
|
|
144
171
|
letter-spacing: 0.05em;
|
|
172
|
+
color: var(--text-muted);
|
|
145
173
|
}
|
|
146
174
|
|
|
147
175
|
.solid_queue_monitor .status-badge {
|
|
@@ -182,6 +210,30 @@ module SolidQueueMonitor
|
|
|
182
210
|
.solid_queue_monitor .status-failed { background: #fee2e2; color: #991b1b; }
|
|
183
211
|
.solid_queue_monitor .status-scheduled { background: #dbeafe; color: #1e40af; }
|
|
184
212
|
.solid_queue_monitor .status-pending { background: #f3f4f6; color: #374151; }
|
|
213
|
+
.solid_queue_monitor .status-active { background: #d1fae5; color: #065f46; }
|
|
214
|
+
.solid_queue_monitor .status-paused { background: #fef3c7; color: #92400e; }
|
|
215
|
+
|
|
216
|
+
.solid_queue_monitor .queue-paused {
|
|
217
|
+
background-color: #fffbeb;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.solid_queue_monitor .pause-button {
|
|
221
|
+
background: #f59e0b;
|
|
222
|
+
color: white;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.solid_queue_monitor .pause-button:hover {
|
|
226
|
+
background: #d97706;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.solid_queue_monitor .resume-button {
|
|
230
|
+
background: #10b981;
|
|
231
|
+
color: white;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.solid_queue_monitor .resume-button:hover {
|
|
235
|
+
background: #059669;
|
|
236
|
+
}
|
|
185
237
|
|
|
186
238
|
.solid_queue_monitor .execute-btn {
|
|
187
239
|
background: var(--primary-color);
|
|
@@ -218,7 +270,7 @@ module SolidQueueMonitor
|
|
|
218
270
|
.solid_queue_monitor footer {
|
|
219
271
|
text-align: center;
|
|
220
272
|
padding: 2rem 0;
|
|
221
|
-
color:
|
|
273
|
+
color: var(--text-muted);
|
|
222
274
|
}
|
|
223
275
|
|
|
224
276
|
.solid_queue_monitor .pagination {
|
|
@@ -265,7 +317,7 @@ module SolidQueueMonitor
|
|
|
265
317
|
}
|
|
266
318
|
|
|
267
319
|
.solid_queue_monitor .pagination-link {
|
|
268
|
-
background:
|
|
320
|
+
background: var(--card-background);
|
|
269
321
|
color: var(--text-color);
|
|
270
322
|
border: 1px solid var(--border-color);
|
|
271
323
|
}
|
|
@@ -296,7 +348,7 @@ module SolidQueueMonitor
|
|
|
296
348
|
max-height: 100px;
|
|
297
349
|
overflow-y: auto;
|
|
298
350
|
padding: 8px;
|
|
299
|
-
background:
|
|
351
|
+
background: var(--code-background);
|
|
300
352
|
border-radius: 4px;
|
|
301
353
|
font-size: 0.9em;
|
|
302
354
|
}
|
|
@@ -304,7 +356,7 @@ module SolidQueueMonitor
|
|
|
304
356
|
.solid_queue_monitor .args-single-line {
|
|
305
357
|
display: inline-block;
|
|
306
358
|
padding: 4px 8px;
|
|
307
|
-
background:
|
|
359
|
+
background: var(--code-background);
|
|
308
360
|
border-radius: 4px;
|
|
309
361
|
font-size: 0.9em;
|
|
310
362
|
}
|
|
@@ -375,10 +427,10 @@ module SolidQueueMonitor
|
|
|
375
427
|
}
|
|
376
428
|
|
|
377
429
|
.solid_queue_monitor .filter-form-container {
|
|
378
|
-
background:
|
|
430
|
+
background: var(--card-background);
|
|
379
431
|
padding: 1rem;
|
|
380
432
|
border-radius: 0.5rem;
|
|
381
|
-
box-shadow:
|
|
433
|
+
box-shadow: var(--card-shadow);
|
|
382
434
|
flex: 3;
|
|
383
435
|
}
|
|
384
436
|
|
|
@@ -387,9 +439,9 @@ module SolidQueueMonitor
|
|
|
387
439
|
flex-direction: row;
|
|
388
440
|
gap: 0.75rem;
|
|
389
441
|
padding: 1rem;
|
|
390
|
-
background:
|
|
442
|
+
background: var(--card-background);
|
|
391
443
|
border-radius: 0.5rem;
|
|
392
|
-
box-shadow:
|
|
444
|
+
box-shadow: var(--card-shadow);
|
|
393
445
|
flex: 2;
|
|
394
446
|
align-items: center;
|
|
395
447
|
justify-content: center;
|
|
@@ -429,16 +481,18 @@ module SolidQueueMonitor
|
|
|
429
481
|
margin-bottom: 0.5rem;
|
|
430
482
|
font-size: 0.875rem;
|
|
431
483
|
font-weight: 500;
|
|
432
|
-
color:
|
|
484
|
+
color: var(--text-muted);
|
|
433
485
|
}
|
|
434
486
|
|
|
435
487
|
.solid_queue_monitor .filter-group input,
|
|
436
488
|
.solid_queue_monitor .filter-group select {
|
|
437
489
|
width: 100%;
|
|
438
490
|
padding: 0.5rem;
|
|
439
|
-
border: 1px solid
|
|
491
|
+
border: 1px solid var(--input-border);
|
|
440
492
|
border-radius: 0.375rem;
|
|
441
493
|
font-size: 0.875rem;
|
|
494
|
+
background: var(--input-background);
|
|
495
|
+
color: var(--text-color);
|
|
442
496
|
}
|
|
443
497
|
|
|
444
498
|
.solid_queue_monitor .filter-actions {
|
|
@@ -462,9 +516,9 @@ module SolidQueueMonitor
|
|
|
462
516
|
}
|
|
463
517
|
|
|
464
518
|
.solid_queue_monitor .reset-button {
|
|
465
|
-
background:
|
|
466
|
-
color:
|
|
467
|
-
border: 1px solid
|
|
519
|
+
background: var(--hover-background);
|
|
520
|
+
color: var(--text-muted);
|
|
521
|
+
border: 1px solid var(--border-color);
|
|
468
522
|
padding: 0.5rem 1rem;
|
|
469
523
|
border-radius: 0.375rem;
|
|
470
524
|
font-size: 0.875rem;
|
|
@@ -474,7 +528,7 @@ module SolidQueueMonitor
|
|
|
474
528
|
}
|
|
475
529
|
|
|
476
530
|
.solid_queue_monitor .reset-button:hover {
|
|
477
|
-
background:
|
|
531
|
+
background: var(--border-color);
|
|
478
532
|
}
|
|
479
533
|
|
|
480
534
|
.solid_queue_monitor .action-button {
|
|
@@ -536,7 +590,7 @@ module SolidQueueMonitor
|
|
|
536
590
|
white-space: pre-wrap;
|
|
537
591
|
max-height: 200px;
|
|
538
592
|
overflow-y: auto;
|
|
539
|
-
background:
|
|
593
|
+
background: var(--code-background);
|
|
540
594
|
padding: 0.5rem;
|
|
541
595
|
border-radius: 0.25rem;
|
|
542
596
|
margin-top: 0.5rem;
|
|
@@ -548,12 +602,12 @@ module SolidQueueMonitor
|
|
|
548
602
|
|
|
549
603
|
.solid_queue_monitor summary {
|
|
550
604
|
cursor: pointer;
|
|
551
|
-
color:
|
|
605
|
+
color: var(--text-muted);
|
|
552
606
|
font-size: 0.75rem;
|
|
553
607
|
}
|
|
554
608
|
|
|
555
609
|
.solid_queue_monitor summary:hover {
|
|
556
|
-
color:
|
|
610
|
+
color: var(--text-color);
|
|
557
611
|
}
|
|
558
612
|
|
|
559
613
|
.solid_queue_monitor .job-checkbox,
|
|
@@ -566,10 +620,10 @@ module SolidQueueMonitor
|
|
|
566
620
|
display: flex;
|
|
567
621
|
gap: 0.75rem;
|
|
568
622
|
margin: 1rem 0;
|
|
569
|
-
background:
|
|
623
|
+
background: var(--card-background);
|
|
570
624
|
padding: 0.75rem;
|
|
571
625
|
border-radius: 0.5rem;
|
|
572
|
-
box-shadow:
|
|
626
|
+
box-shadow: var(--card-shadow);
|
|
573
627
|
}
|
|
574
628
|
|
|
575
629
|
.solid_queue_monitor .bulk-actions-bar .action-button {
|
|
@@ -601,11 +655,11 @@ module SolidQueueMonitor
|
|
|
601
655
|
align-items: center;
|
|
602
656
|
gap: 0.5rem;
|
|
603
657
|
padding: 0.375rem 0.625rem;
|
|
604
|
-
background:
|
|
658
|
+
background: var(--card-background);
|
|
605
659
|
border-radius: 2rem;
|
|
606
|
-
box-shadow:
|
|
660
|
+
box-shadow: var(--card-shadow);
|
|
607
661
|
font-size: 0.75rem;
|
|
608
|
-
color:
|
|
662
|
+
color: var(--text-muted);
|
|
609
663
|
cursor: default;
|
|
610
664
|
}
|
|
611
665
|
|
|
@@ -658,7 +712,7 @@ module SolidQueueMonitor
|
|
|
658
712
|
width: 6px;
|
|
659
713
|
height: 6px;
|
|
660
714
|
border-radius: 50%;
|
|
661
|
-
background:
|
|
715
|
+
background: var(--border-color);
|
|
662
716
|
flex-shrink: 0;
|
|
663
717
|
}
|
|
664
718
|
|
|
@@ -702,7 +756,7 @@ module SolidQueueMonitor
|
|
|
702
756
|
left: 0;
|
|
703
757
|
right: 0;
|
|
704
758
|
bottom: 0;
|
|
705
|
-
background-color:
|
|
759
|
+
background-color: var(--border-color);
|
|
706
760
|
transition: 0.2s;
|
|
707
761
|
border-radius: 18px;
|
|
708
762
|
}
|
|
@@ -714,7 +768,7 @@ module SolidQueueMonitor
|
|
|
714
768
|
width: 14px;
|
|
715
769
|
left: 2px;
|
|
716
770
|
bottom: 2px;
|
|
717
|
-
background-color:
|
|
771
|
+
background-color: var(--card-background);
|
|
718
772
|
transition: 0.2s;
|
|
719
773
|
border-radius: 50%;
|
|
720
774
|
box-shadow: 0 1px 2px rgba(0,0,0,0.2);
|
|
@@ -737,7 +791,7 @@ module SolidQueueMonitor
|
|
|
737
791
|
padding: 0.25rem;
|
|
738
792
|
border-radius: 0.25rem;
|
|
739
793
|
cursor: pointer;
|
|
740
|
-
color:
|
|
794
|
+
color: var(--text-muted);
|
|
741
795
|
transition: all 0.2s;
|
|
742
796
|
}
|
|
743
797
|
|
|
@@ -762,6 +816,344 @@ module SolidQueueMonitor
|
|
|
762
816
|
display: none;
|
|
763
817
|
}
|
|
764
818
|
}
|
|
819
|
+
|
|
820
|
+
/* Navigation active state */
|
|
821
|
+
.solid_queue_monitor .nav-link.active {
|
|
822
|
+
background: var(--primary-color);
|
|
823
|
+
color: white;
|
|
824
|
+
border-left: 3px solid #1d4ed8;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
/* Chart styles */
|
|
828
|
+
.solid_queue_monitor .chart-section {
|
|
829
|
+
background: var(--card-background);
|
|
830
|
+
border-radius: 0.5rem;
|
|
831
|
+
box-shadow: var(--card-shadow);
|
|
832
|
+
padding: 1rem 1.5rem;
|
|
833
|
+
margin-bottom: 2rem;
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
.solid_queue_monitor .chart-section.collapsed {
|
|
837
|
+
padding-bottom: 1rem;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
.solid_queue_monitor .chart-header {
|
|
841
|
+
display: flex;
|
|
842
|
+
justify-content: space-between;
|
|
843
|
+
align-items: center;
|
|
844
|
+
flex-wrap: wrap;
|
|
845
|
+
gap: 0.75rem;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
.solid_queue_monitor .chart-header-left {
|
|
849
|
+
display: flex;
|
|
850
|
+
align-items: center;
|
|
851
|
+
gap: 0.5rem;
|
|
852
|
+
flex-wrap: wrap;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
.solid_queue_monitor .chart-header h3 {
|
|
856
|
+
font-size: 1rem;
|
|
857
|
+
font-weight: 600;
|
|
858
|
+
color: var(--text-color);
|
|
859
|
+
margin: 0;
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
.solid_queue_monitor .chart-toggle-btn {
|
|
863
|
+
display: flex;
|
|
864
|
+
align-items: center;
|
|
865
|
+
justify-content: center;
|
|
866
|
+
width: 28px;
|
|
867
|
+
height: 28px;
|
|
868
|
+
background: var(--hover-background);
|
|
869
|
+
border: 1px solid var(--border-color);
|
|
870
|
+
border-radius: 0.375rem;
|
|
871
|
+
cursor: pointer;
|
|
872
|
+
color: var(--text-muted);
|
|
873
|
+
transition: all 0.2s;
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
.solid_queue_monitor .chart-toggle-btn:hover {
|
|
877
|
+
background: var(--border-color);
|
|
878
|
+
color: var(--text-color);
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
.solid_queue_monitor .chart-toggle-icon {
|
|
882
|
+
transition: transform 0.2s;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
.solid_queue_monitor .chart-section.collapsed .chart-toggle-icon {
|
|
886
|
+
transform: rotate(-90deg);
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
.solid_queue_monitor .chart-summary {
|
|
890
|
+
display: flex;
|
|
891
|
+
align-items: center;
|
|
892
|
+
gap: 0.5rem;
|
|
893
|
+
font-size: 0.8rem;
|
|
894
|
+
color: var(--text-muted);
|
|
895
|
+
margin-left: 0.5rem;
|
|
896
|
+
padding-left: 0.75rem;
|
|
897
|
+
border-left: 1px solid var(--border-color);
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
.solid_queue_monitor .summary-item {
|
|
901
|
+
white-space: nowrap;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
.solid_queue_monitor .summary-created {
|
|
905
|
+
color: #3b82f6;
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
.solid_queue_monitor .summary-completed {
|
|
909
|
+
color: #10b981;
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
.solid_queue_monitor .summary-failed {
|
|
913
|
+
color: #ef4444;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
.solid_queue_monitor .summary-separator {
|
|
917
|
+
color: var(--border-color);
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
.solid_queue_monitor .chart-time-select-wrapper {
|
|
921
|
+
position: relative;
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
.solid_queue_monitor .chart-time-select {
|
|
925
|
+
appearance: none;
|
|
926
|
+
padding: 0.5rem 2rem 0.5rem 0.75rem;
|
|
927
|
+
font-size: 0.8rem;
|
|
928
|
+
color: var(--text-color);
|
|
929
|
+
background: var(--input-background);
|
|
930
|
+
border: 1px solid var(--border-color);
|
|
931
|
+
border-radius: 0.375rem;
|
|
932
|
+
cursor: pointer;
|
|
933
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
|
|
934
|
+
background-repeat: no-repeat;
|
|
935
|
+
background-position: right 0.5rem center;
|
|
936
|
+
background-size: 14px;
|
|
937
|
+
min-width: 140px;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
.solid_queue_monitor .chart-time-select:hover {
|
|
941
|
+
border-color: var(--text-muted);
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
.solid_queue_monitor .chart-time-select:focus {
|
|
945
|
+
outline: none;
|
|
946
|
+
border-color: var(--primary-color);
|
|
947
|
+
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
.solid_queue_monitor .chart-collapsible {
|
|
951
|
+
overflow: hidden;
|
|
952
|
+
transition: max-height 0.3s ease-out, opacity 0.2s ease-out, margin-top 0.3s ease-out;
|
|
953
|
+
max-height: 500px;
|
|
954
|
+
opacity: 1;
|
|
955
|
+
margin-top: 1rem;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
.solid_queue_monitor .chart-section.collapsed .chart-collapsible {
|
|
959
|
+
max-height: 0;
|
|
960
|
+
opacity: 0;
|
|
961
|
+
margin-top: 0;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
.solid_queue_monitor .chart-container {
|
|
965
|
+
width: 100%;
|
|
966
|
+
overflow-x: auto;
|
|
967
|
+
overflow-y: hidden;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
.solid_queue_monitor .chart-container svg {
|
|
971
|
+
display: block;
|
|
972
|
+
width: 100%;
|
|
973
|
+
height: auto;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
.solid_queue_monitor .job-activity-chart {
|
|
977
|
+
width: 100%;
|
|
978
|
+
height: auto;
|
|
979
|
+
min-height: 250px;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
.solid_queue_monitor .grid-line {
|
|
983
|
+
stroke: var(--border-color);
|
|
984
|
+
stroke-width: 1;
|
|
985
|
+
stroke-dasharray: 4 4;
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
.solid_queue_monitor .axis-line {
|
|
989
|
+
stroke: var(--border-color);
|
|
990
|
+
stroke-width: 1;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
.solid_queue_monitor .axis-label {
|
|
994
|
+
font-size: 11px;
|
|
995
|
+
fill: var(--text-muted);
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
.solid_queue_monitor .x-label {
|
|
999
|
+
text-anchor: middle;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
.solid_queue_monitor .y-label {
|
|
1003
|
+
text-anchor: end;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
.solid_queue_monitor .chart-line {
|
|
1007
|
+
stroke-linecap: round;
|
|
1008
|
+
stroke-linejoin: round;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
.solid_queue_monitor .data-point {
|
|
1012
|
+
cursor: pointer;
|
|
1013
|
+
transition: r 0.2s;
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
.solid_queue_monitor .data-point:hover {
|
|
1017
|
+
r: 6;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
.solid_queue_monitor .chart-legend {
|
|
1021
|
+
display: flex;
|
|
1022
|
+
justify-content: center;
|
|
1023
|
+
gap: 1.5rem;
|
|
1024
|
+
margin-top: 1rem;
|
|
1025
|
+
flex-wrap: wrap;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
.solid_queue_monitor .legend-item {
|
|
1029
|
+
display: flex;
|
|
1030
|
+
align-items: center;
|
|
1031
|
+
gap: 0.375rem;
|
|
1032
|
+
font-size: 0.875rem;
|
|
1033
|
+
color: var(--text-muted);
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
.solid_queue_monitor .legend-color {
|
|
1037
|
+
width: 12px;
|
|
1038
|
+
height: 12px;
|
|
1039
|
+
border-radius: 2px;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
.solid_queue_monitor .chart-tooltip {
|
|
1043
|
+
position: fixed;
|
|
1044
|
+
background: #1f2937;
|
|
1045
|
+
color: white;
|
|
1046
|
+
padding: 0.5rem 0.75rem;
|
|
1047
|
+
border-radius: 0.375rem;
|
|
1048
|
+
font-size: 0.75rem;
|
|
1049
|
+
pointer-events: none;
|
|
1050
|
+
z-index: 1000;
|
|
1051
|
+
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
.solid_queue_monitor .tooltip-label {
|
|
1055
|
+
font-weight: 500;
|
|
1056
|
+
margin-bottom: 0.25rem;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
.solid_queue_monitor .tooltip-value {
|
|
1060
|
+
color: #d1d5db;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
.solid_queue_monitor .chart-empty {
|
|
1064
|
+
display: flex;
|
|
1065
|
+
align-items: center;
|
|
1066
|
+
justify-content: center;
|
|
1067
|
+
height: 200px;
|
|
1068
|
+
color: var(--text-muted);
|
|
1069
|
+
font-size: 0.875rem;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
@media (max-width: 768px) {
|
|
1073
|
+
.solid_queue_monitor .chart-section {
|
|
1074
|
+
padding: 1rem;
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
.solid_queue_monitor .chart-header {
|
|
1078
|
+
flex-direction: column;
|
|
1079
|
+
align-items: flex-start;
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
.solid_queue_monitor .chart-header-left {
|
|
1083
|
+
width: 100%;
|
|
1084
|
+
flex-wrap: wrap;
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
.solid_queue_monitor .chart-summary {
|
|
1088
|
+
margin-left: 0;
|
|
1089
|
+
padding-left: 0;
|
|
1090
|
+
border-left: none;
|
|
1091
|
+
margin-top: 0.5rem;
|
|
1092
|
+
width: 100%;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
.solid_queue_monitor .chart-time-select {
|
|
1096
|
+
width: 100%;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
.solid_queue_monitor .job-activity-chart {
|
|
1100
|
+
min-height: 200px;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
.solid_queue_monitor .chart-legend {
|
|
1104
|
+
gap: 1rem;
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
/* Theme toggle button */
|
|
1109
|
+
.solid_queue_monitor .theme-toggle-btn {
|
|
1110
|
+
display: flex;
|
|
1111
|
+
align-items: center;
|
|
1112
|
+
justify-content: center;
|
|
1113
|
+
width: 36px;
|
|
1114
|
+
height: 36px;
|
|
1115
|
+
background: var(--card-background);
|
|
1116
|
+
border: 1px solid var(--border-color);
|
|
1117
|
+
border-radius: 50%;
|
|
1118
|
+
cursor: pointer;
|
|
1119
|
+
color: var(--text-muted);
|
|
1120
|
+
transition: all 0.2s;
|
|
1121
|
+
box-shadow: var(--card-shadow);
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
.solid_queue_monitor .theme-toggle-btn:hover {
|
|
1125
|
+
color: var(--text-color);
|
|
1126
|
+
border-color: var(--text-muted);
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
.solid_queue_monitor .theme-toggle-btn svg {
|
|
1130
|
+
width: 18px;
|
|
1131
|
+
height: 18px;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
/* Hide moon icon in light mode, show sun icon */
|
|
1135
|
+
.solid_queue_monitor .theme-icon-moon {
|
|
1136
|
+
display: none;
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
.solid_queue_monitor .theme-icon-sun {
|
|
1140
|
+
display: block;
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
/* In dark mode, show moon icon, hide sun icon */
|
|
1144
|
+
.solid_queue_monitor.dark-theme .theme-icon-moon {
|
|
1145
|
+
display: block;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
.solid_queue_monitor.dark-theme .theme-icon-sun {
|
|
1149
|
+
display: none;
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
.solid_queue_monitor .header-controls {
|
|
1153
|
+
display: flex;
|
|
1154
|
+
align-items: center;
|
|
1155
|
+
gap: 0.75rem;
|
|
1156
|
+
}
|
|
765
1157
|
CSS
|
|
766
1158
|
end
|
|
767
1159
|
end
|
data/config/database.yml
ADDED
data/config/routes.rb
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
# Guard against multiple loads of routes file in test environment
|
|
3
4
|
SolidQueueMonitor::Engine.routes.draw do
|
|
4
|
-
|
|
5
|
+
return if SolidQueueMonitor::Engine.routes.routes.any? { |r| r.name == 'root' }
|
|
6
|
+
|
|
7
|
+
root to: 'overview#index'
|
|
8
|
+
|
|
9
|
+
get 'chart_data', to: 'overview#chart_data', as: :chart_data
|
|
5
10
|
|
|
6
11
|
resources :ready_jobs, only: [:index]
|
|
7
12
|
resources :scheduled_jobs, only: [:index]
|
|
@@ -17,4 +22,7 @@ SolidQueueMonitor::Engine.routes.draw do
|
|
|
17
22
|
post 'discard_failed_job/:id', to: 'failed_jobs#discard', as: :discard_failed_job
|
|
18
23
|
post 'retry_failed_jobs', to: 'failed_jobs#retry_all', as: :retry_failed_jobs
|
|
19
24
|
post 'discard_failed_jobs', to: 'failed_jobs#discard_all', as: :discard_failed_jobs
|
|
25
|
+
|
|
26
|
+
post 'pause_queue', to: 'queues#pause', as: :pause_queue
|
|
27
|
+
post 'resume_queue', to: 'queues#resume', as: :resume_queue
|
|
20
28
|
end
|
|
@@ -9,6 +9,11 @@ module SolidQueueMonitor
|
|
|
9
9
|
# Optional: Add eager loading for production
|
|
10
10
|
config.eager_load_paths << root.join('app', 'services')
|
|
11
11
|
|
|
12
|
+
# Ensure session middleware is available
|
|
13
|
+
initializer 'solid_queue_monitor.middleware' do |app|
|
|
14
|
+
app.config.session_store :cookie_store, key: '_solid_queue_monitor_session' unless app.config.session_store
|
|
15
|
+
end
|
|
16
|
+
|
|
12
17
|
initializer 'solid_queue_monitor.assets' do |app|
|
|
13
18
|
# Optional: Add assets if needed
|
|
14
19
|
end
|