bull 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/bull +8 -0
- data/lib/bull/bcaptcha.rb +0 -0
- data/lib/bull/client.rb +280 -0
- data/lib/bull/encode_times.rb +35 -0
- data/lib/bull/mrelogin.rb +8 -0
- data/lib/bull/mreport.rb +26 -0
- data/lib/bull/notification.rb +87 -0
- data/lib/bull/reactive_var.rb +94 -0
- data/lib/bull/server.rb +468 -0
- data/lib/bull/start.rb +43 -0
- data/lib/bull/symbolize.rb +10 -0
- data/lib/bull/ui_common.rb +18 -0
- data/lib/bull/ui_core.rb +796 -0
- data/lib/bull/utils.rb +45 -0
- data/template/client/main.rb +8 -0
- metadata +115 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cf058fa3501715d4c28484775065f2b5e1e86081
|
4
|
+
data.tar.gz: 50cf31a2465eb99efdea0d460764cf650c8cdea9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 28e18b4f37962a35f3dcbcdb0792f13d1bdc5bac5ad3a9dbd3a583fbfe29b58207c1eab08c5545e07b7a08531bfa358199d74055132bd85129497fba63735a22
|
7
|
+
data.tar.gz: 7a4d66026d3fcff177a9f44ba5502442c2dfe435a08e6fab06309222fd4d30a275c2934381ba3aa80edf805dcd5420febfb663d064547c59211066a79c1e1699
|
data/bin/bull
ADDED
File without changes
|
data/lib/bull/client.rb
ADDED
@@ -0,0 +1,280 @@
|
|
1
|
+
#require 'opal'
|
2
|
+
require 'browser'
|
3
|
+
require 'browser/socket'
|
4
|
+
require 'browser/delay'
|
5
|
+
require 'promise'
|
6
|
+
require 'json'
|
7
|
+
require 'time'
|
8
|
+
require 'bull/encode_times'
|
9
|
+
require 'bull/reactive_var'
|
10
|
+
require 'bull/notification'
|
11
|
+
require 'bull/mrelogin'
|
12
|
+
|
13
|
+
class BullClientController
|
14
|
+
|
15
|
+
include MNotification
|
16
|
+
#include MRelogin
|
17
|
+
|
18
|
+
attr_accessor :app_rendered
|
19
|
+
attr_accessor :ws
|
20
|
+
attr_reader :connection
|
21
|
+
|
22
|
+
@@ticket = 0
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
@user_id = nil
|
26
|
+
@password = nil
|
27
|
+
@watch = {}
|
28
|
+
@promises = {}
|
29
|
+
@ws = nil
|
30
|
+
@app_rendered = false
|
31
|
+
@files = {}
|
32
|
+
|
33
|
+
@connection = RVar.new 'disconnected'
|
34
|
+
reactive(@connection) do
|
35
|
+
if @connection.value == 'disconnected'
|
36
|
+
notify_error 'disconnected', 1
|
37
|
+
else
|
38
|
+
notify_ok 'connected', 1
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def watch(name, *args, &block)
|
44
|
+
id = get_ticket
|
45
|
+
@watch[id] = {who: block, name: name, args: args}
|
46
|
+
send('watch_' + name, id, *args)
|
47
|
+
id
|
48
|
+
end
|
49
|
+
|
50
|
+
def task(name, *args)
|
51
|
+
send 'task_' + name, -1, *args
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_watch
|
55
|
+
@watch
|
56
|
+
end
|
57
|
+
|
58
|
+
def stop_watch(id)
|
59
|
+
@watch.delete(id)
|
60
|
+
send('stop_watch', id)
|
61
|
+
end
|
62
|
+
|
63
|
+
def rpc(command, *args)
|
64
|
+
id = get_ticket
|
65
|
+
promise = Promise.new
|
66
|
+
send 'rpc_'+command, id, *args
|
67
|
+
@promises[id] = promise
|
68
|
+
promise
|
69
|
+
end
|
70
|
+
|
71
|
+
def file(command, *args)
|
72
|
+
id = get_ticket
|
73
|
+
promise = Promise.new
|
74
|
+
send 'file_'+command, id, *args
|
75
|
+
@promises[id] = promise
|
76
|
+
@files[id] = ""
|
77
|
+
promise
|
78
|
+
end
|
79
|
+
|
80
|
+
def insert(table, hsh)
|
81
|
+
prom = rpc('insert', table, value: hsh).then do |response|
|
82
|
+
if response.nil?
|
83
|
+
#$notifications.add ['error', 'data not inserted', 0] if $notifications
|
84
|
+
notify_error 'data not inserted', 0
|
85
|
+
else
|
86
|
+
#$notifications.add ['ok', 'data inserted', 0] if $notifications
|
87
|
+
notify_ok 'data inserted', 0
|
88
|
+
end
|
89
|
+
response
|
90
|
+
end
|
91
|
+
prom
|
92
|
+
end
|
93
|
+
|
94
|
+
def update(table, id, hsh)
|
95
|
+
prom = rpc('update', table, id, value: hsh).then do |count|
|
96
|
+
if count == 0
|
97
|
+
#$notifications.add ['error', 'data not updated', 0] if $notifications
|
98
|
+
notify_error 'data not updated', 0
|
99
|
+
elsif count == 1
|
100
|
+
#$notifications.add ['ok', 'data updated', 0] if $notifications
|
101
|
+
notify_ok 'data updated', 0
|
102
|
+
end
|
103
|
+
count
|
104
|
+
end
|
105
|
+
prom
|
106
|
+
end
|
107
|
+
|
108
|
+
def delete(table, id)
|
109
|
+
#prom = rpc('delete', table, id).then do |count|
|
110
|
+
rpc('delete', table, id).then do |count|
|
111
|
+
if count == 0
|
112
|
+
#$notifications.add ['error', 'data not deleted', 0] if $notifications
|
113
|
+
notify_error 'data not deleted', 0
|
114
|
+
elsif count == 1
|
115
|
+
#$notifications.add ['ok', 'data deleted', 0] if $notifications
|
116
|
+
notify_ok 'data deleted', 0
|
117
|
+
end
|
118
|
+
#count
|
119
|
+
end
|
120
|
+
#prom
|
121
|
+
end
|
122
|
+
|
123
|
+
def login user, password
|
124
|
+
rpc('login', user, password).then do |response|
|
125
|
+
if response
|
126
|
+
@user_id = user
|
127
|
+
@password = password
|
128
|
+
@roles = response
|
129
|
+
notify_ok 'logged', 0
|
130
|
+
else
|
131
|
+
notify_error 'incorrect user or password', 0
|
132
|
+
end
|
133
|
+
response
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def rewatch
|
138
|
+
@watch.each do |id, value|
|
139
|
+
send 'watch_' + value[:name], id, *value[:args]
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def relogin #password
|
144
|
+
login(@user_id, @password).then do |response|
|
145
|
+
if response
|
146
|
+
#show_relogin false
|
147
|
+
notify_ok 'relogged', 0
|
148
|
+
rewatch
|
149
|
+
else
|
150
|
+
notify_error 'password incorrect', 0
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def logout
|
156
|
+
rpc('logout')
|
157
|
+
clear
|
158
|
+
end
|
159
|
+
|
160
|
+
def notify msg
|
161
|
+
begin
|
162
|
+
msg = JSON.parse(msg)
|
163
|
+
data = msg['data'] || msg['result']
|
164
|
+
if data.instance_of?(String) && msg['times'] && msg['times'][0] == 'result'
|
165
|
+
data = Time.parse data
|
166
|
+
else
|
167
|
+
resolve_times data, msg['times']
|
168
|
+
end
|
169
|
+
if msg['response'] == 'watch'
|
170
|
+
handle_watch_data msg['id'], data
|
171
|
+
elsif msg['response'] == 'rpc'
|
172
|
+
handle_rpc_result msg['id'], data
|
173
|
+
elsif msg['response'] == 'file'
|
174
|
+
handle_file_data msg['id'], data, msg['end']
|
175
|
+
end
|
176
|
+
rescue Exception => e
|
177
|
+
#print e.message
|
178
|
+
#print e.backtrace.inspect
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def start(app)
|
183
|
+
begin
|
184
|
+
controller = self
|
185
|
+
url = 'wss://' + `document.location.hostname` + ':3000'
|
186
|
+
@ws = Browser::Socket.new url do
|
187
|
+
on :open do |e|
|
188
|
+
controller.connection.value = 'connected'
|
189
|
+
if !controller.app_rendered
|
190
|
+
$document.ready do
|
191
|
+
React.render(React.create_element(app), `document.getElementById('container')`)
|
192
|
+
controller.app_rendered = true
|
193
|
+
end
|
194
|
+
else
|
195
|
+
if @user_id
|
196
|
+
#controller.show_relogin true
|
197
|
+
controller.relogin
|
198
|
+
else
|
199
|
+
controller.rewatch
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
on :message do |e|
|
204
|
+
begin
|
205
|
+
controller.notify e.data
|
206
|
+
rescue Exception => e
|
207
|
+
#print e.message
|
208
|
+
#print e.backtrace.inspect
|
209
|
+
end
|
210
|
+
end
|
211
|
+
on :close do |e|
|
212
|
+
#print e.message
|
213
|
+
#print e.backtrace.inspect
|
214
|
+
controller.connection.value = 'disconnected'
|
215
|
+
$window.after(5) {controller.reset}
|
216
|
+
|
217
|
+
end
|
218
|
+
end
|
219
|
+
rescue Exception => e
|
220
|
+
#print e.message
|
221
|
+
#print e.backtrace.inspect
|
222
|
+
$window.after(5) {reset}
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
private
|
227
|
+
|
228
|
+
def get_ticket
|
229
|
+
id = @@ticket
|
230
|
+
@@ticket += 1
|
231
|
+
id
|
232
|
+
end
|
233
|
+
|
234
|
+
def send(command, id, *args, **kwargs)
|
235
|
+
times = encode_times(kwargs)
|
236
|
+
msg = {command: command, id: id, args: args, kwargs: kwargs, times: times}.to_json
|
237
|
+
@ws.send(msg)
|
238
|
+
end
|
239
|
+
|
240
|
+
def handle_watch_data(id, data)
|
241
|
+
w = @watch[id]
|
242
|
+
if w
|
243
|
+
w[:who].call data
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def handle_rpc_result(id, result)
|
248
|
+
@promises[id].resolve result
|
249
|
+
@promises.delete id
|
250
|
+
end
|
251
|
+
|
252
|
+
def handle_file_data(id, data, end_)
|
253
|
+
@files[id] << data
|
254
|
+
if end_
|
255
|
+
@promises[id].resolve @files[id]
|
256
|
+
@promises.delete id
|
257
|
+
@files.delete id
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def clear
|
262
|
+
@watch.each_value do |value|
|
263
|
+
value[:who].call nil
|
264
|
+
end
|
265
|
+
@promises = {}
|
266
|
+
@user_id = nil
|
267
|
+
@password = nil
|
268
|
+
@watch = {} ###
|
269
|
+
end
|
270
|
+
|
271
|
+
def reset
|
272
|
+
#clear
|
273
|
+
@watch.each_value do |value|
|
274
|
+
value[:who].call nil
|
275
|
+
end
|
276
|
+
@promises = {}
|
277
|
+
#@watch = {}
|
278
|
+
start nil
|
279
|
+
end
|
280
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'time'
|
2
|
+
|
3
|
+
def resolve_times doc, keys
|
4
|
+
keys.each do |k|
|
5
|
+
d = doc
|
6
|
+
ks = k.split('.')
|
7
|
+
attr = ks.shift.to_sym
|
8
|
+
while ks != []
|
9
|
+
if d.is_a? Array
|
10
|
+
d = d[attr.to_i]
|
11
|
+
else
|
12
|
+
d = d[attr]
|
13
|
+
end
|
14
|
+
attr = ks.shift.to_sym
|
15
|
+
end
|
16
|
+
begin
|
17
|
+
i = Integer(attr.to_s)
|
18
|
+
d[i] = Time.parse d[i]
|
19
|
+
rescue
|
20
|
+
d[attr] = Time.parse d[attr]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def encode_times doc, base=''
|
26
|
+
ret = []
|
27
|
+
if doc.is_a? Array
|
28
|
+
doc.each_with_index { |v, i| ret << encode_times(v, base + '.' + i.to_s)}
|
29
|
+
elsif doc.is_a? Hash
|
30
|
+
doc.each_pair {|k, v| ret << encode_times(v, base + '.' + k.to_s)}
|
31
|
+
elsif doc.is_a? Time
|
32
|
+
return base[1..-1]
|
33
|
+
end
|
34
|
+
ret.flatten
|
35
|
+
end
|
data/lib/bull/mreport.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'liquid'
|
2
|
+
|
3
|
+
module MReport
|
4
|
+
def reports
|
5
|
+
MReport.reports
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.load_reports path
|
9
|
+
@reports = {}
|
10
|
+
#Dir.glob(File.join('..', '..', '**', 'reports' , '*.html')).each do |file|
|
11
|
+
Dir.glob(File.join(path, '**', 'reports' , '*.html')).each do |file|
|
12
|
+
puts "load file #{file}"
|
13
|
+
html = File.read(file)
|
14
|
+
@reports[File.basename(file, '.html')] = Liquid::Template.parse(html)
|
15
|
+
end
|
16
|
+
puts 'reports loaded'
|
17
|
+
@reports
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.reports
|
21
|
+
return @reports #if !@reports.nil?
|
22
|
+
#load_reports
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
#MReport.load_reports
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'reactive-ruby'
|
2
|
+
|
3
|
+
module MNotification
|
4
|
+
def notifications
|
5
|
+
MNotification.notifications
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.notification_controller= controller
|
9
|
+
@notifications = controller
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.notifications
|
13
|
+
@notifications
|
14
|
+
end
|
15
|
+
|
16
|
+
def notify_ok msg, level=10
|
17
|
+
puts msg
|
18
|
+
notifications.add ['ok', msg, level] if !notifications.nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
def notify_error msg, level=10
|
22
|
+
puts msg
|
23
|
+
notifications.add ['error', msg, level] if !notifications.nil?
|
24
|
+
end
|
25
|
+
|
26
|
+
def notify_info msg, level=10
|
27
|
+
puts msg
|
28
|
+
notifications.add ['info', msg, level] if !notifications.nil?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class NotificationController
|
33
|
+
@@ticket = 0
|
34
|
+
|
35
|
+
def initialize panel, level
|
36
|
+
@panel = panel
|
37
|
+
@level = level
|
38
|
+
end
|
39
|
+
|
40
|
+
def add msg
|
41
|
+
return if msg[-1] < @level
|
42
|
+
id = @@ticket
|
43
|
+
@@ticket += 1
|
44
|
+
@panel.append id, ['animated fadeIn'] + msg
|
45
|
+
$window.after(4) do
|
46
|
+
@panel.update id, ['animated fadeOut'] + msg
|
47
|
+
end
|
48
|
+
$window.after(5) do
|
49
|
+
@panel.delete id
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class Notification < React::Component::Base
|
55
|
+
param :level
|
56
|
+
|
57
|
+
before_mount do
|
58
|
+
state.notifications! Hash.new
|
59
|
+
MNotification.notification_controller = NotificationController.new self, params.level
|
60
|
+
end
|
61
|
+
|
62
|
+
def append id, row
|
63
|
+
aux = state.notifications
|
64
|
+
aux[id] = row
|
65
|
+
state.notifications! aux
|
66
|
+
end
|
67
|
+
|
68
|
+
def update id, row
|
69
|
+
aux = state.notifications
|
70
|
+
aux[id] = row
|
71
|
+
state.notifications! aux
|
72
|
+
end
|
73
|
+
|
74
|
+
def delete id
|
75
|
+
aux = state.notifications
|
76
|
+
aux.delete id
|
77
|
+
state.notifications! aux
|
78
|
+
end
|
79
|
+
|
80
|
+
def render
|
81
|
+
div(style: {position: 'absolute'}) do
|
82
|
+
state.notifications.each_pair do |k, (animation, code, v, level)|
|
83
|
+
div(key: k, class: animation + ' notification ' + code){v}
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|