solid_queue_dashboard 0.0.1 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/CHANGELOG.md +5 -1
  4. data/Procfile.dev +2 -0
  5. data/README.md +73 -21
  6. data/app/assets/javascripts/solid_queue_dashboard/alpine.js +5 -0
  7. data/app/assets/javascripts/solid_queue_dashboard/application.js +46 -0
  8. data/app/assets/stylesheets/solid_queue_dashboard/application.css +2049 -0
  9. data/app/assets/stylesheets/solid_queue_dashboard/tailwind.css +554 -0
  10. data/app/controllers/solid_queue_dashboard/appearance_controller.rb +8 -0
  11. data/app/controllers/solid_queue_dashboard/application_controller.rb +7 -0
  12. data/app/controllers/solid_queue_dashboard/dashboard_controller.rb +8 -0
  13. data/app/controllers/solid_queue_dashboard/jobs_controller.rb +42 -0
  14. data/app/controllers/solid_queue_dashboard/processes_controller.rb +28 -0
  15. data/app/controllers/solid_queue_dashboard/recurring_tasks_controller.rb +30 -0
  16. data/app/helpers/solid_queue_dashboard/appearance_helper.rb +7 -0
  17. data/app/helpers/solid_queue_dashboard/application_helper.rb +7 -0
  18. data/app/helpers/solid_queue_dashboard/icons_helper.rb +231 -0
  19. data/app/helpers/solid_queue_dashboard/jobs_helper.rb +51 -0
  20. data/app/helpers/solid_queue_dashboard/pagination_helper.rb +38 -0
  21. data/app/helpers/solid_queue_dashboard/processes_helper.rb +35 -0
  22. data/app/helpers/solid_queue_dashboard/recurring_tasks_helper.rb +33 -0
  23. data/app/views/layouts/solid_queue_dashboard/application.html.erb +21 -0
  24. data/app/views/solid_queue_dashboard/application/_flash_messages.html.erb +38 -0
  25. data/app/views/solid_queue_dashboard/application/_footer.html.erb +11 -0
  26. data/app/views/solid_queue_dashboard/application/_navbar.html.erb +50 -0
  27. data/app/views/solid_queue_dashboard/application/_pagination.html.erb +19 -0
  28. data/app/views/solid_queue_dashboard/dashboard/index.html.erb +41 -0
  29. data/app/views/solid_queue_dashboard/jobs/_filters.html.erb +87 -0
  30. data/app/views/solid_queue_dashboard/jobs/_table.html.erb +19 -0
  31. data/app/views/solid_queue_dashboard/jobs/_table_row.html.erb +82 -0
  32. data/app/views/solid_queue_dashboard/jobs/index.html.erb +57 -0
  33. data/app/views/solid_queue_dashboard/jobs/show.html.erb +192 -0
  34. data/app/views/solid_queue_dashboard/processes/_filters.html.erb +64 -0
  35. data/app/views/solid_queue_dashboard/processes/_table.html.erb +18 -0
  36. data/app/views/solid_queue_dashboard/processes/_table_row.html.erb +32 -0
  37. data/app/views/solid_queue_dashboard/processes/index.html.erb +27 -0
  38. data/app/views/solid_queue_dashboard/processes/show.html.erb +79 -0
  39. data/app/views/solid_queue_dashboard/recurring_tasks/_filters.html.erb +26 -0
  40. data/app/views/solid_queue_dashboard/recurring_tasks/_table.html.erb +19 -0
  41. data/app/views/solid_queue_dashboard/recurring_tasks/_table_row.html.erb +31 -0
  42. data/app/views/solid_queue_dashboard/recurring_tasks/index.html.erb +21 -0
  43. data/app/views/solid_queue_dashboard/recurring_tasks/show.html.erb +129 -0
  44. data/bun.lockb +0 -0
  45. data/config/routes.rb +18 -0
  46. data/lib/solid_queue_dashboard/configuration.rb +17 -0
  47. data/lib/solid_queue_dashboard/decorators/job_decorator.rb +63 -0
  48. data/lib/solid_queue_dashboard/decorators/jobs_decorator.rb +74 -0
  49. data/lib/solid_queue_dashboard/decorators/process_decorator.rb +13 -0
  50. data/lib/solid_queue_dashboard/decorators/processes_decorator.rb +15 -0
  51. data/lib/solid_queue_dashboard/decorators/recurring_task_decorator.rb +22 -0
  52. data/lib/solid_queue_dashboard/decorators/recurring_tasks_decorator.rb +26 -0
  53. data/lib/solid_queue_dashboard/engine.rb +13 -0
  54. data/lib/solid_queue_dashboard/job.rb +26 -0
  55. data/lib/solid_queue_dashboard/process.rb +24 -0
  56. data/lib/solid_queue_dashboard/recurring_task.rb +14 -0
  57. data/lib/solid_queue_dashboard/version.rb +1 -1
  58. data/lib/solid_queue_dashboard.rb +39 -1
  59. data/package.json +13 -0
  60. data/tailwind.config.js +83 -0
  61. metadata +73 -4
@@ -0,0 +1,554 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ @layer base {
6
+ :root {
7
+ --background: 0 0% 98%;
8
+ --foreground: 240 10% 3.9%;
9
+ --card: 0 0% 100%;
10
+ --card-foreground: 240 10% 3.9%;
11
+ --popover: 0 0% 100%;
12
+ --popover-foreground: 240 10% 3.9%;
13
+ --primary: 240 5.9% 10%;
14
+ --primary-foreground: 0 0% 98%;
15
+ --secondary: 240 4.8% 95.9%;
16
+ --secondary-foreground: 240 5.9% 10%;
17
+ --muted: 240 4.8% 95.9%;
18
+ --muted-foreground: 240 3.8% 46.1%;
19
+ --accent: 240 4.8% 93.8%;
20
+ --accent-foreground: 240 5.9% 10%;
21
+ --destructive: 0 84.2% 60.2%;
22
+ --destructive-foreground: 0 0% 98%;
23
+ --border: 240 5.9% 90%;
24
+ --input: 240 5.9% 90%;
25
+ --ring: 240 5.9% 10%;
26
+ --radius: 0.65rem;
27
+ --chart-1: 12 76% 61%;
28
+ --chart-2: 173 58% 39%;
29
+ --chart-3: 197 37% 24%;
30
+ --chart-4: 43 74% 66%;
31
+ --chart-5: 27 87% 67%;
32
+ }
33
+
34
+ .dark {
35
+ --background: 240 10% 5.4%;
36
+ --foreground: 0 0% 98%;
37
+ --card: 240 10% 3.9%;
38
+ --card-foreground: 0 0% 98%;
39
+ --popover: 240 10% 3.9%;
40
+ --popover-foreground: 0 0% 98%;
41
+ --primary: 0 0% 98%;
42
+ --primary-foreground: 240 5.9% 10%;
43
+ --secondary: 240 3.7% 15.9%;
44
+ --secondary-foreground: 0 0% 98%;
45
+ --muted: 240 3.7% 15.9%;
46
+ --muted-foreground: 240 5% 64.9%;
47
+ --accent: 240 3.7% 15.9%;
48
+ --accent-foreground: 0 0% 98%;
49
+ --destructive: 0 62.8% 30.6%;
50
+ --destructive-foreground: 0 0% 98%;
51
+ --border: 240 3.7% 11%;
52
+ --input: 240 3.7% 15.9%;
53
+ --ring: 240 4.9% 83.9%;
54
+ --chart-1: 220 70% 50%;
55
+ --chart-2: 160 60% 45%;
56
+ --chart-3: 30 80% 55%;
57
+ --chart-4: 280 65% 60%;
58
+ --chart-5: 340 75% 55%;
59
+ }
60
+ }
61
+
62
+ @layer base {
63
+ * {
64
+ @apply border-border;
65
+ }
66
+
67
+ body {
68
+ @apply bg-background text-foreground;
69
+ font-feature-settings: "rlig" 1, "calt" 1;
70
+ }
71
+
72
+ [data-href] {
73
+ @apply cursor-pointer;
74
+ }
75
+
76
+ .link {
77
+ @apply underline hover:opacity-75;
78
+ }
79
+ }
80
+
81
+ @layer components {
82
+ /*
83
+ Label
84
+ */
85
+
86
+ .label {
87
+ @apply text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70;
88
+ }
89
+
90
+ /*
91
+ Select
92
+ */
93
+
94
+ .select {
95
+ @apply form-select w-48 border border-input bg-white dark:bg-black text-foreground rounded-md h-10 px-3 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50;
96
+ }
97
+
98
+ /*
99
+ Badge
100
+ */
101
+
102
+ .badge {
103
+ @apply border inline-flex items-center gap-x-1.5 rounded-md px-1.5 py-0.5 text-sm/5 font-medium sm:text-xs/5 forced-colors:outline;
104
+ }
105
+
106
+ .badge-primary {
107
+ @apply border-transparent bg-primary text-primary-foreground hover:bg-primary/80;
108
+ }
109
+
110
+ .badge-secondary {
111
+ @apply border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80;
112
+ }
113
+
114
+ .badge-destructive {
115
+ @apply border-transparent bg-destructive/15 text-destructive dark:bg-destructive/10 dark:text-destructive-foreground;
116
+ }
117
+
118
+ .badge-outline {
119
+ @apply text-foreground;
120
+ }
121
+
122
+ .badge-red {
123
+ @apply border-transparent bg-red-500/15 text-red-700 dark:bg-red-500/10 dark:text-red-400;
124
+ }
125
+
126
+ .badge-orange {
127
+ @apply border-transparent bg-orange-500/15 text-orange-700 dark:bg-orange-500/10 dark:text-orange-400;
128
+ }
129
+
130
+ .badge-amber {
131
+ @apply border-transparent bg-amber-400/20 text-amber-700 dark:bg-amber-400/10 dark:text-amber-400;
132
+ }
133
+
134
+ .badge-yellow {
135
+ @apply border-transparent bg-yellow-400/20 text-yellow-700 dark:bg-yellow-400/10 dark:text-yellow-300;
136
+ }
137
+
138
+ .badge-lime {
139
+ @apply border-transparent bg-lime-400/20 text-lime-700 dark:bg-lime-400/10 dark:text-lime-300;
140
+ }
141
+
142
+ .badge-green {
143
+ @apply border-transparent bg-green-500/15 text-green-700 dark:bg-green-500/10 dark:text-green-400;
144
+ }
145
+
146
+ .badge-emerald {
147
+ @apply border-transparent bg-emerald-500/15 text-emerald-700 dark:bg-emerald-500/10 dark:text-emerald-400;
148
+ }
149
+
150
+ .badge-teal {
151
+ @apply border-transparent bg-teal-500/15 text-teal-700 dark:bg-teal-500/10 dark:text-teal-300;
152
+ }
153
+
154
+ .badge-cyan {
155
+ @apply border-transparent bg-cyan-400/20 text-cyan-700 dark:bg-cyan-400/10 dark:text-cyan-300;
156
+ }
157
+
158
+ .badge-sky {
159
+ @apply border-transparent bg-sky-500/15 text-sky-700 dark:bg-sky-500/10 dark:text-sky-300;
160
+ }
161
+
162
+ .badge-blue {
163
+ @apply border-transparent bg-blue-500/15 text-blue-700 dark:text-blue-400;
164
+ }
165
+
166
+ .badge-indigo {
167
+ @apply border-transparent bg-indigo-500/15 text-indigo-700 dark:text-indigo-400;
168
+ }
169
+
170
+ .badge-violet {
171
+ @apply border-transparent bg-violet-500/15 text-violet-700 dark:text-violet-400;
172
+ }
173
+
174
+ .badge-purple {
175
+ @apply border-transparent bg-purple-500/15 text-purple-700 dark:text-purple-400;
176
+ }
177
+
178
+ .badge-fuchsia {
179
+ @apply border-transparent bg-fuchsia-400/15 text-fuchsia-700 dark:bg-fuchsia-400/10 dark:text-fuchsia-400;
180
+ }
181
+
182
+ .badge-pink {
183
+ @apply border-transparent bg-pink-400/15 text-pink-700 dark:bg-pink-400/10 dark:text-pink-400;
184
+ }
185
+
186
+ .badge-rose {
187
+ @apply border-transparent bg-rose-400/15 text-rose-700 dark:bg-rose-400/10 dark:text-rose-400;
188
+ }
189
+
190
+ .badge-zinc {
191
+ @apply border-transparent bg-zinc-600/10 text-zinc-700 dark:bg-white/5 dark:text-zinc-400;
192
+ }
193
+
194
+ /*
195
+ Circle
196
+ */
197
+
198
+ .circle {
199
+ @apply size-2 inline-flex items-center justify-center rounded-full;
200
+ }
201
+
202
+ .circle-primary {
203
+ @apply bg-primary;
204
+ }
205
+
206
+ .circle-secondary {
207
+ @apply bg-secondary;
208
+ }
209
+
210
+ .circle-destructive {
211
+ @apply bg-destructive;
212
+ }
213
+
214
+ .circle-outline {
215
+ @apply border border-current bg-background;
216
+ }
217
+
218
+ .circle-red {
219
+ @apply bg-red-500;
220
+ }
221
+
222
+ .circle-orange {
223
+ @apply bg-orange-500;
224
+ }
225
+
226
+ .circle-amber {
227
+ @apply bg-amber-400;
228
+ }
229
+
230
+ .circle-yellow {
231
+ @apply bg-yellow-400;
232
+ }
233
+
234
+ .circle-lime {
235
+ @apply bg-lime-400;
236
+ }
237
+
238
+ .circle-green {
239
+ @apply bg-green-500;
240
+ }
241
+
242
+ .circle-emerald {
243
+ @apply bg-emerald-500;
244
+ }
245
+
246
+ .circle-teal {
247
+ @apply bg-teal-500;
248
+ }
249
+
250
+ .circle-cyan {
251
+ @apply bg-cyan-400;
252
+ }
253
+
254
+ .circle-sky {
255
+ @apply bg-sky-500;
256
+ }
257
+
258
+ .circle-blue {
259
+ @apply bg-blue-500;
260
+ }
261
+
262
+ .circle-indigo {
263
+ @apply bg-indigo-500;
264
+ }
265
+
266
+ .circle-violet {
267
+ @apply bg-violet-500;
268
+ }
269
+
270
+ .circle-purple {
271
+ @apply bg-purple-500;
272
+ }
273
+
274
+ .circle-fuchsia {
275
+ @apply bg-fuchsia-400;
276
+ }
277
+
278
+ .circle-pink {
279
+ @apply bg-pink-400;
280
+ }
281
+
282
+ .circle-rose {
283
+ @apply bg-rose-400;
284
+ }
285
+
286
+ .circle-zinc {
287
+ @apply bg-zinc-600;
288
+ }
289
+
290
+ /*
291
+ Alert
292
+ */
293
+
294
+ .alert {
295
+ @apply relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground;
296
+ }
297
+
298
+ .alert-default {
299
+ @apply bg-background text-foreground;
300
+ }
301
+
302
+ .alert-destructive {
303
+ @apply border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive;
304
+ }
305
+
306
+ .alert-red {
307
+ @apply border-red-500/50 text-red-700 dark:border-red-500 dark:text-red-300 [&>svg]:text-red-500;
308
+ }
309
+
310
+ .alert-green {
311
+ @apply border-green-500/50 text-green-700 dark:border-green-500 dark:text-green-300 [&>svg]:text-green-500;
312
+ }
313
+
314
+ .alert-yellow {
315
+ @apply border-yellow-500/50 text-yellow-700 dark:border-yellow-500 dark:text-yellow-300 [&>svg]:text-yellow-500;
316
+ }
317
+
318
+ .alert-blue {
319
+ @apply border-blue-500/50 text-blue-700 dark:border-blue-500 dark:text-blue-300 [&>svg]:text-blue-500;
320
+ }
321
+
322
+ .alert-purple {
323
+ @apply border-purple-500/50 text-purple-700 dark:border-purple-500 dark:text-purple-300 [&>svg]:text-purple-500;
324
+ }
325
+
326
+ .alert-pink {
327
+ @apply border-pink-500/50 text-pink-700 dark:border-pink-500 dark:text-pink-300 [&>svg]:text-pink-500;
328
+ }
329
+
330
+ .alert-title {
331
+ @apply mb-1 font-medium leading-none tracking-tight;
332
+ }
333
+
334
+ .alert-description {
335
+ @apply text-sm [&_p]:leading-relaxed;
336
+ }
337
+
338
+ /*
339
+ Button
340
+ */
341
+
342
+ .btn {
343
+ @apply inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50;
344
+ }
345
+
346
+ .btn-default {
347
+ @apply bg-primary text-primary-foreground hover:bg-primary/90;
348
+ }
349
+
350
+ .btn-destructive {
351
+ @apply bg-destructive text-destructive-foreground hover:bg-destructive/90;
352
+ }
353
+
354
+ .btn-outline {
355
+ @apply border border-input bg-background hover:bg-accent hover:text-accent-foreground;
356
+ }
357
+
358
+ .btn-secondary {
359
+ @apply bg-secondary text-secondary-foreground hover:bg-secondary/80;
360
+ }
361
+
362
+ .btn-ghost {
363
+ @apply hover:bg-accent hover:text-accent-foreground;
364
+ }
365
+
366
+ .btn-link {
367
+ @apply text-primary underline-offset-4 hover:underline;
368
+ }
369
+
370
+ .btn-xs {
371
+ @apply h-7 rounded-md px-2 gap-1;
372
+ }
373
+
374
+ .btn-sm {
375
+ @apply h-9 rounded-md px-3 gap-1.5;
376
+ }
377
+
378
+ .btn-md {
379
+ @apply h-10 px-4 py-2 gap-1.5;
380
+ }
381
+
382
+ .btn-lg {
383
+ @apply h-11 rounded-md px-8 gap-2;
384
+ }
385
+
386
+ .btn-icon {
387
+ @apply h-10 w-10;
388
+ }
389
+
390
+ /*
391
+ Info Line
392
+ */
393
+
394
+ .info-line {
395
+ @apply flex items-center gap-4;
396
+ }
397
+
398
+ .info-line-label {
399
+ @apply text-zinc-500 whitespace-nowrap;
400
+ }
401
+
402
+ .info-line-separator {
403
+ @apply h-px flex-1 bg-zinc-950/10 dark:border-white/10 translate-y-px;
404
+ }
405
+
406
+ .info-line-value {
407
+ @apply font-medium text-right text-zinc-950 dark:text-white;
408
+ }
409
+
410
+ /*
411
+ Card
412
+ */
413
+
414
+ .card {
415
+ @apply rounded-lg border bg-card text-card-foreground shadow-sm;
416
+ }
417
+
418
+ .card-header {
419
+ @apply flex flex-col space-y-1.5 p-6;
420
+ }
421
+
422
+ .card-title {
423
+ @apply text-2xl font-semibold leading-none tracking-tight;
424
+ }
425
+
426
+ .card-description {
427
+ @apply text-sm text-muted-foreground;
428
+ }
429
+
430
+ .card-content {
431
+ @apply p-6 pt-0;
432
+ }
433
+
434
+ .card-footer {
435
+ @apply flex items-center p-6 pt-0;
436
+ }
437
+
438
+ /*
439
+ Navbar
440
+ */
441
+
442
+ .navbar {
443
+ @apply flex items-center gap-4 bg-background py-4;
444
+ }
445
+
446
+ .navbar-section {
447
+ @apply flex gap-1.5;
448
+ }
449
+
450
+ .navbar-item {
451
+ @apply inline-flex items-center rounded-md justify-center px-3 py-2 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2;
452
+ }
453
+
454
+ .navbar-item-default {
455
+ @apply text-foreground hover:bg-accent hover:text-accent-foreground;
456
+ }
457
+
458
+ .navbar-item-current {
459
+ @apply bg-primary text-primary-foreground;
460
+ }
461
+
462
+ /*
463
+ Table
464
+ */
465
+
466
+ .table-wrapper {
467
+ @apply relative w-full overflow-auto;
468
+ }
469
+
470
+ .table {
471
+ @apply w-full caption-bottom text-sm;
472
+ }
473
+
474
+ .table-header {
475
+ @apply [&_tr]:border-b;
476
+ }
477
+
478
+ .table-body {
479
+ @apply [&_tr:last-child]:border-0;
480
+ }
481
+
482
+ .table-footer {
483
+ @apply border-t bg-muted/50 font-medium [&>tr]:last:border-b-0;
484
+ }
485
+
486
+ .table-row {
487
+ @apply border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted;
488
+ }
489
+
490
+ .table-head {
491
+ @apply h-12 px-4 text-left align-middle font-medium text-muted-foreground whitespace-nowrap [&:has([role=checkbox])]:pr-0;
492
+ }
493
+
494
+ .table-cell {
495
+ @apply p-4 align-middle [&:has([role=checkbox])]:pr-0;
496
+ }
497
+
498
+ .table-caption {
499
+ @apply mt-4 text-sm text-muted-foreground;
500
+ }
501
+
502
+ /*
503
+ Pagination
504
+ */
505
+
506
+ .pagination {
507
+ @apply flex justify-center;
508
+ }
509
+
510
+ .pagination-content {
511
+ @apply flex flex-row items-center gap-1;
512
+ }
513
+
514
+ .pagination-item {
515
+ @apply inline-block;
516
+ }
517
+
518
+ .pagination-link {
519
+ @apply inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50;
520
+ }
521
+
522
+ .pagination-link-active {
523
+ @apply border border-input bg-background hover:bg-accent hover:text-accent-foreground;
524
+ }
525
+
526
+ .pagination-link-inactive {
527
+ @apply hover:bg-accent hover:text-accent-foreground;
528
+ }
529
+
530
+ .pagination-link-icon {
531
+ @apply h-9 w-9;
532
+ }
533
+
534
+ .pagination-link-default {
535
+ @apply h-10 px-4 py-2;
536
+ }
537
+
538
+ .pagination-previous,
539
+ .pagination-next {
540
+ @apply h-10 px-4 py-2 gap-1;
541
+ }
542
+
543
+ .pagination-previous {
544
+ @apply pl-2.5;
545
+ }
546
+
547
+ .pagination-next {
548
+ @apply pr-2.5;
549
+ }
550
+
551
+ .pagination-ellipsis {
552
+ @apply flex h-9 w-9 items-center justify-center;
553
+ }
554
+ }
@@ -0,0 +1,8 @@
1
+ module SolidQueueDashboard
2
+ class AppearanceController < ApplicationController
3
+ def toggle
4
+ cookies[:dark_mode] = cookies[:dark_mode] == "false" ? "true" : "false"
5
+ redirect_to request.referer
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ module SolidQueueDashboard
2
+ class ApplicationController < ActionController::Base
3
+ include SolidQueueDashboard::PaginationHelper
4
+
5
+ layout "solid_queue_dashboard/application"
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ module SolidQueueDashboard
2
+ class DashboardController < ApplicationController
3
+ def index
4
+ @jobs = SolidQueueDashboard.decorate(SolidQueue::Job.all)
5
+ @job_class_names = SolidQueueDashboard.job_class_names
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,42 @@
1
+ module SolidQueueDashboard
2
+ class JobsController < ApplicationController
3
+ before_action :set_jobs, only: [ :index ]
4
+ before_action :set_job, only: [ :show, :retry ]
5
+
6
+ def index
7
+ @job_queue_names = SolidQueueDashboard.job_queue_names
8
+ @job_class_names = SolidQueueDashboard.job_class_names
9
+ end
10
+
11
+ def show
12
+ @job_history = SolidQueueDashboard.decorate(
13
+ SolidQueue::Job
14
+ .where.not(id: @job.id)
15
+ .where(class_name: @job.class_name)
16
+ .order(id: :desc)
17
+ .limit(10)
18
+ )
19
+ end
20
+
21
+ def retry
22
+ @job.retry
23
+ redirect_to @job, notice: "Job has been scheduled for retry"
24
+ end
25
+
26
+ private
27
+
28
+ def set_jobs
29
+ jobs = SolidQueue::Job.order(id: :desc)
30
+ jobs = SolidQueueDashboard.decorate(jobs).with_status(params[:status]) if params[:status].present?
31
+ jobs = jobs.where(class_name: params[:class_name]) if params[:class_name].present?
32
+ jobs = jobs.where(queue_name: params[:queue_name]) if params[:queue_name].present?
33
+
34
+ @pagination = paginate(jobs, page: params[:page].to_i, per_page: params[:per_page].to_i)
35
+ @jobs = SolidQueueDashboard.decorate(@pagination[:records])
36
+ end
37
+
38
+ def set_job
39
+ @job = SolidQueueDashboard.decorate(SolidQueue::Job.find(params[:id]))
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,28 @@
1
+ module SolidQueueDashboard
2
+ class ProcessesController < ApplicationController
3
+ before_action :set_processes, only: [ :index ]
4
+ before_action :set_process, only: [ :show ]
5
+
6
+ def index
7
+ @process_kinds = SolidQueue::Process.distinct.pluck(:kind)
8
+ @process_hostnames = SolidQueue::Process.distinct.pluck(:hostname)
9
+ end
10
+
11
+ def show
12
+ end
13
+
14
+ private
15
+
16
+ def set_processes
17
+ @processes = SolidQueue::Process.all
18
+ @processes = @processes.where(kind: params[:kind]) if params[:kind].present?
19
+ @processes = @processes.where(hostname: params[:hostname]) if params[:hostname].present?
20
+ @processes = @processes.order(id: :desc)
21
+ @processes = SolidQueueDashboard.decorate(@processes)
22
+ end
23
+
24
+ def set_process
25
+ @process = SolidQueueDashboard.decorate(SolidQueue::Process.find(params[:id]))
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,30 @@
1
+ module SolidQueueDashboard
2
+ class RecurringTasksController < ApplicationController
3
+ before_action :set_recurring_tasks, only: [ :index ]
4
+ before_action :set_recurring_task, only: [ :show, :enqueue ]
5
+
6
+ def index
7
+ end
8
+
9
+ def show
10
+ end
11
+
12
+ def enqueue
13
+ @recurring_task.enqueue(at: Time.current)
14
+ redirect_to recurring_tasks_path, notice: "Recurring task enqueued"
15
+ end
16
+
17
+ private
18
+
19
+ def set_recurring_tasks
20
+ @recurring_tasks = SolidQueueDashboard.decorate(SolidQueue::RecurringTask.all)
21
+ @recurring_tasks = @recurring_tasks.with_type(params[:type]) if params[:type].present?
22
+ @recurring_tasks = @recurring_tasks.order(id: :desc)
23
+ @recurring_tasks = SolidQueueDashboard.decorate(@recurring_tasks)
24
+ end
25
+
26
+ def set_recurring_task
27
+ @recurring_task = SolidQueueDashboard.decorate(SolidQueue::RecurringTask.find(params[:id]))
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,7 @@
1
+ module SolidQueueDashboard
2
+ module AppearanceHelper
3
+ def dark_mode?
4
+ cookies[:dark_mode] == "true"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module SolidQueueDashboard
2
+ module ApplicationHelper
3
+ def empty_value
4
+ tag.span("—", class: "text-muted-foreground/30")
5
+ end
6
+ end
7
+ end