rocketjob_mission_control 2.1.1 → 3.0.0.rc1

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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/app/assets/stylesheets/rocket_job_mission_control/callout.scss +1 -1
  4. data/app/assets/stylesheets/rocket_job_mission_control/worker_processes.scss +2 -2
  5. data/app/controllers/rocket_job_mission_control/active_workers_controller.rb +15 -0
  6. data/app/controllers/rocket_job_mission_control/dirmon_entries/index_filters_controller.rb +8 -13
  7. data/app/controllers/rocket_job_mission_control/dirmon_entries_controller.rb +3 -14
  8. data/app/controllers/rocket_job_mission_control/jobs/failures_controller.rb +6 -11
  9. data/app/controllers/rocket_job_mission_control/jobs/index_filters_controller.rb +35 -14
  10. data/app/controllers/rocket_job_mission_control/jobs_controller.rb +12 -15
  11. data/app/controllers/rocket_job_mission_control/servers/index_filters_controller.rb +49 -0
  12. data/app/controllers/rocket_job_mission_control/servers_controller.rb +93 -0
  13. data/app/datatables/rocket_job_mission_control/abstract_datatable.rb +62 -0
  14. data/app/datatables/rocket_job_mission_control/active_workers_datatable.rb +47 -0
  15. data/app/datatables/rocket_job_mission_control/completed_jobs_datatable.rb +1 -1
  16. data/app/datatables/rocket_job_mission_control/dirmon_entries_datatable.rb +10 -72
  17. data/app/datatables/rocket_job_mission_control/interrupted_jobs_datatable.rb +1 -1
  18. data/app/datatables/rocket_job_mission_control/jobs_datatable.rb +16 -91
  19. data/app/datatables/rocket_job_mission_control/queued_jobs_datatable.rb +1 -1
  20. data/app/datatables/rocket_job_mission_control/running_jobs_datatable.rb +23 -12
  21. data/app/datatables/rocket_job_mission_control/scheduled_jobs_datatable.rb +1 -1
  22. data/app/datatables/rocket_job_mission_control/servers_datatable.rb +67 -0
  23. data/app/helpers/rocket_job_mission_control/{workers_helper.rb → servers_helper.rb} +9 -9
  24. data/app/models/job_failures.rb +3 -16
  25. data/app/models/rocket_job_mission_control/query.rb +51 -0
  26. data/app/views/layouts/rocket_job_mission_control/partials/_header.html.haml +3 -3
  27. data/app/views/layouts/rocket_job_mission_control/partials/_sidebar.html.haml +2 -2
  28. data/app/views/rocket_job_mission_control/{active_processes → active_workers}/index.html.haml +3 -3
  29. data/app/views/rocket_job_mission_control/dirmon_entries/_properties.html.haml +7 -18
  30. data/app/views/rocket_job_mission_control/dirmon_entries/_status.html.haml +0 -5
  31. data/app/views/rocket_job_mission_control/dirmon_entries/show.html.haml +4 -3
  32. data/app/views/rocket_job_mission_control/jobs/_status.html.haml +22 -17
  33. data/app/views/rocket_job_mission_control/jobs/edit.html.haml +1 -1
  34. data/app/views/rocket_job_mission_control/jobs/exceptions.html.haml +29 -0
  35. data/app/views/rocket_job_mission_control/jobs/failures/index.html.haml +7 -7
  36. data/app/views/rocket_job_mission_control/jobs/show.html.haml +23 -11
  37. data/app/views/rocket_job_mission_control/servers/_actions.html.haml +9 -0
  38. data/app/views/rocket_job_mission_control/servers/_sidebar.html.haml +20 -0
  39. data/app/views/rocket_job_mission_control/{workers → servers}/index.html.haml +9 -9
  40. data/app/views/rocket_job_mission_control/{workers → servers}/index_filters/paused.html.haml +8 -8
  41. data/app/views/rocket_job_mission_control/{workers → servers}/index_filters/running.html.haml +8 -8
  42. data/app/views/rocket_job_mission_control/{workers → servers}/index_filters/starting.html.haml +8 -8
  43. data/app/views/rocket_job_mission_control/{workers → servers}/index_filters/stopping.html.haml +8 -8
  44. data/config/locales/en.yml +2 -2
  45. data/config/routes.rb +7 -6
  46. data/lib/rocket_job_mission_control/engine.rb +0 -12
  47. data/lib/rocket_job_mission_control/version.rb +1 -1
  48. data/spec/controllers/dirmon_entries/index_filters_controller_spec.rb +2 -4
  49. data/spec/controllers/dirmon_entries_controller_spec.rb +15 -72
  50. data/spec/controllers/jobs/index_filters_controller_spec.rb +1 -1
  51. data/spec/controllers/workers/index_filters_controller_spec.rb +9 -9
  52. data/spec/controllers/workers_controller_spec.rb +47 -47
  53. data/spec/dummy/config/mongoid.yml +88 -0
  54. data/spec/dummy/config/symmetric-encryption.yml +8 -0
  55. data/spec/dummy/log/test.log +89072 -0
  56. data/spec/helpers/servers_helper_spec.rb +16 -0
  57. data/spec/spec_helper.rb +3 -0
  58. metadata +31 -45
  59. data/app/controllers/rocket_job_mission_control/active_processes_controller.rb +0 -27
  60. data/app/controllers/rocket_job_mission_control/workers/index_filters_controller.rb +0 -50
  61. data/app/controllers/rocket_job_mission_control/workers_controller.rb +0 -93
  62. data/app/datatables/rocket_job_mission_control/active_processes_datatable.rb +0 -79
  63. data/app/datatables/rocket_job_mission_control/workers_datatable.rb +0 -127
  64. data/app/interactors/rocket_job_mission_control/dirmon_entries/search.rb +0 -19
  65. data/app/interactors/rocket_job_mission_control/jobs/search.rb +0 -19
  66. data/app/interactors/rocket_job_mission_control/workers/search.rb +0 -19
  67. data/app/views/rocket_job_mission_control/workers/_actions.html.haml +0 -9
  68. data/app/views/rocket_job_mission_control/workers/_sidebar.html.haml +0 -20
  69. data/spec/dummy/config/mongo.yml +0 -15
  70. data/spec/helpers/workers_helper_spec.rb +0 -16
  71. data/spec/interactors/jobs/search_spec.rb +0 -35
@@ -1,21 +1,21 @@
1
1
  module RocketJobMissionControl
2
- module WorkersHelper
3
- def worker_counts_by_state(state)
4
- RocketJob::Worker.counts_by_state.fetch(state.downcase.to_sym, 0)
2
+ module ServersHelper
3
+ def server_counts_by_state(state)
4
+ RocketJob::Server.counts_by_state.fetch(state.downcase.to_sym, 0)
5
5
  end
6
6
 
7
- def worker_icon(worker)
7
+ def server_icon(server)
8
8
  state =
9
- if worker.zombie?
9
+ if server.zombie?
10
10
  'zombie'
11
11
  else
12
- worker.state
12
+ server.state
13
13
  end
14
14
  state_icon(state)
15
15
  end
16
16
 
17
- def worker_card_class(worker)
18
- if worker.zombie?
17
+ def server_card_class(server)
18
+ if server.zombie?
19
19
  'callout-zombie'
20
20
  else
21
21
  map = {
@@ -23,7 +23,7 @@ module RocketJobMissionControl
23
23
  paused: 'callout-warning',
24
24
  stopping: 'callout-alert',
25
25
  }
26
- map[worker.state] || 'callout-info'
26
+ map[server.state] || 'callout-info'
27
27
  end
28
28
  end
29
29
  end
@@ -10,24 +10,11 @@ class JobFailures
10
10
  end
11
11
 
12
12
  def list
13
- @slice_errors ||= job.input.collection.aggregate(
14
- [
15
- {
16
- '$match' => {state: 'failed'}
17
- },
18
- {
19
- '$group' => {
20
- _id: {error_class: '$exception.class_name'},
21
- messages: {'$addToSet' => '$exception.message'},
22
- count: {'$sum' => 1}
23
- },
24
- }
25
- ]
26
- )
13
+ @slice_errors ||= job.input.group_exceptions
27
14
  end
28
15
 
29
16
  def for_error(error_type, page_offset=0)
30
- query = {'state' => 'failed', 'exception.class_name' => error_type}
31
- @job.input.collection.find(query).limit(1).skip(page_offset)
17
+ query = {'exception.class_name' => error_type}
18
+ job.input.failed.where(query).limit(1).skip(page_offset).first
32
19
  end
33
20
  end
@@ -0,0 +1,51 @@
1
+ module RocketJobMissionControl
2
+ class Query
3
+ attr_reader :scope, :default_order
4
+ attr_accessor :search_term, :order_by, :search_term, :start, :page_size,
5
+ :search_columns, :display_columns
6
+
7
+ def initialize(scope, default_order = {})
8
+ @scope = scope
9
+ @order_by = @default_order = default_order
10
+ @search_columns = []
11
+ @display_columns = []
12
+ end
13
+
14
+ # Returns the filtered query expression
15
+ def unsorted_query
16
+ records = scope
17
+ # Text Search
18
+ if search_term
19
+ escaped = Regexp.escape(search_term)
20
+ regexp = Regexp.new(escaped, Regexp::IGNORECASE)
21
+ if search_columns.size == 1
22
+ records = records.where(search_columns.first => regexp)
23
+ else
24
+ cols = search_columns.collect { |col| {col => regexp} }
25
+ records = records.where('$or' => cols)
26
+ end
27
+ end
28
+
29
+ # Pagination
30
+ if start && page_size
31
+ records = records.skip(start).limit(page_size)
32
+ end
33
+ records
34
+ end
35
+
36
+ # Returns the filtered query expression with the sort applied
37
+ def query
38
+ # Sort must be applied last
39
+ order_by ? unsorted_query.sort(order_by) : unsorted_query
40
+ end
41
+
42
+ def count
43
+ unsorted_query.count
44
+ end
45
+
46
+ def unfiltered_count
47
+ scope.count
48
+ end
49
+
50
+ end
51
+ end
@@ -16,13 +16,13 @@
16
16
  %i.fa.fa-home
17
17
  Jobs
18
18
  %li
19
- = link_to workers_path, class: active_page(workers_path) do
19
+ = link_to servers_path, class: active_page(servers_path) do
20
20
  %i.fa.fa-database
21
21
  Servers
22
22
  %li
23
- = link_to active_processes_path, class: active_page(active_processes_path) do
23
+ = link_to active_workers_path, class: active_page(active_workers_path) do
24
24
  %i.fa.fa-circle-o-notch
25
- Activity
25
+ Workers
26
26
  %li
27
27
  = link_to enabled_dirmon_entries_path, class: active_page(enabled_dirmon_entries_path) do
28
28
  %i.fa.fa-folder-o
@@ -7,5 +7,5 @@
7
7
  = render partial: 'rocket_job_mission_control/jobs/sidebar'
8
8
  - if @dirmon_sidebar
9
9
  = render partial: 'rocket_job_mission_control/dirmon_entries/sidebar'
10
- - if @workers_sidebar
11
- = render partial: 'rocket_job_mission_control/workers/sidebar'
10
+ - if @servers_sidebar
11
+ = render partial: 'rocket_job_mission_control/servers/sidebar'
@@ -6,10 +6,10 @@
6
6
  .col-sm-2
7
7
  .btn.btn-default.pull-right.dt-reload{ data: { behavior: 'reload' } }
8
8
  %i.fa.fa-refresh
9
- %table.table.datatable.active-processes-datatable{ style: "width: 100%", data: { source: "#{active_processes_url(format: 'json')}", column_num: 4 } }
9
+ %table.table.datatable.active-workers-datatable{ style: "width: 100%", data: { source: "#{active_workers_url(format: 'json')}", column_num: 4 } }
10
10
  %thead
11
11
  %tr
12
- %th Hostname : PID
12
+ %th Worker Name
13
13
  %th Class
14
14
  %th Description
15
15
  %th Started
@@ -18,7 +18,7 @@
18
18
  :javascript
19
19
  jQuery(function() {
20
20
  new RjmcDatatable(
21
- $('.active-processes-datatable'),
21
+ $('.active-workers-datatable'),
22
22
  [{data: '0'}, {data: '1'}, {data: '2'}, {data: '3'}],
23
23
  {ordering: false, searching: false});
24
24
  });
@@ -1,34 +1,23 @@
1
1
  - if @dirmon_entry.job_class
2
2
  .arguments
3
3
  .job_arguments.form-group
4
- - count = @dirmon_entry.job_class.rocket_job_argument_count
5
- - count.times do |counter|
6
- - argument = @dirmon_entry.arguments[counter]
7
- = f.label "Argument #{counter + 1}:"
8
- = f.text_field :arguments,
9
- value: argument.is_a?(Hash) || argument.is_a?(Array) ? argument.to_json : argument,
10
- name: 'rocket_job_dirmon_entry[arguments][]',
11
- rows: 10,
12
- placeholder: '{"argument1":"value1", "argument2":"value2", "argument3":"value3"}',
13
- class: 'form-control'
14
4
  = f.fields_for :properties do |properties|
15
- - @dirmon_entry.job_class.rocket_job_properties.each do |property_name|
16
- - next if property_name == :arguments
17
- - key = @dirmon_entry.job_class.keys[property_name.to_s]
18
- - next unless key && key.type
19
- - placeholder = key.default? ? key.default : nil
5
+ - @dirmon_entry.job_class.user_editable_fields.each do |property_name|
6
+ - field = @dirmon_entry.job_class.fields[property_name.to_s]
7
+ - next unless field && field.type
8
+ - placeholder = field.default_val
20
9
  .form-group
21
10
  = properties.label property_name.to_s
22
- - case key.type.name
11
+ - case field.type.name
23
12
  - when 'Integer'
24
13
  = properties.number_field property_name, value: @dirmon_entry.properties[property_name], class: 'form-control', placeholder: placeholder
25
14
  - when 'Hash'
26
15
  - value = @dirmon_entry.properties[property_name]
27
- = properties.text_field property_name, value: value ? value.to_json : '', class: 'form-control', placeholder: '{"argument1":"value1", "argument2":"value2", "argument3":"value3"}'
16
+ = properties.text_field property_name, value: value ? value.to_json : '', class: 'form-control', placeholder: '{"key1":"value1", "key2":"value2", "key3":"value3"}'
28
17
  - when 'Array'
29
18
  - options = Array(@dirmon_entry.properties[property_name])
30
19
  = properties.select property_name, options_for_select(options, options), {include_hidden: false}, {class: 'selectize', multiple: true}
31
- - when 'Boolean'
20
+ - when 'Mongoid::Boolean'
32
21
  - name = "#{property_name}_true".to_sym
33
22
  .radio-buttons
34
23
  = properties.label name, 'true'
@@ -10,11 +10,6 @@
10
10
  %div
11
11
  %label Archive Directory:
12
12
  = @dirmon_entry.archive_directory
13
- -if @dirmon_entry.arguments.size > 0
14
- .parameters
15
- %label Arguments:
16
- %pre
17
- %code= pretty_print_array_or_hash(@dirmon_entry.arguments)
18
13
  - @dirmon_entry.properties.each_pair do |name, value|
19
14
  .parameters
20
15
  %label= "#{name.to_s.titleize}:"
@@ -8,14 +8,15 @@
8
8
  = @dirmon_entry.state
9
9
 
10
10
  .btn-toolbar.job-actions.pull-right
11
- .btn-group{ style: 'margin-right: 1em;' }
12
- = link_to "Destroy", dirmon_entry_path(@dirmon_entry), method: :delete, class: 'btn btn-default', :data => { :confirm => 'Are you sure?' }
11
+ .btn-group
12
+ = link_to "Edit", edit_dirmon_entry_path(@dirmon_entry), class: "btn btn-default"
13
+ .btn-group
13
14
  - if @dirmon_entry.disabled? || @dirmon_entry.pending?
14
15
  = link_to "Enable", enable_dirmon_entry_path(@dirmon_entry.id), method: :put, class: "btn btn-default"
15
16
  - if @dirmon_entry.enabled?
16
17
  = link_to "Disable", disable_dirmon_entry_path(@dirmon_entry.id), method: :put, class: "btn btn-default", :data => { :confirm => 'Are you sure?' }
17
18
  .btn-group
18
- = link_to "Edit", edit_dirmon_entry_path(@dirmon_entry), class: "btn btn-default"
19
+ = link_to "Destroy", dirmon_entry_path(@dirmon_entry), method: :delete, class: 'btn btn-default', :data => { :confirm => 'Are you sure?' }
19
20
 
20
21
  .clearfix
21
22
 
@@ -1,31 +1,36 @@
1
1
  - status = job.status(Time.zone)
2
2
  .id
3
3
  %label ID:
4
- = status.delete('id')
5
- .status-message
6
- %label Description:
7
- = status.delete('description')
8
- .status-message
9
- %label Duration:
10
- = status.delete('duration')
11
- .status-message
12
- %label Record Count:
13
- = status.delete('record_count')
4
+ = status.delete('_id')
5
+ - if description = status.delete('description')
6
+ .status-message
7
+ %label Description:
8
+ = description
9
+ - if duration = status.delete('duration')
10
+ .status-message
11
+ %label Duration:
12
+ = duration
13
+ - if record_count = status.delete('record_count')
14
+ .status-message
15
+ %label Record Count:
16
+ = record_count
14
17
  .created_at
15
18
  %label Created At:
16
19
  = status.delete('created_at')
17
- .status-message
18
- %label Started At:
19
- = status.delete('started_at')
20
- .status-message
21
- %label % Complete:
22
- = status.delete('percent_complete')
20
+ - if started_at = status.delete('started_at')
21
+ .status-message
22
+ %label Started At:
23
+ = started_at
24
+ - if percent_complete = status.delete('percent_complete')
25
+ .status-message
26
+ %label % Complete:
27
+ = percent_complete
23
28
 
24
29
  - remaining = {}
25
30
  - status.each_pair do |key, value|
26
31
  - next if value.blank?
27
32
  .status-message
28
- - if ['state', '_type'].include?(key)
33
+ - if ['state', '_type', 'sub_state'].include?(key)
29
34
  - elsif value.kind_of?(Hash) || value.kind_of?(Array)
30
35
  - remaining[key] = value
31
36
  - else
@@ -18,7 +18,7 @@
18
18
  = f.number_field :priority, value: @job.priority, class: 'form-control'
19
19
  .col-md-4
20
20
  = f.label :log_level
21
- = f.select :log_level, ['trace', 'debug', 'info', 'warn', 'error', 'fatal'], { include_blank: true }, { class: 'form-control' }
21
+ = f.select :log_level, SemanticLogger::LEVELS.collect(&:to_s), { include_blank: true }, { class: 'form-control' }
22
22
  - if @job.respond_to?(:max_active_workers)
23
23
  .col-md-4
24
24
  = f.label :max_active_workers
@@ -0,0 +1,29 @@
1
+ .job-list
2
+ .list
3
+ .row
4
+ .col-sm-10
5
+ %h2 Exceptions
6
+ = link_to(@job.class.name, job_path(@job))
7
+ = h(@job.description)
8
+ .col-sm-2
9
+ .btn.btn-default.pull-right.dt-reload{ data: { behavior: 'reload' } }
10
+ %i.fa.fa-refresh
11
+ %table.table.datatable.jobs-datatable{ style: 'width: 100%', data: { source: "#{jobs_url(format: 'json')}" } }
12
+ %thead
13
+ %tr
14
+ %th Count
15
+ %th Exception Class
16
+ %th Exception Messages
17
+ %tbody
18
+ - class_name = nil
19
+ - @exceptions.each do |exception|
20
+ - exception.messages.each do |message|
21
+ %tr
22
+ %th
23
+ = exception.count if exception.class_name != class_name
24
+ %th
25
+ - if exception.class_name != class_name
26
+ = link_to(exception.class_name, job_failures_path(@job, error_type: exception.class_name), class: "card callout")
27
+ %th
28
+ = message
29
+ - class_name = exception.class_name
@@ -8,25 +8,25 @@
8
8
  .clearfix
9
9
  .list
10
10
  - @slice_errors.each do |slice_error|
11
- = link_to(job_failures_path(@job, error_type: slice_error['_id']['error_class']), class: "card callout") do
11
+ = link_to(job_failures_path(@job, error_type: slice_error.class_name), class: "card callout") do
12
12
  .inner
13
13
  .title
14
14
  .lead
15
- = slice_error['_id']['error_class']
15
+ = slice_error.class_name
16
16
 
17
17
  .description
18
- = "Occurrences: #{slice_error['count'].to_i}"
18
+ = "Occurrences: #{slice_error.count}"
19
19
 
20
20
  - if @failure_exception
21
21
  .col-md-8
22
22
  .job-status
23
23
  .failures
24
- .lead= @failure_exception['class_name']
25
- .pagination-buttons.pull-right= render partial: 'pagination', locals: { error_type: @failure_exception['class_name'], pagination: @pagination }
24
+ .lead= @failure_exception.class_name
25
+ .pagination-buttons.pull-right= render partial: 'pagination', locals: { error_type: @failure_exception.class_name, pagination: @pagination }
26
26
 
27
27
  .clearfix
28
28
  .message
29
29
  %pre
30
- %code= @failure_exception['message']
30
+ %code= @failure_exception.message
31
31
  .error
32
- %pre.small= @failure_exception['backtrace'].join("\n")
32
+ %pre.small= @failure_exception.backtrace.join("\n")
@@ -4,21 +4,26 @@
4
4
  .lead= @job.class.name
5
5
 
6
6
  .job-state.inline-block
7
- .left state
7
+ .left State
8
8
  .right{ class: @job.state.to_s }
9
9
  = @job.state
10
+ - if sub_state = @job['sub_state']
11
+ .job-state.inline-block
12
+ .left Batch
13
+ .right{ class: 'running' }
14
+ = sub_state
10
15
 
11
16
  .btn-toolbar.job-actions.pull-right
12
- .btn-group
13
- - valid_events = @job.aasm.events.collect{ |e| e.name }
14
- - if valid_events.include?(:abort)
15
- = job_action_link('Abort', rocket_job_mission_control.abort_job_path(@job), :patch)
17
+ - if @job.respond_to?(:input) && @job.input.failed.count > 0
18
+ .btn-group
19
+ = link_to('Show Exceptions', exceptions_job_path(@job), class: 'btn btn-default')
16
20
 
17
- - if @job.completed? || @job.aborted?
18
- = job_action_link('Destroy', rocket_job_mission_control.job_path(@job), :delete)
21
+ - if @job.scheduled?
22
+ .btn-group
23
+ = job_action_link('Run', rocket_job_mission_control.run_now_job_path(@job), :patch)
19
24
 
20
- - if valid_events.include?(:fail)
21
- = job_action_link('Fail', rocket_job_mission_control.fail_job_path(@job), :patch)
25
+ .btn-group
26
+ - valid_events = @job.aasm.events.collect{ |e| e.name }
22
27
 
23
28
  - if valid_events.include?(:pause)
24
29
  = job_action_link('Pause', rocket_job_mission_control.pause_job_path(@job), :patch)
@@ -29,8 +34,15 @@
29
34
  - if valid_events.include?(:retry)
30
35
  = job_action_link('Retry', rocket_job_mission_control.retry_job_path(@job), :patch)
31
36
 
32
- - if @job.respond_to?(:input) && @job.input.failed_count > 0
33
- = link_to('View Errors', job_failures_path(@job), class: 'btn btn-default')
37
+ .btn-group
38
+ - if valid_events.include?(:fail)
39
+ = job_action_link('Fail', rocket_job_mission_control.fail_job_path(@job), :patch)
40
+
41
+ - if valid_events.include?(:abort)
42
+ = job_action_link('Abort', rocket_job_mission_control.abort_job_path(@job), :patch)
43
+
44
+ = job_action_link('Destroy', rocket_job_mission_control.job_path(@job), :delete)
45
+
34
46
  - unless @job.completed? || @job.aborted?
35
47
  .btn-group
36
48
  = link_to "Edit", edit_job_path(@job), class: "btn btn-default"
@@ -0,0 +1,9 @@
1
+ - if server.stopping?
2
+ %p Server is stopping...
3
+ = link_to "destroy", rocket_job_mission_control.server_path(server), method: :delete, class: 'btn btn-danger'
4
+ -else
5
+ = link_to "stop", rocket_job_mission_control.stop_server_path(server), method: :patch, class: 'btn btn-danger'
6
+ - if server.paused?
7
+ = link_to "resume", rocket_job_mission_control.resume_server_path(server), method: :patch, class: 'btn btn-default'
8
+ - else
9
+ = link_to "pause", rocket_job_mission_control.pause_server_path(server), method: :patch, class: 'btn btn-default'
@@ -0,0 +1,20 @@
1
+ %ul#lg-menu.nav.hidden-xs
2
+ %li
3
+ = link_to(servers_path) do
4
+ %i.fa.fa-list
5
+ All
6
+ - RocketJob::Server.aasm.states.map { |s| s.name.to_s }.each do |state|
7
+ %li{class: state}
8
+ = link_to("#{state}_servers".to_sym) do
9
+ %i.fa{class: state_icon(state)}
10
+ = state.to_s.capitalize!
11
+ = "(#{server_counts_by_state(state)})"
12
+ / tiny only nav
13
+ %ul#xs-menu.nav.visible-xs
14
+ %li
15
+ = link_to(servers_path) do
16
+ %i.fa.fa-list
17
+ - RocketJob::Server.aasm.states.map { |s| s.name.to_s }.each do |state|
18
+ %li{class: state}
19
+ = link_to("#{state}_servers".to_sym) do
20
+ %i.fa{class: state_icon(state)}