rocketjob_mission_control 5.0.1 → 6.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/app/assets/config/manifest.js +3 -0
  4. data/app/assets/javascripts/rocket_job_mission_control/application.js +1 -1
  5. data/app/assets/javascripts/rocket_job_mission_control/nested_fields.js +112 -0
  6. data/app/assets/stylesheets/rocket_job_mission_control/{application.scss → application.css} +9 -8
  7. data/app/assets/stylesheets/rocket_job_mission_control/base.css +420 -0
  8. data/app/assets/stylesheets/rocket_job_mission_control/{callout.scss → callout.css} +50 -52
  9. data/app/assets/stylesheets/rocket_job_mission_control/jobs.css +57 -0
  10. data/app/assets/stylesheets/rocket_job_mission_control/worker_processes.css +7 -0
  11. data/app/controllers/rocket_job_mission_control/dirmon_entries_controller.rb +20 -20
  12. data/app/controllers/rocket_job_mission_control/jobs_controller.rb +44 -4
  13. data/app/datatables/rocket_job_mission_control/jobs_datatable.rb +1 -1
  14. data/app/helpers/rocket_job_mission_control/application_helper.rb +43 -26
  15. data/app/helpers/rocket_job_mission_control/dirmon_entries_helper.rb +8 -0
  16. data/app/helpers/rocket_job_mission_control/jobs_helper.rb +76 -8
  17. data/app/models/rocket_job_mission_control/dirmon_sanitizer.rb +68 -0
  18. data/app/models/rocket_job_mission_control/job_sanitizer.rb +35 -0
  19. data/app/views/rocket_job_mission_control/dirmon_entries/_form.html.erb +78 -42
  20. data/app/views/rocket_job_mission_control/dirmon_entries/_input_categories.html.erb +59 -0
  21. data/app/views/rocket_job_mission_control/dirmon_entries/_input_category_fields.html.erb +56 -0
  22. data/app/views/rocket_job_mission_control/dirmon_entries/_output_categories.html.erb +44 -0
  23. data/app/views/rocket_job_mission_control/dirmon_entries/_output_category_fields.html.erb +36 -0
  24. data/app/views/rocket_job_mission_control/dirmon_entries/_status.html.erb +22 -16
  25. data/app/views/rocket_job_mission_control/dirmon_entries/copy.html.erb +1 -1
  26. data/app/views/rocket_job_mission_control/dirmon_entries/edit.html.erb +7 -3
  27. data/app/views/rocket_job_mission_control/dirmon_entries/show.html.erb +2 -3
  28. data/app/views/rocket_job_mission_control/jobs/_attributes.html.erb +89 -0
  29. data/app/views/rocket_job_mission_control/jobs/_dates.html.erb +39 -0
  30. data/app/views/rocket_job_mission_control/jobs/_details.html.erb +86 -0
  31. data/app/views/rocket_job_mission_control/jobs/_exception.html.erb +33 -0
  32. data/app/views/rocket_job_mission_control/jobs/_input_categories.html.erb +126 -0
  33. data/app/views/rocket_job_mission_control/jobs/_input_category_fields.html.erb +56 -0
  34. data/app/views/rocket_job_mission_control/jobs/_output_categories.html.erb +60 -0
  35. data/app/views/rocket_job_mission_control/jobs/_output_category_fields.html.erb +36 -0
  36. data/app/views/rocket_job_mission_control/jobs/_retryable.html.erb +27 -0
  37. data/app/views/rocket_job_mission_control/jobs/_status.html.erb +21 -49
  38. data/app/views/rocket_job_mission_control/jobs/edit.html.erb +28 -0
  39. data/app/views/rocket_job_mission_control/jobs/exception.html.erb +1 -1
  40. data/app/views/rocket_job_mission_control/jobs/index.html.erb +24 -18
  41. data/app/views/rocket_job_mission_control/jobs/show.html.erb +32 -58
  42. data/app/views/rocket_job_mission_control/jobs/view_slice.html.erb +4 -4
  43. data/config/initializers/assets.rb +3 -4
  44. data/lib/rocket_job_mission_control/engine.rb +0 -1
  45. data/lib/rocket_job_mission_control/version.rb +1 -1
  46. data/test/controllers/rocket_job_mission_control/jobs_controller_test.rb +2 -1
  47. data/test/models/rocket_job_mission_control/dirmon_sanitizer_test.rb +146 -0
  48. data/test/test_helper.rb +5 -11
  49. data/vendor/assets/fonts/glyphicons-halflings-regular.eot +0 -0
  50. data/vendor/assets/fonts/glyphicons-halflings-regular.svg +288 -0
  51. data/vendor/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
  52. data/vendor/assets/fonts/glyphicons-halflings-regular.woff +0 -0
  53. data/vendor/assets/fonts/glyphicons-halflings-regular.woff2 +0 -0
  54. data/vendor/assets/stylesheets/bootstrap.min.css.erb +6 -0
  55. metadata +37 -29
  56. data/app/assets/stylesheets/rocket_job_mission_control/base.scss +0 -436
  57. data/app/assets/stylesheets/rocket_job_mission_control/bootstrap_and_overrides.scss +0 -488
  58. data/app/assets/stylesheets/rocket_job_mission_control/jobs.scss +0 -72
  59. data/app/assets/stylesheets/rocket_job_mission_control/worker_processes.scss +0 -9
  60. data/vendor/assets/stylesheets/bootstrap.min.css +0 -6
@@ -0,0 +1,126 @@
1
+ <div class='lead'>Input Categories:</div>
2
+ <% @job.input_categories.each do |category| %>
3
+ <div class='row'>
4
+ <div class='col-md-12'>
5
+ <div class='status-message'><label><%= category.name.to_s.camelcase %>:</label></div>
6
+ <div class='row'>
7
+ <div class='col-md-12'>
8
+ <table>
9
+ <% if category.name == :main %>
10
+ <tr>
11
+ <td><label>Record Count:</label></td>
12
+ <td><%= @job.record_count %></td>
13
+ </tr>
14
+ <% if @job.completed? %>
15
+ <tr>
16
+ <td><label>Records Per Hour:</label></td>
17
+ <td><%= job_records_per_hour(@job) %></td>
18
+ </tr>
19
+ <% elsif @job.running? || @job.paused? || @job.failed? %>
20
+ <tr>
21
+ <td><label>Progress:</label></td>
22
+ <td><%= @job.percent_complete %> %</td>
23
+ </tr>
24
+ <% if @job.running? %>
25
+ <tr>
26
+ <td><label>Est. Time Remaining:</label></td>
27
+ <td><%= job_estimated_time_left(@job) %></td>
28
+ </tr>
29
+ <% end %>
30
+ <tr>
31
+ <td><label>Queued Slices:</label></td>
32
+ <td><%= @job.input.queued.count %></td>
33
+ </tr>
34
+ <tr>
35
+ <td><label>Active Slices:</label></td>
36
+ <td><%= @job.input.running.count %></td>
37
+ </tr>
38
+ <tr>
39
+ <td><label>Failed Slices:</label></td>
40
+ <td><%= @job.input.failed.count %></td>
41
+ </tr>
42
+ <% end %>
43
+ <tr>
44
+ <td><label>Slice Size:</label></td>
45
+ <td><%= category.slice_size %></td>
46
+ </tr>
47
+ <% end %>
48
+ <% if category.serializer %>
49
+ <tr>
50
+ <td><label>Serializer:</label></td>
51
+ <td><%= category.serializer %></td>
52
+ </tr>
53
+ <% end %>
54
+ <% if category.file_name %>
55
+ <tr>
56
+ <td><label>File Name:</label></td>
57
+ <td><%= category.file_name %></td>
58
+ </tr>
59
+ <% end %>
60
+ </tr>
61
+ <% if category.format %>
62
+ <tr>
63
+ <td><label>Format:</label></td>
64
+ <td><%= category.format %></td>
65
+ </tr>
66
+ <tr>
67
+ <td><label>Header Cleanser:</label></td>
68
+ <td><%= category.header_cleanser %></td>
69
+ </tr>
70
+ <% if category.allowed_columns %>
71
+ <tr>
72
+ <td><label>Allowed Columns:</label></td>
73
+ <td><%= category.allowed_columns.ai(plain: true) %></td>
74
+ </tr>
75
+ <% end %>
76
+ <% if category.required_columns %>
77
+ <tr>
78
+ <td><label>Required Columns:</label></td>
79
+ <td><%= category.required_columns.ai(plain: true) %></td>
80
+ </tr>
81
+ <% end %>
82
+ <% if category.skip_unknown %>
83
+ <tr>
84
+ <td><label>Skip Unknown Columns:</label></td>
85
+ <td><%= category.skip_unknown %></td>
86
+ </tr>
87
+ <% end %>
88
+ <% if category.mode != :line %>
89
+ <tr>
90
+ <td><label>Mode:</label></td>
91
+ <td><%= category.mode %></td>
92
+ </tr>
93
+ <% end %>
94
+ <% if category.format_options %>
95
+ <tr>
96
+ <td><label>Format Options:</label></td>
97
+ <td>
98
+ <pre><code><%= category.format_options.ai(plain: true, ruby19_syntax: true, sort_keys: true) %></code></pre>
99
+ </td>
100
+ </tr>
101
+ <% end %>
102
+ <% end %>
103
+ <% if category.columns %>
104
+ <% first = true %>
105
+ <% category.columns.each do |item| %>
106
+ <% if first %>
107
+ <tr>
108
+ <td><label>Columns:</label></td>
109
+ <td><%= item %></td>
110
+ </tr>
111
+ <% first = false %>
112
+ <% else %>
113
+ <tr>
114
+ <td></td>
115
+ <td><%= item %></td>
116
+ </tr>
117
+ <% end %>
118
+ <% end %>
119
+ <% end %>
120
+ </table>
121
+ </div>
122
+ </div>
123
+ </div>
124
+ </div>
125
+ <br/>
126
+ <% end %>
@@ -0,0 +1,56 @@
1
+ <% input_category = f.object %>
2
+
3
+ <div class="nested-fields">
4
+ <div class="panel panel-primary">
5
+ <div class="panel-heading">
6
+ <div class="row">
7
+ <div class="col-sm-12">
8
+ <h4><%= input_category.name %></h4>
9
+ </div>
10
+ </div>
11
+ </div>
12
+
13
+ <div class="panel-body">
14
+ <%= f.hidden_field :name, value: input_category.name %>
15
+
16
+ <div class="form-group">
17
+ <%= f.label :columns %>
18
+ <% options = input_category.columns || [] %>
19
+ <%= f.select(:columns, options_for_select(options, options), { include_hidden: false }, { class: "selectize form-control", multiple: true }) %>
20
+ </div>
21
+
22
+ <div class="form-group">
23
+ <%= f.label :format %>
24
+ <% options = extract_inclusion_values(RocketJob::Category::Input, :format) %>
25
+ <% value = input_category.format %>
26
+ <%= f.select(:format, options, { include_blank: true, selected: value }, { class: "selectize form-control" }) %>
27
+ </div>
28
+
29
+ <div class="form-group">
30
+ <%= f.label :format_options %>
31
+ <% value = input_category.format_options %>
32
+ <%= f.text_field(:format_options, value: value ? value.to_json : nil, class: "form-control", placeholder: '{"key1":"value1", "key2":"value2", "key3":"value3"}') %>
33
+ </div>
34
+
35
+ <div class="form-group">
36
+ <%= f.label :mode %>
37
+ <% options = extract_inclusion_values(RocketJob::Category::Input, :mode) %>
38
+ <% value = input_category.mode %>
39
+ <%= f.select(:mode, options, { include_blank: true, selected: value }, { class: "selectize form-control" }) %>
40
+ </div>
41
+
42
+ <div class="form-group">
43
+ <%= f.label "Skip and Ignore Unknown Columns" %>
44
+ <% options = extract_inclusion_values(RocketJob::Category::Input, :skip_unknown) %>
45
+ <% value = input_category.skip_unknown %>
46
+ <%= f.select(:skip_unknown, options, { include_blank: true, selected: value }, { class: "selectize form-control" }) %>
47
+ </div>
48
+
49
+ <div class="form-group">
50
+ <%= f.label :slice_size %>
51
+ <% value = input_category.slice_size %>
52
+ <%= f.number_field(:slice_size, value: value, class: "form-control") %>
53
+ </div>
54
+ </div>
55
+ </div>
56
+ </div>
@@ -0,0 +1,60 @@
1
+ <div class='lead'>Output Categories:</div>
2
+ <% @job.output_categories.each do |category| %>
3
+ <div class='row'>
4
+ <div class='col-md-12'>
5
+ <div class='status-message'><label><%= category.name.to_s.camelcase %>:</label></div>
6
+ <div class='row'>
7
+ <div class='col-md-12'>
8
+ <table>
9
+ <% if category.serializer %>
10
+ <tr>
11
+ <td><label>Serializer:</label></td>
12
+ <td><%= category.serializer %></td>
13
+ </tr>
14
+ <% end %>
15
+ <tr>
16
+ <td><label>Collect nil output:</label></td>
17
+ <td><%= category.nils %></td>
18
+ </tr>
19
+ <% if category.file_name %>
20
+ <tr>
21
+ <td><label>File Name:</label></td>
22
+ <td><%= category.file_name %></td>
23
+ </tr>
24
+ <% end %>
25
+ <% if category.format %>
26
+ <tr>
27
+ <td><label>Format:</label></td>
28
+ <td><%= category.format %></td>
29
+ </tr>
30
+ <% if category.format_options %>
31
+ <tr>
32
+ <td><label>Format Options:</label></td>
33
+ <td><pre><code><%= category.format_options.ai(plain: true, ruby19_syntax: true, sort_keys: true) %></code></pre></td>
34
+ </tr>
35
+ <% end %>
36
+ <% end %>
37
+ <% if category.columns %>
38
+ <% first = true %>
39
+ <% category.columns.each do |item| %>
40
+ <% if first %>
41
+ <tr>
42
+ <td><label>Columns:</label></td>
43
+ <td><%= item %></td>
44
+ </tr>
45
+ <% first = false %>
46
+ <% else %>
47
+ <tr>
48
+ <td></td>
49
+ <td><%= item %></td>
50
+ </tr>
51
+ <% end %>
52
+ <% end %>
53
+ <% end %>
54
+ </table>
55
+ </div>
56
+ </div>
57
+ </div>
58
+ </div>
59
+ <br/>
60
+ <% end %>
@@ -0,0 +1,36 @@
1
+ <% output_category = f.object %>
2
+
3
+ <div class="nested-fields">
4
+ <div class="panel panel-success">
5
+ <div class="panel-heading">
6
+ <div class="row">
7
+ <div class="col-sm-12">
8
+ <h4 class="pull-left"><%= output_category.name %></h4>
9
+ </div>
10
+ </div>
11
+ </div>
12
+
13
+ <div class="panel-body">
14
+ <%= f.hidden_field :name, value: output_category.name %>
15
+
16
+ <div class="form-group">
17
+ <%= f.label :columns %>
18
+ <% options = output_category.columns || [] %>
19
+ <%= f.select(:columns, options_for_select(options, options), { include_hidden: false }, { class: "selectize form-control", multiple: true }) %>
20
+ </div>
21
+
22
+ <div class="form-group">
23
+ <%= f.label :format %>
24
+ <% options = extract_inclusion_values(RocketJob::Category::Output, :format) %>
25
+ <% value = output_category.format %>
26
+ <%= f.select(:format, options, { include_blank: true, selected: value }, { class: "selectize form-control" }) %>
27
+ </div>
28
+
29
+ <div class="form-group">
30
+ <%= f.label :format_options %>
31
+ <% value = output_category.format_options %>
32
+ <%= f.text_field(:format_options, value: value ? value.to_json : nil, class: "form-control", placeholder: '{"key1":"value1", "key2":"value2", "key3":"value3"}') %>
33
+ </div>
34
+ </div>
35
+ </div>
36
+ </div>
@@ -0,0 +1,27 @@
1
+ <div class='lead'>Retryable:</div>
2
+ <div class='row'>
3
+ <div class='col-md-12'>
4
+ <table>
5
+ <% first = true %>
6
+ <% @job.failed_at_list.each do |time| %>
7
+ <% if first %>
8
+ <tr>
9
+ <td><label>Retry Limit</label></td>
10
+ <td><%= @job.retry_limit %></td>
11
+ <td><label>Failures</label></td>
12
+ <td><%= job_time(time) %></td>
13
+ </tr>
14
+ <% first = false %>
15
+ <% else %>
16
+ <tr>
17
+ <td></td>
18
+ <td></td>
19
+ <td></td>
20
+ <td><%= job_time(time) %></td>
21
+ </tr>
22
+ <% end %>
23
+ <% end %>
24
+ </table>
25
+ </div>
26
+ </div>
27
+ <br/>
@@ -1,58 +1,30 @@
1
- <% status = job.status(Time.zone) %>
2
-
3
- <div class='id'>
4
- <label>ID:</label> <%= status.delete('_id') %>
5
- </div>
6
-
7
- <% if description = status.delete('description') %>
8
- <div class='status-message'><label>Description:</label> <%= description %></div>
1
+ <%= render partial: 'details', locals: {job: @job} %>
2
+ <%= render partial: 'dates', locals: {job: @job} %>
3
+ <% if @job.respond_to?(:failed_at_list) && @job.failed_at_list.present? %>
4
+ <%= render partial: 'retryable', locals: {job: @job} %>
9
5
  <% end %>
10
-
11
- <% if duration = status.delete('duration') %>
12
- <div class='status-message'><label>Duration:</label> <%= duration %></div>
13
- <% end %>
14
-
15
- <% if record_count = status.delete('record_count') %>
16
- <div class='status-message'><label>Record Count:</label> <%= record_count %></div>
17
- <% end %>
18
-
19
- <div class='created_at'>
20
- <label>Created At:</label> <%= status.delete('created_at') %>
21
- </div>
22
-
23
- <% if started_at = status.delete('started_at') %>
24
- <div class='status-message'><label>Started At:</label> <%= started_at %></div>
25
- <% end %>
26
-
27
- <% if percent_complete = status.delete('percent_complete') %>
28
- <div class='status-message'><label>% Complete:</label> <%= percent_complete %></div>
29
- <% end %>
30
-
31
- <%
32
- remaining = {}
33
- status.each_pair do |key, value|
34
- next if ((value != false) && value.blank?) || ['state', '_type', 'sub_state'].include?(key)
35
- if value.kind_of?(Hash) || value.kind_of?(Array)
36
- remaining[key] = value
37
- next
38
- end
39
- %>
40
- <div class='status-message'><label><%= key.to_s.titleize %>:</label> <%= value %></div>
41
- <% end %>
42
-
43
- <div class='clearfix'></div>
44
-
45
- <% if job.respond_to?('input') && job.input.failed.count.positive? %>
46
- <% status.delete('exception') %>
6
+ <% if @job.respond_to?(:input) && @job.input.failed.count.positive? %>
47
7
  <div class='status-message'>
48
8
  <label><%= 'Exceptions' %>:</label>
49
9
  <%= render partial: 'exceptions', locals: {job: @job} %>
50
10
  </div>
11
+ <% elsif @job.exception.present? %>
12
+ <%= render partial: 'exception', locals: {job: @job} %>
51
13
  <% end %>
52
-
53
- <% remaining.each_pair do |key, value| %>
14
+ <% if @job.respond_to?(:statistics) && @job.statistics.present? %>
54
15
  <div class='status-message'>
55
- <label><%= key.to_s.titleize %>:</label>
56
- <pre><code><%= pretty_print_array_or_hash(value) %></code></pre>
16
+ <label>Statistics:</label>
17
+ <pre><code><%= @job.statistics.ai(plain: true, ruby19_syntax: true, sort_keys: true) %></code></pre>
57
18
  </div>
19
+ <br/>
20
+ <% end %>
21
+ <% if @job.respond_to?(:input_categories) %>
22
+ <%= render partial: 'input_categories', locals: {job: @job} %>
23
+ <% end %>
24
+ <% if @job.respond_to?(:output_categories) %>
25
+ <%= render partial: 'output_categories', locals: {job: @job} %>
26
+ <% end %>
27
+ <% @attributes = job_custom_fields(@job) %>
28
+ <% if @attributes.present? %>
29
+ <%= render partial: 'attributes', locals: {attributes: @attributes} %>
58
30
  <% end %>
@@ -24,6 +24,34 @@
24
24
  <% end %>
25
25
  </div>
26
26
  </div>
27
+
28
+ <% if @job.class.respond_to?(:defined_input_categories) && @job.class.respond_to?(:defined_output_categories) %>
29
+ <div class="row">
30
+ <div class="col-sm-6">
31
+ <div class="panel panel-primary">
32
+ <div class="panel-body">
33
+ <div class='lead'>Input Categories</div>
34
+
35
+ <%= f.fields_for :input_categories do |i| %>
36
+ <%= render "input_category_fields.html", f: i %>
37
+ <% end %>
38
+ </div>
39
+ </div>
40
+ </div>
41
+
42
+ <div class="col-sm-6">
43
+ <div class="panel panel-success">
44
+ <div class="panel-body">
45
+ <div class='lead'>Output Categories</div>
46
+
47
+ <%= f.fields_for :output_categories do |o| %>
48
+ <%= render "output_category_fields.html", f: o %>
49
+ <% end %>
50
+ </div>
51
+ </div>
52
+ </div>
53
+ </div>
54
+ <% end %>
27
55
  </div>
28
56
  </div>
29
57
 
@@ -11,7 +11,7 @@
11
11
  <div class='clearfix'></div>
12
12
 
13
13
  <div class='message'>
14
- <pre><code><%= @failure_exception.message %></code></pre>
14
+ <pre><code class="language-html"><%= @failure_exception.message %></code></pre>
15
15
  </div>
16
16
 
17
17
  <div class='error'>
@@ -1,28 +1,34 @@
1
1
  <div class='job-list'>
2
2
  <div class='list'>
3
- <div class='row'>
4
- <div class='col-sm-10'>
5
- <h2><%= @description %> Jobs</h2>
6
- </div>
3
+ <div class="panel panel-default">
4
+ <div class="panel-heading">
5
+ <div class='row'>
6
+ <div class='col-sm-10'>
7
+ <h2><%= @description %> Jobs</h2>
8
+ </div>
7
9
 
8
- <div class='col-sm-2'>
9
- <div class='btn btn-default pull-right dt-reload' data-behavior='reload'>
10
- <i class='fas fa-sync'></i>
10
+ <div class='col-sm-2'>
11
+ <div class='btn btn-default pull-right dt-reload' data-behavior='reload'>
12
+ <i class='fas fa-sync'></i>
13
+ </div>
14
+ </div>
11
15
  </div>
12
16
  </div>
13
- </div>
14
17
 
15
- <table class='table datatable jobs-datatable' data-source='<%= @data_table_url %>' style='width: 100%'>
16
- <thead>
17
- <tr>
18
- <% @columns.each do |column| %>
19
- <th><%= column[:display] %></th>
20
- <% end %>
21
- </tr>
22
- </thead>
18
+ <div class="panel-body">
19
+ <table class='table datatable jobs-datatable' data-source='<%= @data_table_url %>' style='width: 100%'>
20
+ <thead>
21
+ <tr>
22
+ <% @columns.each do |column| %>
23
+ <th><%= column[:display] %></th>
24
+ <% end %>
25
+ </tr>
26
+ </thead>
23
27
 
24
- <tbody></tbody>
25
- </table>
28
+ <tbody></tbody>
29
+ </table>
30
+ </div>
31
+ </div>
26
32
  </div>
27
33
  </div>
28
34