rocketjob_mission_control 4.3.0 → 5.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +12 -12
- data/app/controllers/rocket_job_mission_control/application_controller.rb +1 -2
- data/app/controllers/rocket_job_mission_control/dirmon_entries_controller.rb +20 -19
- data/app/controllers/rocket_job_mission_control/jobs_controller.rb +36 -35
- data/app/controllers/rocket_job_mission_control/servers_controller.rb +32 -38
- data/app/datatables/rocket_job_mission_control/abstract_datatable.rb +8 -6
- data/app/datatables/rocket_job_mission_control/active_workers_datatable.rb +5 -5
- data/app/datatables/rocket_job_mission_control/dirmon_entries_datatable.rb +4 -4
- data/app/datatables/rocket_job_mission_control/jobs_datatable.rb +55 -62
- data/app/datatables/rocket_job_mission_control/servers_datatable.rb +13 -14
- data/app/helpers/rocket_job_mission_control/application_helper.rb +42 -41
- data/app/helpers/rocket_job_mission_control/jobs_helper.rb +9 -10
- data/app/helpers/rocket_job_mission_control/pagination_helper.rb +1 -1
- data/app/helpers/rocket_job_mission_control/servers_helper.rb +6 -6
- data/app/helpers/rocket_job_mission_control/slices_helper.rb +2 -4
- data/app/models/rocket_job_mission_control/access_policy.rb +1 -2
- data/app/models/rocket_job_mission_control/authorization.rb +3 -2
- data/app/models/rocket_job_mission_control/job_sanitizer.rb +14 -17
- data/app/models/rocket_job_mission_control/query.rb +2 -5
- data/app/views/rocket_job_mission_control/jobs/_exceptions.html.erb +1 -1
- data/app/views/rocket_job_mission_control/jobs/edit_slice.html.erb +1 -1
- data/app/views/rocket_job_mission_control/servers/index.html.erb +2 -2
- data/config/initializers/assets.rb +5 -7
- data/config/locales/en.yml +3 -0
- data/config/routes.rb +20 -21
- data/lib/rocket_job_mission_control/engine.rb +8 -9
- data/lib/rocket_job_mission_control/version.rb +1 -1
- data/lib/rocketjob_mission_control.rb +1 -1
- data/test/compare_hashes.rb +1 -2
- data/test/controllers/rocket_job_mission_control/application_controller_test.rb +13 -13
- data/test/controllers/rocket_job_mission_control/dirmon_entries_controller_test.rb +107 -108
- data/test/controllers/rocket_job_mission_control/jobs_controller_test.rb +89 -93
- data/test/controllers/rocket_job_mission_control/servers_controller_test.rb +66 -103
- data/test/helpers/rocket_job_mission_control/application_helper_test.rb +13 -14
- data/test/helpers/rocket_job_mission_control/jobs_helper_test.rb +31 -31
- data/test/helpers/rocket_job_mission_control/pagination_helper_test.rb +7 -9
- data/test/helpers/rocket_job_mission_control/servers_helper_test.rb +15 -15
- data/test/helpers/rocket_job_mission_control/slices_helper_test.rb +8 -10
- data/test/models/rocket_job_mission_control/job_sanitizer_test.rb +39 -40
- data/test/models/rocket_job_mission_control/query_test.rb +26 -28
- data/test/test_helper.rb +12 -12
- metadata +28 -28
@@ -1,7 +1,7 @@
|
|
1
1
|
module RocketJobMissionControl
|
2
2
|
class AbstractDatatable
|
3
3
|
delegate :params, :link_to, :render, to: :@view
|
4
|
-
delegate :h, to:
|
4
|
+
delegate :h, to: "ERB::Util"
|
5
5
|
|
6
6
|
attr_accessor :view, :query
|
7
7
|
|
@@ -11,7 +11,7 @@ module RocketJobMissionControl
|
|
11
11
|
extract_query_params
|
12
12
|
end
|
13
13
|
|
14
|
-
def as_json(
|
14
|
+
def as_json(_options = {})
|
15
15
|
{
|
16
16
|
draw: params[:draw].to_i,
|
17
17
|
recordsTotal: query.unfiltered_count,
|
@@ -39,7 +39,7 @@ module RocketJobMissionControl
|
|
39
39
|
end
|
40
40
|
|
41
41
|
# Pagination
|
42
|
-
unless params[:length].present? && params[:length] ==
|
42
|
+
unless params[:length].present? && params[:length] == "-1"
|
43
43
|
query.start = params[:start].to_i
|
44
44
|
query.page_size = params.fetch(:length, 10).to_i
|
45
45
|
end
|
@@ -49,13 +49,15 @@ module RocketJobMissionControl
|
|
49
49
|
return nil unless order.present?
|
50
50
|
|
51
51
|
sort_by = {}
|
52
|
-
order.each_pair do |
|
52
|
+
order.each_pair do |_key, value|
|
53
53
|
name = query.display_columns[value[:column].to_i]
|
54
|
-
|
54
|
+
unless name.present?
|
55
|
+
raise(ArgumentError, "Invalid column id: #{value[:column]}. Must fit #{query.display_columns.inspect}")
|
56
|
+
end
|
57
|
+
|
55
58
|
sort_by[name] = value[:dir]
|
56
59
|
end
|
57
60
|
sort_by
|
58
61
|
end
|
59
|
-
|
60
62
|
end
|
61
63
|
end
|
@@ -10,11 +10,11 @@ module RocketJobMissionControl
|
|
10
10
|
|
11
11
|
def map(active_worker)
|
12
12
|
{
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
"0" => worker_name_with_icon(active_worker, active_worker.job),
|
14
|
+
"1" => job_name_with_link(active_worker.job.class.name, active_worker.job.id),
|
15
|
+
"2" => h(active_worker.job.description.try!(:truncate, 50)),
|
16
|
+
"3" => h("#{active_worker.duration} ago"),
|
17
|
+
"DT_RowClass" => "card callout callout-running"
|
18
18
|
}
|
19
19
|
end
|
20
20
|
|
@@ -6,10 +6,10 @@ module RocketJobMissionControl
|
|
6
6
|
|
7
7
|
def map(dirmon)
|
8
8
|
{
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
"0" => name_with_link(dirmon),
|
10
|
+
"1" => h(dirmon.job_class_name),
|
11
|
+
"2" => h(dirmon.pattern.try(:truncate, 80)),
|
12
|
+
"DT_RowClass" => "card callout callout-#{dirmon.state}"
|
13
13
|
}
|
14
14
|
end
|
15
15
|
|
@@ -4,68 +4,68 @@ module RocketJobMissionControl
|
|
4
4
|
:abort_job_path, :job_path, :fail_job_path, :run_now_job_path, :pause_job_path,
|
5
5
|
:resume_job_path, :retry_job_path, :exception_job_path, :job_action_link, :exceptions_job_path, to: :@view
|
6
6
|
|
7
|
-
COMMON_FIELDS = [
|
7
|
+
COMMON_FIELDS = %i[id _type description completed_at created_at started_at state worker_name login].freeze
|
8
8
|
|
9
9
|
ABORTED_COLUMNS = [
|
10
|
-
{display:
|
11
|
-
{display:
|
12
|
-
{display:
|
13
|
-
{display:
|
14
|
-
]
|
10
|
+
{display: "Class", value: :class_with_link, field: "_type", width: "30%"},
|
11
|
+
{display: "Description", value: :description, field: "description", width: "30%"},
|
12
|
+
{display: "Aborted", value: :completed_ago, field: "completed_at"},
|
13
|
+
{display: "Actions", value: :action_buttons, orderable: false}
|
14
|
+
].freeze
|
15
15
|
|
16
16
|
COMPLETED_COLUMNS = [
|
17
|
-
{display:
|
18
|
-
{display:
|
19
|
-
{display:
|
20
|
-
{display:
|
21
|
-
{display:
|
22
|
-
]
|
17
|
+
{display: "Class", value: :class_with_link, field: "_type", width: "30%"},
|
18
|
+
{display: "Description", value: :description, field: "description", width: "30%"},
|
19
|
+
{display: "Duration", value: :duration, field: "duration", orderable: false},
|
20
|
+
{display: "Completed", value: :completed_ago, field: "completed_at"},
|
21
|
+
{display: "Actions", value: :action_buttons, orderable: false}
|
22
|
+
].freeze
|
23
23
|
|
24
24
|
FAILED_COLUMNS = ABORTED_COLUMNS.deep_dup
|
25
|
-
FAILED_COLUMNS[2][:display] =
|
25
|
+
FAILED_COLUMNS[2][:display] = "Failed"
|
26
26
|
|
27
27
|
PAUSED_COLUMNS = ABORTED_COLUMNS.deep_dup
|
28
|
-
PAUSED_COLUMNS[2][:display] =
|
28
|
+
PAUSED_COLUMNS[2][:display] = "Paused"
|
29
29
|
|
30
30
|
QUEUED_COLUMNS = [
|
31
|
-
{display:
|
32
|
-
{display:
|
33
|
-
{display:
|
34
|
-
{display:
|
35
|
-
{display:
|
36
|
-
{display:
|
37
|
-
]
|
38
|
-
QUEUED_FIELDS
|
31
|
+
{display: "Class", value: :class_with_link, field: "_type"},
|
32
|
+
{display: "Description", value: :description, field: "description"},
|
33
|
+
{display: "Record Count", value: :record_count, field: "record_count"},
|
34
|
+
{display: "Priority", value: :priority, field: "priority"},
|
35
|
+
{display: "Queued For", value: :duration, field: "duration", orderable: false},
|
36
|
+
{display: "Actions", value: :action_buttons, orderable: false}
|
37
|
+
].freeze
|
38
|
+
QUEUED_FIELDS = (COMMON_FIELDS + %i[record_count run_at priority]).freeze
|
39
39
|
|
40
40
|
RUNNING_COLUMNS = [
|
41
|
-
{display:
|
42
|
-
{display:
|
43
|
-
{display:
|
44
|
-
{display:
|
45
|
-
{display:
|
46
|
-
{display:
|
47
|
-
{display:
|
48
|
-
{display:
|
49
|
-
]
|
50
|
-
RUNNING_FIELDS
|
41
|
+
{display: "Class", value: :class_with_link, field: "_type"},
|
42
|
+
{display: "Description", value: :description, field: "description"},
|
43
|
+
{display: "Record Count", value: :record_count, field: "record_count"},
|
44
|
+
{display: "Progress", value: :progress, field: "percent_complete", orderable: false},
|
45
|
+
{display: "Workers", value: :worker_count, field: "worker_count", orderable: false},
|
46
|
+
{display: "Priority", value: :priority, field: "priority"},
|
47
|
+
{display: "Started", value: :started, field: "started_at"},
|
48
|
+
{display: "Actions", value: :action_buttons, orderable: false}
|
49
|
+
].freeze
|
50
|
+
RUNNING_FIELDS = (COMMON_FIELDS + %i[record_count collect_output input_categories output_categories encrypt compress slice_size priority sub_state percent_complete]).freeze
|
51
51
|
|
52
52
|
SCHEDULED_COLUMNS = [
|
53
|
-
{display:
|
54
|
-
{display:
|
55
|
-
{display:
|
56
|
-
{display:
|
57
|
-
{display:
|
58
|
-
]
|
59
|
-
SCHEDULED_FIELDS
|
53
|
+
{display: "Class", value: :class_with_link, field: "_type"},
|
54
|
+
{display: "Description", value: :description, field: "description"},
|
55
|
+
{display: "Runs in", value: :time_till_run, field: "run_at"},
|
56
|
+
{display: "Cron Schedule", value: :cron_schedule, field: "cron_schedule"},
|
57
|
+
{display: "Actions", value: :action_buttons, orderable: false}
|
58
|
+
].freeze
|
59
|
+
SCHEDULED_FIELDS = (COMMON_FIELDS + %i[run_at cron_schedule]).freeze
|
60
60
|
|
61
61
|
ALL_COLUMNS = [
|
62
|
-
{display:
|
63
|
-
{display:
|
64
|
-
{display:
|
65
|
-
{display:
|
66
|
-
{display:
|
67
|
-
]
|
68
|
-
ALL_FIELDS
|
62
|
+
{display: "Class", value: :class_with_link, field: "_type"},
|
63
|
+
{display: "Description", value: :description, field: "description"},
|
64
|
+
{display: "Created", value: :created_at, field: "created_at"},
|
65
|
+
{display: "Duration", value: :duration, field: "duration", orderable: false},
|
66
|
+
{display: "Actions", value: :action_buttons, orderable: false}
|
67
|
+
].freeze
|
68
|
+
ALL_FIELDS = (QUEUED_FIELDS + RUNNING_FIELDS + SCHEDULED_FIELDS).uniq.freeze
|
69
69
|
|
70
70
|
def initialize(view, query, columns)
|
71
71
|
@columns = columns
|
@@ -84,9 +84,9 @@ module RocketJobMissionControl
|
|
84
84
|
h = {}
|
85
85
|
@columns.each do |column|
|
86
86
|
h[index.to_s] = send(column[:value], job)
|
87
|
-
index
|
87
|
+
index += 1
|
88
88
|
end
|
89
|
-
h[
|
89
|
+
h["DT_RowClass"] = "card callout callout-#{job_state(job)}"
|
90
90
|
h
|
91
91
|
end
|
92
92
|
|
@@ -121,7 +121,7 @@ module RocketJobMissionControl
|
|
121
121
|
end
|
122
122
|
|
123
123
|
def record_count(job)
|
124
|
-
job.attributes.key?(
|
124
|
+
job.attributes.key?("record_count") ? h(job.record_count) : 0
|
125
125
|
end
|
126
126
|
|
127
127
|
def started(job)
|
@@ -141,7 +141,7 @@ module RocketJobMissionControl
|
|
141
141
|
end
|
142
142
|
|
143
143
|
def progress(job)
|
144
|
-
if (sub_state = job.attributes[
|
144
|
+
if (sub_state = job.attributes["sub_state"]) && %i[before after].include?(sub_state)
|
145
145
|
<<-EOS
|
146
146
|
<div class="job-status">
|
147
147
|
<div class="job-state">
|
@@ -162,27 +162,20 @@ module RocketJobMissionControl
|
|
162
162
|
def action_buttons(job)
|
163
163
|
events = valid_events(job)
|
164
164
|
buttons = "<div class='inline-job-actions'>"
|
165
|
-
if job.scheduled? && view.can?(:run_now, job)
|
166
|
-
buttons += "#{ job_action_link('Run', run_now_job_path(job), :patch) }"
|
167
|
-
end
|
165
|
+
buttons += job_action_link("Run", run_now_job_path(job), :patch).to_s if job.scheduled? && view.can?(:run_now, job)
|
168
166
|
if events.include?(:pause) && job.pausable? && view.can?(:pause, job)
|
169
|
-
buttons +=
|
167
|
+
buttons += job_action_link("Pause", pause_job_path(job), :patch).to_s
|
170
168
|
end
|
171
169
|
if events.include?(:resume) && view.can?(:resume, job)
|
172
|
-
buttons +=
|
173
|
-
end
|
174
|
-
if events.include?(:retry) && view.can?(:retry, job)
|
175
|
-
buttons += "#{ job_action_link('Retry', retry_job_path(job), :patch) }"
|
176
|
-
end
|
177
|
-
if view.can?(:destroy, job)
|
178
|
-
buttons += "#{ job_action_link('Destroy', job_path(job), :delete) }"
|
170
|
+
buttons += job_action_link("Resume", resume_job_path(job), :patch).to_s
|
179
171
|
end
|
172
|
+
buttons += job_action_link("Retry", retry_job_path(job), :patch).to_s if events.include?(:retry) && view.can?(:retry, job)
|
173
|
+
buttons += job_action_link("Destroy", job_path(job), :delete).to_s if view.can?(:destroy, job)
|
180
174
|
buttons += "</div>"
|
181
175
|
end
|
182
176
|
|
183
177
|
def valid_events(job)
|
184
178
|
job.aasm.events.collect(&:name)
|
185
179
|
end
|
186
|
-
|
187
180
|
end
|
188
181
|
end
|
@@ -12,12 +12,12 @@ module RocketJobMissionControl
|
|
12
12
|
|
13
13
|
def map(server)
|
14
14
|
{
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
15
|
+
"0" => name_with_icon(server),
|
16
|
+
"1" => h(threads(server)),
|
17
|
+
"2" => h(started_ago(server)),
|
18
|
+
"3" => h(time_since_heartbeat(server)),
|
19
|
+
"4" => action_links_html(server),
|
20
|
+
"DT_RowClass" => "card callout #{server_card_class(server)}"
|
21
21
|
}
|
22
22
|
end
|
23
23
|
|
@@ -45,33 +45,32 @@ module RocketJobMissionControl
|
|
45
45
|
events = valid_events(server)
|
46
46
|
|
47
47
|
if events.include?(:resume) && view.can?(:resume, server)
|
48
|
-
actions +=
|
48
|
+
actions += (link_to "resume", resume_server_path(server), method: :patch, class: "btn btn-default", data: {confirm: "Resume this server?"}).to_s
|
49
49
|
end
|
50
50
|
|
51
51
|
if events.include?(:pause) && view.can?(:pause, server)
|
52
|
-
actions +=
|
52
|
+
actions += (link_to "pause", pause_server_path(server), method: :patch, class: "btn btn-default", data: {confirm: "Pause this server?"}).to_s
|
53
53
|
end
|
54
54
|
|
55
55
|
if events.include?(:stop) && view.can?(:stop, server)
|
56
|
-
actions +=
|
56
|
+
actions += (link_to "stop", stop_server_path(server), method: :patch, class: "btn btn-danger", data: {confirm: "Stop this server?"}).to_s
|
57
57
|
end
|
58
58
|
|
59
59
|
if server.stopping? && view.can?(:destroy, server)
|
60
|
-
actions
|
61
|
-
confirmation =
|
60
|
+
actions += "Server is stopping..."
|
61
|
+
confirmation = ""
|
62
62
|
unless server.zombie?
|
63
63
|
confirmation << "Warning!\n\nDestroying this server will hard kill its active workers/jobs.\nKilled jobs will be requeued for processing on another worker.\n\n"
|
64
64
|
end
|
65
65
|
confirmation << "Are you sure you want to destroy #{server.name} ?"
|
66
|
-
actions +=
|
66
|
+
actions += (link_to "destroy", server_path(server), method: :delete, class: "btn btn-danger", data: {confirm: confirmation}).to_s
|
67
67
|
end
|
68
68
|
|
69
|
-
actions +=
|
69
|
+
actions += "</div>"
|
70
70
|
end
|
71
71
|
|
72
72
|
def valid_events(server)
|
73
73
|
server.aasm.events.collect(&:name)
|
74
74
|
end
|
75
|
-
|
76
75
|
end
|
77
76
|
end
|
@@ -1,42 +1,43 @@
|
|
1
1
|
module RocketJobMissionControl
|
2
2
|
module ApplicationHelper
|
3
3
|
STATE_ICON_MAP = {
|
4
|
-
aborted:
|
5
|
-
completed:
|
6
|
-
disabled:
|
7
|
-
enabled:
|
8
|
-
failed:
|
9
|
-
paused:
|
10
|
-
pending:
|
11
|
-
queued:
|
12
|
-
running:
|
13
|
-
sleeping:
|
14
|
-
scheduled:
|
15
|
-
starting:
|
16
|
-
stopping:
|
17
|
-
zombie:
|
18
|
-
}
|
4
|
+
aborted: "fas fa-stop",
|
5
|
+
completed: "fas fa-check",
|
6
|
+
disabled: "fas fa-stop",
|
7
|
+
enabled: "fas fa-check",
|
8
|
+
failed: "fas fa-exclamation-triangle",
|
9
|
+
paused: "fas fa-pause",
|
10
|
+
pending: "fas fa-inbox",
|
11
|
+
queued: "fas fa-inbox",
|
12
|
+
running: "fas fa-play",
|
13
|
+
sleeping: "fas fa-hourglass",
|
14
|
+
scheduled: "fas fa-clock",
|
15
|
+
starting: "fas fa-cogs",
|
16
|
+
stopping: "fas fa-stop",
|
17
|
+
zombie: "fas fa-hourglass"
|
18
|
+
}.freeze
|
19
19
|
|
20
20
|
def state_icon(state)
|
21
|
-
STATE_ICON_MAP[state.to_sym] +
|
21
|
+
STATE_ICON_MAP[state.to_sym] + " " + state.to_s
|
22
22
|
end
|
23
23
|
|
24
24
|
def site_title
|
25
|
-
|
25
|
+
"Rocket Job Mission Control"
|
26
26
|
end
|
27
27
|
|
28
28
|
def title
|
29
29
|
@page_title ||= params[:controller].to_s.titleize
|
30
|
-
h(@full_title || [@page_title, site_title].compact.join(
|
30
|
+
h(@full_title || [@page_title, site_title].compact.join(" | "))
|
31
31
|
end
|
32
32
|
|
33
33
|
def active_page(path)
|
34
|
-
|
34
|
+
"active" if current_page?(path)
|
35
35
|
end
|
36
36
|
|
37
37
|
def pretty_print_array_or_hash(arguments)
|
38
|
-
return arguments unless arguments.
|
39
|
-
|
38
|
+
return arguments unless arguments.is_a?(Array) || arguments.is_a?(Hash)
|
39
|
+
|
40
|
+
json_string_options = {space: " ", indent: " ", array_nl: "<br />", object_nl: "<br />"}
|
40
41
|
JSON.generate(arguments, json_string_options).html_safe
|
41
42
|
end
|
42
43
|
|
@@ -60,49 +61,49 @@ module RocketJobMissionControl
|
|
60
61
|
# When editing a job the values are of the correct type.
|
61
62
|
# When editing a dirmon entry values are strings.
|
62
63
|
field = klass.fields[field_name.to_s]
|
63
|
-
return unless field
|
64
|
+
return unless field&.type
|
64
65
|
|
65
66
|
placeholder = field.default_val
|
66
67
|
placeholder = nil if placeholder.is_a?(Proc)
|
67
68
|
|
68
69
|
case field.type.name
|
69
|
-
when
|
70
|
+
when "Symbol", "String", "Integer"
|
70
71
|
options = extract_inclusion_values(klass, field_name)
|
71
72
|
str = "[#{field.type.name}]\n".html_safe
|
72
73
|
if options
|
73
|
-
str + f.select(field_name, options, {
|
74
|
+
str + f.select(field_name, options, {include_blank: options.include?(nil) || include_nil_selectors, selected: value}, {class: "selectize form-control"})
|
74
75
|
else
|
75
|
-
if field.type.name ==
|
76
|
-
str + f.number_field(field_name, value: value, class:
|
76
|
+
if field.type.name == "Integer"
|
77
|
+
str + f.number_field(field_name, value: value, class: "form-control", placeholder: placeholder)
|
77
78
|
else
|
78
|
-
str + f.text_field(field_name, value: value, class:
|
79
|
+
str + f.text_field(field_name, value: value, class: "form-control", placeholder: placeholder)
|
79
80
|
end
|
80
81
|
end
|
81
|
-
when
|
82
|
+
when "Hash"
|
82
83
|
"[JSON Hash]\n".html_safe +
|
83
|
-
f.text_field(field_name, value: value ? value.to_json :
|
84
|
-
when
|
84
|
+
f.text_field(field_name, value: value ? value.to_json : "", class: "form-control", placeholder: '{"key1":"value1", "key2":"value2", "key3":"value3"}')
|
85
|
+
when "Array"
|
85
86
|
options = Array(value)
|
86
87
|
"[Array]\n".html_safe +
|
87
|
-
f.select(field_name, options_for_select(options, options), {
|
88
|
-
when
|
88
|
+
f.select(field_name, options_for_select(options, options), {include_hidden: false}, {class: "selectize form-control", multiple: true})
|
89
|
+
when "Mongoid::Boolean"
|
89
90
|
name = "#{field_name}_true".to_sym
|
90
91
|
value = value.to_s
|
91
|
-
str
|
92
|
-
str << f.radio_button(field_name,
|
93
|
-
str <<
|
94
|
-
str <<
|
95
|
-
str <<
|
92
|
+
str = '<div class="radio-buttons">'.html_safe
|
93
|
+
str << f.radio_button(field_name, "true", checked: value == "true")
|
94
|
+
str << " ".html_safe + f.label(name, "true")
|
95
|
+
str << " ".html_safe + f.radio_button(field_name, "false", checked: value == "false")
|
96
|
+
str << " ".html_safe + f.label(name, "false")
|
96
97
|
# Allow this field to be unset (nil).
|
97
98
|
if include_nil_selectors
|
98
|
-
str <<
|
99
|
-
str <<
|
99
|
+
str << " ".html_safe + f.radio_button(field_name, "", checked: value == "")
|
100
|
+
str << " ".html_safe + f.label(name, "nil")
|
100
101
|
end
|
101
102
|
|
102
|
-
str <<
|
103
|
+
str << "</div>".html_safe
|
103
104
|
else
|
104
105
|
"[#{field.type.name}]".html_safe +
|
105
|
-
f.text_field(field_name, value: value, class:
|
106
|
+
f.text_field(field_name, value: value, class: "form-control", placeholder: placeholder)
|
106
107
|
end
|
107
108
|
end
|
108
109
|
end
|
@@ -20,7 +20,7 @@ module RocketJobMissionControl
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def job_states_with_scheduled
|
23
|
-
@job_states_with_scheduled ||= [
|
23
|
+
@job_states_with_scheduled ||= ["scheduled"] + job_states
|
24
24
|
end
|
25
25
|
|
26
26
|
def job_counts_by_state(state)
|
@@ -32,35 +32,34 @@ module RocketJobMissionControl
|
|
32
32
|
@job_counts.fetch(state.downcase.to_sym, 0)
|
33
33
|
end
|
34
34
|
|
35
|
-
def job_action_link(action, path, http_method
|
35
|
+
def job_action_link(action, path, http_method = :get)
|
36
36
|
link_to(
|
37
37
|
action,
|
38
38
|
path,
|
39
39
|
method: http_method,
|
40
40
|
title: "#{action} job",
|
41
|
-
class:
|
42
|
-
data: {confirm: t(:confirm, scope: [
|
41
|
+
class: "btn btn-default",
|
42
|
+
data: {confirm: t(:confirm, scope: %i[job action], action: action)}
|
43
43
|
)
|
44
44
|
end
|
45
45
|
|
46
|
-
def job_action_links_for_show(action, path, http_method
|
46
|
+
def job_action_links_for_show(action, path, http_method = :get)
|
47
47
|
link_to(
|
48
48
|
action,
|
49
49
|
path,
|
50
50
|
method: http_method,
|
51
51
|
title: "#{action} job",
|
52
|
-
class:
|
53
|
-
data: {confirm: t(:confirm, scope: [
|
52
|
+
class: "btn btn-primary",
|
53
|
+
data: {confirm: t(:confirm, scope: %i[job action], action: action)}
|
54
54
|
)
|
55
55
|
end
|
56
56
|
|
57
57
|
def job_selected_class(job, selected_job)
|
58
58
|
if selected_job.present? && job.id == selected_job.id
|
59
|
-
|
59
|
+
"selected"
|
60
60
|
else
|
61
|
-
|
61
|
+
""
|
62
62
|
end
|
63
63
|
end
|
64
|
-
|
65
64
|
end
|
66
65
|
end
|