nestene 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +15 -0
- data/.rspec +1 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +31 -0
- data/Rakefile +2 -0
- data/TODO.txt +7 -0
- data/api.rb +8 -0
- data/autons.rb +13 -0
- data/bin/nestene.rb +5 -0
- data/config.ru +21 -0
- data/features/api/api_create_auton.feature +6 -0
- data/features/api/api_credentials.feature +11 -0
- data/features/api/api_list_of_autons.feature +6 -0
- data/features/callback.feature +13 -0
- data/features/create_auton.feature +11 -0
- data/features/credentials.feature +7 -0
- data/features/execute_step.feature +59 -0
- data/features/restart.feature +7 -0
- data/features/schedule_steps.feature +7 -0
- data/features/step_definitions/api/api_create_auton_steps.rb +16 -0
- data/features/step_definitions/api/api_credentials_steps.rb +22 -0
- data/features/step_definitions/api/api_list_of_autons_steps.rb +8 -0
- data/features/step_definitions/callback_steps.rb +75 -0
- data/features/step_definitions/create_auton_steps.rb +32 -0
- data/features/step_definitions/credentials_steps.rb +24 -0
- data/features/step_definitions/execute_step_steps.rb +177 -0
- data/features/step_definitions/restart_steps.rb +5 -0
- data/features/step_definitions/schedule_steps_steps.rb +29 -0
- data/features/step_definitions/time_delayed_steps_steps.rb +103 -0
- data/features/step_definitions/ui/create_auton_steps.rb +21 -0
- data/features/step_definitions/ui/list_of_autons_steps.rb +18 -0
- data/features/step_definitions/ui/schedule_auton_step_steps.rb +64 -0
- data/features/step_definitions/ui/show_auton_steps.rb +49 -0
- data/features/support/env.rb +36 -0
- data/features/time_delayed_steps.feature +28 -0
- data/features/ui/create_auton.feature +7 -0
- data/features/ui/list_of_autons.feature +7 -0
- data/features/ui/schedule_auton_step.feature +12 -0
- data/features/ui/show_auton.feature +14 -0
- data/lib/nestene/actor/auton_queue.rb +87 -0
- data/lib/nestene/actor/auton_storage.rb +50 -0
- data/lib/nestene/actor/core.rb +150 -0
- data/lib/nestene/actor/delayed_scheduler.rb +76 -0
- data/lib/nestene/auton_context.rb +31 -0
- data/lib/nestene/auton_execution_queue.rb +43 -0
- data/lib/nestene/auton_state.rb +27 -0
- data/lib/nestene/callback.rb +7 -0
- data/lib/nestene/delayed_method.rb +17 -0
- data/lib/nestene/executed_method.rb +29 -0
- data/lib/nestene/executing_method.rb +23 -0
- data/lib/nestene/execution_error.rb +39 -0
- data/lib/nestene/scheduled_method.rb +21 -0
- data/lib/nestene/storage.rb +72 -0
- data/lib/nestene/ui/app.rb +103 -0
- data/lib/nestene/ui/public/app/application.js +75 -0
- data/lib/nestene/ui/public/vendor/angular-ui-sortable/sortable.min.js +1 -0
- data/lib/nestene/ui/public/vendor/angular.min.js +248 -0
- data/lib/nestene/ui/public/vendor/bootstrap/css/bootstrap-theme.css +347 -0
- data/lib/nestene/ui/public/vendor/bootstrap/css/bootstrap-theme.min.css +7 -0
- data/lib/nestene/ui/public/vendor/bootstrap/css/bootstrap.css +5785 -0
- data/lib/nestene/ui/public/vendor/bootstrap/css/bootstrap.min.css +7 -0
- data/lib/nestene/ui/public/vendor/bootstrap/fonts/glyphicons-halflings-regular.eot +0 -0
- data/lib/nestene/ui/public/vendor/bootstrap/fonts/glyphicons-halflings-regular.svg +229 -0
- data/lib/nestene/ui/public/vendor/bootstrap/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/lib/nestene/ui/public/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff +0 -0
- data/lib/nestene/ui/public/vendor/bootstrap/js/bootstrap.js +1951 -0
- data/lib/nestene/ui/public/vendor/bootstrap/js/bootstrap.min.js +6 -0
- data/lib/nestene/ui/public/vendor/jquery-ui.min.js +13 -0
- data/lib/nestene/ui/public/vendor/jquery.bootstrap-growl.min.js +1 -0
- data/lib/nestene/ui/public/vendor/jquery.min.js +5 -0
- data/lib/nestene/ui/public/vendor/json-editor/directives.js +245 -0
- data/lib/nestene/ui/public/vendor/json-editor/styles.css +165 -0
- data/lib/nestene/ui/views/auton.haml +42 -0
- data/lib/nestene/ui/views/auton_form.haml +8 -0
- data/lib/nestene/ui/views/index.haml +35 -0
- data/lib/nestene/ui/views/layout.haml +40 -0
- data/lib/nestene/ui/views/schedule_step.haml +14 -0
- data/lib/nestene/version.rb +3 -0
- data/lib/nestene.rb +50 -0
- data/nestene.gemspec +39 -0
- data/spec/nestene/auton_execution_queue_spec.rb +78 -0
- data/spec/nestene/nestene_spec.rb +137 -0
- data/spec/nestene/storage_spec.rb +125 -0
- data/spec/spec_helper.rb +2 -0
- metadata +373 -0
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'celluloid'
|
2
|
+
|
3
|
+
module Nestene
|
4
|
+
module Actor
|
5
|
+
class DelayedScheduler
|
6
|
+
|
7
|
+
include Celluloid
|
8
|
+
include Celluloid::Notifications
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
subscribe('state_update', :update_schedule)
|
12
|
+
@schedule = []
|
13
|
+
@timer = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def update_schedule topic, auton_id, state
|
18
|
+
|
19
|
+
@schedule.delete_if{|e| e.first == auton_id}
|
20
|
+
|
21
|
+
state.queue.delayed.each do |d|
|
22
|
+
@schedule << [auton_id, d]
|
23
|
+
end
|
24
|
+
|
25
|
+
@schedule.sort_by!{|e| e[1].execute_at}
|
26
|
+
|
27
|
+
async.schedule_methods
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
def schedule_methods
|
33
|
+
|
34
|
+
if @timer
|
35
|
+
@timer.cancel
|
36
|
+
end
|
37
|
+
|
38
|
+
now = Time.now
|
39
|
+
|
40
|
+
loop do
|
41
|
+
(auton_id, delayed_method) = @schedule.shift
|
42
|
+
|
43
|
+
if auton_id
|
44
|
+
execute_in = delayed_method.execute_at - now
|
45
|
+
if execute_in <= 0
|
46
|
+
Celluloid::Actor["storage:%s" % auton_id].update do |state|
|
47
|
+
delayed = state.queue.delayed.shift
|
48
|
+
execute_in = delayed.execute_at - now
|
49
|
+
if execute_in <= 0
|
50
|
+
method = ScheduledMethod.new(delayed)
|
51
|
+
state.queue.to_execute << method
|
52
|
+
end
|
53
|
+
if delayed.every
|
54
|
+
delayed.execute_at += delayed.every
|
55
|
+
state.queue.add_delayed(delayed)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
else
|
59
|
+
@schedule.unshift [auton_id, delayed_method]
|
60
|
+
break
|
61
|
+
end
|
62
|
+
else
|
63
|
+
break
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
unless @schedule.empty?
|
68
|
+
to_wait = @schedule.first[1].execute_at - now
|
69
|
+
@timer = after(to_wait){async.schedule_methods}
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Nestene
|
2
|
+
class AutonContext
|
3
|
+
|
4
|
+
def initialize auton_id
|
5
|
+
@auton_id = auton_id
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_accessor :steps_to_schedule
|
9
|
+
|
10
|
+
def schedule_callback auton_id, method, parameters, callback_method
|
11
|
+
Celluloid::Actor[:nestene_core].schedule_step auton_id, method, parameters, @auton_id, callback_method
|
12
|
+
end
|
13
|
+
|
14
|
+
def schedule_step name, parameters=[]
|
15
|
+
Celluloid::Actor[:nestene_core].schedule_step @auton_id, name, parameters
|
16
|
+
end
|
17
|
+
|
18
|
+
def schedule_delayed_step delay, name, parameters=[]
|
19
|
+
Celluloid::Actor[:nestene_core].schedule_delayed_step @auton_id, delay, name, parameters
|
20
|
+
end
|
21
|
+
|
22
|
+
def schedule_repeating_delayed_step every, delay, name, parameters=[]
|
23
|
+
Celluloid::Actor[:nestene_core].schedule_repeating_delayed_step @auton_id, every, delay, name, parameters
|
24
|
+
end
|
25
|
+
|
26
|
+
def credentials
|
27
|
+
Celluloid::Actor[:nestene_core].get_credentials
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'nestene/delayed_method'
|
2
|
+
require 'securerandom'
|
3
|
+
require 'structure_mapper'
|
4
|
+
|
5
|
+
module Nestene
|
6
|
+
class AutonExecutionQueue
|
7
|
+
include StructureMapper::Hash
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
self.to_execute = []
|
11
|
+
self.executed = []
|
12
|
+
self.delayed = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_delayed_method name, parameters, delay, every = nil
|
16
|
+
delayed_method = DelayedMethod.new
|
17
|
+
delayed_method.uuid = SecureRandom.uuid
|
18
|
+
delayed_method.name = name
|
19
|
+
delayed_method.parameters = parameters
|
20
|
+
delayed_method.execute_at = Time.now + delay
|
21
|
+
delayed_method.every = every
|
22
|
+
add_delayed(delayed_method)
|
23
|
+
delayed_method
|
24
|
+
end
|
25
|
+
|
26
|
+
def add_delayed delayed_method
|
27
|
+
delayed << delayed_method
|
28
|
+
delayed.sort_by! {|x| x.execute_at}
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
def remove_delayed_method method_uuid
|
33
|
+
delayed.delete_if{|m| m.uuid == method_uuid}
|
34
|
+
end
|
35
|
+
|
36
|
+
attribute failed: Boolean
|
37
|
+
attribute to_execute: [ScheduledMethod]
|
38
|
+
attribute executed: [ExecutedMethod]
|
39
|
+
attribute currently_executing: ExecutingMethod
|
40
|
+
attribute delayed: [DelayedMethod]
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Nestene
|
2
|
+
class AutonState
|
3
|
+
|
4
|
+
include StructureMapper::Hash
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
self.queue=AutonExecutionQueue.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def state
|
11
|
+
if queue.currently_executing == nil
|
12
|
+
queue.failed ? :failed : :ready
|
13
|
+
else
|
14
|
+
:running
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
attribute type: String
|
19
|
+
attribute serialized: {}
|
20
|
+
attribute queue: AutonExecutionQueue
|
21
|
+
|
22
|
+
def type_as_class
|
23
|
+
self.type ? Nestene::class_from_string(self.type) : nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Nestene
|
2
|
+
class DelayedMethod
|
3
|
+
include StructureMapper::Hash
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
self.parameters = []
|
7
|
+
self.scheduled_at = Time.now
|
8
|
+
end
|
9
|
+
|
10
|
+
attribute name: Symbol
|
11
|
+
attribute parameters: []
|
12
|
+
attribute uuid: String
|
13
|
+
attribute scheduled_at: Time
|
14
|
+
attribute execute_at: Time
|
15
|
+
attribute every: Float
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Nestene
|
2
|
+
class ExecutedMethod
|
3
|
+
include StructureMapper::Hash
|
4
|
+
|
5
|
+
def initialize(executing_method = nil)
|
6
|
+
self.parameters = []
|
7
|
+
if executing_method
|
8
|
+
self.name = executing_method.name
|
9
|
+
self.parameters = executing_method.parameters
|
10
|
+
self.uuid = executing_method.uuid
|
11
|
+
self.scheduled_at = executing_method.scheduled_at
|
12
|
+
self.started_at = executing_method.started_at
|
13
|
+
self.duration = Time.now - executing_method.started_at
|
14
|
+
self.callback = executing_method.callback
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
attribute name: Symbol
|
19
|
+
attribute parameters: []
|
20
|
+
attribute uuid: String
|
21
|
+
attribute result: {}
|
22
|
+
attribute error: Exception
|
23
|
+
attribute scheduled_at: Time
|
24
|
+
attribute started_at: Time
|
25
|
+
attribute duration: Float
|
26
|
+
attribute callback: Callback
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Nestene
|
2
|
+
class ExecutingMethod
|
3
|
+
include StructureMapper::Hash
|
4
|
+
|
5
|
+
def initialize(scheduled_method = nil)
|
6
|
+
if scheduled_method
|
7
|
+
self.name = scheduled_method.name
|
8
|
+
self.parameters = scheduled_method.parameters
|
9
|
+
self.uuid = scheduled_method.uuid
|
10
|
+
self.scheduled_at = scheduled_method.scheduled_at
|
11
|
+
self.started_at = Time.now
|
12
|
+
self.callback = scheduled_method.callback
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
attribute name: Symbol
|
17
|
+
attribute parameters: []
|
18
|
+
attribute uuid: String
|
19
|
+
attribute scheduled_at: Time
|
20
|
+
attribute started_at: Time
|
21
|
+
attribute callback: Callback
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Nestene
|
2
|
+
|
3
|
+
class ExecutionError
|
4
|
+
include StructureMapper::Hash
|
5
|
+
|
6
|
+
def initialize(exception = nil)
|
7
|
+
|
8
|
+
if exception
|
9
|
+
self.message = exception.message
|
10
|
+
self.type = exception.class.name
|
11
|
+
self.backtrace = exception.backtrace
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
attribute message: String
|
16
|
+
attribute type: String
|
17
|
+
attribute backtrace: [String]
|
18
|
+
|
19
|
+
|
20
|
+
def to_exception
|
21
|
+
exception = Nestene.class_from_string(type).new(message)
|
22
|
+
exception.set_backtrace self.backtrace
|
23
|
+
exception
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
class Exception
|
30
|
+
|
31
|
+
def to_structure
|
32
|
+
Nestene::ExecutionError.new(self).to_structure
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.from_structure structure
|
36
|
+
structure ? Nestene::ExecutionError.from_structure(structure).to_exception : nil
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Nestene
|
2
|
+
class ScheduledMethod
|
3
|
+
include StructureMapper::Hash
|
4
|
+
|
5
|
+
def initialize(delayed_method = nil)
|
6
|
+
self.parameters = []
|
7
|
+
self.scheduled_at = Time.now
|
8
|
+
if delayed_method
|
9
|
+
self.uuid = delayed_method.uuid
|
10
|
+
self.name = delayed_method.name
|
11
|
+
self.parameters = delayed_method.parameters
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
attribute name: Symbol
|
16
|
+
attribute parameters: []
|
17
|
+
attribute uuid: String
|
18
|
+
attribute scheduled_at: Time
|
19
|
+
attribute callback: Callback
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Nestene
|
4
|
+
|
5
|
+
|
6
|
+
class FileNameConverter
|
7
|
+
|
8
|
+
def key_to_file_name(key)
|
9
|
+
key.gsub(/[^a-zA-Z0-9]/){|x| "_%x" % x.ord}
|
10
|
+
end
|
11
|
+
|
12
|
+
def file_name_to_key file_name
|
13
|
+
file_name.gsub(/_[a-zA-Z0-9]{2}/){|x| x[1..-1].hex.chr}
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
class DiskStorage
|
19
|
+
|
20
|
+
def initialize(dir)
|
21
|
+
@dir=dir
|
22
|
+
@converter = FileNameConverter.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def list
|
26
|
+
entries = Dir.entries(@dir)
|
27
|
+
entries.delete('.')
|
28
|
+
entries.delete('..')
|
29
|
+
entries.delete('__credentials__')
|
30
|
+
entries.map{|fn| @converter.file_name_to_key(fn)}
|
31
|
+
end
|
32
|
+
|
33
|
+
def store(key, value)
|
34
|
+
final_name = "%s/%s" % [@dir,@converter.key_to_file_name(key)]
|
35
|
+
tmp_name = "%s.temp" % final_name
|
36
|
+
File.open(tmp_name,"w") do |f|
|
37
|
+
f.write(JSON.pretty_generate(value))
|
38
|
+
end
|
39
|
+
File.rename(tmp_name, final_name)
|
40
|
+
end
|
41
|
+
|
42
|
+
def load(key)
|
43
|
+
file_name = "%s/%s" % [@dir,@converter.key_to_file_name(key)]
|
44
|
+
if File.exist?(file_name)
|
45
|
+
File.open(file_name,"r"){|f| JSON.parse(f.read)}
|
46
|
+
else
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
class MemoryStorage
|
54
|
+
|
55
|
+
def initialize
|
56
|
+
@storage = {}
|
57
|
+
end
|
58
|
+
|
59
|
+
def list
|
60
|
+
@storage.keys
|
61
|
+
end
|
62
|
+
|
63
|
+
def load(key)
|
64
|
+
@storage[key]
|
65
|
+
end
|
66
|
+
|
67
|
+
def store(key, value)
|
68
|
+
@storage[key] = value
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'haml'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Nestene
|
6
|
+
module Ui
|
7
|
+
class App < Sinatra::Base
|
8
|
+
|
9
|
+
|
10
|
+
get '/autons.json' do
|
11
|
+
content_type :json
|
12
|
+
Celluloid::Actor[:nestene_core].auton_names.to_json
|
13
|
+
end
|
14
|
+
|
15
|
+
get '/credentials' do
|
16
|
+
content_type :json
|
17
|
+
Celluloid::Actor[:nestene_core].get_credentials.to_json
|
18
|
+
end
|
19
|
+
|
20
|
+
post '/credentials' do
|
21
|
+
content_type :json
|
22
|
+
begin
|
23
|
+
credentials = JSON.parse(request.body.read)
|
24
|
+
auton_id = Celluloid::Actor[:nestene_core].set_credentials credentials
|
25
|
+
status 200
|
26
|
+
rescue Exception => e
|
27
|
+
puts e
|
28
|
+
status 500
|
29
|
+
{message: e.message}.to_json
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
post '/autons' do
|
34
|
+
content_type :json
|
35
|
+
begin
|
36
|
+
type = JSON.parse(request.body.read).fetch('auton_type')
|
37
|
+
raise "auton_type not set" unless type
|
38
|
+
auton_id = Celluloid::Actor[:nestene_core].create_auton type
|
39
|
+
status 201
|
40
|
+
{auton_id: auton_id}.to_json
|
41
|
+
rescue Exception => e
|
42
|
+
status 500
|
43
|
+
{message: e.message}.to_json
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
get '/' do
|
49
|
+
@auton_names = Celluloid::Actor[:nestene_core].auton_names
|
50
|
+
haml :index
|
51
|
+
end
|
52
|
+
|
53
|
+
get '/auton/create' do
|
54
|
+
haml :auton_form
|
55
|
+
end
|
56
|
+
|
57
|
+
get '/auton/:id' do
|
58
|
+
@auton_id = params[:id]
|
59
|
+
@auton_state = Celluloid::Actor[:nestene_core].get_state(@auton_id)
|
60
|
+
haml :auton
|
61
|
+
end
|
62
|
+
|
63
|
+
get '/auton/:id/schedule_step' do
|
64
|
+
@auton_id = params[:id]
|
65
|
+
@auton_state = Celluloid::Actor[:nestene_core].get_state(@auton_id)
|
66
|
+
auton_type = @auton_state.type_as_class
|
67
|
+
@available_methods = auton_type.instance_methods(false).map{|name| auton_type.instance_method(name)}
|
68
|
+
@number_of_params = 0
|
69
|
+
haml :schedule_step
|
70
|
+
end
|
71
|
+
|
72
|
+
post '/auton/:id/schedule_step' do
|
73
|
+
parameters = params[:parameters] || []
|
74
|
+
step_name = params[:step_name]
|
75
|
+
|
76
|
+
@auton_id = params[:id]
|
77
|
+
@auton_state = Celluloid::Actor[:nestene_core].get_state(@auton_id)
|
78
|
+
auton_type = @auton_state.type_as_class
|
79
|
+
@available_methods = auton_type.instance_methods(false).sort.map{|name| auton_type.instance_method(name)}
|
80
|
+
|
81
|
+
method = @available_methods.find{|m| m.name.to_s == step_name}
|
82
|
+
|
83
|
+
if method && method.arity == parameters.size
|
84
|
+
step_id = Celluloid::Actor[:nestene_core].schedule_step(params[:id],step_name, parameters)
|
85
|
+
headers['X-AUTON-STEP-ID'] = step_id
|
86
|
+
redirect '/auton/%s' % params[:id]
|
87
|
+
else
|
88
|
+
@method = method
|
89
|
+
@number_of_params = method ? method.arity : 0
|
90
|
+
@step_name = step_name
|
91
|
+
haml :schedule_step
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
post '/auton/create' do
|
96
|
+
Celluloid::Actor[:nestene_core].create_auton params[:auton_type]
|
97
|
+
redirect '/'
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
var nestene = angular.module('nestene', ['JSONedit']);
|
2
|
+
|
3
|
+
nestene.controller('AutonsController', function($scope, $http, $timeout) {
|
4
|
+
$scope.autons=[];
|
5
|
+
|
6
|
+
$scope.getAutons = function() {
|
7
|
+
var autonsPromise = $http.get("autons.json");
|
8
|
+
autonsPromise.success(function(data, status, headers, config) {
|
9
|
+
$scope.autons = data;
|
10
|
+
});
|
11
|
+
|
12
|
+
autonsPromise.error(function(data, status, headers, config) {
|
13
|
+
$.bootstrapGrowl("getting autons failed!", { type: 'danger' });
|
14
|
+
});
|
15
|
+
}
|
16
|
+
|
17
|
+
$scope.intervalFunction = function() {
|
18
|
+
$timeout(function() {
|
19
|
+
$scope.getAutons();
|
20
|
+
$scope.intervalFunction();
|
21
|
+
}, 1000);
|
22
|
+
};
|
23
|
+
|
24
|
+
$scope.intervalFunction();
|
25
|
+
|
26
|
+
});
|
27
|
+
|
28
|
+
nestene.controller('CreateAutonFormController', function($scope,$http) {
|
29
|
+
$scope.autonType = '';
|
30
|
+
$scope.createAuton = function() {
|
31
|
+
var postPromise = $http.post("autons",{auton_type: $scope.autonType});
|
32
|
+
postPromise.success(function(data, status, headers, config) {
|
33
|
+
$.bootstrapGrowl("Created "+data['auton_id'], { type: 'success' });
|
34
|
+
});
|
35
|
+
postPromise.error(function(data, status, headers, config) {
|
36
|
+
$.bootstrapGrowl("Could not create Auton: "+data['message'], { type: 'error' });
|
37
|
+
});
|
38
|
+
};
|
39
|
+
});
|
40
|
+
|
41
|
+
nestene.controller('CredentialsController', function($scope,$http) {
|
42
|
+
$scope.credentials={};
|
43
|
+
$scope.loaded = false;
|
44
|
+
|
45
|
+
|
46
|
+
$scope.loadCredentials = function() {
|
47
|
+
var getPromise = $http.get("credentials");
|
48
|
+
getPromise.success(function(data, status, headers, config) {
|
49
|
+
$scope.credentials = data;
|
50
|
+
$scope.loaded = true;
|
51
|
+
});
|
52
|
+
|
53
|
+
getPromise.error(function(data, status, headers, config) {
|
54
|
+
$.bootstrapGrowl("getting credentials failed!", { type: 'danger' });
|
55
|
+
});
|
56
|
+
}
|
57
|
+
|
58
|
+
$scope.loadCredentials();
|
59
|
+
|
60
|
+
$scope.storeCredentials = function() {
|
61
|
+
var postPromise = $http.post("credentials",$scope.credentials);
|
62
|
+
postPromise.success(function(data, status, headers, config) {
|
63
|
+
$.bootstrapGrowl("Credentials saved", { type: 'success' });
|
64
|
+
});
|
65
|
+
postPromise.error(function(data, status, headers, config) {
|
66
|
+
$.bootstrapGrowl("Could not save credentials", { type: 'danger' });
|
67
|
+
});
|
68
|
+
};
|
69
|
+
});
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
!function(a,b){"use strict";b.module("ui.sortable",[]).value("uiSortableConfig",{}).directive("uiSortable",["uiSortableConfig","$timeout","$log",function(a,c,d){return{require:"?ngModel",link:function(e,f,g,h){function i(a,b){return b&&"function"==typeof b?function(c,d){a(c,d),b(c,d)}:a}function j(a,b){var c=a.sortable("option","helper");return"clone"===c||"function"==typeof c&&b.item.sortable.isCustomHelperUsed()}var k,l={},m={receive:null,remove:null,start:null,stop:null,update:null},n={helper:null};return b.extend(l,a,e.$eval(g.uiSortable)),b.element.fn&&b.element.fn.jquery?(h?(e.$watch(g.ngModel+".length",function(){c(function(){f.data("ui-sortable")&&f.sortable("refresh")})}),m.start=function(a,b){b.item.sortable={index:b.item.index(),cancel:function(){b.item.sortable._isCanceled=!0},isCanceled:function(){return b.item.sortable._isCanceled},isCustomHelperUsed:function(){return!!b.item.sortable._isCustomHelperUsed},_isCanceled:!1,_isCustomHelperUsed:b.item.sortable._isCustomHelperUsed}},m.activate=function(){k=f.contents();var a=f.sortable("option","placeholder");if(a&&a.element&&"function"==typeof a.element){var c=a.element();c=b.element(c);var d=f.find('[class="'+c.attr("class")+'"]');k=k.not(d)}},m.update=function(a,b){b.item.sortable.received||(b.item.sortable.dropindex=b.item.index(),b.item.sortable.droptarget=b.item.parent(),f.sortable("cancel")),j(f,b)&&!b.item.sortable.received&&(k=k.not(k.last())),k.appendTo(f),b.item.sortable.received&&(k=null),b.item.sortable.received&&!b.item.sortable.isCanceled()&&e.$apply(function(){h.$modelValue.splice(b.item.sortable.dropindex,0,b.item.sortable.moved)})},m.stop=function(a,b){!b.item.sortable.received&&"dropindex"in b.item.sortable&&!b.item.sortable.isCanceled()?e.$apply(function(){h.$modelValue.splice(b.item.sortable.dropindex,0,h.$modelValue.splice(b.item.sortable.index,1)[0])}):"dropindex"in b.item.sortable&&!b.item.sortable.isCanceled()||j(f,b)||k.appendTo(f),k=null},m.receive=function(a,b){b.item.sortable.received=!0},m.remove=function(a,b){"dropindex"in b.item.sortable||(f.sortable("cancel"),b.item.sortable.cancel()),b.item.sortable.isCanceled()||e.$apply(function(){b.item.sortable.moved=h.$modelValue.splice(b.item.sortable.index,1)[0]})},n.helper=function(a){return a&&"function"==typeof a?function(b,c){var d=a(b,c);return c.sortable._isCustomHelperUsed=c!==d,d}:a},e.$watch(g.uiSortable,function(a){f.data("ui-sortable")&&b.forEach(a,function(a,b){m[b]?("stop"===b&&(a=i(a,function(){e.$apply()})),a=i(m[b],a)):n[b]&&(a=n[b](a)),f.sortable("option",b,a)})},!0),b.forEach(m,function(a,b){l[b]=i(a,l[b])})):d.info("ui.sortable: ngModel not provided!",f),void f.sortable(l)):void d.error("ui.sortable: jQuery should be included before AngularJS!")}}}])}(window,window.angular);
|