diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a5585a..f775c19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Recurring Tasks page (`/jobs/recurring_tasks`) showing key, cron schedule, job class or command, queue, next run time, last run time, and Static/Dynamic badge; eager loads recurring executions to avoid N+1 +- Recurring Tasks stat card on the dashboard (cyan, links to the page) +- "View recurring tasks" button in the dashboard Quick Links +- `sqd-badge--static` (green) and `sqd-badge--dynamic` (purple) badge variants - Hamburger toggle nav for viewports narrower than 576px — three-bar button opens a full-width dropdown with vertically stacked links; no JS file required - `sqd-grid-2` utility class for responsive two-column layouts (collapses to one column at ≤768px) - `.sqd-sr-only` utility class for visually-hidden text @@ -22,6 +26,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Dashboard stat card order aligned with nav: Ready, Scheduled, Running, Blocked, Failed, Queues, Recurring, Processes +- Stat grid minimum cell width reduced from 150px to 128px so all 8 cards fit in one row - Navbar title and links constrained to the same max-width as page content so they align horizontally with the dashboard - Page headers stack vertically on mobile (≤640px) - Stat grid uses a smaller minimum cell width on mobile diff --git a/app/assets/stylesheets/solid_queue_web/application.css b/app/assets/stylesheets/solid_queue_web/application.css index 96342e0..78fca7e 100644 --- a/app/assets/stylesheets/solid_queue_web/application.css +++ b/app/assets/stylesheets/solid_queue_web/application.css @@ -149,7 +149,7 @@ body { /* Stat cards */ .sqd-stats { display: grid; - grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); + grid-template-columns: repeat(auto-fill, minmax(128px, 1fr)); gap: 1rem; margin-bottom: 2rem; } @@ -183,6 +183,7 @@ body { .sqd-stat--blocked .sqd-stat__value { color: var(--warning); } .sqd-stat--queues .sqd-stat__value { color: var(--purple); } .sqd-stat--processes .sqd-stat__value { color: var(--muted); } +.sqd-stat--recurring .sqd-stat__value { color: var(--info); } .sqd-stat--link { display: block; @@ -267,6 +268,8 @@ tbody tr:hover { background: var(--bg); } .sqd-badge--claimed { background: #cfe2ff; color: #084298; } .sqd-badge--failed { background: #f8d7da; color: #842029; } .sqd-badge--blocked { background: #fff3cd; color: #664d03; } +.sqd-badge--static { background: #d1e7dd; color: #0f5132; } +.sqd-badge--dynamic { background: #e0d7f5; color: #4a2c8a; } .sqd-badge--paused { background: #e2e3e5; color: #41464b; } .sqd-badge--running { background: #d1e7dd; color: #0f5132; } .sqd-badge--supervisor { background: #e0d7f5; color: #4a2c8a; } diff --git a/app/controllers/solid_queue_web/dashboard_controller.rb b/app/controllers/solid_queue_web/dashboard_controller.rb index 2ed86e4..f92335f 100644 --- a/app/controllers/solid_queue_web/dashboard_controller.rb +++ b/app/controllers/solid_queue_web/dashboard_controller.rb @@ -8,7 +8,8 @@ def index failed: SolidQueue::FailedExecution.count, blocked: SolidQueue::BlockedExecution.count, queues: SolidQueue::Job.select(:queue_name).distinct.count, - processes: SolidQueue::Process.count + processes: SolidQueue::Process.count, + recurring: SolidQueue::RecurringTask.count } end end diff --git a/app/controllers/solid_queue_web/recurring_tasks_controller.rb b/app/controllers/solid_queue_web/recurring_tasks_controller.rb new file mode 100644 index 0000000..a719304 --- /dev/null +++ b/app/controllers/solid_queue_web/recurring_tasks_controller.rb @@ -0,0 +1,7 @@ +module SolidQueueWeb + class RecurringTasksController < ApplicationController + def index + @recurring_tasks = SolidQueue::RecurringTask.includes(:recurring_executions).order(:key) + end + end +end diff --git a/app/views/layouts/solid_queue_web/application.html.erb b/app/views/layouts/solid_queue_web/application.html.erb index d11ad2f..fdefcb9 100644 --- a/app/views/layouts/solid_queue_web/application.html.erb +++ b/app/views/layouts/solid_queue_web/application.html.erb @@ -26,6 +26,7 @@
| Key | +Schedule | +Job / Command | +Queue | +Next Run | +Last Run | +Type | +
|---|---|---|---|---|---|---|
| <%= task.key %> | +<%= task.schedule %> | +
+ <% if task.class_name.present? %>
+ <%= task.class_name %>
+ <% if task.arguments.present? %>
+
+ <%= task.arguments.inspect %>
+
+ <% end %>
+ <% else %>
+ <%= task.command %>
+ <% end %>
+ <% if task.description.present? %>
+
+ <%= task.description %>
+
+ <% end %>
+ |
+ <%= task.queue_name.presence || "default" %> | ++ <% + next_run = begin + task.next_time.strftime("%Y-%m-%d %H:%M %Z") + rescue + nil + end + %> + <%= next_run || "—" %> + | ++ <% last_run = task.last_enqueued_time %> + <%= last_run ? last_run.strftime("%Y-%m-%d %H:%M %Z") : "—" %> + | ++ <% if task.static? %> + Static + <% else %> + Dynamic + <% end %> + | +