good_job 4.12.1 → 4.13.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +41 -0
- data/README.md +3 -2
- data/app/controllers/good_job/batches_controller.rb +1 -1
- data/app/controllers/good_job/cron_entries_controller.rb +3 -3
- data/app/controllers/good_job/frontends_controller.rb +15 -10
- data/app/controllers/good_job/jobs_controller.rb +7 -7
- data/app/controllers/good_job/pauses_controller.rb +2 -2
- data/app/frontend/good_job/application.js +23 -9
- data/app/frontend/good_job/modules/form_controller.js +11 -0
- data/app/frontend/good_job/vendor/turbo.js +34 -0
- data/app/models/good_job/batch.rb +2 -0
- data/app/models/good_job/batch_record.rb +2 -0
- data/app/models/good_job/discrete_execution.rb +1 -0
- data/app/models/good_job/job.rb +2 -2
- data/app/models/good_job/process.rb +2 -0
- data/app/models/good_job/setting.rb +2 -0
- data/app/views/good_job/_custom_head.html.erb +7 -0
- data/app/views/good_job/batches/_jobs.erb +4 -4
- data/app/views/good_job/batches/_table.erb +2 -2
- data/app/views/good_job/batches/show.html.erb +1 -1
- data/app/views/good_job/cron_entries/index.html.erb +2 -2
- data/app/views/good_job/jobs/_table.erb +12 -9
- data/app/views/good_job/jobs/show.html.erb +4 -4
- data/app/views/good_job/pauses/_group.html.erb +1 -1
- data/app/views/good_job/pauses/_pause.html.erb +1 -1
- data/app/views/good_job/shared/_filter.erb +4 -14
- data/app/views/good_job/shared/_navbar.erb +6 -6
- data/app/views/layouts/good_job/application.html.erb +12 -8
- data/config/brakeman.ignore +25 -25
- data/config/locales/de.yml +21 -21
- data/config/locales/zh-CN.yml +295 -0
- data/lib/generators/good_job/templates/install/migrations/create_good_jobs.rb.erb +1 -1
- data/lib/generators/good_job/templates/update/migrations/05_add_index_good_jobs_finished_at_for_cleanup.rb.erb +17 -0
- data/lib/generators/good_job/templates/update/migrations/06_remove_extraneous_finished_at_index.rb.erb +17 -0
- data/lib/good_job/active_job_extensions/labels.rb +1 -0
- data/lib/good_job/active_job_extensions/notify_options.rb +1 -0
- data/lib/good_job/notifier.rb +1 -0
- data/lib/good_job/version.rb +1 -1
- data/lib/good_job.rb +1 -1
- metadata +13 -9
- data/app/frontend/good_job/modules/document_ready.js +0 -7
- data/app/frontend/good_job/vendor/rails_ujs.js +0 -7
data/app/models/good_job/job.rb
CHANGED
|
@@ -250,8 +250,8 @@ module GoodJob
|
|
|
250
250
|
)
|
|
251
251
|
end
|
|
252
252
|
|
|
253
|
-
def
|
|
254
|
-
return true
|
|
253
|
+
def historic_finished_at_index_migrated?
|
|
254
|
+
return true unless connection.index_name_exists?(:good_jobs, :index_good_jobs_jobs_on_finished_at)
|
|
255
255
|
|
|
256
256
|
migration_pending_warning!
|
|
257
257
|
false
|
|
@@ -68,26 +68,26 @@
|
|
|
68
68
|
<ul class="dropdown-menu shadow" aria-labelledby="<%= dom_id(job, :actions) %>">
|
|
69
69
|
<li>
|
|
70
70
|
<% job_reschedulable = job.status.in? [:scheduled, :retried, :queued] %>
|
|
71
|
-
<%=
|
|
71
|
+
<%= button_to reschedule_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job_reschedulable}", title: t(".actions.reschedule"), data: { turbo_confirm: t(".actions.confirm_reschedule") } do %>
|
|
72
72
|
<%= render_icon "skip_forward" %>
|
|
73
73
|
<%= t "good_job.actions.reschedule" %>
|
|
74
74
|
<% end %>
|
|
75
75
|
</li>
|
|
76
76
|
<li>
|
|
77
77
|
<% job_discardable = job.status.in? [:scheduled, :retried, :queued] %>
|
|
78
|
-
<%=
|
|
78
|
+
<%= button_to discard_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job_discardable}", title: t(".actions.discard"), data: { turbo_confirm: t(".actions.confirm_discard") } do %>
|
|
79
79
|
<%= render_icon "stop" %>
|
|
80
80
|
<%= t "good_job.actions.discard" %>
|
|
81
81
|
<% end %>
|
|
82
82
|
</li>
|
|
83
83
|
<li>
|
|
84
|
-
<%=
|
|
84
|
+
<%= button_to retry_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job.status == :discarded}", title: t(".actions.retry"), data: { turbo_confirm: t(".actions.confirm_retry") } do %>
|
|
85
85
|
<%= render_icon "arrow_clockwise" %>
|
|
86
86
|
<%= t "good_job.actions.retry" %>
|
|
87
87
|
<% end %>
|
|
88
88
|
</li>
|
|
89
89
|
<li>
|
|
90
|
-
<%=
|
|
90
|
+
<%= button_to job_path(job.id), method: :delete, class: "dropdown-item #{'disabled' unless job.finished?}", title: t(".actions.destroy"), data: { turbo_confirm: t(".actions.confirm_destroy") } do %>
|
|
91
91
|
<%= render_icon "trash" %>
|
|
92
92
|
<%= t "good_job.actions.destroy" %>
|
|
93
93
|
<% end %>
|
|
@@ -58,9 +58,9 @@
|
|
|
58
58
|
<div class="d-lg-none small text-muted mt-1"><%= t "good_job.models.batch.jobs" %></div>
|
|
59
59
|
<%= batch.jobs.size %>
|
|
60
60
|
</div>
|
|
61
|
-
<div class="col text-end">
|
|
61
|
+
<div class="col text-end d-flex flex-row justify-content-end">
|
|
62
62
|
<% if batch.discarded? %>
|
|
63
|
-
<%=
|
|
63
|
+
<%= button_to retry_batch_path(batch), method: :put, class: "btn btn-sm btn-outline-primary", title: t("good_job.batches.actions.retry"), data: { turbo_confirm: t("good_job.batches.actions.confirm_retry") } do %>
|
|
64
64
|
<%= render_icon "arrow_clockwise" %>
|
|
65
65
|
<%= t "good_job.batches.actions.retry" %>
|
|
66
66
|
<% end %>
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
</div>
|
|
13
13
|
<div class="col text-end">
|
|
14
14
|
<% if @batch.discarded? %>
|
|
15
|
-
<%= button_to retry_batch_path(@batch), method: :put, class: "btn btn-sm btn-outline-primary", form_class: "d-inline-block", aria: { label: t("good_job.batches.actions.retry") }, title: t("good_job.batches.actions.retry"), data: {
|
|
15
|
+
<%= button_to retry_batch_path(@batch), method: :put, class: "btn btn-sm btn-outline-primary", form_class: "d-inline-block", aria: { label: t("good_job.batches.actions.retry") }, title: t("good_job.batches.actions.retry"), data: { turbo_confirm: t("good_job.batches.actions.confirm_retry") } do %>
|
|
16
16
|
<%= render_icon "arrow_clockwise" %>
|
|
17
17
|
<%= t "good_job.actions.retry" %>
|
|
18
18
|
<% end %>
|
|
@@ -58,11 +58,11 @@
|
|
|
58
58
|
<% end %>
|
|
59
59
|
|
|
60
60
|
<% if cron_entry.enabled? %>
|
|
61
|
-
<%= button_to disable_cron_entry_path(cron_entry), method: :put, class: "btn btn-sm btn-outline-primary", form_class: "d-inline-block", aria: { label: t("good_job.cron_entries.actions.disable") }, title: t("good_job.cron_entries.actions.disable"), data: {
|
|
61
|
+
<%= button_to disable_cron_entry_path(cron_entry), method: :put, class: "btn btn-sm btn-outline-primary", form_class: "d-inline-block", aria: { label: t("good_job.cron_entries.actions.disable") }, title: t("good_job.cron_entries.actions.disable"), data: { turbo_confirm: t("good_job.cron_entries.actions.confirm_disable") } do %>
|
|
62
62
|
<%= render_icon "pause" %>
|
|
63
63
|
<% end %>
|
|
64
64
|
<% else %>
|
|
65
|
-
<%= button_to enable_cron_entry_path(cron_entry), method: :put, class: "btn btn-sm btn-outline-primary", form_class: "d-inline-block", aria: { label: t("good_job.cron_entries.actions.enable") }, title: t("good_job.cron_entries.actions.enable"), data: {
|
|
65
|
+
<%= button_to enable_cron_entry_path(cron_entry), method: :put, class: "btn btn-sm btn-outline-primary", form_class: "d-inline-block", aria: { label: t("good_job.cron_entries.actions.enable") }, title: t("good_job.cron_entries.actions.enable"), data: { turbo_confirm: t("good_job.cron_entries.actions.confirm_enable") } do %>
|
|
66
66
|
<%= render_icon "play" %>
|
|
67
67
|
<% end %>
|
|
68
68
|
<% end %>
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
<%= form_with(id: "job_action_form", method: :put, model: false, local: true) { nil } %>
|
|
2
|
+
<%= form_with(id: "job_destroy_form", method: :delete, model: false, local: true) { nil } %>
|
|
3
|
+
|
|
1
4
|
<%= form_with(model: false, url: mass_update_jobs_path(filter.to_params), method: :put, local: true, data: { "checkbox-toggle": "job_ids" }) do |form| %>
|
|
2
5
|
<div class="my-3 card" data-gj-poll-replace id="jobs-table">
|
|
3
6
|
<div class="list-group list-group-flush text-nowrap table-jobs" role="table">
|
|
@@ -8,16 +11,16 @@
|
|
|
8
11
|
<%= check_box_tag('toggle_job_ids', "1", false, data: { "checkbox-toggle-all": "job_ids" }) %>
|
|
9
12
|
<%= label_tag('toggle_job_ids', t(".toggle_all_jobs"), class: "visually-hidden") %>
|
|
10
13
|
</div>
|
|
11
|
-
<%= form.button type: 'submit', name: 'mass_action', value: 'reschedule', class: 'ms-1 btn btn-sm btn-outline-secondary', title: t(".actions.reschedule_all"), data: {
|
|
14
|
+
<%= form.button type: 'submit', name: 'mass_action', value: 'reschedule', class: 'ms-1 btn btn-sm btn-outline-secondary', title: t(".actions.reschedule_all"), data: { turbo_confirm: t(".actions.confirm_reschedule_all") } do %>
|
|
12
15
|
<span class="me-1"><%= render_icon "skip_forward" %></span> <%= t "good_job.actions.reschedule" %>
|
|
13
16
|
<% end %>
|
|
14
17
|
|
|
15
|
-
<%= form.button type: 'submit', name: 'mass_action', value: 'retry', class: 'btn btn-sm btn-outline-secondary', title: t(".actions.retry_all"), data: {
|
|
18
|
+
<%= form.button type: 'submit', name: 'mass_action', value: 'retry', class: 'btn btn-sm btn-outline-secondary', title: t(".actions.retry_all"), data: { turbo_confirm: t(".actions.confirm_retry_all") } do %>
|
|
16
19
|
<span class="me-1"><%= render_icon "arrow_clockwise" %></span> <%= t "good_job.actions.retry" %>
|
|
17
20
|
<% end %>
|
|
18
21
|
|
|
19
22
|
<div class="btn-group" role="group">
|
|
20
|
-
<%= form.button type: 'submit', name: 'mass_action', value: 'discard', class: 'btn btn-sm btn-outline-secondary', title: t(".actions.discard_all"), data: {
|
|
23
|
+
<%= form.button type: 'submit', name: 'mass_action', value: 'discard', class: 'btn btn-sm btn-outline-secondary', title: t(".actions.discard_all"), data: { turbo_confirm: t(".actions.confirm_discard_all") } do %>
|
|
21
24
|
<span class="me-1"><%= render_icon "stop" %></span> <%= t "good_job.actions.discard" %>
|
|
22
25
|
<% end %>
|
|
23
26
|
<button id="destroy-dropdown-toggle" type="button" class="btn btn-sm btn-outline-secondary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false">
|
|
@@ -25,7 +28,7 @@
|
|
|
25
28
|
</button>
|
|
26
29
|
<ul class="dropdown-menu" aria-labelledby="destroy-dropdown-toggle">
|
|
27
30
|
<li>
|
|
28
|
-
<%= form.button type: 'submit', name: 'mass_action', value: 'destroy', class: 'btn dropdown-item', title: t(".actions.destroy_all"), data: {
|
|
31
|
+
<%= form.button type: 'submit', name: 'mass_action', value: 'destroy', class: 'btn dropdown-item', title: t(".actions.destroy_all"), data: { turbo_confirm: t(".actions.confirm_destroy_all") } do %>
|
|
29
32
|
<span class="me-1"><%= render_icon "trash" %></span> <%= t "good_job.actions.destroy" %>
|
|
30
33
|
<% end %>
|
|
31
34
|
</li>
|
|
@@ -125,33 +128,33 @@
|
|
|
125
128
|
<ul class="dropdown-menu shadow" aria-labelledby="<%= dom_id(job, :actions) %>">
|
|
126
129
|
<li>
|
|
127
130
|
<% job_reschedulable = job.status.in? [:scheduled, :retried, :queued] %>
|
|
128
|
-
<%=
|
|
131
|
+
<%= tag.button form: "job_action_form", formaction: reschedule_job_path(job.id), class: "dropdown-item #{'disabled' unless job_reschedulable}", title: t("good_job.jobs.actions.reschedule"), data: { turbo_confirm: t("good_job.jobs.actions.confirm_reschedule") } do %>
|
|
129
132
|
<%= render_icon "skip_forward" %>
|
|
130
133
|
<%= t "good_job.actions.reschedule" %>
|
|
131
134
|
<% end %>
|
|
132
135
|
</li>
|
|
133
136
|
<li>
|
|
134
137
|
<% job_discardable = job.status.in? [:scheduled, :retried, :queued] %>
|
|
135
|
-
<%=
|
|
138
|
+
<%= tag.button form: "job_action_form", formaction: discard_job_path(job.id), class: "dropdown-item #{'disabled' unless job_discardable}", title: t("good_job.jobs.actions.discard"), data: { turbo_confirm: t("good_job.jobs.actions.confirm_discard") } do %>
|
|
136
139
|
<%= render_icon "stop" %>
|
|
137
140
|
<%= t "good_job.actions.discard" %>
|
|
138
141
|
<% end %>
|
|
139
142
|
</li>
|
|
140
143
|
<li>
|
|
141
144
|
<% job_force_discardable = job.status.in? [:running] %>
|
|
142
|
-
<%=
|
|
145
|
+
<%= tag.button form: "job_action_form", formaction: force_discard_job_path(job.id), class: "dropdown-item #{'disabled' unless job_force_discardable}", title: t("good_job.jobs.actions.force_discard"), data: { turbo_confirm: t("good_job.jobs.actions.confirm_force_discard") } do %>
|
|
143
146
|
<%= render_icon "eject" %>
|
|
144
147
|
<%= t "good_job.actions.force_discard" %>
|
|
145
148
|
<% end %>
|
|
146
149
|
</li>
|
|
147
150
|
<li>
|
|
148
|
-
<%=
|
|
151
|
+
<%= tag.button form: "job_action_form", formaction: retry_job_path(job.id), class: "dropdown-item #{'disabled' unless job.status == :discarded}", title: t("good_job.jobs.actions.retry"), data: { turbo_confirm: t("good_job.jobs.actions.confirm_retry") } do %>
|
|
149
152
|
<%= render_icon "arrow_clockwise" %>
|
|
150
153
|
<%= t "good_job.actions.retry" %>
|
|
151
154
|
<% end %>
|
|
152
155
|
</li>
|
|
153
156
|
<li>
|
|
154
|
-
<%=
|
|
157
|
+
<%= tag.button form: "job_destroy_form", formaction: job_path(job.id), class: "dropdown-item #{'disabled' unless job.status.in? [:discarded, :succeeded]}", title: t("good_job.jobs.actions.destroy"), data: { turbo_confirm: t("good_job.jobs.actions.confirm_destroy") } do %>
|
|
155
158
|
<%= render_icon "trash" %>
|
|
156
159
|
<%= t "good_job.actions.destroy" %>
|
|
157
160
|
<% end %>
|
|
@@ -33,28 +33,28 @@
|
|
|
33
33
|
form_class: "d-inline-block",
|
|
34
34
|
aria: { label: t("good_job.jobs.actions.reschedule") },
|
|
35
35
|
title: t("good_job.jobs.actions.reschedule"),
|
|
36
|
-
data: {
|
|
36
|
+
data: { turbo_confirm: t("good_job.jobs.actions.confirm_reschedule") } do %>
|
|
37
37
|
<%= render_icon "skip_forward" %>
|
|
38
38
|
<%= t "good_job.actions.reschedule" %>
|
|
39
39
|
<% end %>
|
|
40
40
|
<% end %>
|
|
41
41
|
|
|
42
42
|
<% if @job.status.in? [:scheduled, :retried, :queued] %>
|
|
43
|
-
<%= button_to discard_job_path(@job.id), method: :put, class: "btn btn-sm btn-outline-primary", form_class: "d-inline-block", aria: { label: t("good_job.jobs.actions.discard") }, title: t("good_job.jobs.actions.discard"), data: {
|
|
43
|
+
<%= button_to discard_job_path(@job.id), method: :put, class: "btn btn-sm btn-outline-primary", form_class: "d-inline-block", aria: { label: t("good_job.jobs.actions.discard") }, title: t("good_job.jobs.actions.discard"), data: { turbo_confirm: t("good_job.jobs.actions.confirm_discard") } do %>
|
|
44
44
|
<%= render_icon "stop" %>
|
|
45
45
|
<%= t "good_job.actions.discard" %>
|
|
46
46
|
<% end %>
|
|
47
47
|
<% end %>
|
|
48
48
|
|
|
49
49
|
<% if @job.status == :discarded %>
|
|
50
|
-
<%= button_to retry_job_path(@job.id), method: :put, class: "btn btn-sm btn-outline-primary", form_class: "d-inline-block", aria: { label: t("good_job.jobs.actions.retry") }, title: t("good_job.jobs.actions.retry"), data: {
|
|
50
|
+
<%= button_to retry_job_path(@job.id), method: :put, class: "btn btn-sm btn-outline-primary", form_class: "d-inline-block", aria: { label: t("good_job.jobs.actions.retry") }, title: t("good_job.jobs.actions.retry"), data: { turbo_confirm: t("good_job.jobs.actions.confirm_retry") } do %>
|
|
51
51
|
<%= render_icon "arrow_clockwise" %>
|
|
52
52
|
<%= t "good_job.actions.retry" %>
|
|
53
53
|
<% end %>
|
|
54
54
|
<% end %>
|
|
55
55
|
|
|
56
56
|
<% if @job.status.in? [:discarded, :succeeded] %>
|
|
57
|
-
<%= button_to job_path(@job.id), method: :delete, class: "btn btn-sm btn-outline-primary", form_class: "d-inline-block", aria: { label: t("good_job.jobs.actions.destroy") }, title: t("good_job.jobs.actions.destroy"), data: {
|
|
57
|
+
<%= button_to job_path(@job.id), method: :delete, class: "btn btn-sm btn-outline-primary", form_class: "d-inline-block", aria: { label: t("good_job.jobs.actions.destroy") }, title: t("good_job.jobs.actions.destroy"), data: { turbo_confirm: t("good_job.jobs.actions.confirm_destroy") } do %>
|
|
58
58
|
<%= render_icon "trash" %>
|
|
59
59
|
<%= t "good_job.actions.destroy" %>
|
|
60
60
|
<% end %>
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
{ action: :destroy, type: type, value: value },
|
|
17
17
|
method: :delete,
|
|
18
18
|
class: 'btn btn-sm btn-outline-primary',
|
|
19
|
-
data: {
|
|
19
|
+
data: { turbo_confirm: t('good_job.pauses.index.confirm_unpause', value: value) }
|
|
20
20
|
) do %>
|
|
21
21
|
<%= render_icon "play" %>
|
|
22
22
|
<%= t("good_job.pauses.index.unpause") %>
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
{ action: :destroy, type: type, value: value },
|
|
5
5
|
method: :delete,
|
|
6
6
|
class: 'btn btn-sm btn-outline-primary',
|
|
7
|
-
data: {
|
|
7
|
+
data: { turbo_confirm: t('good_job.pauses.index.confirm_unpause', value: value) } %>
|
|
8
8
|
</li>
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
<h2 class="pt-3 pb-2"><%= title %></h2>
|
|
5
5
|
</div>
|
|
6
6
|
|
|
7
|
-
<%= form_with(model: false, url: "", method: :get, local: true,
|
|
7
|
+
<%= form_with(model: false, url: "", method: :get, local: true, data: { controller: "form" }) do |form| %>
|
|
8
8
|
<%= hidden_field_tag :poll, params[:poll] %>
|
|
9
9
|
<%= hidden_field_tag :state, params[:state] %>
|
|
10
10
|
<%= hidden_field_tag :locale, params[:locale] if params[:locale] %>
|
|
11
11
|
<div class="d-md-flex flex-row w-100">
|
|
12
12
|
<div class="me-md-2 mb-2 mb-md-0">
|
|
13
13
|
<%= label_tag "job_queue_filter", t(".queue_name"), class: "visually-hidden" %>
|
|
14
|
-
<select name="queue_name" id="job_queue_filter" class="form-select form-select-sm">
|
|
14
|
+
<select name="queue_name" id="job_queue_filter" class="form-select form-select-sm" data-action="change->form#submit">
|
|
15
15
|
<option value="" <%= "selected='selected'" if params[:queue_name].blank? %>><%= t ".all_queues" %></option>
|
|
16
16
|
|
|
17
17
|
<% filter.queues.each do |name, count| %>
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
<div class="me-md-2 mb-2 mb-md-0">
|
|
24
24
|
<%= label_tag "job_class_filter", t(".job_name"), class: "visually-hidden" %>
|
|
25
|
-
<select name="job_class" id="job_class_filter" class="form-select form-select-sm">
|
|
25
|
+
<select name="job_class" id="job_class_filter" class="form-select form-select-sm" data-action="change->form#submit">
|
|
26
26
|
<option value="" <%= "selected='selected'" if params[:job_class].blank? %>><%= t ".all_jobs" %></option>
|
|
27
27
|
|
|
28
28
|
<% filter.job_classes.each do |name, count| %>
|
|
@@ -56,20 +56,10 @@
|
|
|
56
56
|
<li class="nav-item">
|
|
57
57
|
<%= link_to filter.to_params(state: name), class: "nav-link #{'active' if params[:state] == name}" do %>
|
|
58
58
|
<%= t(name, scope: 'good_job.status') %>
|
|
59
|
-
<span data-async-values-target="value" data-async-values-key="<%= name %>" data-async-values-zero-class="
|
|
59
|
+
<span data-async-values-target="value" data-async-values-key="<%= name %>" data-async-values-zero-class="bg-secondary" class="badge text-bg-primary rounded-pill d-none" id="filter_state_<%= name %>" data-turbo-permanent></span>
|
|
60
60
|
<% end %>
|
|
61
61
|
</li>
|
|
62
62
|
<% end %>
|
|
63
63
|
</ul>
|
|
64
64
|
</div>
|
|
65
|
-
|
|
66
|
-
<script nonce="<%= content_security_policy_nonce %>">
|
|
67
|
-
document.addEventListener("DOMContentLoaded", () => {
|
|
68
|
-
document.querySelectorAll("#job_class_filter, #job_queue_filter").forEach((filter) => {
|
|
69
|
-
filter.addEventListener("change", () => {
|
|
70
|
-
document.querySelector("#filter_form").submit();
|
|
71
|
-
});
|
|
72
|
-
})
|
|
73
|
-
})
|
|
74
|
-
</script>
|
|
75
65
|
</div>
|
|
@@ -18,25 +18,25 @@
|
|
|
18
18
|
<li class="nav-item">
|
|
19
19
|
<%= link_to jobs_path, class: ["nav-link", ("active" if controller_name == 'jobs')] do %>
|
|
20
20
|
<%= t(".jobs") %>
|
|
21
|
-
<span data-async-values-target="value" data-async-values-key="jobs_count" class="badge text-bg-secondary rounded-pill d-none"></span>
|
|
21
|
+
<span data-async-values-target="value" data-async-values-key="jobs_count" class="badge text-bg-secondary rounded-pill d-none" id="navbar_jobs_count" data-turbo-permanent></span>
|
|
22
22
|
<% end %>
|
|
23
23
|
</li>
|
|
24
24
|
<li class="nav-item">
|
|
25
25
|
<%= link_to batches_path, class: ["nav-link", ("active" if controller_name == 'batches')] do %>
|
|
26
26
|
<%= t ".batches" %>
|
|
27
|
-
<span data-async-values-target="value" data-async-values-key="batches_count" class="badge text-bg-secondary rounded-pill
|
|
27
|
+
<span data-async-values-target="value" data-async-values-key="batches_count" class="badge text-bg-secondary rounded-pill d-none" id="navbar_batches_count" data-turbo-permanent></span>
|
|
28
28
|
<% end %>
|
|
29
29
|
</li>
|
|
30
30
|
<li class="nav-item">
|
|
31
31
|
<%= link_to cron_entries_path, class: ["nav-link", ("active" if controller_name == 'cron_entries')] do %>
|
|
32
32
|
<%= t(".cron_schedules") %>
|
|
33
|
-
<span data-async-values-target="value" data-async-values-key="cron_entries_count" class="badge text-bg-secondary rounded-pill d-none"></span>
|
|
33
|
+
<span data-async-values-target="value" data-async-values-key="cron_entries_count" class="badge text-bg-secondary rounded-pill d-none" id="navbar_cron_entries_count" data-turbo-permanent></span>
|
|
34
34
|
<% end %>
|
|
35
35
|
</li>
|
|
36
36
|
<li class="nav-item">
|
|
37
37
|
<%= link_to processes_path, class: ["nav-link", ("active" if controller_name == 'processes')] do %>
|
|
38
38
|
<%= t(".processes") %>
|
|
39
|
-
<span data-async-values-target="value" data-async-values-key="processes_count" data-async-values-zero-class="
|
|
39
|
+
<span data-async-values-target="value" data-async-values-key="processes_count" data-async-values-zero-class="bg-danger" class="badge text-bg-secondary rounded-pill d-none" id="navbar_processes_count" data-turbo-permanent></span>
|
|
40
40
|
<% end %>
|
|
41
41
|
</li>
|
|
42
42
|
<li class="nav-item">
|
|
@@ -47,13 +47,13 @@
|
|
|
47
47
|
<li class="nav-item">
|
|
48
48
|
<%= link_to pauses_path, class: ["nav-link", ("active" if controller_name == 'pauses')] do %>
|
|
49
49
|
<%= t(".pauses") %>
|
|
50
|
-
<span data-async-values-target="value" data-async-values-key="pauses_count" data-async-values-zero-class="d-none" class="badge text-bg-warning rounded-pill d-none"></span>
|
|
50
|
+
<span data-async-values-target="value" data-async-values-key="pauses_count" data-async-values-zero-class="d-none" class="badge text-bg-warning rounded-pill d-none" id="navbar_pauses_count" data-turbo-permanent></span>
|
|
51
51
|
<% end %>
|
|
52
52
|
</li>
|
|
53
53
|
<li class="nav-item">
|
|
54
54
|
<%= link_to cleaner_index_path, class: ["nav-link", ("active" if controller_name == 'cleaner')] do %>
|
|
55
55
|
<%= t(".cleaner") %>
|
|
56
|
-
<span data-async-values-target="value" data-async-values-key="discarded_count" class="badge text-bg-secondary rounded-pill d-none"></span>
|
|
56
|
+
<span data-async-values-target="value" data-async-values-key="discarded_count" class="badge text-bg-secondary rounded-pill d-none" id="navbar_discarded_count" data-turbo-permanent></span>
|
|
57
57
|
<% end %>
|
|
58
58
|
</li>
|
|
59
59
|
</ul>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
|
-
<html lang="<%= I18n.locale %>" data-bs-theme="auto">
|
|
2
|
+
<html lang="<%= I18n.locale %>" data-bs-theme="auto" data-turbo-unloaded>
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
|
|
@@ -18,20 +18,24 @@
|
|
|
18
18
|
</script>
|
|
19
19
|
|
|
20
20
|
<%# Do not use asset tag helpers to avoid paths being overriden by config.asset_host %>
|
|
21
|
-
<%= tag.link rel: "stylesheet", href: frontend_static_path(:bootstrap, format: :css, locale: nil), nonce: content_security_policy_nonce %>
|
|
22
|
-
<%= tag.link rel: "stylesheet", href: frontend_static_path(:style, format: :css, locale: nil), nonce: content_security_policy_nonce %>
|
|
21
|
+
<%= tag.link rel: "stylesheet", href: frontend_static_path(:bootstrap, format: :css, locale: nil), nonce: content_security_policy_nonce, data: { turbo_track: "reload" } %>
|
|
22
|
+
<%= tag.link rel: "stylesheet", href: frontend_static_path(:style, format: :css, locale: nil), nonce: content_security_policy_nonce, data: { turbo_track: "reload" } %>
|
|
23
23
|
<%= tag.script "", src: frontend_static_path(:bootstrap, format: :js, locale: nil), nonce: content_security_policy_nonce %>
|
|
24
24
|
<%= tag.script "", src: frontend_static_path(:chartjs, format: :js, locale: nil), nonce: content_security_policy_nonce %>
|
|
25
|
-
<%= tag.script "", src: frontend_static_path(:rails_ujs, format: :js, locale: nil), nonce: content_security_policy_nonce %>
|
|
26
25
|
<%= tag.script "", src: frontend_static_path(:es_module_shims, format: :js, locale: nil), async: true, nonce: content_security_policy_nonce %>
|
|
26
|
+
|
|
27
27
|
<% importmaps = GoodJob::FrontendsController.js_modules.keys.index_with { |module_name| frontend_module_path(module_name, format: :js, locale: nil) } %>
|
|
28
|
-
<%= tag.script({ imports: importmaps }.to_json.html_safe, type: "importmap", nonce: content_security_policy_nonce) %>
|
|
29
|
-
|
|
28
|
+
<%= tag.script({ imports: importmaps }.to_json.html_safe, type: "importmap", nonce: content_security_policy_nonce, data: { turbo_track: "reload" }) %>
|
|
29
|
+
<% importmaps.each do |_module_name, path| %>
|
|
30
|
+
<%= tag.link rel: "modulepreload", href: path, nonce: content_security_policy_nonce %>
|
|
31
|
+
<% end %>
|
|
32
|
+
|
|
33
|
+
<%= tag.script "import \"application\";".html_safe, type: "module", nonce: content_security_policy_nonce %>
|
|
30
34
|
|
|
31
|
-
<title>Good Job Dashboard</title>
|
|
32
|
-
<%= tag.link rel: "icon", href: 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="10 0 100 100"><text y=".90em" font-size="90">👍</text></svg>' %>
|
|
33
35
|
<%= csrf_meta_tags %>
|
|
34
36
|
<%= csp_meta_tag %>
|
|
37
|
+
|
|
38
|
+
<%= render "good_job/custom_head" %>
|
|
35
39
|
</head>
|
|
36
40
|
<body>
|
|
37
41
|
<div class="d-flex flex-column min-vh-100">
|
data/config/brakeman.ignore
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"check_name": "Render",
|
|
8
8
|
"message": "Render path contains parameter value",
|
|
9
9
|
"file": "app/controllers/good_job/frontends_controller.rb",
|
|
10
|
-
"line":
|
|
10
|
+
"line": 52,
|
|
11
11
|
"link": "https://brakemanscanner.org/docs/warning_types/dynamic_render_path/",
|
|
12
12
|
"code": "render(file => (self.class.js_modules[params[:id].to_sym] or raise(ActionController::RoutingError, \"Not Found\")), {})",
|
|
13
13
|
"render_path": null,
|
|
@@ -23,29 +23,6 @@
|
|
|
23
23
|
],
|
|
24
24
|
"note": "Files are explicitly enumerated in the array"
|
|
25
25
|
},
|
|
26
|
-
{
|
|
27
|
-
"warning_type": "Dynamic Render Path",
|
|
28
|
-
"warning_code": 15,
|
|
29
|
-
"fingerprint": "b0c2888c9b217671d90d0141b49b036af3b2a70c63b02968cc97ae2052c86272",
|
|
30
|
-
"check_name": "Render",
|
|
31
|
-
"message": "Render path contains parameter value",
|
|
32
|
-
"file": "app/controllers/good_job/frontends_controller.rb",
|
|
33
|
-
"line": 41,
|
|
34
|
-
"link": "https://brakemanscanner.org/docs/warning_types/dynamic_render_path/",
|
|
35
|
-
"code": "render(file => ({ :css => ({ :bootstrap => GoodJob::Engine.root.join(\"app\", \"frontend\", \"good_job\", \"vendor\", \"bootstrap\", \"bootstrap.min.css\"), :style => GoodJob::Engine.root.join(\"app\", \"frontend\", \"good_job\", \"style.css\") }), :js => ({ :bootstrap => GoodJob::Engine.root.join(\"app\", \"frontend\", \"good_job\", \"vendor\", \"bootstrap\", \"bootstrap.bundle.min.js\"), :chartjs => GoodJob::Engine.root.join(\"app\", \"frontend\", \"good_job\", \"vendor\", \"chartjs\", \"chart.min.js\"), :es_module_shims => GoodJob::Engine.root.join(\"app\", \"frontend\", \"good_job\", \"vendor\", \"es_module_shims.js\"), :rails_ujs => GoodJob::Engine.root.join(\"app\", \"frontend\", \"good_job\", \"vendor\", \"rails_ujs.js\") }), :svg => ({ :icons => GoodJob::Engine.root.join(\"app\", \"frontend\", \"good_job\", \"icons.svg\") }) }.dig(params[:format].to_sym, params[:id].to_sym) or raise(ActionController::RoutingError, \"Not Found\")), {})",
|
|
36
|
-
"render_path": null,
|
|
37
|
-
"location": {
|
|
38
|
-
"type": "method",
|
|
39
|
-
"class": "GoodJob::FrontendsController",
|
|
40
|
-
"method": "static"
|
|
41
|
-
},
|
|
42
|
-
"user_input": "params[:id].to_sym",
|
|
43
|
-
"confidence": "Weak",
|
|
44
|
-
"cwe_id": [
|
|
45
|
-
22
|
|
46
|
-
],
|
|
47
|
-
"note": "Files are explicitly enumerated in the array"
|
|
48
|
-
},
|
|
49
26
|
{
|
|
50
27
|
"warning_type": "Dangerous Eval",
|
|
51
28
|
"warning_code": 13,
|
|
@@ -115,7 +92,30 @@
|
|
|
115
92
|
77
|
|
116
93
|
],
|
|
117
94
|
"note": ""
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"warning_type": "Dynamic Render Path",
|
|
98
|
+
"warning_code": 15,
|
|
99
|
+
"fingerprint": "ebc35a48169b7ee1f2e1b024f3bf6abe7138924a3a318ab2ad405c2b6e9bbb55",
|
|
100
|
+
"check_name": "Render",
|
|
101
|
+
"message": "Render path contains parameter value",
|
|
102
|
+
"file": "app/controllers/good_job/frontends_controller.rb",
|
|
103
|
+
"line": 46,
|
|
104
|
+
"link": "https://brakemanscanner.org/docs/warning_types/dynamic_render_path/",
|
|
105
|
+
"code": "render(file => ({ :css => ({ :bootstrap => asset_path(\"vendor\", \"bootstrap\", \"bootstrap.min.css\"), :style => asset_path(\"style.css\") }), :js => ({ :bootstrap => asset_path(\"vendor\", \"bootstrap\", \"bootstrap.bundle.min.js\"), :chartjs => asset_path(\"vendor\", \"chartjs\", \"chart.min.js\"), :es_module_shims => asset_path(\"vendor\", \"es_module_shims.js\"), :turbo => asset_path(\"vendor\", \"turbo.js\") }), :svg => ({ :icons => asset_path(\"icons.svg\") }) }.dig(params[:format].to_sym, params[:id].to_sym) or raise(ActionController::RoutingError, \"Not Found\")), {})",
|
|
106
|
+
"render_path": null,
|
|
107
|
+
"location": {
|
|
108
|
+
"type": "method",
|
|
109
|
+
"class": "GoodJob::FrontendsController",
|
|
110
|
+
"method": "static"
|
|
111
|
+
},
|
|
112
|
+
"user_input": "params[:id].to_sym",
|
|
113
|
+
"confidence": "Weak",
|
|
114
|
+
"cwe_id": [
|
|
115
|
+
22
|
|
116
|
+
],
|
|
117
|
+
"note": ""
|
|
118
118
|
}
|
|
119
119
|
],
|
|
120
|
-
"brakeman_version": "7.
|
|
120
|
+
"brakeman_version": "7.1.1"
|
|
121
121
|
}
|
data/config/locales/de.yml
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
de:
|
|
3
3
|
good_job:
|
|
4
4
|
actions:
|
|
5
|
-
destroy:
|
|
5
|
+
destroy: Löschen
|
|
6
6
|
discard: Verwerfen
|
|
7
7
|
force_discard: Verwerfen erzwingen
|
|
8
8
|
inspect: Prüfen
|
|
@@ -17,11 +17,11 @@ de:
|
|
|
17
17
|
title: Batches
|
|
18
18
|
jobs:
|
|
19
19
|
actions:
|
|
20
|
-
confirm_destroy: Bist du sicher, dass du diesen Job
|
|
20
|
+
confirm_destroy: Bist du sicher, dass du diesen Job löschen wilst?
|
|
21
21
|
confirm_discard: Bist du sicher, dass du diesen Job verwerfen willst?
|
|
22
22
|
confirm_reschedule: Bist du sicher, dass du diesen Job verschieben willst?
|
|
23
23
|
confirm_retry: Bist du sicher, dass du diesen Job erneut versuchen willst?
|
|
24
|
-
destroy: Job
|
|
24
|
+
destroy: Job löschen
|
|
25
25
|
discard: Job verwerfen
|
|
26
26
|
reschedule: Job neu planen
|
|
27
27
|
retry: Job wiederholen
|
|
@@ -38,15 +38,15 @@ de:
|
|
|
38
38
|
cleaner:
|
|
39
39
|
index:
|
|
40
40
|
all: All
|
|
41
|
-
class:
|
|
41
|
+
class: Klasse
|
|
42
42
|
exception: Exception
|
|
43
|
-
grouped_by_class: Discards
|
|
44
|
-
grouped_by_exception: Discards
|
|
45
|
-
last_1_hour:
|
|
46
|
-
last_24_hours:
|
|
47
|
-
last_3_days:
|
|
48
|
-
last_3_hours:
|
|
49
|
-
last_7_days:
|
|
43
|
+
grouped_by_class: Discards groupiert nach Klasse
|
|
44
|
+
grouped_by_exception: Discards groupiert nach Exception
|
|
45
|
+
last_1_hour: Letzte Stunde
|
|
46
|
+
last_24_hours: Letzte 24 Stunden
|
|
47
|
+
last_3_days: Letzte 3 Tage
|
|
48
|
+
last_3_hours: Letzte 3 Stunden
|
|
49
|
+
last_7_days: Letzte 7 Tage
|
|
50
50
|
title: Discard Cleaner
|
|
51
51
|
total: Total
|
|
52
52
|
cron_entries:
|
|
@@ -126,18 +126,18 @@ de:
|
|
|
126
126
|
past: Vor %{time}
|
|
127
127
|
jobs:
|
|
128
128
|
actions:
|
|
129
|
-
confirm_destroy: Bist du sicher, dass du diesen Job
|
|
129
|
+
confirm_destroy: Bist du sicher, dass du diesen Job löschen willst?
|
|
130
130
|
confirm_discard: Bist du sicher, dass du diesen Job verwerfen willst?
|
|
131
131
|
confirm_force_discard: Bist du sicher, dass du das Verwerfen dieses Jobs erzwingen möchten? Der Job wird als verworfen markiert, aber der laufende Job wird nicht gestoppt – er wird jedoch bei Fehlern nicht erneut versucht.
|
|
132
132
|
confirm_reschedule: Bist du sicher, dass du diesen Job verschieben willst?
|
|
133
133
|
confirm_retry: Bist du sicher, dass du diesen Job wiederholen willst?
|
|
134
|
-
destroy: Job
|
|
134
|
+
destroy: Job löschen
|
|
135
135
|
discard: Job verwerfen
|
|
136
136
|
force_discard: Job verwerfen erzwingen
|
|
137
137
|
reschedule: Job neu planen
|
|
138
138
|
retry: Job wiederholen
|
|
139
139
|
destroy:
|
|
140
|
-
notice:
|
|
140
|
+
notice: Job wurde gelöscht
|
|
141
141
|
discard:
|
|
142
142
|
notice: Job wurde verworfen
|
|
143
143
|
executions:
|
|
@@ -145,14 +145,14 @@ de:
|
|
|
145
145
|
full_trace: Full Trace
|
|
146
146
|
in_queue: in der Warteschlange
|
|
147
147
|
runtime: Laufzeit
|
|
148
|
-
title:
|
|
148
|
+
title: Ausführungen
|
|
149
149
|
force_discard:
|
|
150
150
|
notice: Der Job wurde zwangsweise verworfen. Die Ausführung wird fortgesetzt, bei Fehlern wird der Vorgang jedoch nicht wiederholt
|
|
151
151
|
index:
|
|
152
152
|
job_pagination: Job-Paginierung
|
|
153
153
|
older_jobs: Ältere Jobs
|
|
154
154
|
reschedule:
|
|
155
|
-
notice: Job wurde neu
|
|
155
|
+
notice: Job wurde neu geplant
|
|
156
156
|
retry:
|
|
157
157
|
notice: Job wurde wiederholt
|
|
158
158
|
show:
|
|
@@ -166,7 +166,7 @@ de:
|
|
|
166
166
|
confirm_discard_all: Bist du sicher, dass du die ausgewählten Jobs verferfen willst?
|
|
167
167
|
confirm_reschedule_all: Bist du sicher, dass du die ausgewählten Jobs neu planen willst?
|
|
168
168
|
confirm_retry_all: Bist du sicher, dass du die ausgewählten Jobs wiederholen willst?
|
|
169
|
-
destroy_all: Alle
|
|
169
|
+
destroy_all: Alle löschen
|
|
170
170
|
discard_all: Alle verwerfen
|
|
171
171
|
reschedule_all: Alle neu planen
|
|
172
172
|
retry_all: Alle wiederholen
|
|
@@ -220,11 +220,11 @@ de:
|
|
|
220
220
|
unit: ''
|
|
221
221
|
pauses:
|
|
222
222
|
index:
|
|
223
|
-
confirm_pause:
|
|
224
|
-
confirm_unpause:
|
|
225
|
-
disabled: Die experimentelle Pausenfunktion von GoodJob ist standardmäßig deaktiviert, da sie die Leistung beeinträchtigen kann.
|
|
223
|
+
confirm_pause: Bist du sicher, dass du %{value} pausieren möchten?
|
|
224
|
+
confirm_unpause: Bist du sicher, dass du %{value} fortsetzen möchten?
|
|
225
|
+
disabled: Die experimentelle Pausenfunktion von GoodJob ist standardmäßig deaktiviert, da sie die Leistung beeinträchtigen kann. Konfiguriere sie zur Aktivierung.
|
|
226
226
|
job_class: Job-Klasse
|
|
227
|
-
label:
|
|
227
|
+
label: Etikette
|
|
228
228
|
pause: Pausieren
|
|
229
229
|
queue: Warteschlange
|
|
230
230
|
title: Pausen
|