solid_queue_dashboard 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/CHANGELOG.md +1 -1
  4. data/Procfile.dev +2 -0
  5. data/README.md +72 -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 +2062 -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 +72 -3
@@ -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