flight_control 2.0.0.beta.2 → 2.0.0.beta.3

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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/app/assets/config/flight_control_manifest.js +3 -0
  4. data/app/assets/stylesheets/flight_control/application.css +5 -0
  5. data/app/assets/stylesheets/flight_control/bulma.min.css +21013 -0
  6. data/app/assets/stylesheets/flight_control/forms.css +8 -0
  7. data/app/assets/stylesheets/flight_control/jobs.css +42 -0
  8. data/app/controllers/concerns/flight_control/adapter_features.rb +25 -0
  9. data/app/controllers/concerns/flight_control/application_scoped.rb +39 -0
  10. data/app/controllers/concerns/flight_control/basic_authentication.rb +34 -0
  11. data/app/controllers/concerns/flight_control/failed_jobs_bulk_operations.rb +18 -0
  12. data/app/controllers/concerns/flight_control/job_filters.rb +44 -0
  13. data/app/controllers/concerns/flight_control/job_scoped.rb +17 -0
  14. data/app/controllers/concerns/flight_control/not_found_redirections.rb +36 -0
  15. data/app/controllers/concerns/flight_control/queue_scoped.rb +13 -0
  16. data/app/controllers/flight_control/application_controller.rb +35 -0
  17. data/app/controllers/flight_control/bulk_discards_controller.rb +21 -0
  18. data/app/controllers/flight_control/bulk_retries_controller.rb +10 -0
  19. data/app/controllers/flight_control/discards_controller.rb +19 -0
  20. data/app/controllers/flight_control/dispatches_controller.rb +19 -0
  21. data/app/controllers/flight_control/job_launches_controller.rb +28 -0
  22. data/app/controllers/flight_control/jobs_controller.rb +40 -0
  23. data/app/controllers/flight_control/queues/pauses_controller.rb +15 -0
  24. data/app/controllers/flight_control/queues_controller.rb +17 -0
  25. data/app/controllers/flight_control/recurring_tasks_controller.rb +39 -0
  26. data/app/controllers/flight_control/retries_controller.rb +14 -0
  27. data/app/controllers/flight_control/workers_controller.rb +24 -0
  28. data/app/helpers/flight_control/application_helper.rb +12 -0
  29. data/app/helpers/flight_control/dates_helper.rb +30 -0
  30. data/app/helpers/flight_control/interface_helper.rb +23 -0
  31. data/app/helpers/flight_control/jobs_helper.rb +105 -0
  32. data/app/helpers/flight_control/navigation_helper.rb +61 -0
  33. data/app/javascript/flight_control/application.js +3 -0
  34. data/app/javascript/flight_control/controllers/application.js +9 -0
  35. data/app/javascript/flight_control/controllers/form_controller.js +8 -0
  36. data/app/javascript/flight_control/controllers/index.js +11 -0
  37. data/app/javascript/flight_control/controllers/local_time_controller.js +27 -0
  38. data/app/models/flight_control/application_record.rb +5 -0
  39. data/app/models/flight_control/current.rb +3 -0
  40. data/app/models/flight_control/job_launch.rb +75 -0
  41. data/app/models/flight_control/page.rb +49 -0
  42. data/app/models/flight_control/recurring_task.rb +26 -0
  43. data/app/models/flight_control/worker.rb +18 -0
  44. data/app/views/flight_control/job_launches/new.html.erb +53 -0
  45. data/app/views/flight_control/jobs/_date_range_filter.html.erb +11 -0
  46. data/app/views/flight_control/jobs/_error_information.html.erb +24 -0
  47. data/app/views/flight_control/jobs/_filters.html.erb +49 -0
  48. data/app/views/flight_control/jobs/_general_information.html.erb +77 -0
  49. data/app/views/flight_control/jobs/_job.html.erb +13 -0
  50. data/app/views/flight_control/jobs/_jobs_page.html.erb +13 -0
  51. data/app/views/flight_control/jobs/_raw_data.html.erb +4 -0
  52. data/app/views/flight_control/jobs/_title.html.erb +19 -0
  53. data/app/views/flight_control/jobs/_toolbar.html.erb +18 -0
  54. data/app/views/flight_control/jobs/blocked/_actions.html.erb +3 -0
  55. data/app/views/flight_control/jobs/blocked/_job.html.erb +8 -0
  56. data/app/views/flight_control/jobs/failed/_actions.html.erb +5 -0
  57. data/app/views/flight_control/jobs/failed/_backtrace_toggle.html.erb +14 -0
  58. data/app/views/flight_control/jobs/failed/_job.html.erb +8 -0
  59. data/app/views/flight_control/jobs/finished/_job.html.erb +3 -0
  60. data/app/views/flight_control/jobs/in_progress/_job.html.erb +9 -0
  61. data/app/views/flight_control/jobs/index.html.erb +19 -0
  62. data/app/views/flight_control/jobs/scheduled/_actions.html.erb +5 -0
  63. data/app/views/flight_control/jobs/scheduled/_job.html.erb +13 -0
  64. data/app/views/flight_control/jobs/show.html.erb +6 -0
  65. data/app/views/flight_control/queues/_actions.html.erb +7 -0
  66. data/app/views/flight_control/queues/_job.html.erb +15 -0
  67. data/app/views/flight_control/queues/_queue.html.erb +16 -0
  68. data/app/views/flight_control/queues/_queue_title.html.erb +17 -0
  69. data/app/views/flight_control/queues/index.html.erb +21 -0
  70. data/app/views/flight_control/queues/show.html.erb +25 -0
  71. data/app/views/flight_control/recurring_tasks/_actions.html.erb +5 -0
  72. data/app/views/flight_control/recurring_tasks/_general_information.html.erb +37 -0
  73. data/app/views/flight_control/recurring_tasks/_recurring_task.html.erb +22 -0
  74. data/app/views/flight_control/recurring_tasks/_title.html.erb +10 -0
  75. data/app/views/flight_control/recurring_tasks/index.html.erb +18 -0
  76. data/app/views/flight_control/recurring_tasks/show.html.erb +14 -0
  77. data/app/views/flight_control/shared/_job.html.erb +27 -0
  78. data/app/views/flight_control/shared/_jobs.html.erb +14 -0
  79. data/app/views/flight_control/shared/_pagination_toolbar.html.erb +7 -0
  80. data/app/views/flight_control/workers/_configuration.html.erb +6 -0
  81. data/app/views/flight_control/workers/_raw_data.html.erb +6 -0
  82. data/app/views/flight_control/workers/_title.html.erb +11 -0
  83. data/app/views/flight_control/workers/_worker.html.erb +21 -0
  84. data/app/views/flight_control/workers/_workers_page.html.erb +15 -0
  85. data/app/views/flight_control/workers/index.html.erb +6 -0
  86. data/app/views/flight_control/workers/show.html.erb +14 -0
  87. data/app/views/layouts/flight_control/_application_selection.html.erb +14 -0
  88. data/app/views/layouts/flight_control/_flash.html.erb +9 -0
  89. data/app/views/layouts/flight_control/_navigation.html.erb +9 -0
  90. data/app/views/layouts/flight_control/application.html.erb +28 -0
  91. data/app/views/layouts/flight_control/application_selection/_applications.html.erb +13 -0
  92. data/app/views/layouts/flight_control/application_selection/_servers.html.erb +15 -0
  93. data/config/importmap.rb +5 -0
  94. data/config/routes.rb +34 -0
  95. data/lib/flight_control/version.rb +1 -1
  96. metadata +93 -1
@@ -0,0 +1,19 @@
1
+ <h1 class="title">
2
+ <div class="level">
3
+ <div class="level-left">
4
+ <%= job_title(job) %>
5
+ <div class="<%= modifier_for_status(job.status) %> tag ml-4"><%= job.status %></div>
6
+ </div>
7
+ <div class="level-right">
8
+ <% if job.failed? %>
9
+ <%= render "flight_control/jobs/failed/actions", job: job %>
10
+ <% end %>
11
+ <% if job.blocked? %>
12
+ <%= render "flight_control/jobs/blocked/actions", job: job %>
13
+ <% end %>
14
+ <% if job.scheduled? %>
15
+ <%= render "flight_control/jobs/scheduled/actions", job: job %>
16
+ <% end %>
17
+ </div>
18
+ </div>
19
+ </h1>
@@ -0,0 +1,18 @@
1
+ <div class="buttons is-right level-right">
2
+ <% if active_filters? %>
3
+ <span class="mr-5">
4
+ <%= jobs_count %> jobs found
5
+ </span>
6
+ <% end %>
7
+
8
+ <% if jobs_status.failed? %>
9
+ <% target = active_filters? ? "selection" : "all" %>
10
+
11
+ <%= button_to "Discard #{target}", application_bulk_discards_path(@application, **jobs_filter_param),
12
+ method: :post, disabled: jobs_count == 0, class: "button is-danger is-light",
13
+ form: { data: { turbo_confirm: "This will delete #{jobs_count} jobs and can't be undone. Are you sure?" } } %>
14
+ <%= button_to "Retry #{target}", application_bulk_retries_path(@application, **jobs_filter_param),
15
+ method: :post, disabled: jobs_count == 0,
16
+ class: "button is-warning is-light mr-0" %>
17
+ <% end %>
18
+ </div>
@@ -0,0 +1,3 @@
1
+ <div class="buttons is-right">
2
+ <%= button_to "Run now", application_job_dispatch_path(@application, job.job_id), class: "button is-warning is-light mr-0" %>
3
+ </div>
@@ -0,0 +1,8 @@
1
+ <td><%= link_to job.queue_name, application_queue_path(@application, job.queue) %></td>
2
+ <td>
3
+ <div class="is-family-monospace is-size-7"><%= job.blocked_by %></div>
4
+ <div class="has-text-grey is-size-7"><%= blocked_job_expiration(job) %></div>
5
+ </td>
6
+ <td class="pr-0">
7
+ <%= render "flight_control/jobs/blocked/actions", job: job %>
8
+ </td>
@@ -0,0 +1,5 @@
1
+ <div class="buttons is-right">
2
+ <%= button_to "Discard", application_job_discard_path(@application, job.job_id, params: jobs_filter_param), class: "button is-danger is-light mr-0",
3
+ form: { data: { turbo_confirm: "This will delete the job and can't be undone. Are you sure?" } } %>
4
+ <%= button_to "Retry", application_job_retry_path(@application, job.job_id, params: jobs_filter_param), class: "button is-warning is-light mr-0" %>
5
+ </div>
@@ -0,0 +1,14 @@
1
+ <%# locals: (application:, job:) %>
2
+
3
+ <div class="is-flex is-justify-content-flex-end mb-2 mr-2 backtrace-toggle-selector">
4
+ <div class="tabs is-toggle is-toggle-rounded is-small">
5
+ <ul>
6
+ <li class="<%= class_names('backtrace-clean-link', 'is-active' => clean_backtrace?) %>">
7
+ <%= link_to "Clean", application_job_path(application, job.job_id, clean_backtrace: true) %>
8
+ </li>
9
+ <li class="<%= class_names('backtrace-full-link', 'is-active' => !clean_backtrace?) %>">
10
+ <%= link_to "Full", application_job_path(application, job.job_id, clean_backtrace: false) %>
11
+ </li>
12
+ </ul>
13
+ </div>
14
+ </div>
@@ -0,0 +1,8 @@
1
+ <td>
2
+ <%= link_to failed_job_error(job), application_job_path(@application, job.job_id, anchor: "error") %>
3
+ <div class="has-text-grey"><%= time_distance_in_words_with_title(job.failed_at) %> ago</div>
4
+ </td>
5
+ <td><div class="has-text-grey"><%= job_duration(job) %></div></td>
6
+ <td class="pr-0">
7
+ <%= render "flight_control/jobs/failed/actions", job: job %>
8
+ </td>
@@ -0,0 +1,3 @@
1
+ <td><%= link_to job.queue_name, application_queue_path(@application, job.queue) %></td>
2
+ <td><div class="has-text-grey"><%= job_duration(job) %></div></td>
3
+ <td><div class="has-text-grey"><%= time_distance_in_words_with_title(job.finished_at) %> ago</div></td>
@@ -0,0 +1,9 @@
1
+ <td><%= link_to job.queue_name, application_queue_path(@application, job.queue) %></td>
2
+ <td>
3
+ <% if job.worker_id %>
4
+ <%= link_to "worker #{job.worker_id}", application_worker_path(@application, job.worker_id) %>
5
+ <% else %>
6
+
7
+ <% end %>
8
+ </td>
9
+ <td><div class="has-text-grey"><%= job.started_at ? time_distance_in_words_with_title(job.started_at) : "(Finished)" %></div></td>
@@ -0,0 +1,19 @@
1
+ <% navigation(title: "#{jobs_status.titleize} jobs", section: "#{jobs_status}_jobs".to_sym) %>
2
+
3
+ <% if @jobs_page.empty? && !active_filters? %>
4
+ <%= blank_status_notice "There are no #{jobs_status.dasherize} jobs #{blank_status_emoji(jobs_status)}" %>
5
+ <% else %>
6
+ <div class="level is-flex-wrap-wrap">
7
+ <%= render "flight_control/jobs/filters", job_class_names: @job_class_names, queue_names: @queue_names %>
8
+ <%= render "flight_control/jobs/toolbar", jobs_count: @jobs_count %>
9
+ </div>
10
+
11
+ <% if @jobs_page.empty? %>
12
+ <%= blank_status_notice "No #{jobs_status.dasherize} jobs found with the given filters" %>
13
+ <% else %>
14
+ <%= render "flight_control/jobs/jobs_page", jobs_page: @jobs_page %>
15
+
16
+ <%= render "flight_control/shared/pagination_toolbar", page: @jobs_page, filter_param: jobs_filter_param %>
17
+ <% end %>
18
+ <% end %>
19
+
@@ -0,0 +1,5 @@
1
+ <div class="buttons is-right">
2
+ <%= button_to "Run now", application_job_dispatch_path(@application, job.job_id), class: "button is-warning is-light mr-0" %>
3
+ <%= button_to "Discard", application_job_discard_path(@application, job.job_id), class: "button is-danger is-light mr-0",
4
+ form: { data: { turbo_confirm: "This will delete the job and can't be undone. Are you sure?" } } %>
5
+ </div>
@@ -0,0 +1,13 @@
1
+ <td><%= link_to job.queue_name, application_queue_path(@application, job.queue) %></td>
2
+ <td>
3
+ <%= bidirectional_time_distance_in_words_with_title(job.scheduled_at) %>
4
+ <% if job.executions > 0 %>
5
+ <div class="is-warning tag ml-4"><%= job.executions.ordinalize %> retry</div>
6
+ <% end %>
7
+ <% if job_delayed?(job) %>
8
+ <div class="is-danger tag ml-4">delayed</div>
9
+ <% end %>
10
+ </td>
11
+ <td class="pr-0">
12
+ <%= render "flight_control/jobs/scheduled/actions", job: job %>
13
+ </td>
@@ -0,0 +1,6 @@
1
+ <% navigation(title: "Job #{@job.job_id}", section: navigation_section_for_status(@job.status)) %>
2
+
3
+ <%= render "flight_control/jobs/title", job: @job %>
4
+ <%= render "flight_control/jobs/general_information", job: @job %>
5
+ <%= render "flight_control/jobs/error_information", job: @job %>
6
+ <%= render "flight_control/jobs/raw_data", job: @job %>
@@ -0,0 +1,7 @@
1
+ <div class="buttons is-right">
2
+ <% if queue.active? %>
3
+ <%= button_to "Pause", application_queue_pause_path(@application, queue.name), method: :post, class: "button is-success is-light mr-0" %>
4
+ <% else %>
5
+ <%= button_to "Resume", application_queue_pause_path(@application, queue.name), method: :delete, class: "button is-warning is-light mr-0" %>
6
+ <% end %>
7
+ </div>
@@ -0,0 +1,15 @@
1
+ <tr class="job">
2
+ <td>
3
+ <%= link_to application_job_path(@application, job.job_id, filter: { queue_name: job.queue }) do %>
4
+ <%= job_title(job) %>
5
+ <% end %>
6
+ <div class="has-text-grey">Enqueued <%= time_distance_in_words_with_title(job.enqueued_at.to_datetime) %> ago</div>
7
+ </td>
8
+ <td>
9
+ <% if job.serialized_arguments.present? %>
10
+ <span class="is-family-monospace">
11
+ <%= truncate(job_arguments(job), length: 300) %>
12
+ </span>
13
+ <% end %>
14
+ </td>
15
+ </tr>
@@ -0,0 +1,16 @@
1
+ <tr class="queue">
2
+ <td>
3
+ <%= link_to queue.name, application_queue_path(@application, queue) %>
4
+ <% if queue.paused? %>
5
+ <span class="ml-4 tag is-warning">Paused</span>
6
+ <% end %>
7
+ </td>
8
+ <td>
9
+ <%= queue.size %>
10
+ </td>
11
+ <td class="pr-0">
12
+ <% if queue_pausing_supported? %>
13
+ <%= render "flight_control/queues/actions", queue: queue %>
14
+ <% end %>
15
+ </td>
16
+ </tr>
@@ -0,0 +1,17 @@
1
+ <h1 class="title">
2
+ <div class="level">
3
+ <div class="level-left">
4
+ <%= queue.name %>
5
+ <% if queue.paused? %>
6
+ <span class="ml-4 tag is-warning">Paused</span>
7
+ <% end %>
8
+ </div>
9
+ <% if queue_pausing_supported? %>
10
+ <div class="level-right">
11
+ <%= render "flight_control/queues/actions", queue: queue %>
12
+ </div>
13
+ <% end %>
14
+ </div>
15
+ </h1>
16
+
17
+ <h2 class="subtitle"><%= pluralize queue.size, "pending job" %></h2>
@@ -0,0 +1,21 @@
1
+ <% navigation(title: "Queues", section: :queues) %>
2
+
3
+ <% if @queues.any? %>
4
+ <p class="has-text-grey mb-4"><%= pluralize(@queues.sum(&:size), "pending job") %> across <%= pluralize(@queues.size, "queue") %></p>
5
+ <% end %>
6
+
7
+ <table class="queues table is-hoverable is-fullwidth">
8
+ <thead>
9
+ <tr>
10
+ <th>Queue</th>
11
+ <th>Pending jobs</th>
12
+ <th></th>
13
+ </tr>
14
+ </thead>
15
+
16
+ <tbody>
17
+
18
+ <%= render partial: "flight_control/queues/queue", collection: @queues %>
19
+
20
+ </tbody>
21
+ </table>
@@ -0,0 +1,25 @@
1
+ <% navigation(title: "Queue #{@queue.name}", section: :queues) %>
2
+
3
+ <%= render "flight_control/queues/queue_title", queue: @queue %>
4
+
5
+ <% if @jobs_page.empty? %>
6
+ <%= blank_status_notice "The queue is empty" %>
7
+ <% else %>
8
+ <table class="jobs table queues is-hoverable is-fullwidth">
9
+ <tbody>
10
+ <thead>
11
+ <tr>
12
+ <th class="job-header">Job</th>
13
+ <th></th>
14
+ </tr>
15
+ </thead>
16
+
17
+ <%= render partial: "flight_control/queues/job", collection: @jobs_page.records %>
18
+
19
+ </tbody>
20
+ </table>
21
+
22
+ <%= render "flight_control/shared/pagination_toolbar", page: @jobs_page, filter_param: {} %>
23
+ <% end %>
24
+
25
+
@@ -0,0 +1,5 @@
1
+ <div class="buttons is-right">
2
+ <% if recurring_task.runnable? %>
3
+ <%= button_to "Run now", application_recurring_task_path(@application, recurring_task.id), class: "button is-warning is-light mr-0", method: :put %>
4
+ <% end %>
5
+ </div>
@@ -0,0 +1,37 @@
1
+ <table class="table">
2
+ <tbody>
3
+ <% if recurring_task.job_class_name.present? %>
4
+ <tr>
5
+ <th>Job class</th>
6
+ <td><%= recurring_task.job_class_name %></td>
7
+ </tr>
8
+
9
+ <tr>
10
+ <th>Arguments</th>
11
+ <td><div class="is-family-monospace"><%= recurring_task.arguments.join(",") %></div></td>
12
+ </tr>
13
+ <% elsif recurring_task.command.present? %>
14
+ <tr>
15
+ <th>Command</th>
16
+ <td><div class="is-family-monospace"><%= recurring_task.command %></div></td>
17
+ </tr>
18
+ <% end %>
19
+
20
+ <tr>
21
+ <th>Schedule</th>
22
+ <td><%= recurring_task.schedule %></td>
23
+ </tr>
24
+ <% if recurring_task.queue_name.present? %>
25
+ <tr>
26
+ <th>Queue</th>
27
+ <td><%= recurring_task.queue_name %></td>
28
+ </tr>
29
+ <% end %>
30
+ <% if recurring_task.priority.present? %>
31
+ <tr>
32
+ <th>Priority</th>
33
+ <td><%= recurring_task.priority %></td>
34
+ </tr>
35
+ <% end %>
36
+ </tbody>
37
+ </table>
@@ -0,0 +1,22 @@
1
+ <tr class="recurring_task">
2
+ <td>
3
+ <%= link_to recurring_task.id, application_recurring_task_path(@application, recurring_task.id) %>
4
+ </td>
5
+ <td>
6
+ <% if recurring_task.job_class_name.present? %>
7
+ <%= recurring_task.job_class_name %>
8
+
9
+ <% if recurring_task.arguments.present? %>
10
+ <div class="is-family-monospace"><%= recurring_task.arguments.join(",") %></div>
11
+ <% end %>
12
+ <% elsif recurring_task.command.present? %>
13
+ <div class="is-family-monospace"><%= recurring_task.command %></div>
14
+ <% end %>
15
+ </td>
16
+ <td> <%= recurring_task.schedule %> </td>
17
+ <td><div class="has-text-grey"><%= recurring_task.last_enqueued_at ? bidirectional_time_distance_in_words_with_title(recurring_task.last_enqueued_at) : "Never" %></div></td>
18
+ <td class="next_time"><div class="has-text-grey"><%= bidirectional_time_distance_in_words_with_title(recurring_task.next_time) %></div></td>
19
+ <td class="pr-0">
20
+ <%= render "flight_control/recurring_tasks/actions", recurring_task: recurring_task %>
21
+ </td>
22
+ </tr>
@@ -0,0 +1,10 @@
1
+ <h1 class="title">
2
+ <div class="level">
3
+ <div class="level-left">
4
+ <%= recurring_task.id %>
5
+ </div>
6
+ <div class="level-right">
7
+ <%= render "flight_control/recurring_tasks/actions", recurring_task: recurring_task %>
8
+ </div>
9
+ </div>
10
+ </h1>
@@ -0,0 +1,18 @@
1
+ <% navigation(title: "Recurring tasks", section: :recurring_tasks) %>
2
+
3
+ <table class="recurring-tasks table jobs is-hoverable is-fullwidth">
4
+ <tbody>
5
+ <thead>
6
+ <tr>
7
+ <th></th>
8
+ <th>Job</th>
9
+ <th>Schedule</th>
10
+ <th>Last enqueued</th>
11
+ <th>Next</th>
12
+ <th></th>
13
+ </tr>
14
+ </thead>
15
+
16
+ <%= render partial: "flight_control/recurring_tasks/recurring_task", collection: @recurring_tasks %>
17
+ </tbody>
18
+ </table>
@@ -0,0 +1,14 @@
1
+ <% navigation(title: @recurring_task.id, section: :recurring_tasks) %>
2
+
3
+ <%= render "flight_control/recurring_tasks/title", recurring_task: @recurring_task %>
4
+ <%= render "flight_control/recurring_tasks/general_information", recurring_task: @recurring_task %>
5
+
6
+ <% if @jobs_page.empty? %>
7
+ <%= blank_status_notice "No jobs found for this recurring task" %>
8
+ <% else %>
9
+ <h2 class="subtitle"><%= pluralize @recurring_task.jobs.count, "job" %></h2>
10
+
11
+ <%= render "flight_control/shared/jobs", jobs: @jobs_page.records %>
12
+
13
+ <%= render "flight_control/shared/pagination_toolbar", page: @jobs_page, filter_param: jobs_filter_param %>
14
+ <% end %>
@@ -0,0 +1,27 @@
1
+ <tr class="job">
2
+ <td>
3
+ <%= link_to application_job_path(@application, job.job_id, filter: { queue_name: job.queue }) do %>
4
+ <%= job_title(job) %>
5
+ <% end %>
6
+ <div class="has-text-grey">Enqueued <%= time_distance_in_words_with_title(job.enqueued_at.to_datetime) %> ago</div>
7
+ </td>
8
+ <td>
9
+ <% if job.serialized_arguments.present? %>
10
+ <span class="is-family-monospace">
11
+ <%= truncate(job_arguments(job), length: 300) %>
12
+ </span>
13
+ <% end %>
14
+ </td>
15
+
16
+ <td>
17
+ <div class="has-text-grey">
18
+ <% if job.started_at %>
19
+ Running for <%= time_distance_in_words_with_title(job.started_at) %>
20
+ <% elsif job.finished_at %>
21
+ Finished <%= time_distance_in_words_with_title(job.finished_at) %> ago
22
+ <% else %>
23
+ Pending
24
+ <% end %>
25
+ </div>
26
+ </td>
27
+ </tr>
@@ -0,0 +1,14 @@
1
+ <table class="jobs table is-hoverable is-fullwidth">
2
+ <tbody>
3
+ <thead>
4
+ <tr>
5
+ <th class="job-header">Job</th>
6
+ <th></th>
7
+ <th class="duration-header"></th>
8
+ </tr>
9
+ </thead>
10
+
11
+ <%= render partial: "flight_control/shared/job", collection: jobs %>
12
+
13
+ </tbody>
14
+ </table>
@@ -0,0 +1,7 @@
1
+ <nav class="buttons is-right" role="navigation" aria-label="pagination">
2
+ <span class="mr-3"><%= page.index %> / <%= page.pages_count || "..." %></span>
3
+ <%= link_to "↞", url_for(page: 1, **filter_param), class: "pagination-previous", disabled: page.first? %>
4
+ <%= link_to "Previous page", url_for(page: page.previous_index, **filter_param), class: "pagination-previous", disabled: page.first? %>
5
+ <%= link_to "Next page", url_for(page: page.next_index, **filter_param), class: "pagination-next", disabled: page.last? %>
6
+ <%= link_to "↠", url_for(page: page.pages_count, **filter_param), class: "pagination-next", disabled: page.last? %>
7
+ </nav>
@@ -0,0 +1,6 @@
1
+ <h2 class="subtitle mt-2">Configuration</h2>
2
+ <pre>
3
+ <%= JSON.pretty_generate(worker.configuration) %>
4
+ </pre>
5
+
6
+ <hr />
@@ -0,0 +1,6 @@
1
+ <hr />
2
+
3
+ <h2 class="subtitle">Raw data</h2>
4
+ <pre>
5
+ <%= JSON.pretty_generate(worker.raw_data) %>
6
+ </pre>
@@ -0,0 +1,11 @@
1
+ <h1 class="title">
2
+ <div class="level">
3
+ <div class="level-left">
4
+ <%= "Worker #{worker.id} — #{worker.name}" %>
5
+ </div>
6
+
7
+ <div class="level-right is-family-monospace">
8
+ <%= worker.hostname %>
9
+ </div>
10
+ </div>
11
+ </h1>
@@ -0,0 +1,21 @@
1
+ <tr class="worker">
2
+ <td>
3
+ <%= link_to "worker #{worker.id}", application_worker_path(@application, worker.id) %>
4
+ <br />
5
+ <%= worker.name %>
6
+ </td>
7
+ <td><%= worker.hostname %></td>
8
+ <td>
9
+ <% worker.jobs.each do |job| %>
10
+ <div>
11
+ <%= link_to job_title(job), application_job_path(@application, job.job_id) %>
12
+
13
+ <% if job.serialized_arguments.present? %>
14
+ <div class="is-family-monospace is-size-7"><%= truncate(job_arguments(job), length: 300) %></div>
15
+ <% end %>
16
+ </div>
17
+ <% end %>
18
+ </td>
19
+
20
+ <td><div class="has-text-grey"><%= time_distance_in_words_with_title(worker.last_heartbeat_at) %> ago</div></td>
21
+ </tr>
@@ -0,0 +1,15 @@
1
+ <table class="workers table jobs is-hoverable is-fullwidth">
2
+ <tbody>
3
+ <thead>
4
+ <tr>
5
+ <th>Worker</th>
6
+ <th>Hostname</th>
7
+ <th class="job-header">Jobs</th>
8
+ <th>Last heartbeat</th>
9
+ </tr>
10
+ </thead>
11
+
12
+ <%= render partial: "flight_control/workers/worker", collection: workers_page.records %>
13
+
14
+ </tbody>
15
+ </table>
@@ -0,0 +1,6 @@
1
+ <% navigation(title: "Workers", section: :workers) %>
2
+
3
+ <%= render "flight_control/workers/workers_page", workers_page: @workers_page %>
4
+
5
+ <%= render "flight_control/shared/pagination_toolbar", page: @workers_page, filter_param: {} %>
6
+
@@ -0,0 +1,14 @@
1
+ <% navigation(title: "Worker #{@worker.id}", section: :workers) %>
2
+
3
+ <%= render "flight_control/workers/title", worker: @worker %>
4
+ <%= render "flight_control/workers/configuration", worker: @worker %>
5
+
6
+ <% if @worker.jobs.empty? %>
7
+ <%= blank_status_notice "This worker is idle" %>
8
+ <% else %>
9
+ <h2 class="subtitle">Running <%= pluralize @worker.jobs.size, "job" %></h2>
10
+
11
+ <%= render "flight_control/shared/jobs", jobs: @worker.jobs %>
12
+ <% end %>
13
+
14
+ <%= render "flight_control/workers/raw_data", worker: @worker %>
@@ -0,0 +1,14 @@
1
+ <nav class="navbar" role="navigation" aria-label="main navigation">
2
+ <div class="navbar-menu is-active mb-4">
3
+ <div class="navbar-start">
4
+ <% if (path = back_to_main_app_path) %>
5
+ <%= link_to "Back to main app", path %>
6
+ <% end %>
7
+ </div>
8
+
9
+ <div class="navbar-end">
10
+ <%= render "layouts/flight_control/application_selection/servers", application: @application %>
11
+ <%= render "layouts/flight_control/application_selection/applications" if selectable_applications.any? %>
12
+ </div>
13
+ </div>
14
+ </nav>
@@ -0,0 +1,9 @@
1
+ <% flash.each do |name, message| -%>
2
+ <% message_class = { notice: "is-success", alert: "is-danger" }[name.to_sym] %>
3
+
4
+ <article class="message <%= message_class %>">
5
+ <div class="message-body">
6
+ <%= message %>
7
+ </div>
8
+ </article>
9
+ <% end -%>
@@ -0,0 +1,9 @@
1
+ <div class="tabs is-boxed">
2
+ <ul>
3
+ <% navigation_sections.each do |key, (label, url)| %>
4
+ <li class="<%= "is-active" if key == current_section %>">
5
+ <%= link_to label, url %>
6
+ </li>
7
+ <% end %>
8
+ </ul>
9
+ </div>
@@ -0,0 +1,28 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Flight Control - <%= page_title %></title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <meta name="viewport" content="width=device-width,initial-scale=1">
9
+ <meta name="turbo-cache-control" content="no-cache">
10
+ <meta name="turbo-prefetch" content="false">
11
+
12
+ <%= stylesheet_link_tag "flight_control/bulma.min" %>
13
+ <%= stylesheet_link_tag "flight_control/application", "flight_control/forms", "flight_control/jobs", "data-turbo-track": "reload" %>
14
+ <%= javascript_importmap_tags "application", importmap: FlightControl.importmap %>
15
+ </head>
16
+ <body>
17
+
18
+ <section class="section">
19
+ <div class="container">
20
+ <%= render "layouts/flight_control/application_selection" %>
21
+ <%= render "layouts/flight_control/flash" %>
22
+ <%= render "layouts/flight_control/navigation" %>
23
+ <%= yield %>
24
+ </div>
25
+ </section>
26
+
27
+ </body>
28
+ </html>
@@ -0,0 +1,13 @@
1
+ <div class="application-selector navbar-item has-dropdown is-hoverable">
2
+ <a class="navbar-link">
3
+ <%= FlightControl::Current.application.name %>
4
+ </a>
5
+
6
+ <div class="navbar-dropdown">
7
+ <% selectable_applications.each do |application| %>
8
+ <%= link_to application_queues_path(application, server_id: nil), class: "navbar-item" do %>
9
+ <span><%= application.name %></span>
10
+ <% end %>
11
+ <% end %>
12
+ </div>
13
+ </div>
@@ -0,0 +1,15 @@
1
+ <% if application.servers.many? %>
2
+ <div class="server-selector navbar-item">
3
+ <div class="tabs is-toggle is-toggle-rounded is-small">
4
+ <ul>
5
+ <% application.servers.each do |server| %>
6
+ <li class="<%= "is-active" if selected_server?(server) %>">
7
+ <%= link_to application_queues_path(application, server_id: server) do %>
8
+ <span><%= server.name %></span>
9
+ <% end %>
10
+ </li>
11
+ <% end %>
12
+ </ul>
13
+ </div>
14
+ </div>
15
+ <% end %>
@@ -0,0 +1,5 @@
1
+ pin "application", to: "flight_control/application.js", preload: true
2
+ pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
3
+ pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
4
+ pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
5
+ pin_all_from FlightControl::Engine.root.join("app/javascript/flight_control/controllers"), under: "controllers", to: "flight_control/controllers"