good_job 3.0.2 → 3.3.0
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 +52 -1
- data/README.md +35 -31
- data/app/assets/good_job/modules/application.js +2 -0
- data/app/assets/good_job/modules/popovers.js +7 -0
- data/app/assets/good_job/style.css +4 -0
- data/app/controllers/good_job/jobs_controller.rb +1 -1
- data/app/helpers/good_job/application_helper.rb +2 -2
- data/app/views/good_job/cron_entries/index.html.erb +60 -57
- data/app/views/good_job/jobs/_executions.erb +31 -28
- data/app/views/good_job/jobs/_table.erb +138 -109
- data/app/views/good_job/jobs/show.html.erb +41 -32
- data/app/views/good_job/processes/index.html.erb +60 -32
- data/app/views/good_job/shared/_filter.erb +1 -1
- data/app/views/good_job/shared/_navbar.erb +15 -3
- data/app/views/good_job/shared/icons/_dots.html.erb +3 -0
- data/app/views/good_job/shared/icons/_info.html.erb +4 -0
- data/config/locales/en.yml +19 -0
- data/config/locales/es.yml +19 -0
- data/config/locales/nl.yml +19 -0
- data/config/locales/ru.yml +19 -0
- data/lib/generators/good_job/templates/install/migrations/create_good_jobs.rb.erb +4 -4
- data/lib/generators/good_job/templates/update/migrations/01_create_good_jobs.rb.erb +4 -4
- data/lib/good_job/daemon.rb +2 -2
- data/lib/good_job/job_performer.rb +1 -1
- data/lib/good_job/version.rb +1 -1
- data/lib/models/good_job/cron_entry.rb +4 -2
- data/lib/models/good_job/execution.rb +63 -40
- data/lib/models/good_job/job.rb +32 -7
- data/lib/models/good_job/process.rb +2 -0
- data/lib/models/good_job/reportable.rb +43 -0
- metadata +6 -2
@@ -1,122 +1,151 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
<
|
12
|
-
|
13
|
-
<th>Executions</th>
|
14
|
-
<th>Error</th>
|
15
|
-
<th>
|
16
|
-
ActiveJob Params
|
17
|
-
<%= tag.button "Toggle", type: "button", class: "btn btn-sm btn-outline-primary", role: "button",
|
18
|
-
data: { bs_toggle: "collapse", bs_target: ".job-params" },
|
19
|
-
aria: { expanded: false, controls: jobs.map { |job| "##{dom_id(job, "params")}" }.join(" ") }
|
20
|
-
%>
|
21
|
-
</th>
|
22
|
-
<th>
|
23
|
-
Actions<br>
|
1
|
+
<%= form_with(url: mass_update_jobs_path(filter.to_params), method: :put, local: true, data: { "checkbox-toggle": "job_ids" }) do |form| %>
|
2
|
+
<div class="my-3 card" data-gj-poll-replace id="jobs-table">
|
3
|
+
<div class="list-group list-group-flush text-nowrap table-jobs" role="table">
|
4
|
+
<header class="list-group-item bg-light">
|
5
|
+
<div class="row small text-muted text-uppercase align-items-center">
|
6
|
+
<div class="col-auto">
|
7
|
+
<%= check_box_tag('toggle_job_ids', "1", false, data: { "checkbox-toggle-all": "job_ids" }) %>
|
8
|
+
</div>
|
9
|
+
<div class="col-4">
|
10
|
+
<%= form.button type: 'submit', name: 'mass_action', value: 'reschedule', class: 'btn btn-sm btn-outline-secondary', title: "Reschedule all", data: { confirm: "Are you sure you want to reschedule the selected jobs?", disable: true } do %>
|
11
|
+
<span class="me-1"><%= render_icon "skip_forward" %></span> Reschedule
|
12
|
+
<% end %>
|
24
13
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
<% end %>
|
14
|
+
<%= form.button type: 'submit', name: 'mass_action', value: 'retry', class: 'btn btn-sm btn-outline-secondary', title: "Retry all", data: { confirm: "Are you sure you want to retry the selected jobs?", disable: true } do %>
|
15
|
+
<span class="me-1"><%= render_icon "arrow_clockwise" %></span> Retry
|
16
|
+
<% end %>
|
29
17
|
|
30
|
-
|
31
|
-
|
18
|
+
<div class="btn-group" role="group">
|
19
|
+
<%= form.button type: 'submit', name: 'mass_action', value: 'discard', class: 'btn btn-sm btn-outline-secondary', title: "Discard all", data: { confirm: "Are you usure you want to discard the selected jobs?", disable: true } do %>
|
20
|
+
<span class="me-1"><%= render_icon "stop" %></span> Discard
|
21
|
+
<% end %>
|
22
|
+
<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">
|
23
|
+
<span class="visually-hidden">Toggle Actions</span>
|
24
|
+
</button>
|
25
|
+
<div class="dropdown-menu" aria-labelledby="destroy-dropdown-toggle">
|
26
|
+
<li>
|
27
|
+
<%= form.button type: 'submit', name: 'mass_action', value: 'destroy', class: 'btn', title: "Destroy all", data: { confirm: "Are you sure you want to destroy the selected jobs?", disable: true } do %>
|
28
|
+
<span class="me-1"><%= render_icon "trash" %></span> Destroy
|
32
29
|
<% end %>
|
30
|
+
</li>
|
31
|
+
</div>
|
32
|
+
</div>
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
</div>
|
35
|
+
<div class="col-1">Queue</div>
|
36
|
+
<div class="col-1">Priority</div>
|
37
|
+
<div class="col-1 text-end">Attempts</div>
|
38
|
+
<div class="col text-end">
|
39
|
+
<%= tag.button type: "button", class: "btn btn-sm text-muted", role: "button",
|
40
|
+
data: { bs_toggle: "collapse", bs_target: ".job-params" },
|
41
|
+
aria: { expanded: false, controls: jobs.map { |job| "##{dom_id(job, "params")}" }.join(" ") } do %>
|
42
|
+
<%= render_icon "info" %>
|
43
|
+
<span class="visually-hidden">Inspect</span>
|
44
|
+
<% end %>
|
45
|
+
</div>
|
46
|
+
</div>
|
47
|
+
</header>
|
48
|
+
<label role="row" class="list-group-item list-group-item-warning list-group-item-action py-3 d-none" data-checkbox-toggle-show="job_ids">
|
49
|
+
<div class="row">
|
50
|
+
<div class="col-auto">
|
51
|
+
<%= check_box_tag "all_job_ids", 1, false, disabled: true, data: { "checkbox-toggle-show": "job_ids"} %>
|
52
|
+
</div>
|
53
|
+
<div class="col-auto">
|
54
|
+
Apply to all <%= filter.filtered_count %> <%= "job".pluralize(filter.filtered_count) %>.
|
55
|
+
</div>
|
56
|
+
</div>
|
57
|
+
</label>
|
37
58
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
<
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
<
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
<%=
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
<button class="btn btn-sm btn-outline-secondary" disabled><%= render_icon "skip_forward" %></button>
|
59
|
+
<% if jobs.present? %>
|
60
|
+
<% jobs.each do |job| %>
|
61
|
+
<%= label_tag dom_id(job, :checkbox), id: dom_id(job), role: "row", class: "list-group-item list-group-item-action py-3" do %>
|
62
|
+
<div class="row align-items-center">
|
63
|
+
<div class="col-auto">
|
64
|
+
<%= check_box_tag 'job_ids[]', job.id, false, id: dom_id(job, :checkbox), data: { "checkbox-toggle-each": "job_ids" } %>
|
65
|
+
</div>
|
66
|
+
<div class="col-4">
|
67
|
+
<%= tag.code link_to(job.id, job_path(job), class: "small text-muted text-decoration-none") %>
|
68
|
+
<%= tag.h5 tag.code(link_to(job.job_class, job_path(job), class: "text-reset text-decoration-none")), class: "text-reset mb-0" %>
|
69
|
+
</div>
|
70
|
+
<div class="col-1">
|
71
|
+
<span class="badge bg-primary bg-opacity-25 text-dark font-monospace"><%= job.queue_name %></span>
|
72
|
+
</div>
|
73
|
+
<div class="col-1 small text-center">
|
74
|
+
<span class="font-monospace fw-bold"><%= job.priority %></span>
|
75
|
+
</div>
|
76
|
+
<div class="col-1 text-center">
|
77
|
+
<% if job.executions_count > 0 && job.status != :finished %>
|
78
|
+
<%= tag.span job.executions_count, class: "badge rounded-pill bg-danger", data: {
|
79
|
+
bs_toggle: "popover",
|
80
|
+
bs_trigger: "hover focus click",
|
81
|
+
bs_placement: "bottom",
|
82
|
+
bs_content: job.recent_error
|
83
|
+
} %>
|
84
|
+
<% else %>
|
85
|
+
<span class="badge bg-secondary bg-opacity-50 rounded-pill"><%= job.executions_count %></span>
|
86
|
+
<% end %>
|
87
|
+
</div>
|
88
|
+
<div class="col d-flex gap-3 align-items-center justify-content-end">
|
89
|
+
<%= tag.span relative_time(job.last_status_at), class: "small" %>
|
90
|
+
<%= status_badge job.status %>
|
91
|
+
</div>
|
92
|
+
<div class="col-auto">
|
93
|
+
<div class="dropdown float-end">
|
94
|
+
<button class="d-flex align-items-center btn btn-sm" type="button" id="<%= dom_id(job, :actions) %>" data-bs-toggle="dropdown" aria-expanded="false">
|
95
|
+
<%= render "good_job/shared/icons/dots" %>
|
96
|
+
<span class="visually-hidden">Actions</span>
|
97
|
+
</button>
|
98
|
+
<ul class="dropdown-menu shadow" aria-labelledby="<%= dom_id(job, :actions) %>">
|
99
|
+
<li>
|
100
|
+
<% job_reschedulable = job.status.in? [:scheduled, :retried, :queued] %>
|
101
|
+
<%= link_to reschedule_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job_reschedulable}", title: "Reschedule job", data: { confirm: "Confirm reschedule", disable: true } do %>
|
102
|
+
<%= render "good_job/shared/icons/skip_forward" %>
|
103
|
+
Reschedule
|
84
104
|
<% end %>
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
<button class="btn btn-sm btn-outline-secondary" disabled><%= render_icon "stop" %></button>
|
105
|
+
</li>
|
106
|
+
<li>
|
107
|
+
<% job_discardable = job.status.in? [:scheduled, :retried, :queued] %>
|
108
|
+
<%= link_to discard_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job_discardable}", title: "Discard job", data: { confirm: "Confirm discard", disable: true } do %>
|
109
|
+
<%= render "good_job/shared/icons/stop" %>
|
110
|
+
Discard
|
92
111
|
<% end %>
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
<%
|
99
|
-
|
112
|
+
</li>
|
113
|
+
<li>
|
114
|
+
<%= link_to retry_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job.status == :discarded}", title: "Retry job", data: { confirm: "Confirm retry", disable: true } do %>
|
115
|
+
<%= render "good_job/shared/icons/arrow_clockwise" %>
|
116
|
+
Retry
|
117
|
+
<% end %>
|
118
|
+
</li>
|
119
|
+
<li>
|
120
|
+
<%= link_to job_path(job.id), method: :delete, class: "dropdown-item #{'disabled' unless job.status.in? [:discarded, :finished]}", title: "Destroy job", data: { confirm: "Confirm destroy", disable: true } do %>
|
121
|
+
<%= render_icon "trash" %>
|
122
|
+
Destroy
|
100
123
|
<% end %>
|
124
|
+
</li>
|
101
125
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
126
|
+
<li>
|
127
|
+
<%= link_to "##{dom_id(job, 'params')}",
|
128
|
+
class: "dropdown-item",
|
129
|
+
data: { bs_toggle: "collapse" },
|
130
|
+
aria: { expanded: false, controls: dom_id(job, "params") } do %>
|
131
|
+
<%= render_icon "info" %>
|
132
|
+
Inspect
|
108
133
|
<% end %>
|
109
|
-
</
|
110
|
-
</
|
111
|
-
</
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
134
|
+
</li>
|
135
|
+
</ul>
|
136
|
+
</div>
|
137
|
+
</div>
|
138
|
+
</div>
|
139
|
+
<% end %>
|
140
|
+
<%= tag.div id: dom_id(job, "params"), class: "job-params list-group-item collapse small bg-dark text-light" do %>
|
141
|
+
<%= tag.pre JSON.pretty_generate(job.display_serialized_params) %>
|
142
|
+
<% end %>
|
143
|
+
<% end %>
|
144
|
+
<% else %>
|
145
|
+
<div class="list-group-item py-4 text-center text-muted">
|
146
|
+
No jobs found.
|
147
|
+
</div>
|
120
148
|
<% end %>
|
121
149
|
</div>
|
122
150
|
</div>
|
151
|
+
<% end %>
|
@@ -1,48 +1,57 @@
|
|
1
1
|
<div class="break-out bg-light border-bottom py-2 mb-3">
|
2
2
|
<div class="container-fluid pt-2">
|
3
|
-
<div class="
|
4
|
-
<div class="
|
3
|
+
<div class="row align-items-center">
|
4
|
+
<div class="col-5">
|
5
5
|
<nav aria-label="breadcrumb">
|
6
6
|
<ol class="breadcrumb small mb-0">
|
7
7
|
<li class="breadcrumb-item"><%= link_to "Jobs", jobs_path %></li>
|
8
|
-
<li class="breadcrumb-item active" aria-current="page"
|
8
|
+
<li class="breadcrumb-item active" aria-current="page"><%= tag.code @job.id, class: "text-muted" %></li>
|
9
9
|
</ol>
|
10
10
|
</nav>
|
11
|
-
<h2 class="mb-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
<h2 class="mb-0"><%= tag.code @job.job_class %></h2>
|
12
|
+
</div>
|
13
|
+
<div class="col-2">
|
14
|
+
<div class="small text-muted text-uppercase">Queue</div>
|
15
|
+
<div class="badge bg-primary bg-opacity-25 text-dark font-monospace my-2">
|
16
|
+
<%= tag.strong @job.queue_name %>
|
16
17
|
</div>
|
17
18
|
</div>
|
18
|
-
<div>
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
19
|
+
<div class="col-2">
|
20
|
+
<div class="small text-muted text-uppercase">Priority</div>
|
21
|
+
<div class="font-monospace fw-bold small my-2"><%= tag.strong @job.priority %></div>
|
22
|
+
</div>
|
23
|
+
<div class="col text-end">
|
24
|
+
<% if @job.status.in? [:scheduled, :retried, :queued] %>
|
25
|
+
<%= button_to reschedule_job_path(@job.id), method: :put,
|
26
|
+
class: "btn btn-sm btn-outline-primary",
|
27
|
+
form_class: "d-inline-block",
|
28
|
+
aria: { label: "Reschedule job" },
|
29
|
+
title: "Reschedule job",
|
30
|
+
data: { confirm: "Confirm reschedule" } do %>
|
31
|
+
<%= render_icon "skip_forward" %>
|
32
|
+
Reschedule
|
33
|
+
<% end %>
|
29
34
|
<% end %>
|
30
35
|
|
31
|
-
<%
|
32
|
-
|
33
|
-
|
34
|
-
|
36
|
+
<% if @job.status.in? [:scheduled, :retried, :queued] %>
|
37
|
+
<%= button_to discard_job_path(@job.id), method: :put, class: "btn btn-sm btn-outline-primary", form_class: "d-inline-block", aria: { label: "Discard job" }, title: "Discard job", data: { confirm: "Confirm discard" } do %>
|
38
|
+
<%= render_icon "stop" %>
|
39
|
+
Discard
|
40
|
+
<% end %>
|
35
41
|
<% end %>
|
36
42
|
|
37
|
-
|
38
|
-
<%=
|
39
|
-
|
43
|
+
<% if @job.status == :discarded %>
|
44
|
+
<%= button_to retry_job_path(@job.id), method: :put, class: "btn btn-sm btn-outline-primary", form_class: "d-inline-block", aria: { label: "Retry job" }, title: "Retry job", data: { confirm: "Confirm retry" } do %>
|
45
|
+
<%= render_icon "arrow_clockwise" %>
|
46
|
+
Retry
|
47
|
+
<% end %>
|
40
48
|
<% end %>
|
41
49
|
|
42
|
-
<%
|
43
|
-
|
44
|
-
|
45
|
-
|
50
|
+
<% if @job.status.in? [:discarded, :finished] %>
|
51
|
+
<%= button_to job_path(@job.id), method: :delete, class: "btn btn-sm btn-outline-primary", form_class: "d-inline-block", aria: { label: "Destroy job" }, title: "Destroy job", data: { confirm: "Confirm destroy" } do %>
|
52
|
+
<%= render_icon "trash" %>
|
53
|
+
Destroy
|
54
|
+
<% end %>
|
46
55
|
<% end %>
|
47
56
|
</div>
|
48
57
|
</div>
|
@@ -51,7 +60,7 @@
|
|
51
60
|
|
52
61
|
<div class="my-4">
|
53
62
|
<h5>Arguments</h5>
|
54
|
-
<%= tag.pre @job.serialized_params["arguments"].map(&:inspect).join(', ') %>
|
63
|
+
<%= tag.pre @job.serialized_params["arguments"].map(&:inspect).join(', '), class: 'text-wrap text-break' %>
|
55
64
|
</div>
|
56
65
|
|
57
|
-
<%= render 'executions', executions: @job.executions.reverse %>
|
66
|
+
<%= render 'executions', executions: @job.executions.includes_advisory_locks.reverse %>
|
@@ -1,38 +1,66 @@
|
|
1
|
-
<div class="
|
2
|
-
<h2>Processes</h2>
|
1
|
+
<div class="bg-light break-out border-bottom">
|
2
|
+
<h2 class="container-fluid pt-3 pb-2">Processes</h2>
|
3
3
|
</div>
|
4
4
|
|
5
|
-
<div data-live-poll-region="processes">
|
6
|
-
|
7
|
-
<
|
8
|
-
<div class="
|
9
|
-
<
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
<td><%= process.id %></td>
|
21
|
-
<td><%= relative_time(process.created_at) %></td>
|
22
|
-
<td><%= tag.pre JSON.pretty_generate(process.state) %></td>
|
23
|
-
</tr>
|
5
|
+
<div class="card my-3" data-live-poll-region="processes">
|
6
|
+
<div class="list-group list-group-flush text-nowrap" role="table">
|
7
|
+
<header class="list-group-item bg-light">
|
8
|
+
<div class="row small text-muted text-uppercase align-items-center">
|
9
|
+
<div class="col">Process</div>
|
10
|
+
<div class="col">Schedulers</div>
|
11
|
+
<div class="col-2 d-flex gap-2">
|
12
|
+
<span>Started</span>
|
13
|
+
</div>
|
14
|
+
<div class="col-auto">
|
15
|
+
<%= tag.button type: "button", class: "btn btn-sm text-muted ms-auto", role: "button",
|
16
|
+
data: { bs_toggle: "collapse", bs_target: ".process-state" },
|
17
|
+
aria: { expanded: false, controls: @processes.map { |process| "##{dom_id(process, 'state')}" }.join(" ") } do %>
|
18
|
+
<%= render_icon "info" %>
|
19
|
+
<span class="visually-hidden">Inspect</span>
|
24
20
|
<% end %>
|
25
|
-
|
26
|
-
</table>
|
21
|
+
</div>
|
27
22
|
</div>
|
28
|
-
</
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
23
|
+
</header>
|
24
|
+
<% @processes.each do |process| %>
|
25
|
+
<div id="<%= dom_id(process) %>" class="<%= dom_class(process) %> list-group-item py-3" role="row">
|
26
|
+
<div class="row align-items-center">
|
27
|
+
<div class="col">
|
28
|
+
<code class="font-monospace">
|
29
|
+
<span class="text-muted opacity-50">$</span>
|
30
|
+
<%= process.state["proctitle"] %>
|
31
|
+
</code>
|
32
|
+
<div>
|
33
|
+
<span class="text-muted small">PID</span>
|
34
|
+
<span class="badge rounded-pill bg-light text-dark"><%= process.state["pid"] %></span>
|
35
|
+
<span class="text-muted small">@</span>
|
36
|
+
<span class="badge rounded-pill bg-light text-dark"><%= process.state["hostname"] %></span>
|
37
|
+
</div>
|
38
|
+
</div>
|
39
|
+
<div class="col">
|
40
|
+
<% process.state["schedulers"].each do |scheduler| %>
|
41
|
+
<pre class="mb-0"><%= scheduler %></pre>
|
42
|
+
<% end %>
|
43
|
+
</div>
|
44
|
+
<div class="col-2 small"><%= relative_time(process.created_at) %></div>
|
45
|
+
<div class="col-auto">
|
46
|
+
<%= tag.button type: "button", class: "btn btn-sm text-muted ms-auto", role: "button",
|
47
|
+
title: "Inspect",
|
48
|
+
data: { bs_toggle: "collapse", bs_target: "##{dom_id(process, 'state')}" },
|
49
|
+
aria: { expanded: false, controls: dom_id(process, "state") } do %>
|
50
|
+
<%= render_icon "info" %>
|
51
|
+
<span class="visually-hidden">Inspect</span>
|
52
|
+
<% end %>
|
53
|
+
</div>
|
54
|
+
</div>
|
35
55
|
</div>
|
36
|
-
|
37
|
-
|
56
|
+
<%= tag.div id: dom_id(process, "state"), class: "process-state list-group-item collapse small bg-dark text-light" do %>
|
57
|
+
<%= tag.pre JSON.pretty_generate(process.state) %>
|
58
|
+
<% end %>
|
59
|
+
<% end %>
|
60
|
+
<% if @processes.empty? %>
|
61
|
+
<div class="list-group-item py-4 text-center text-muted">
|
62
|
+
No GoodJob processes found.
|
63
|
+
</div>
|
64
|
+
<% end %>
|
65
|
+
</div>
|
38
66
|
</div>
|
@@ -11,7 +11,7 @@
|
|
11
11
|
<li class="nav-item">
|
12
12
|
<%= link_to url_for({state: name}), class: "nav-link #{"active" if params[:state] == name}" do %>
|
13
13
|
<%= t(name, scope: 'good_job.status') %>
|
14
|
-
<span class="badge bg-primary rounded-pill <%= "bg-secondary" if count == 0 %>"><%= count %></span>
|
14
|
+
<span class="badge bg-primary rounded-pill <%= "bg-secondary" if count == 0 %>"><%= number_with_delimiter(count) %></span>
|
15
15
|
<% end %>
|
16
16
|
</li>
|
17
17
|
<% end %>
|
@@ -8,13 +8,25 @@
|
|
8
8
|
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
9
9
|
<ul class="navbar-nav me-auto">
|
10
10
|
<li class="nav-item">
|
11
|
-
<%= link_to
|
11
|
+
<%= link_to jobs_path, class: ["nav-link", ("active" if controller_name == 'jobs')] do %>
|
12
|
+
<%= t(".jobs") %>
|
13
|
+
<% jobs_count = GoodJob::Job.count %>
|
14
|
+
<span class="badge bg-secondary rounded-pill"><%= number_to_human(jobs_count) %></span>
|
15
|
+
<% end %>
|
12
16
|
</li>
|
13
17
|
<li class="nav-item">
|
14
|
-
<%= link_to
|
18
|
+
<%= link_to cron_entries_path, class: ["nav-link", ("active" if controller_name == 'cron_entries')] do %>
|
19
|
+
<%= t(".cron_schedules") %>
|
20
|
+
<% cron_entries_count = GoodJob::CronEntry.all.size %>
|
21
|
+
<span class="badge bg-secondary rounded-pill"><%= cron_entries_count %></span>
|
22
|
+
<% end %>
|
15
23
|
</li>
|
16
24
|
<li class="nav-item">
|
17
|
-
<%= link_to
|
25
|
+
<%= link_to processes_path, class: ["nav-link", ("active" if controller_name == 'processes')] do %>
|
26
|
+
<%= t(".processes") %>
|
27
|
+
<% processes_count = GoodJob::Process.count %>
|
28
|
+
<span class="badge bg-secondary rounded-pill <%= "bg-danger" if processes_count == 0 %>"><%= processes_count %></span>
|
29
|
+
<% end %>
|
18
30
|
</li>
|
19
31
|
</ul>
|
20
32
|
<div class="nav-item pe-2">
|
@@ -0,0 +1,3 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-three-dots" viewBox="0 0 16 16">
|
2
|
+
<path d="M3 9.5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z" />
|
3
|
+
</svg>
|
@@ -0,0 +1,4 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-info-circle" viewBox="0 0 16 16">
|
2
|
+
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z" />
|
3
|
+
<path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533L8.93 6.588zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z" />
|
4
|
+
</svg>
|
data/config/locales/en.yml
CHANGED
@@ -63,3 +63,22 @@ en:
|
|
63
63
|
retried: Retried
|
64
64
|
running: Running
|
65
65
|
scheduled: Scheduled
|
66
|
+
number:
|
67
|
+
format:
|
68
|
+
delimiter: ","
|
69
|
+
separator: "."
|
70
|
+
human:
|
71
|
+
decimal_units:
|
72
|
+
format: "%n%u"
|
73
|
+
units:
|
74
|
+
billion: B
|
75
|
+
hundred: ''
|
76
|
+
million: M
|
77
|
+
quadrillion: Q
|
78
|
+
thousand: K
|
79
|
+
trillion: T
|
80
|
+
unit: ''
|
81
|
+
format:
|
82
|
+
delimiter: ","
|
83
|
+
precision: 3
|
84
|
+
separator: "."
|
data/config/locales/es.yml
CHANGED
@@ -63,3 +63,22 @@ es:
|
|
63
63
|
retried: reintentado
|
64
64
|
running: Corriendo
|
65
65
|
scheduled: Programado
|
66
|
+
number:
|
67
|
+
format:
|
68
|
+
delimiter: " "
|
69
|
+
separator: ","
|
70
|
+
human:
|
71
|
+
decimal_units:
|
72
|
+
format: "%n%u"
|
73
|
+
units:
|
74
|
+
billion: B
|
75
|
+
hundred: ''
|
76
|
+
million: M
|
77
|
+
quadrillion: q
|
78
|
+
thousand: k
|
79
|
+
trillion: T
|
80
|
+
unit: ''
|
81
|
+
format:
|
82
|
+
delimiter: " "
|
83
|
+
precision: 3
|
84
|
+
separator: ","
|
data/config/locales/nl.yml
CHANGED
@@ -63,3 +63,22 @@ nl:
|
|
63
63
|
retried: Opnieuw geprobeerd
|
64
64
|
running: Rennen
|
65
65
|
scheduled: Gepland
|
66
|
+
number:
|
67
|
+
format:
|
68
|
+
delimiter: "."
|
69
|
+
separator: ","
|
70
|
+
human:
|
71
|
+
decimal_units:
|
72
|
+
format: "%n%u"
|
73
|
+
units:
|
74
|
+
billion: B
|
75
|
+
hundred: ''
|
76
|
+
million: M
|
77
|
+
quadrillion: Q
|
78
|
+
thousand: K
|
79
|
+
trillion: T
|
80
|
+
unit: ''
|
81
|
+
format:
|
82
|
+
delimiter: "."
|
83
|
+
precision: 3
|
84
|
+
separator: ","
|
data/config/locales/ru.yml
CHANGED
@@ -87,3 +87,22 @@ ru:
|
|
87
87
|
retried: Повторная попытка
|
88
88
|
running: Бег
|
89
89
|
scheduled: по расписанию
|
90
|
+
number:
|
91
|
+
format:
|
92
|
+
delimiter: " "
|
93
|
+
separator: ","
|
94
|
+
human:
|
95
|
+
decimal_units:
|
96
|
+
format: "%n%u"
|
97
|
+
units:
|
98
|
+
billion: Б
|
99
|
+
hundred: ''
|
100
|
+
million: М
|
101
|
+
quadrillion: Q
|
102
|
+
thousand: К
|
103
|
+
trillion: Т
|
104
|
+
unit: ''
|
105
|
+
format:
|
106
|
+
delimiter: " "
|
107
|
+
precision: 3
|
108
|
+
separator: ","
|