level_up 0.2.0 → 0.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.
Files changed (48) hide show
  1. data/CHANGELOG.txt +4 -0
  2. data/app/assets/stylesheets/level_up/application.css.scss +1 -1
  3. data/app/controllers/level_up/flowcharts_controller.rb +38 -0
  4. data/app/controllers/level_up/jobs_controller.rb +7 -30
  5. data/app/models/level_up/graph_builder.rb +80 -0
  6. data/app/views/layouts/level_up/_header.html.erb +3 -2
  7. data/app/views/level_up/flowcharts/index.html.erb +36 -0
  8. data/app/views/level_up/flowcharts/show.html.erb +20 -0
  9. data/config/routes.rb +4 -0
  10. data/lib/level_up/version.rb +1 -1
  11. data/test/dummy/config/environments/development.rb +3 -3
  12. data/test/dummy/config/initializers/preload_sti_models.rb +5 -0
  13. data/test/dummy/db/development.sqlite3 +0 -0
  14. data/test/dummy/log/development.log +845 -3294
  15. data/test/dummy/log/test.log +6557 -14587
  16. data/test/dummy/tmp/{job_1.svg → account_banish.svg} +0 -0
  17. data/test/dummy/tmp/account_downgrade.svg +123 -0
  18. data/test/dummy/tmp/account_upgrade.svg +48 -0
  19. data/test/dummy/tmp/cache/assets/C2C/CE0/sprockets%2F33f519d653c9b4886c417440a0993824 +0 -0
  20. data/test/dummy/tmp/cache/assets/C6A/F00/sprockets%2F177385361781d5fe78d217f1f48b8566 +0 -0
  21. data/test/dummy/tmp/cache/assets/C6C/ED0/sprockets%2F320c25374f5ea136824c04c256e1605b +0 -0
  22. data/test/dummy/tmp/cache/assets/C87/110/sprockets%2Fc4428c04b8830f451f7636c2811f975d +0 -0
  23. data/test/dummy/tmp/cache/assets/CB9/E40/sprockets%2F43e6286ecc7751fc65d32b72c6158940 +0 -0
  24. data/test/dummy/tmp/cache/assets/CCE/7E0/sprockets%2F7d295633b50bfa8b04345d5e600b343a +0 -0
  25. data/test/dummy/tmp/cache/assets/CD5/450/sprockets%2F2ac0e7e07211a99107e0ba7e2680c885 +0 -0
  26. data/test/dummy/tmp/cache/assets/CE4/220/sprockets%2Ff1a78dd6750c553265fd3a242d76c277 +0 -0
  27. data/test/dummy/tmp/cache/assets/CF7/BA0/sprockets%2F8f9487ea6943415e46a5d895e0920ebe +0 -0
  28. data/test/dummy/tmp/cache/assets/D0E/2B0/sprockets%2F3e386ff8d231b92766061c4fad4ad504 +0 -0
  29. data/test/dummy/tmp/cache/assets/D19/660/sprockets%2F018d64588c824dd3e7e6c8d6d0d6510e +0 -0
  30. data/test/dummy/tmp/cache/assets/D25/E10/sprockets%2F989ec024c5db6ae875689b410f8e6d53 +0 -0
  31. data/test/dummy/tmp/cache/assets/D33/200/sprockets%2Fc291105cf21ca8e744c65f3d4f446aa1 +0 -0
  32. data/test/dummy/tmp/cache/assets/D34/610/sprockets%2Fcc081ecb5b32894151f16a144383befe +0 -0
  33. data/test/dummy/tmp/cache/assets/D4D/110/sprockets%2Fc16dfb491d9b98f482b4f0059dd355b8 +0 -0
  34. data/test/dummy/tmp/cache/assets/D4F/890/sprockets%2Fe3f96e9aa9b032c43788676c5ce066db +0 -0
  35. data/test/dummy/tmp/cache/assets/D53/370/sprockets%2F1cf0ca91840a1483edcac4d0c403b149 +0 -0
  36. data/test/dummy/tmp/cache/assets/D69/B90/sprockets%2Fdb0ee3e51128419c85616ceaca66ab58 +0 -0
  37. data/test/dummy/tmp/cache/assets/D75/B20/sprockets%2Fb659146edbe91be3b1b9d64cb9370c76 +0 -0
  38. data/test/dummy/tmp/cache/assets/D79/430/sprockets%2Fc030f9d26fab468c49dc494195d77eab +0 -0
  39. data/test/dummy/tmp/cache/assets/D9D/3C0/sprockets%2F3019d99c7bae1e55eb7c2bf4688b1b1a +0 -0
  40. data/test/dummy/tmp/cache/assets/DAA/1A0/sprockets%2Fba643993838fce8ddc1d42e6ce1fc346 +0 -0
  41. data/test/dummy/tmp/cache/assets/DD4/DA0/sprockets%2F17fadf3354a429c53acfe9fca6268d5d +0 -0
  42. data/test/dummy/tmp/cache/assets/DF8/880/sprockets%2F255d8bde2bf6681724e4ddedcc3cbc02 +0 -0
  43. data/test/dummy/tmp/job_2.svg +109 -64
  44. data/test/dummy/tmp/pids/server.pid +1 -0
  45. data/test/unit/level_up/graph_builder_test.rb +77 -0
  46. data/test/unit/level_up/job_test.rb +7 -7
  47. metadata +20 -8
  48. data/test/dummy/tmp/job_3.svg +0 -78
data/CHANGELOG.txt CHANGED
@@ -1,3 +1,7 @@
1
+ == 0.3.0 Wave Race
2
+ * Flowcharts (svg representation of jobs) accessible from the mountable web app
3
+ * New GraphBuilder class to easily build and customize Graphviz graphs
4
+
1
5
  == 0.2.0 Hungry Beast
2
6
  * Configurable size of saved backtrace when rescuing from an error
3
7
  * Renamed 'states' into 'tasks'
@@ -62,7 +62,7 @@ header {
62
62
  -webkit-box-sizing: border-box;
63
63
  -moz-box-sizing: border-box;
64
64
  box-sizing: border-box;
65
- width: 50%;
65
+ width: 33.33%;
66
66
 
67
67
  &:first-child {
68
68
  a.app-link {
@@ -0,0 +1,38 @@
1
+ require_dependency 'level_up/application_controller'
2
+
3
+ module LevelUp
4
+ class FlowchartsController < ApplicationController
5
+ if Configuration.http_authentication
6
+ http_basic_authenticate_with name: Configuration.http_login, password: Configuration.http_password
7
+ end
8
+
9
+ def index
10
+ @job_classes = LevelUp::Job.descendants.map { |klass| klass }
11
+ end
12
+
13
+ def show
14
+ @job_type = params[:id]
15
+ @job_class = @job_type.camelize.safe_constantize
16
+ if @job_class
17
+
18
+ else
19
+ flash.now[:alert] = "Job class not found"
20
+ end
21
+ end
22
+
23
+ respond_to :svg
24
+ def graphviz
25
+ job_type = params[:id]
26
+ job_class = job_type.camelize.safe_constantize
27
+
28
+ if job_class
29
+ builder = GraphBuilder.new(job_class)
30
+ graph = builder.graph
31
+ graph.output(:svg => "#{Rails.root}/tmp/#{job_type}.svg")
32
+ send_data(File.open("#{Rails.root}/tmp/#{job_type}.svg").read, filename: "#{job_type}.svg", type: 'image/svg+xml', disposition: 'inline')
33
+ else
34
+ render text: "Job class not found", status: 404
35
+ end
36
+ end
37
+ end
38
+ end
@@ -79,38 +79,15 @@ module LevelUp
79
79
  respond_to :svg
80
80
  def graphviz
81
81
  job = Job.find params[:id]
82
- g = GraphViz.new(:G, type: :digraph)
83
- g[:bgcolor]= '#fafbfb'
84
82
 
85
- g.node[:color] = '#111111'
86
- g.node[:style] = 'filled'
87
- g.node[:shape] = 'box'
88
- g.node[:fillcolor] = '#666666'
89
- g.node[:fontcolor] = 'white'
90
- g.node[:fontname] = 'Verdana'
91
- g.edge[:color] = '#000000'
92
- g.edge[:arrowhead] = 'open'
93
-
94
- tasks = {}
95
- job.tasks.each do |task|
96
- tasks[task] = g.add_nodes(task.to_s.humanize.downcase)
97
- if task == :start
98
- tasks[task][:fillcolor] = '#5db1a4'
99
- tasks[task][:color] = '#048282'
100
- elsif task == :end
101
- tasks[task][:fillcolor] = '#b40d28'
102
- tasks[task][:color] = '#600615'
103
- end
104
- end
105
-
106
- job.tasks.each do |task|
107
- job.transitions(task).each do |transition|
108
- g.add_edges(tasks[task], tasks[transition])
109
- end
83
+ if job
84
+ builder = GraphBuilder.new(job)
85
+ graph = builder.graph
86
+ graph.output(:svg => "#{Rails.root}/tmp/job_#{job.id}.svg")
87
+ send_data(File.open("#{Rails.root}/tmp/job_#{job.id}.svg").read, filename: "job_#{job.id}.svg", type: 'image/svg+xml', disposition: 'inline')
88
+ else
89
+ render text: "Job not found", status: 404
110
90
  end
111
-
112
- g.output(:svg => "#{Rails.root}/tmp/job_#{job.id}.svg")
113
- send_data(File.open("#{Rails.root}/tmp/job_#{job.id}.svg").read, filename: "job_#{job.id}.svg", type: 'image/svg+xml', disposition: 'inline')
114
91
  end
115
92
  end
116
93
  end
@@ -0,0 +1,80 @@
1
+ module LevelUp
2
+ class GraphBuilder
3
+ attr_accessor :target
4
+ attr_reader :configuration
5
+
6
+ @default_configuration = {
7
+ bgcolor: '#fafbfb',
8
+
9
+ node: {
10
+ color: '#111111',
11
+ style: 'filled',
12
+ shape: 'box',
13
+ fillcolor: '#666666',
14
+ fontcolor: 'white',
15
+ fontname: 'Verdana',
16
+
17
+ start: {
18
+ fillcolor: '#5db1a4',
19
+ color: '#048282'
20
+ },
21
+
22
+ end: {
23
+ fillcolor: '#b40d28',
24
+ color: '#600615'
25
+ }
26
+ },
27
+
28
+ edge: {
29
+ color: '#000000',
30
+ arrowhead: 'open'
31
+ }
32
+ }
33
+
34
+ class << self
35
+ attr_reader :default_configuration
36
+ end
37
+
38
+ def initialize(target, options = {})
39
+ @target = target
40
+ @configuration = self.class.default_configuration.deep_merge(options)
41
+ end
42
+
43
+ def graph
44
+ graph = GraphViz.new(:G, type: :digraph)
45
+
46
+ graph[:bgcolor] = @configuration[:bgcolor]
47
+
48
+ @configuration[:node].each do |k, v|
49
+ graph.node[k] = v unless v.is_a? Hash
50
+ end
51
+
52
+ @configuration[:edge].each do |k, v|
53
+ graph.edge[k] = v unless v.is_a? Hash
54
+ end
55
+
56
+ tasks = {}
57
+ @target.tasks.each do |task|
58
+ tasks[task] = graph.add_nodes(task.to_s.humanize.downcase)
59
+ if @configuration[:node].has_key? task
60
+ @configuration[:node][task].each do |k, v|
61
+ tasks[task][k] = v
62
+ end
63
+ end
64
+ end
65
+
66
+ @target.tasks.each do |task|
67
+ @target.transitions(task).each do |transition|
68
+ edge = graph.add_edges(tasks[task], tasks[transition])
69
+ if @configuration[:edge].has_key? task
70
+ @configuration[:edge][task].each do |k, v|
71
+ edge[k] = v
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ graph
78
+ end
79
+ end
80
+ end
@@ -4,13 +4,14 @@
4
4
  <div class="grid-2">
5
5
  <h1>Level<span class="colored-part">Up</span></h1>
6
6
  </div>
7
- <div class="grid-3">
7
+ <div class="grid-4">
8
8
  <ul>
9
9
  <li><%= link_to "Dashboard", root_path, class: "app-link" %></li>
10
10
  <li><%= link_to "Jobs", jobs_path, class: "app-link" %></li>
11
+ <li><%= link_to "Flowcharts", flowcharts_path, class: "app-link" %></li>
11
12
  </ul>
12
13
  </div>
13
- <div class="grid-7">
14
+ <div class="grid-6">
14
15
  <div class="search-bar">
15
16
  <%= form_tag jobs_path, method: :get do %>
16
17
  <%= text_field_tag 'search[key_contains]', nil, placeholder: "Search for jobs by key" %>
@@ -0,0 +1,36 @@
1
+ <div class="container-12">
2
+ <div class="grid-12">
3
+ <div class="breadcrumbs">
4
+ <ul>
5
+ <li><%= link_to "Dashboard", root_path %></li> /
6
+ <li>Flowcharts</li>
7
+ </ul>
8
+ </div>
9
+ </div>
10
+
11
+ <div class="grid-12">
12
+ <table class="table-bordered">
13
+ <thead>
14
+ <tr>
15
+ <th>Type</th>
16
+ <th>Number of tasks</th>
17
+ <th>Number of transitions</th>
18
+ </tr>
19
+ </thead>
20
+ <tbody>
21
+ <% @job_classes.each do |job_class| %>
22
+ <tr>
23
+ <td><%= link_to job_class.name.underscore, flowchart_path(id: job_class.name.underscore) %></td>
24
+ <td><%= job_class.tasks.size %></td>
25
+ <td><%= job_class.schema.values.flatten.size %></td>
26
+ </tr>
27
+ <% end %>
28
+ <% if @job_classes.empty? %>
29
+ <tr>
30
+ <td colspan="3">No classes found</td>
31
+ </tr>
32
+ <% end %>
33
+ </tbody>
34
+ </table>
35
+ </div>
36
+ </div>
@@ -0,0 +1,20 @@
1
+ <div class="container-12">
2
+ <div class="grid-12">
3
+ <div class="breadcrumbs">
4
+ <ul>
5
+ <li><%= link_to "Dashboard", root_path %></li> /
6
+ <li><%= link_to "Flowcharts", flowcharts_path %></li> /
7
+ <li><%= @job_type %></li>
8
+ </ul>
9
+ </div>
10
+ </div>
11
+
12
+ <div class="grid-12">
13
+ <div class="simple-panel">
14
+ <h2>Job Flow</h2>
15
+ <div class="svg-graph">
16
+ <object id="svg-object" data="<%= graphviz_flowchart_path(id: @job_type, format: :svg) %>" type="image/svg+xml"></object>
17
+ </div>
18
+ </div>
19
+ </div>
20
+ </div>
data/config/routes.rb CHANGED
@@ -10,4 +10,8 @@ LevelUp::Engine.routes.draw do
10
10
  get "graphviz"
11
11
  end
12
12
  end
13
+
14
+ resources :flowcharts, only: [:index, :show] do
15
+ get "graphviz", on: :member
16
+ end
13
17
  end
@@ -1,3 +1,3 @@
1
1
  module LevelUp
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -35,7 +35,7 @@ Dummy::Application.configure do
35
35
  # Expands the lines which load the assets
36
36
  config.assets.debug = true
37
37
 
38
- config.level_up.http_authentication = true
39
- config.level_up.http_login = "admin"
40
- config.level_up.http_password = "pwd"
38
+ #config.level_up.http_authentication = true
39
+ #config.level_up.http_login = "admin"
40
+ #config.level_up.http_password = "password"
41
41
  end
@@ -0,0 +1,5 @@
1
+ if Rails.env.development?
2
+ %w[account_banish account_downgrade account_upgrade].each do |job_type|
3
+ require_dependency File.join("app","models", "#{job_type}.rb")
4
+ end
5
+ end
Binary file