rocketjob_mission_control 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/rocket_job_mission_control/dirmon_entries.js.coffee +18 -0
  3. data/app/assets/stylesheets/rocket_job_mission_control/base.scss +33 -59
  4. data/app/assets/stylesheets/rocket_job_mission_control/bootstrap_and_overrides.scss +12 -0
  5. data/app/assets/stylesheets/rocket_job_mission_control/callout.scss +8 -0
  6. data/app/assets/stylesheets/rocket_job_mission_control/jobs.scss +35 -0
  7. data/app/controllers/rocket_job_mission_control/application_controller.rb +0 -2
  8. data/app/controllers/rocket_job_mission_control/dirmon_entries_controller.rb +125 -0
  9. data/app/controllers/rocket_job_mission_control/jobs/failures_controller.rb +31 -0
  10. data/app/helpers/rocket_job_mission_control/application_helper.rb +7 -0
  11. data/app/helpers/rocket_job_mission_control/jobs_helper.rb +18 -11
  12. data/app/helpers/rocket_job_mission_control/pagination_helper.rb +7 -0
  13. data/app/helpers/rocket_job_mission_control/slices_helper.rb +9 -0
  14. data/app/models/job_failures.rb +30 -0
  15. data/app/views/layouts/rocket_job_mission_control/application.html.haml +3 -1
  16. data/app/views/layouts/rocket_job_mission_control/partials/_header.html.haml +2 -2
  17. data/app/views/layouts/rocket_job_mission_control/partials/_sidebar.html.haml +4 -0
  18. data/app/views/rocket_job_mission_control/dirmon_entries/_form.html.haml +36 -0
  19. data/app/views/rocket_job_mission_control/dirmon_entries/_list.html.haml +31 -0
  20. data/app/views/rocket_job_mission_control/dirmon_entries/_properties.html.haml +8 -0
  21. data/app/views/rocket_job_mission_control/dirmon_entries/_status.html.haml +23 -0
  22. data/app/views/rocket_job_mission_control/dirmon_entries/edit.html.haml +8 -0
  23. data/app/views/rocket_job_mission_control/dirmon_entries/index.html.haml +11 -0
  24. data/app/views/rocket_job_mission_control/dirmon_entries/new.html.haml +9 -0
  25. data/app/views/rocket_job_mission_control/dirmon_entries/show.html.haml +26 -0
  26. data/app/views/rocket_job_mission_control/jobs/_list.html.haml +34 -30
  27. data/app/views/rocket_job_mission_control/jobs/failures/_pagination.html.haml +16 -0
  28. data/app/views/rocket_job_mission_control/jobs/failures/index.html.haml +32 -0
  29. data/app/views/rocket_job_mission_control/jobs/index.html.haml +10 -8
  30. data/app/views/rocket_job_mission_control/jobs/running.html.haml +1 -1
  31. data/app/views/rocket_job_mission_control/jobs/show.html.haml +39 -35
  32. data/app/views/rocket_job_mission_control/workers/_actions.html.haml +4 -4
  33. data/app/views/rocket_job_mission_control/workers/index.html.haml +50 -45
  34. data/config/locales/en.yml +23 -1
  35. data/config/routes.rb +8 -0
  36. data/lib/rocket_job_mission_control/version.rb +1 -1
  37. data/spec/controllers/dirmon_entries_controller_spec.rb +451 -0
  38. data/spec/controllers/jobs/failures_controller_spec.rb +60 -0
  39. data/spec/dummy/config/environments/test.rb +1 -1
  40. data/spec/dummy/config/mongo.yml +15 -0
  41. data/spec/dummy/log/development.log +2 -0
  42. data/spec/dummy/log/test.log +52763 -2015
  43. data/spec/helpers/jobs_helper_spec.rb +27 -0
  44. data/spec/helpers/pagination_helper_spec.rb +21 -0
  45. data/spec/helpers/slices_helper_spec.rb +33 -0
  46. data/spec/models/job_failures_spec.rb +14 -0
  47. data/spec/views/workers/index.html.haml_spec.rb +23 -0
  48. metadata +35 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7e41c195c2f19cc796166af9416626e889f659ae
4
- data.tar.gz: de8a20f45aec4ca0fd5d6de4a6e2a6ac8fd923c2
3
+ metadata.gz: c8d7c96f03155c733cf07a5e81796020552dd378
4
+ data.tar.gz: cf0647850f7b019530b1f1c6d4a511dbcb5fcc5b
5
5
  SHA512:
6
- metadata.gz: 286dfb374edb8f8ff0da5cc215aedb9197369e9ad825289e6588cac983be1faaccf5b049f435909f5c35c5bc1a27251955af99a6897e41eb06f1ad588fe2f5eb
7
- data.tar.gz: daf53bdc5365b5ba592eba9fdbf8f32bc03aa50d92a1c26b49131f6a44fdc2ac02fdb3a468545be334e718ca96791a86ae1f44be6f3caf0f525506c6e09c33f6
6
+ metadata.gz: 4639ef836e562dc597c5e0651571111ac84b3a217b3599da8f06807513375c73b44eb9a091517da37c57f6fa9d478fa2f23f75825ef6c8afad0e899f4892d67b
7
+ data.tar.gz: fe70a9fd5c6cbd029443dda89be419f9c08b6de28fe3a90f2908bccd753f3d4c5837fb239e9d970170e3849c7086e33d9ee5b38518298676b0844308298b9303
@@ -0,0 +1,18 @@
1
+ $(document).on 'ready', ->
2
+ $('.filter .state-toggle').on 'change', ->
3
+ active_states = $('.filter :checked')
4
+ param_string = "?"
5
+ active_states.each (_, state) ->
6
+ param_string += "states[]=" + $(state).attr('id') + "&"
7
+ window.location.href = window.location.href.replace( /[\?#].*|$/, param_string );
8
+
9
+ if $('#properties').length
10
+ $('#expand').on 'click', ->
11
+ $(this).hide()
12
+ $('#collapse').show()
13
+ $('#properties').show()
14
+ $('#collapse').on 'click', ->
15
+ $(this).hide()
16
+ $('#expand').show()
17
+ $('#properties').hide()
18
+
@@ -3,6 +3,13 @@
3
3
  overflow: hidden;
4
4
  }
5
5
 
6
+ .footer {
7
+ position: relative;
8
+ height: 100px;
9
+ clear:both;
10
+ padding-top:20px;
11
+ }
12
+
6
13
  body.rocket_job {
7
14
  padding: 0;
8
15
 
@@ -10,8 +17,8 @@ body.rocket_job {
10
17
 
11
18
  .job-list {
12
19
  height: 100%;
20
+ min-height: 768px;
13
21
  border-right: 1px solid #ddd;
14
- padding: 0;
15
22
  }
16
23
 
17
24
  .job-status {
@@ -41,7 +48,7 @@ body.rocket_job {
41
48
  p { font-size: 16px; }
42
49
  }
43
50
 
44
- .job-retry {
51
+ .job-actions {
45
52
  float: left;
46
53
  margin-top: 23px;
47
54
  margin-left: 20px;
@@ -49,6 +56,12 @@ body.rocket_job {
49
56
  .btn { padding: 2px 6px; }
50
57
  }
51
58
 
59
+ .pagination-buttons {
60
+ float: left;
61
+ margin-top: 23px;
62
+ margin-left: 20px;
63
+ }
64
+
52
65
  .job-state {
53
66
  margin-left: 20px;
54
67
  padding: 0;
@@ -75,10 +88,10 @@ body.rocket_job {
75
88
  border-bottom-right-radius: 3px;
76
89
  }
77
90
 
78
- .queued { background-color: darkgrey; }
91
+ .queued, .pending { background-color: darkgrey; }
79
92
  .running { background-color: #337ab7; }
80
- .completed { background-color: green; }
81
- .paused { background-color: orange; }
93
+ .completed, .enabled { background-color: green; }
94
+ .paused, .disabled { background-color: orange; }
82
95
  .failed { background-color: red; }
83
96
  .aborted { background-color: darkorange; }
84
97
  }
@@ -125,11 +138,18 @@ body.rocket_job {
125
138
  text-align: center;
126
139
 
127
140
  a {
141
+ display: inline-block;
128
142
  color: orange;
129
143
  font-weight: bold;
144
+
130
145
  }
131
146
 
132
- .color {
147
+ a:hover, a:active {
148
+ text-decoration: none;
149
+ }
150
+
151
+
152
+ span {
133
153
  display: inline-block;
134
154
  position: relative;
135
155
  left: -3px;
@@ -278,7 +298,7 @@ body.rocket_job {
278
298
  a { display: block; }
279
299
 
280
300
  .card:nth-child(1) { border-top: 1px solid #ddd; }
281
- .card:nth-child(odd) { background-color: #fff; }
301
+ .card:nth-child(odd):not(.selected) { background-color: #fff; }
282
302
 
283
303
  .card {
284
304
  border-bottom: 1px solid #ddd;
@@ -305,6 +325,8 @@ body.rocket_job {
305
325
  i.paused { color: orange; }
306
326
  i.failed { color: red; }
307
327
  i.aborted { color: darkorange; }
328
+ i.enabled { color: green; }
329
+ i.disabled { color: orange; }
308
330
 
309
331
  h3 {
310
332
  font-weight: bold;
@@ -336,9 +358,9 @@ body.rocket_job {
336
358
  }
337
359
 
338
360
  .selected {
339
- border-bottom: 2px solid blue;
340
- border-right: 2px solid blue;
341
- border-top: 2px solid blue;
361
+ border-bottom: 1px solid blue;
362
+ border-right: 1px solid blue;
363
+ border-top: 1px solid blue;
342
364
  background-color: lightcyan;
343
365
  }
344
366
 
@@ -367,12 +389,6 @@ body.rocket_job {
367
389
  position: relative;
368
390
  text-align: center;
369
391
 
370
- .icon {
371
- color: #83ADFA;
372
- text-align: center;
373
- font-size: 50px;
374
- }
375
-
376
392
  .title, .state, .threads, .time { margin-bottom: 10px; }
377
393
 
378
394
  .actions {
@@ -395,7 +411,7 @@ body.rocket_job {
395
411
  }
396
412
  }
397
413
 
398
- .spinner {
414
+ .priority-group {
399
415
  width: 67px;
400
416
  margin: 0 auto;
401
417
 
@@ -436,51 +452,9 @@ body.rocket_job {
436
452
  }
437
453
  }
438
454
 
439
- .green.signal {
440
- -webkit-animation: greenPulse 2s infinite;
441
- -moz-animation: greenPulse 2s infinite;
442
- -o-animation: greenPulse 2s infinite;
443
- animation: greenPulse 2s infinite;
444
- margin: 0 5px 0 10px;
445
- }
446
-
447
455
  .code-block { margin-top: 25px; }
448
456
 
449
457
  .status {
450
458
  padding: 1em;
451
459
  }
452
-
453
- // Warnings & Notifications
454
-
455
- .no-servers {
456
- text-align: center;
457
- font-size: 23px;
458
- padding-top: 50px;
459
- color: #777;
460
- }
461
- }
462
-
463
- // Rocket Job Animations
464
- @-webkit-keyframes greenPulse {
465
- 0% { color: #91bd09; -webkit-box-shadow: 0 0 9px #91bd09; border-radius: 30px; }
466
- 50% { color: rgb(107, 240, 123); -webkit-box-shadow: 0 0 18px rgb(107, 240, 123); border-radius: 30px; }
467
- 100% { color: #91bd09; -webkit-box-shadow: 0 0 9px #91bd09; border-radius: 30px; }
468
- }
469
-
470
- @-moz-keyframes greenPulse {
471
- 0% { background-color: #749a02; -moz-box-shadow: 0 0 9px #333; }
472
- 50% { background-color: lime; -moz-box-shadow: 0 0 18px #91bd09; }
473
- 100% { background-color: #749a02; -moz-box-shadow: 0 0 9px #333; }
474
- }
475
-
476
- @-o-keyframes greenPulse {
477
- 0% { background-color: #749a02; box-shadow: 0 0 9px #749a02; }
478
- 50% { background-color: #91bd09; box-shadow: 0 0 18px #91bd09; }
479
- 100% { background-color: #749a02; box-shadow: 0 0 9px #749a02; }
480
- }
481
-
482
- @keyframes greenPulse {
483
- 0% { background-color: #749a02; box-shadow: 0 0 9px #333; }
484
- 50% { background-color: #91bd09; box-shadow: 0 0 18px #91bd09; }
485
- 100% { background-color: #749a02; box-shadow: 0 0 9px #333; }
486
460
  }
@@ -1,6 +1,18 @@
1
+ $border-radius-small: 2px;
2
+ $border-radius-base: 3px;
3
+ $border-radius-large: 4px;
4
+
1
5
  @import "bootstrap-sprockets";
2
6
  @import "bootstrap";
3
7
 
8
+ .alert {
9
+ margin-bottom: 0px;
10
+ }
11
+
4
12
  .alert-notice {
5
13
  @extend .alert-info
6
14
  }
15
+
16
+ .alert-alert {
17
+ @extend .alert-danger
18
+ }
@@ -22,6 +22,14 @@
22
22
  border-left-color: darkorange;
23
23
  }
24
24
 
25
+ /* Used by Dirmon Entries */
26
+ .callout-enabled {
27
+ border-left-color: green;
28
+ }
29
+ .callout-disabled {
30
+ border-left-color: orange;
31
+ }
32
+
25
33
  /* Used by Workers */
26
34
  .callout-top {
27
35
  border: 1px solid #eee;
@@ -1,4 +1,18 @@
1
1
  .job-list {
2
+ .breadcrumb {
3
+ margin-bottom: 0px;
4
+ }
5
+
6
+ /*padding: 1px 1px 1px 1px;*/
7
+
8
+ .breadcrumb {
9
+ padding: 2px;
10
+
11
+ > li {
12
+ margin: 5px 0 0 5px;
13
+ }
14
+ }
15
+
2
16
  .list {
3
17
  .progress {
4
18
  width: 16em;
@@ -14,3 +28,24 @@
14
28
  }
15
29
  }
16
30
  }
31
+
32
+ .error {
33
+ pre {
34
+ margin: 0px 0px 0px 0px;
35
+ border-bottom: 0;
36
+ border-radius: 0;
37
+ word-wrap: normal;
38
+ }
39
+
40
+ pre:last-child {
41
+ border: 1px solid #cccccc;
42
+ }
43
+ }
44
+
45
+ .pagination {
46
+ margin-top: 1em;
47
+
48
+ .btn {
49
+ border-radius: 0;
50
+ }
51
+ }
@@ -1,7 +1,5 @@
1
1
  module RocketJobMissionControl
2
2
  class ApplicationController < ActionController::Base
3
- include ActionController::Live
4
-
5
3
  around_action :with_time_zone
6
4
 
7
5
  private
@@ -0,0 +1,125 @@
1
+ module RocketJobMissionControl
2
+ class DirmonEntriesController < RocketJobMissionControl::ApplicationController
3
+ before_filter :find_entry_or_redirect, except: [:index, :new, :create]
4
+ before_filter :clean_values, only: [:create, :update]
5
+ before_action :load_entries, only: [:index, :show, :new, :edit]
6
+
7
+ def index
8
+ end
9
+
10
+ def show
11
+ end
12
+
13
+ def new
14
+ @dirmon_entry = RocketJob::DirmonEntry.new(arguments: nil)
15
+ end
16
+
17
+ def create
18
+ @dirmon_entry = RocketJob::DirmonEntry.new(dirmon_params)
19
+
20
+ parse_and_assign_arguments
21
+
22
+ if @dirmon_entry.errors.empty? && @dirmon_entry.save
23
+ flash[:success] = t(:success, scope: [:dirmon_entry, :create])
24
+ redirect_to(dirmon_entry_path(@dirmon_entry))
25
+ else
26
+ load_entries
27
+ render :new
28
+ end
29
+ end
30
+
31
+ def destroy
32
+ @dirmon_entry.destroy
33
+ flash[:success] = t(:success, scope: [:dirmon_entry, :destroy])
34
+
35
+ redirect_to(dirmon_entries_path)
36
+ end
37
+
38
+ def edit
39
+ end
40
+
41
+ def update
42
+ parse_and_assign_arguments
43
+ if @dirmon_entry.errors.empty? && @dirmon_entry.update_attributes(dirmon_params)
44
+ flash[:success] = t(:success, scope: [:dirmon_entry, :update])
45
+ redirect_to(rocket_job_mission_control.dirmon_entry_path(@dirmon_entry))
46
+ else
47
+ load_entries
48
+ render :edit
49
+ end
50
+ end
51
+
52
+ def enable
53
+ if @dirmon_entry.may_enable?
54
+ @dirmon_entry.enable!
55
+ flash[:success] = t(:success, scope: [:dirmon_entry, :enable])
56
+ redirect_to(rocket_job_mission_control.dirmon_entry_path(@dirmon_entry))
57
+ else
58
+ flash[:alert] = t(:failure, scope: [:dirmon_entry, :enable])
59
+ load_entries
60
+ render(:show)
61
+ end
62
+ end
63
+
64
+ def disable
65
+ if @dirmon_entry.may_disable?
66
+ @dirmon_entry.disable!
67
+ flash[:success] = t(:success, scope: [:dirmon_entry, :disable])
68
+ redirect_to(rocket_job_mission_control.dirmon_entry_path(@dirmon_entry))
69
+ else
70
+ flash[:alert] = t(:failure, scope: [:dirmon_entry, :disable])
71
+ load_entries
72
+ render(:show)
73
+ end
74
+ end
75
+
76
+ private
77
+
78
+ def parse_and_assign_arguments
79
+ if arguments = params[:rocket_job_dirmon_entry][:arguments]
80
+ begin
81
+ arguments = JSON.parse(arguments)
82
+ @dirmon_entry.arguments = arguments.kind_of?(Array) ? arguments : [arguments]
83
+ rescue JSON::ParserError => e
84
+ @dirmon_entry.errors.add(:arguments, e.message)
85
+ end
86
+ end
87
+
88
+ end
89
+
90
+ def clean_values
91
+ params[:rocket_job_dirmon_entry].fetch(:properties, {}).each_pair do |param, value|
92
+ params[:rocket_job_dirmon_entry][:properties].delete(param) if value.blank?
93
+ end
94
+ end
95
+
96
+ def load_entries
97
+ @states = dirmons_params
98
+ @dirmons = RocketJob::DirmonEntry.limit(1000).sort(created_at: :desc)
99
+ @dirmons = @dirmons.where(state: @states) unless @states.empty?
100
+ end
101
+
102
+ def find_entry_or_redirect
103
+ @dirmon_entry = RocketJob::DirmonEntry.find(params[:id])
104
+
105
+ if @dirmon_entry.nil?
106
+ flash[:alert] = t(:failure, scope: [:dirmon_entry, :find], id: params[:id])
107
+
108
+ redirect_to(dirmon_entries_path)
109
+ end
110
+ end
111
+
112
+ def dirmons_params
113
+ params.fetch(:states, [])
114
+ end
115
+
116
+ def dirmon_params
117
+ params
118
+ .require(:rocket_job_dirmon_entry)
119
+ .permit(:name, :archive_directory, :pattern, :job_class_name).tap do |whitelist|
120
+ whitelist[:properties] = params[:rocket_job_dirmon_entry][:properties] if params[:rocket_job_dirmon_entry][:properties]
121
+ end
122
+ end
123
+
124
+ end
125
+ end
@@ -0,0 +1,31 @@
1
+ module RocketJobMissionControl
2
+ module Jobs
3
+ class FailuresController < RocketJobMissionControl::ApplicationController
4
+ def index
5
+ job_failures = JobFailures.new(params[:job_id])
6
+ @job = job_failures.job
7
+
8
+ if @job && @job.failed?
9
+ @slice_errors = job_failures.list
10
+ @error_type = params[:error_type] || @slice_errors.first['_id']['error_class']
11
+
12
+ offset = params.fetch(:offset, 1).to_i
13
+ selected_exception = job_failures.for_error(@error_type, offset)
14
+ current_failure = selected_exception.first
15
+
16
+ @pagination = {
17
+ offset: offset,
18
+ total: (selected_exception.count - 1),
19
+ }
20
+
21
+ if current_failure.present?
22
+ @failure_exception = current_failure['exception']
23
+ end
24
+
25
+ else
26
+ redirect_to(job_path(params[:job_id]))
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -12,5 +12,12 @@ module RocketJobMissionControl
12
12
  def active_page(path)
13
13
  'active' if current_page?(path)
14
14
  end
15
+
16
+ def pretty_print_array_or_hash(arguments)
17
+ return arguments unless arguments.kind_of?(Array) || arguments.kind_of?(Hash)
18
+ json_string_options = { space: ' ', indent: ' ', array_nl: '<br />', object_nl: '<br />' }
19
+ JSON.generate(arguments, json_string_options).html_safe
20
+ end
21
+
15
22
  end
16
23
  end
@@ -1,13 +1,16 @@
1
1
  module RocketJobMissionControl
2
2
  module JobsHelper
3
3
  STATE_ICON_MAP = {
4
- queued: 'fa-inbox',
4
+ aborted: 'fa-stop',
5
+ completed: 'fa-check',
6
+ disabled: 'fa-stop',
7
+ enabled: 'fa-check',
8
+ failed: 'fa-exclamation-triangle',
5
9
  paused: 'fa-pause',
10
+ pending: 'fa-inbox',
11
+ queued: 'fa-inbox',
6
12
  running: 'fa-play',
7
- completed: 'fa-check',
8
- aborted: 'fa-stop',
9
- failed: 'fa-times',
10
- scheduled: 'fa-clock-o'
13
+ scheduled: 'fa-clock-o',
11
14
  }
12
15
 
13
16
  def job_state_icon(state)
@@ -25,14 +28,18 @@ module RocketJobMissionControl
25
28
  job_state_icon(state)
26
29
  end
27
30
 
28
- def job_states
29
- @job_states ||= RocketJob::Job.aasm.states.collect { |state| state.name.to_s }
31
+ def job_action_link(action, path, http_method=:get)
32
+ link_to(
33
+ action,
34
+ path,
35
+ method: http_method,
36
+ class: 'btn btn-default',
37
+ data: { confirm: t(:confirm, scope: [:job, :action], action: action)}
38
+ )
30
39
  end
31
40
 
32
- def pretty_print_array_or_hash(arguments)
33
- return arguments unless arguments.kind_of?(Array) || arguments.kind_of?(Hash)
34
- json_string_options = { space: ' ', indent: ' ', array_nl: '<br />', object_nl: '<br />' }
35
- JSON.generate(arguments, json_string_options).html_safe
41
+ def job_states
42
+ @job_states ||= RocketJob::Job.aasm.states.map { |state| state.name.to_s }
36
43
  end
37
44
 
38
45
  def job_selected_class(job, selected_job)
@@ -0,0 +1,7 @@
1
+ module RocketJobMissionControl
2
+ module PaginationHelper
3
+ def page_nav_disabled_class(current_position, boundary)
4
+ current_position.to_i == boundary.to_i ? 'disabled' : ''
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ module RocketJobMissionControl
2
+ module SlicesHelper
3
+
4
+ def display_slice_info(slice, encrypted=false)
5
+ encrypted ? 'encrypted' : pretty_print_array_or_hash(slice.to_a)
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,30 @@
1
+ class JobFailures
2
+ attr_reader :job_id
3
+
4
+ def initialize(job_id)
5
+ @job_id = job_id
6
+ end
7
+
8
+ def job
9
+ @job ||= RocketJob::Job.find(job_id)
10
+ end
11
+
12
+ def list
13
+ @slice_errors ||= job.input.collection.aggregate(
14
+ [
15
+ {
16
+ '$group' => {
17
+ _id: { error_class: '$exception.class_name' },
18
+ messages: { '$addToSet' => '$exception.message' },
19
+ count: { '$sum' => 1 }
20
+ },
21
+ }
22
+ ]
23
+ )
24
+ end
25
+
26
+ def for_error(error_type, page_offset=0)
27
+ query = { 'state' => 'failed', 'exception.class_name' => error_type }
28
+ @job.input.collection.find(query).limit(1).skip(page_offset)
29
+ end
30
+ end
@@ -18,7 +18,7 @@
18
18
 
19
19
  = csrf_meta_tag
20
20
 
21
- %link{href: "//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css", rel: "stylesheet"}/
21
+ %link{href: "//maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css", rel: "stylesheet"}/
22
22
 
23
23
  %body.rocket_job
24
24
  #wrapper.toggled
@@ -41,3 +41,5 @@
41
41
  = msg.html_safe
42
42
 
43
43
  = yield
44
+
45
+ %footer.footer
@@ -13,6 +13,6 @@
13
13
 
14
14
  .brand
15
15
  = link_to root_path, class: 'text-center' do
16
- = image_tag('rocket_job_mission_control/rocket-icon-64x64.png', size: '56x32')
16
+ = image_tag('rocket_job_mission_control/rocket-icon-64x64.png', size: '32x32')
17
17
  rocket
18
- .color job
18
+ %span job
@@ -18,3 +18,7 @@
18
18
  = link_to running_jobs_path, class: active_page(running_jobs_path) do
19
19
  %i.fa.fa-circle-o-notch
20
20
  Running
21
+ %li
22
+ = link_to dirmon_entries_path, class: active_page(dirmon_entries_path) do
23
+ %i.fa.fa-folder-o
24
+ Dirmon
@@ -0,0 +1,36 @@
1
+ - action ||= :create
2
+ - if @dirmon_entry.errors.present?
3
+ .alert.alert-alert
4
+ Error saving entry!
5
+ - @dirmon_entry.errors.messages.each_pair do |field, message|
6
+ .message
7
+ = "#{field}: #{message}"
8
+ = form_for @dirmon_entry, url: {action: action} do |f|
9
+ .name.form-group
10
+ = f.label :name
11
+ = f.text_field :name, class: 'form-control'
12
+ .path.form-group
13
+ = f.label :pattern
14
+ = f.text_field :pattern, class: 'form-control'
15
+ .path.form-group
16
+ = f.label :archive_directory
17
+ = f.text_field :archive_directory, class: 'form-control'
18
+ .job.form-group
19
+ = f.label :job_class_name
20
+ = f.text_field :job_class_name, class: 'form-control'
21
+ .job_arguments.form-group
22
+ = f.label :arguments
23
+ = f.text_area :arguments,
24
+ value: @dirmon_entry.arguments.empty? ? nil : @dirmon_entry.arguments.to_json,
25
+ rows: 10,
26
+ placeholder: '{"argument1"":"value1", "argument2":"value2", "argument3":"value3"}',
27
+ class: 'form-control'
28
+ .row
29
+ .col-md-12#properties{ style: 'display:none;' }
30
+ = render partial: 'properties', locals: { f: f }
31
+
32
+ .buttons
33
+ = f.submit action, class: 'btn btn-primary'
34
+ = link_to 'cancel', :back, class: 'btn btn-default'
35
+ = button_tag 'properties',type: 'button', class: 'btn btn-default', id: 'expand'
36
+ = button_tag 'collapse',type: 'button', class: 'btn btn-default', id: 'collapse', style: 'display:none;'
@@ -0,0 +1,31 @@
1
+ .col-md-4
2
+ .job-list
3
+ .filter
4
+ %ol.breadcrumb
5
+ %li.active Dirmon Entries
6
+ .pull-right
7
+ = link_to "Create", new_dirmon_entry_path, class: "btn btn-default"
8
+ .btn-group{ data: { toggle: 'buttons' } }
9
+ - RocketJob::DirmonEntry.aasm.states.map { |s| s.name.to_s }.each do |state|
10
+ - enabled = @states.include?(state.to_s) || @states.empty?
11
+ - title = enabled ? 'Hide' : 'Show'
12
+ %label.btn.btn-default.state-toggle{ class: ('active' if enabled), title: "#{title} #{state.to_s.capitalize}" }
13
+ = check_box_tag(state.to_s, state.to_s, enabled)
14
+ %i.fa{class: job_state_icon(state)}
15
+ .clearfix
16
+ .list
17
+ - if @dirmons.empty?
18
+ .card.inner
19
+ .title
20
+ .lead.text-center No Dirmon Entries Found.
21
+ - else
22
+ - @dirmons.each do |dirmon|
23
+ - state = dirmon.enabled? ? :enabled : :disabled
24
+ = link_to dirmon_entry_path(id: dirmon.id, states: @states), class: "card callout callout-#{dirmon.state} #{job_selected_class(dirmon, @dirmon_entry)}" do
25
+ .inner
26
+ .title
27
+ .lead
28
+ %i.fa{class: job_state_icon(dirmon.state), style: 'font-size: 75%;', title: dirmon.state}
29
+ = dirmon.name
30
+
31
+ .description= dirmon.pattern.try(:truncate, 80)
@@ -0,0 +1,8 @@
1
+ .arguments
2
+ = f.fields_for :properties do |properties|
3
+ .form-group
4
+ = properties.label :description
5
+ = properties.text_field :description, value: @dirmon_entry.properties[:description], placeholder: "max length: 128", class: 'form-control'
6
+ .form-group
7
+ = properties.label :priority
8
+ = properties.text_field :priority, value: @dirmon_entry.properties[:priority], placeholder: "e.g 1..100", class: 'form-control'