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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +41 -0
  3. data/README.md +3 -2
  4. data/app/controllers/good_job/batches_controller.rb +1 -1
  5. data/app/controllers/good_job/cron_entries_controller.rb +3 -3
  6. data/app/controllers/good_job/frontends_controller.rb +15 -10
  7. data/app/controllers/good_job/jobs_controller.rb +7 -7
  8. data/app/controllers/good_job/pauses_controller.rb +2 -2
  9. data/app/frontend/good_job/application.js +23 -9
  10. data/app/frontend/good_job/modules/form_controller.js +11 -0
  11. data/app/frontend/good_job/vendor/turbo.js +34 -0
  12. data/app/models/good_job/batch.rb +2 -0
  13. data/app/models/good_job/batch_record.rb +2 -0
  14. data/app/models/good_job/discrete_execution.rb +1 -0
  15. data/app/models/good_job/job.rb +2 -2
  16. data/app/models/good_job/process.rb +2 -0
  17. data/app/models/good_job/setting.rb +2 -0
  18. data/app/views/good_job/_custom_head.html.erb +7 -0
  19. data/app/views/good_job/batches/_jobs.erb +4 -4
  20. data/app/views/good_job/batches/_table.erb +2 -2
  21. data/app/views/good_job/batches/show.html.erb +1 -1
  22. data/app/views/good_job/cron_entries/index.html.erb +2 -2
  23. data/app/views/good_job/jobs/_table.erb +12 -9
  24. data/app/views/good_job/jobs/show.html.erb +4 -4
  25. data/app/views/good_job/pauses/_group.html.erb +1 -1
  26. data/app/views/good_job/pauses/_pause.html.erb +1 -1
  27. data/app/views/good_job/shared/_filter.erb +4 -14
  28. data/app/views/good_job/shared/_navbar.erb +6 -6
  29. data/app/views/layouts/good_job/application.html.erb +12 -8
  30. data/config/brakeman.ignore +25 -25
  31. data/config/locales/de.yml +21 -21
  32. data/config/locales/zh-CN.yml +295 -0
  33. data/lib/generators/good_job/templates/install/migrations/create_good_jobs.rb.erb +1 -1
  34. data/lib/generators/good_job/templates/update/migrations/05_add_index_good_jobs_finished_at_for_cleanup.rb.erb +17 -0
  35. data/lib/generators/good_job/templates/update/migrations/06_remove_extraneous_finished_at_index.rb.erb +17 -0
  36. data/lib/good_job/active_job_extensions/labels.rb +1 -0
  37. data/lib/good_job/active_job_extensions/notify_options.rb +1 -0
  38. data/lib/good_job/notifier.rb +1 -0
  39. data/lib/good_job/version.rb +1 -1
  40. data/lib/good_job.rb +1 -1
  41. metadata +13 -9
  42. data/app/frontend/good_job/modules/document_ready.js +0 -7
  43. data/app/frontend/good_job/vendor/rails_ujs.js +0 -7
@@ -184,3 +184,5 @@ module GoodJob
184
184
  attr_accessor :record
185
185
  end
186
186
  end
187
+
188
+ ActiveSupport.run_load_hooks(:good_job_batch, GoodJob::Batch)
@@ -123,3 +123,5 @@ module GoodJob
123
123
  end
124
124
  end
125
125
  end
126
+
127
+ ActiveSupport.run_load_hooks(:good_job_batch_record, GoodJob::BatchRecord)
@@ -6,5 +6,6 @@ module GoodJob
6
6
  end
7
7
 
8
8
  include ActiveSupport::Deprecation::DeprecatedConstantAccessor
9
+
9
10
  deprecate_constant :DiscreteExecution, 'Execution', deprecator: GoodJob.deprecator
10
11
  end
@@ -250,8 +250,8 @@ module GoodJob
250
250
  )
251
251
  end
252
252
 
253
- def job_class_index_migrated?
254
- return true if connection.index_name_exists?(:good_jobs, :index_good_jobs_on_job_class)
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
@@ -167,3 +167,5 @@ module GoodJob # :nodoc:
167
167
  end
168
168
  end
169
169
  end
170
+
171
+ ActiveSupport.run_load_hooks(:good_job_process, GoodJob::Process)
@@ -127,3 +127,5 @@ module GoodJob
127
127
  end
128
128
  end
129
129
  end
130
+
131
+ ActiveSupport.run_load_hooks(:good_job_setting, GoodJob::Setting)
@@ -0,0 +1,7 @@
1
+ <%#
2
+ Content added to this partial will be added to the end of the head tag of all GoodJob dashboard pages.
3
+
4
+ You can make use of the following variables:
5
+
6
+ - `main_app`: Use this to access helpers (e.g. route helpers) from your application.
7
+ %>
@@ -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
- <%= link_to reschedule_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job_reschedulable}", title: t(".actions.reschedule"), data: { confirm: t(".actions.confirm_reschedule"), disable: true } do %>
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
- <%= link_to discard_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job_discardable}", title: t(".actions.discard"), data: { confirm: t(".actions.confirm_discard"), disable: true } do %>
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
- <%= link_to retry_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job.status == :discarded}", title: t(".actions.retry"), data: { confirm: t(".actions.confirm_retry"), disable: true } do %>
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
- <%= link_to job_path(job.id), method: :delete, class: "dropdown-item #{'disabled' unless job.finished?}", title: t(".actions.destroy"), data: { confirm: t(".actions.confirm_destroy"), disable: true } do %>
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
- <%= link_to retry_batch_path(batch), method: :put, class: "btn btn-sm btn-outline-primary", title: t("good_job.batches.actions.retry"), data: { confirm: t("good_job.batches.actions.confirm_retry") } do %>
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: { confirm: t("good_job.batches.actions.confirm_retry") } do %>
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: { confirm: t("good_job.cron_entries.actions.confirm_disable") } do %>
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: { confirm: t("good_job.cron_entries.actions.confirm_enable") } do %>
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: { confirm: t(".actions.confirm_reschedule_all"), disable: true } do %>
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: { confirm: t(".actions.confirm_retry_all"), disable: true } do %>
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: { confirm: t(".actions.confirm_discard_all"), disable: true } do %>
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: { confirm: t(".actions.confirm_destroy_all"), disable: true } do %>
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
- <%= link_to reschedule_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job_reschedulable}", title: t("good_job.jobs.actions.reschedule"), data: { confirm: t("good_job.jobs.actions.confirm_reschedule"), disable: true } do %>
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
- <%= link_to discard_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job_discardable}", title: t("good_job.jobs.actions.discard"), data: { confirm: t("good_job.jobs.actions.confirm_discard"), disable: true } do %>
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
- <%= link_to force_discard_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job_force_discardable}", title: t("good_job.jobs.actions.force_discard"), data: { confirm: t("good_job.jobs.actions.confirm_force_discard"), disable: true } do %>
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
- <%= link_to retry_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job.status == :discarded}", title: t("good_job.jobs.actions.retry"), data: { confirm: t("good_job.jobs.actions.confirm_retry"), disable: true } do %>
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
- <%= link_to job_path(job.id), method: :delete, class: "dropdown-item #{'disabled' unless job.status.in? [:discarded, :succeeded]}", title: t("good_job.jobs.actions.destroy"), data: { confirm: t("good_job.jobs.actions.confirm_destroy"), disable: true } do %>
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: { confirm: t("good_job.jobs.actions.confirm_reschedule") } do %>
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: { confirm: t("good_job.jobs.actions.confirm_discard") } do %>
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: { confirm: t("good_job.jobs.actions.confirm_retry") } do %>
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: { confirm: t("good_job.jobs.actions.confirm_destroy") } do %>
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: { confirm: t('good_job.pauses.index.confirm_unpause', value: value) }
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: { confirm: t('good_job.pauses.index.confirm_unpause', value: value) } %>
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, id: "filter_form", class: "") do |form| %>
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="text-bg-secondary" class="badge text-bg-primary rounded-pill d-none"></span>
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 d-none"></span>
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="text-bg-danger" class="badge text-bg-secondary rounded-pill d-none"></span>
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
- <%= tag.script "", type: "module", nonce: content_security_policy_nonce do %> import "application"; <% end %>
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">
@@ -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": 47,
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.0.2"
120
+ "brakeman_version": "7.1.1"
121
121
  }
@@ -2,7 +2,7 @@
2
2
  de:
3
3
  good_job:
4
4
  actions:
5
- destroy: Zerstören
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 zerstören wilst?
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 zerstören
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: Class
41
+ class: Klasse
42
42
  exception: Exception
43
- grouped_by_class: Discards grouped by Class
44
- grouped_by_exception: Discards grouped by Exception
45
- last_1_hour: Last 1 hour
46
- last_24_hours: Last 24 hours
47
- last_3_days: Last 3 days
48
- last_3_hours: Last 3 hours
49
- last_7_days: 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 zerstören willst?
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 zerstören
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: Hiob wurde zerstört
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: Hinrichtungen
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 planen
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 zerstören
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: Sind Sie sicher, dass Sie %{value} pausieren möchten?
224
- confirm_unpause: Sind Sie sicher, dass Sie %{value} fortsetzen möchten?
225
- disabled: Die experimentelle Pausenfunktion von GoodJob ist standardmäßig deaktiviert, da sie die Leistung beeinträchtigen kann. Konfigurieren Sie sie zur Aktivierung
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: Label
227
+ label: Etikette
228
228
  pause: Pausieren
229
229
  queue: Warteschlange
230
230
  title: Pausen