-
-
Notifications
You must be signed in to change notification settings - Fork 208
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add batch operations for jobs to Dashboard
- Loading branch information
1 parent
c548fb7
commit ca5fb4c
Showing
20 changed files
with
432 additions
and
99 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,14 @@ | ||
/*jshint esversion: 6, strict: false */ | ||
|
||
import renderCharts from "charts"; | ||
import checkboxToggle from "checkbox_toggle"; | ||
import documentReady from "document_ready"; | ||
import showToasts from "toasts"; | ||
import renderCharts from "charts"; | ||
import Poller from "poller"; | ||
|
||
documentReady(function() { | ||
renderCharts(); | ||
showToasts(); | ||
checkboxToggle(); | ||
Poller.start(); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/*jshint esversion: 6, strict: false */ | ||
|
||
// How to use: | ||
//<form data-checkbox-toggle="{key}"> | ||
// <input type="checkbox" data-checkbox-toggle-all="{key}" /> | ||
// | ||
// <input type="checkbox" data-checkbox-toggle-each="{key}" /> | ||
// <input type="checkbox" data-checkbox-toggle-each="{key}" /> | ||
// ... | ||
|
||
export default function checkboxToggle() { | ||
document.querySelectorAll("form[data-checkbox-toggle]").forEach(function (form) { | ||
const keyName = form.dataset.checkboxToggle; | ||
const checkboxToggle = form.querySelector(`input[type=checkbox][data-checkbox-toggle-all=${keyName}]`); | ||
const checkboxes = form.querySelectorAll(`input[type=checkbox][data-checkbox-toggle-each=${keyName}]`); | ||
const showables = form.querySelectorAll(`[data-checkbox-toggle-show=${keyName}]`); | ||
|
||
// Check or uncheck all checkboxes | ||
checkboxToggle.addEventListener("change", function (event) { | ||
checkboxes.forEach(function (checkbox) { | ||
checkbox.checked = checkboxToggle.checked; | ||
}); | ||
|
||
showables.forEach(function (showable) { | ||
showable.classList.toggle("d-none", !checkboxToggle.checked); | ||
}); | ||
}); | ||
|
||
// check or uncheck the "all" checkbox when all checkboxes are checked or unchecked | ||
form.addEventListener("change", function (event) { | ||
if (!event.target.matches(`input[type=checkbox][data-checkbox-toggle-each=${keyName}]`)) { | ||
return; | ||
} | ||
const checkedCount = Array.from(checkboxes).filter(function (checkbox) { | ||
return checkbox.checked; | ||
}).length; | ||
|
||
const allChecked = checkedCount === checkboxes.length; | ||
const indeterminateChecked = !allChecked && checkedCount > 0; | ||
|
||
checkboxToggle.checked = allChecked; | ||
checkboxToggle.indeterminate = indeterminateChecked; | ||
|
||
showables.forEach(function (showable) { | ||
showable.classList.toggle("d-none", !allChecked); | ||
}); | ||
}); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,72 +1,111 @@ | ||
<div class="my-3" data-gj-poll-replace id="jobs-table"> | ||
<div class="table-responsive"> | ||
<table class="table table-hover table-sm mb-0"> | ||
<thead> | ||
<tr> | ||
<th>ActiveJob ID</th> | ||
<th>State</th> | ||
<th>Job Class</th> | ||
<th>Queue</th> | ||
<th>Scheduled At</th> | ||
<th>Executions</th> | ||
<th>Error</th> | ||
<th> | ||
ActiveJob Params | ||
<%= tag.button "Toggle", type: "button", class: "btn btn-sm btn-outline-primary", role: "button", | ||
data: { bs_toggle: "collapse", bs_target: ".job-params" }, | ||
aria: { expanded: false, controls: jobs.map { |job| "##{dom_id(job, "params")}" }.join(" ") } | ||
%> | ||
</th> | ||
<th>Actions</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
<% if jobs.present? %> | ||
<% jobs.each do |job| %> | ||
<tr class="<%= dom_class(job) %>" id="<%= dom_id(job) %>"> | ||
<td> | ||
<%= link_to job_path(job.id) do %> | ||
<code><%= job.id %></code> | ||
<%= form_with(url: batch_jobs_path, method: :put, local: true, data: { "checkbox-toggle": "job_ids" }) do |form| %> | ||
<table class="table table-hover table-sm mb-0"> | ||
<thead> | ||
<tr> | ||
<th><%= check_box_tag('toggle_job_ids', "1", false, data: { "checkbox-toggle-all": "job_ids" }) %></th> | ||
<th>ActiveJob ID</th> | ||
<th>State</th> | ||
<th>Job Class</th> | ||
<th>Queue</th> | ||
<th>Scheduled At</th> | ||
<th>Executions</th> | ||
<th>Error</th> | ||
<th> | ||
ActiveJob Params | ||
<%= tag.button "Toggle", type: "button", class: "btn btn-sm btn-outline-primary", role: "button", | ||
data: { bs_toggle: "collapse", bs_target: ".job-params" }, | ||
aria: { expanded: false, controls: jobs.map { |job| "##{dom_id(job, "params")}" }.join(" ") } | ||
%> | ||
</th> | ||
<th> | ||
Actions<br> | ||
|
||
<div class="d-inline text-nowrap"> | ||
<%= form.button type: 'submit', name: 'batch_action', value: 'reschedule', class: 'btn btn-sm btn-outline-primary', title: "Reschedule all", data: { confirm: "Confirm reschedule all", disable: true } do %> | ||
<%= render_icon "skip_forward" %> All | ||
<% end %> | ||
</td> | ||
<td><%= status_badge(job.status) %></td> | ||
<td><%= job.job_class %></td> | ||
<td><%= job.queue_name %></td> | ||
<td><%= relative_time(job.scheduled_at || job.created_at) %></td> | ||
<td><%= job.executions_count %></td> | ||
<td class="text-break"><%= truncate(job.recent_error, length: 1_000) %></td> | ||
<td> | ||
<%= tag.button "Preview", type: "button", class: "btn btn-sm btn-outline-primary", role: "button", | ||
data: { bs_toggle: "collapse", bs_target: "##{dom_id(job, 'params')}" }, | ||
aria: { expanded: false, controls: dom_id(job, "params") } | ||
%> | ||
<%= tag.pre JSON.pretty_generate(job.serialized_params), id: dom_id(job, "params"), class: "collapse job-params" %> | ||
</td> | ||
<td> | ||
<div class="text-nowrap"> | ||
<% job_reschedulable = job.status.in? [:scheduled, :retried, :queued] %> | ||
<%= button_to reschedule_job_path(job.id), method: :put, class: "btn btn-sm #{job_reschedulable ? 'btn-outline-primary' : 'btn-outline-secondary'}", form_class: "d-inline-block", disabled: !job_reschedulable, aria: { label: "Reschedule job" }, title: "Reschedule job", data: { confirm: "Confirm reschedule" } do %> | ||
<%= render "good_job/shared/icons/skip_forward" %> | ||
<% end %> | ||
|
||
<% job_discardable = job.status.in? [:scheduled, :retried, :queued] %> | ||
<%= button_to discard_job_path(job.id), method: :put, class: "btn btn-sm #{job_discardable ? 'btn-outline-primary' : 'btn-outline-secondary'}", form_class: "d-inline-block", disabled: !job_discardable, aria: { label: "Discard job" }, title: "Discard job", data: { confirm: "Confirm discard" } do %> | ||
<%= render "good_job/shared/icons/stop" %> | ||
<% end %> | ||
<%= form.button type: 'submit', name: 'batch_action', value: 'discard', class: 'btn btn-sm btn-outline-primary', title: "Discard all", data: { confirm: "Confirm discard all", disable: true } do %> | ||
<%= render_icon "stop" %> All | ||
<% end %> | ||
|
||
<%= button_to retry_job_path(job.id), method: :put, class: "btn btn-sm #{job.status == :discarded ? 'btn-outline-primary' : 'btn-outline-secondary'}", form_class: "d-inline-block", disabled: job.status != :discarded, aria: { label: "Retry job" }, title: "Retry job", data: { confirm: "Confirm retry" } do %> | ||
<%= render "good_job/shared/icons/arrow_clockwise" %> | ||
<%= form.button type: 'submit', name: 'batch_action', value: 'retry', class: 'btn btn-sm btn-outline-primary', title: "Retry all", data: { confirm: "Confirm retry all", disable: true } do %> | ||
<%= render_icon "arrow_clockwise" %> All | ||
<% end %> | ||
</div> | ||
</tr> | ||
<tr class="d-none" data-checkbox-toggle-show="job_ids"> | ||
<td class="text-center table-warning" colspan="10"> | ||
<% all_jobs_count = local_assigns[:all_jobs_count] %> | ||
<label> | ||
<%= check_box_tag "all_job_ids" %> | ||
Apply to all <%= all_jobs_count.present? ? all_jobs_count.to_s(:delimited) : "" %> <%= "job".pluralize(all_jobs_count || 99) %>. | ||
<em>This could be a lot.</em> | ||
</label> | ||
</td> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
<% if jobs.present? %> | ||
<% jobs.each do |job| %> | ||
<tr class="<%= dom_class(job) %>" id="<%= dom_id(job) %>"> | ||
<td><%= check_box_tag 'job_ids[]', job.id, false, data: { "checkbox-toggle-each": "job_ids" } %></td> | ||
<td> | ||
<%= link_to job_path(job.id) do %> | ||
<code><%= job.id %></code> | ||
<% end %> | ||
</div> | ||
</td> | ||
</td> | ||
<td><%= status_badge(job.status) %></td> | ||
<td><%= job.job_class %></td> | ||
<td><%= job.queue_name %></td> | ||
<td><%= relative_time(job.scheduled_at || job.created_at) %></td> | ||
<td><%= job.executions_count %></td> | ||
<td class="text-break"><%= truncate(job.recent_error, length: 1_000) %></td> | ||
<td> | ||
<%= tag.button "Preview", type: "button", class: "btn btn-sm btn-outline-primary", role: "button", | ||
data: { bs_toggle: "collapse", bs_target: "##{dom_id(job, 'params')}" }, | ||
aria: { expanded: false, controls: dom_id(job, "params") } | ||
%> | ||
<%= tag.pre JSON.pretty_generate(job.serialized_params), id: dom_id(job, "params"), class: "collapse job-params" %> | ||
</td> | ||
<td> | ||
<div class="text-nowrap"> | ||
<% if job.status.in? [:scheduled, :retried, :queued] %> | ||
<%= link_to reschedule_job_path(job.id), method: :put, class: "btn btn-sm btn-outline-primary", title: "Reschedule job", data: { confirm: "Confirm reschedule", disable: true } do %> | ||
<%= render_icon "skip_forward" %> | ||
<% end %> | ||
<% else %> | ||
<button class="btn btn-sm btn-outline-secondary" disabled><%= render_icon "skip_forward" %></button> | ||
<% end %> | ||
|
||
<% if job.status.in? [:scheduled, :retried, :queued] %> | ||
<%= link_to discard_job_path(job.id), method: :put, class: "btn btn-sm btn-outline-primary", title: "Discard job", data: { confirm: "Confirm discard", disable: true } do %> | ||
<%= render_icon "stop" %> | ||
<% end %> | ||
<% else %> | ||
<button class="btn btn-sm btn-outline-secondary" disabled><%= render_icon "stop" %></button> | ||
<% end %> | ||
|
||
<% if job.status == :discarded %> | ||
<%= link_to retry_job_path(job.id), method: :put, class: "btn btn-sm btn-outline-primary", title: "Retry job", data: { confirm: "Confirm retry", disable: true } do %> | ||
<%= render_icon "arrow_clockwise" %> | ||
<% end %> | ||
<% else %> | ||
<button class="btn btn-sm btn-outline-secondary" disabled><%= render_icon "arrow_clockwise" %></button> | ||
<% end %> | ||
</div> | ||
</td> | ||
</tr> | ||
<% end %> | ||
<% else %> | ||
<tr> | ||
<td colspan="8" class="py-2 text-center text-muted">No jobs found.</td> | ||
</tr> | ||
<% end %> | ||
<% else %> | ||
<tr> | ||
<td colspan="8" class="py-2 text-center text-muted">No jobs found.</td> | ||
</tr> | ||
<% end %> | ||
</tbody> | ||
</table> | ||
</tbody> | ||
</table> | ||
<% end %> | ||
</div> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.