bull 0.0.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.
- 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
|