rbbt-rest 1.9.1 → 2.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 +4 -4
- data/lib/rbbt/rest/common/cache.rb +13 -5
- data/lib/rbbt/rest/common/locate.rb +4 -3
- data/lib/rbbt/rest/common/misc.rb +36 -6
- data/lib/rbbt/rest/common/render.rb +12 -6
- data/lib/rbbt/rest/common/table.rb +14 -48
- data/lib/rbbt/rest/entity/helpers.rb +1 -1
- data/lib/rbbt/rest/entity/locate.rb +4 -10
- data/lib/rbbt/rest/entity/render.rb +1 -2
- data/lib/rbbt/rest/entity/rest.rb +1 -2
- data/lib/rbbt/rest/entity.rb +3 -1
- data/lib/rbbt/rest/main.rb +2 -1
- data/lib/rbbt/rest/workflow/jobs.rb +6 -2
- data/lib/rbbt/rest/workflow/locate.rb +1 -1
- data/lib/rbbt/rest/workflow.rb +2 -1
- data/share/views/entity_partials/action_controller.haml +1 -1
- data/share/views/entity_partials/entity_card.haml +1 -1
- data/share/views/entity_partials/entity_map_card.haml +1 -1
- data/share/views/error.haml +9 -8
- data/share/views/job_info.haml +3 -2
- data/share/views/job_result/text.haml +3 -1
- data/share/views/job_result.haml +1 -1
- data/share/views/layout/top_menu.haml +18 -4
- data/share/views/partials/dependencies.haml +74 -73
- data/share/views/partials/form.haml +3 -2
- data/share/views/partials/table.haml +6 -1
- data/share/views/public/js/rbbt/list.js +1 -1
- data/share/views/tasks.haml +2 -4
- data/share/views/tools/Rggplot.haml +6 -2
- data/share/views/wait.haml +23 -16
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee4b57a3f56a52f3fee6a0a1b8827835d7b0c8d45376be1f666faf4501451560
|
4
|
+
data.tar.gz: f703d52fc992dc38937859074ee046d06ac6028b596536f8ec4ebddcf5445144
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd74b954053885e3eb8fa97d3c160cc3d4c148dc18f4f013489d296dc07cad2ca93b577e8119fc82240ea7ad5e49ed60545460a7684ebe592cb1a1567a72d6eb
|
7
|
+
data.tar.gz: 1ed08a5a7b9ecd465acb27e4cedff76affdb581980449883c2540f3ff941ee4bfdcfdc0a3c621d66e6f283d9bcecedfe046478f0423f995fcac40d29d55e45fe
|
@@ -50,17 +50,22 @@ module RbbtRESTHelpers
|
|
50
50
|
params[:cache_file]
|
51
51
|
else
|
52
52
|
if post_hash = params["__post_hash_id"]
|
53
|
-
name = name.gsub("/",'
|
53
|
+
name = name.gsub("/",'·') << "_" << post_hash
|
54
54
|
elsif params
|
55
55
|
param_hash = Misc.obj2digest(params)
|
56
|
-
name = name.gsub("/",'
|
56
|
+
name = name.gsub("/",'·') << "_" << param_hash
|
57
57
|
end
|
58
58
|
settings.cache_dir[name].find
|
59
59
|
end
|
60
60
|
|
61
61
|
task = Task.setup(:name => orig_name, :result_type => :string, &block)
|
62
62
|
|
63
|
-
|
63
|
+
if defined?(Scout)
|
64
|
+
step = Step.new(path, nil, nil, self, &task)
|
65
|
+
step.exec_context = self
|
66
|
+
else
|
67
|
+
step = Step.new(path, task, nil, nil, self)
|
68
|
+
end
|
64
69
|
|
65
70
|
halt 200, step.info.to_json if @format == :info
|
66
71
|
|
@@ -103,7 +108,9 @@ module RbbtRESTHelpers
|
|
103
108
|
#step.instance_variable_set(:@url_path, URI(clean_url).path)
|
104
109
|
step.instance_variable_set(:@url, clean_url)
|
105
110
|
step.instance_variable_set(:@url_path, URI(clean_url).path)
|
106
|
-
step.
|
111
|
+
if (step.error? && step.recoverable_error?) || step.aborted?
|
112
|
+
step.clean
|
113
|
+
end
|
107
114
|
|
108
115
|
Thread.current["step_path"] = step.path
|
109
116
|
# Issue
|
@@ -170,7 +177,7 @@ module RbbtRESTHelpers
|
|
170
177
|
tsv = tsv_process(raw_tsv)
|
171
178
|
|
172
179
|
list = tsv.values.flatten
|
173
|
-
tsv.prepare_entity(list, tsv.fields.first, tsv.entity_options)
|
180
|
+
list = tsv.prepare_entity(list, tsv.fields.first, tsv.entity_options)
|
174
181
|
type = list.annotation_types.last
|
175
182
|
list_id = "List of #{type} in table #{ @fragment }"
|
176
183
|
list_id << " (#{ @filter })" if @filter
|
@@ -306,6 +313,7 @@ data = NULL
|
|
306
313
|
begin
|
307
314
|
|
308
315
|
if step.done?
|
316
|
+
step.join
|
309
317
|
case
|
310
318
|
when @permalink
|
311
319
|
redirect to(permalink(step.path))
|
@@ -10,7 +10,8 @@ module RbbtRESTHelpers
|
|
10
10
|
def add_search_paths(path, resources)
|
11
11
|
resources.reverse.each do |resource|
|
12
12
|
name = Misc.snake_case(resource.to_s.gsub('/','_'))
|
13
|
-
path.prepend_search_path(name, resource)
|
13
|
+
#path.prepend_search_path(name, resource)
|
14
|
+
path.prepend_path(name, resource)
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
@@ -38,11 +39,11 @@ module RbbtRESTHelpers
|
|
38
39
|
#{{{ TEMPLATE
|
39
40
|
|
40
41
|
def self.template_resources
|
41
|
-
|
42
|
+
@@template_resources ||= [Rbbt.share.views.find(:lib)]
|
42
43
|
end
|
43
44
|
|
44
45
|
def template_resources
|
45
|
-
|
46
|
+
[Rbbt.www.views] + RbbtRESTHelpers.template_resources
|
46
47
|
end
|
47
48
|
|
48
49
|
def locate_template(template)
|
@@ -4,6 +4,11 @@ require 'haml'
|
|
4
4
|
module RbbtRESTHelpers
|
5
5
|
class Retry < Exception; end
|
6
6
|
|
7
|
+
def persist(name, type = :marshal, options = {}, &block)
|
8
|
+
options[:dir] = settings.cache_dir.find
|
9
|
+
Persist.persist(name, type, options, &block)
|
10
|
+
end
|
11
|
+
|
7
12
|
def check_step(step)
|
8
13
|
if File.exist?(step.info_file) and Time.now - File.atime(step.info_file) > 60
|
9
14
|
done = step.done?
|
@@ -57,7 +62,12 @@ module RbbtRESTHelpers
|
|
57
62
|
end
|
58
63
|
|
59
64
|
def process_common_parameters
|
65
|
+
process_request_and_params(request, params)
|
66
|
+
end
|
67
|
+
|
68
|
+
def process_request_and_params(request, params)
|
60
69
|
@ajax = request.xhr?
|
70
|
+
@params = params
|
61
71
|
|
62
72
|
@uri = request.env["REQUEST_URI"]
|
63
73
|
@uri = remove_GET_param(@uri, ["_update", "_", "_layout"])
|
@@ -66,12 +76,12 @@ module RbbtRESTHelpers
|
|
66
76
|
|
67
77
|
@uri = post_uri if @is_method_post
|
68
78
|
|
69
|
-
@
|
79
|
+
@path_info = request.env["PATH_INFO"]
|
70
80
|
@query = request.env["QUERY_STRING"]
|
71
|
-
@fullpath = (@query && ! @query.empty?) ? @
|
81
|
+
@fullpath = (@query && ! @query.empty?) ? @path_info + "?" + @query : @path_info
|
72
82
|
@fullpath = remove_GET_param(@fullpath, ["_update", "_", "_layout"])
|
73
83
|
|
74
|
-
@ajax_url = @
|
84
|
+
@ajax_url = @fullpath
|
75
85
|
|
76
86
|
@layout = consume_parameter(:_layout)
|
77
87
|
|
@@ -143,7 +153,7 @@ module RbbtRESTHelpers
|
|
143
153
|
end
|
144
154
|
|
145
155
|
def consume_parameter(parameter, params = nil)
|
146
|
-
params = self.params if params.nil?
|
156
|
+
params = @params ||= self.params if params.nil?
|
147
157
|
|
148
158
|
val = params.delete(parameter.to_sym)
|
149
159
|
val = params.delete(parameter.to_s) if val.nil?
|
@@ -274,10 +284,14 @@ module RbbtRESTHelpers
|
|
274
284
|
param.each do |p|
|
275
285
|
url = remove_GET_param(url, p)
|
276
286
|
end
|
277
|
-
url
|
278
287
|
else
|
279
|
-
url.gsub(
|
288
|
+
url = url.gsub(/(\?|&)#{param}=[^&]+/,'\1')
|
280
289
|
end
|
290
|
+
|
291
|
+
url = url.sub(/&$/, '')
|
292
|
+
url = url.sub(/\?$/,'')
|
293
|
+
|
294
|
+
url
|
281
295
|
end
|
282
296
|
|
283
297
|
def add_GET_param(url, param, value)
|
@@ -320,6 +334,22 @@ module RbbtRESTHelpers
|
|
320
334
|
halt response, html
|
321
335
|
end
|
322
336
|
|
337
|
+
def capture(*args, &block)
|
338
|
+
|
339
|
+
variables = block.binding.local_variables
|
340
|
+
buff_var = variables.select{|v| v.to_s =~ /^_module\d+$/}.sort_by{|v| v.to_s.scan(/\d+/).first.to_i}.last
|
341
|
+
buff_was = block.binding.local_variable_get(buff_var) if variables.include? buff_var
|
342
|
+
block.binding.local_variable_set(buff_var,'') if buff_var
|
343
|
+
begin
|
344
|
+
raw = block.call(*args)
|
345
|
+
captured = block.binding.local_variable_get(buff_var) if block.binding.local_variables.include?(buff_var)
|
346
|
+
captured = "" if captured.nil?
|
347
|
+
captured = raw if captured.empty?
|
348
|
+
captured
|
349
|
+
ensure
|
350
|
+
block.binding.local_variable_set(buff_var, buff_was) if buff_was
|
351
|
+
end
|
352
|
+
end
|
323
353
|
end
|
324
354
|
|
325
355
|
if $haml_6
|
@@ -6,9 +6,15 @@ Tilt::SYMBOL_ARRAY_SORTABLE = false
|
|
6
6
|
module RbbtRESTHelpers
|
7
7
|
def error_for(job, layout = nil)
|
8
8
|
if ex = job.info[:exception]
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
if Exception === ex
|
10
|
+
klass = ex.class
|
11
|
+
msg = ex.message
|
12
|
+
bkt = ex.backtrace
|
13
|
+
else
|
14
|
+
klass = ex[:class]
|
15
|
+
msg = ex[:message]
|
16
|
+
bkt = ex[:backtrace]
|
17
|
+
end
|
12
18
|
elsif job.dirty?
|
13
19
|
klass = "Exception"
|
14
20
|
msg = "Job dirty"
|
@@ -232,7 +238,7 @@ module RbbtRESTHelpers
|
|
232
238
|
filename = Misc.sanitize_filename(Misc.name2basename(filename))
|
233
239
|
|
234
240
|
if @step
|
235
|
-
url = add_GET_param(remove_GET_param(@
|
241
|
+
url = add_GET_param(remove_GET_param(@fullpath, ["_update", "_"]), "_fragment", "html_resources/#{ filename }")
|
236
242
|
f = @step.file(:html_resources)[filename].find
|
237
243
|
else
|
238
244
|
url = "/files/#{ filename }"
|
@@ -249,7 +255,7 @@ module RbbtRESTHelpers
|
|
249
255
|
when :image
|
250
256
|
"<img src='#{url}' alt='#{text}' class='file_resource'/>"
|
251
257
|
when :link
|
252
|
-
"<a href='#{url}' class='file_resource'>#{ text }</a>"
|
258
|
+
"<a href='#{url}' class='file_resource' download='#{filename}'>#{ text }</a>"
|
253
259
|
when :linked_image
|
254
260
|
"<a href='#{url}' class='file_resource' target='_blank'><img src='#{url}' class='file_resource'/></a>"
|
255
261
|
when :zoomable_image
|
@@ -270,7 +276,7 @@ module RbbtRESTHelpers
|
|
270
276
|
filename = File.basename(TmpFile.tmp_file) if filename.nil?
|
271
277
|
|
272
278
|
if @step
|
273
|
-
url = add_GET_param(remove_GET_param(@
|
279
|
+
url = add_GET_param(remove_GET_param(@fullpath, ["_update", "_"]), "_fragment", "json_resources/#{ filename }")
|
274
280
|
f = @step.file(:json_resources)[filename].find
|
275
281
|
else
|
276
282
|
url = "/files/#{ filename }"
|
@@ -77,6 +77,12 @@ module NumericValue
|
|
77
77
|
extend Entity
|
78
78
|
|
79
79
|
self.format =(<<-EOF
|
80
|
+
NumericValue
|
81
|
+
Numeric Value
|
82
|
+
Numeric
|
83
|
+
numeric_value
|
84
|
+
numeric value
|
85
|
+
numeric
|
80
86
|
p-value
|
81
87
|
p-value
|
82
88
|
p.value
|
@@ -147,44 +153,19 @@ end
|
|
147
153
|
|
148
154
|
module RbbtRESTHelpers
|
149
155
|
|
150
|
-
def capture(*args, &block)
|
151
|
-
|
152
|
-
variables = block.binding.local_variables
|
153
|
-
#variables.each do |v|
|
154
|
-
# iif [v, block.binding.local_variable_get(v)]
|
155
|
-
#end
|
156
|
-
buff_var = variables.select{|v| v.to_s =~ /^_module\d+$/}.sort_by{|v| v.to_s.scan(/\d+/).first.to_i}.last
|
157
|
-
buff_was = block.binding.local_variable_get(buff_var) if variables.include? buff_var
|
158
|
-
block.binding.local_variable_set(buff_var,'') if buff_var
|
159
|
-
begin
|
160
|
-
raw = block.call(*args)
|
161
|
-
#variables = block.binding.local_variables
|
162
|
-
#iii variables
|
163
|
-
#variables.each do |v|
|
164
|
-
# iif [v, block.binding.local_variable_get(v)]
|
165
|
-
#end
|
166
|
-
captured = block.binding.local_variable_get(buff_var) if block.binding.local_variables.include?(buff_var)
|
167
|
-
captured = "" if captured.nil?
|
168
|
-
captured = raw if captured.empty?
|
169
|
-
captured
|
170
|
-
ensure
|
171
|
-
block.binding.local_variable_set(buff_var, buff_was) if buff_was
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
156
|
def tsv_rows_full(tsv)
|
176
157
|
case tsv.type
|
177
158
|
when :single
|
178
159
|
tsv.collect{|id, value| [id, value]}
|
179
160
|
when :list
|
180
161
|
key_field = tsv.key_field
|
181
|
-
tsv.collect{|id, values| new_values = [id].concat(values); begin NamedArray.setup(new_values, values.fields, id, values.entity_options
|
162
|
+
tsv.collect{|id, values| new_values = [id].concat(values); begin NamedArray.setup(new_values, values.fields, id, values.entity_options); new_values.fields = [key_field].concat values.fields end if values.respond_to? :fields; new_values }
|
182
163
|
when :flat
|
183
164
|
key_field = tsv.key_field
|
184
165
|
tsv.collect{|id, values| [id, values]}
|
185
166
|
when :double
|
186
167
|
key_field = tsv.key_field
|
187
|
-
tsv.collect{|id, value_lists| new_value_lists = [id].concat(value_lists); begin NamedArray.setup(new_value_lists, value_lists.fields, id, value_lists.entity_options
|
168
|
+
tsv.collect{|id, value_lists| new_value_lists = [id].concat(value_lists); begin NamedArray.setup(new_value_lists, value_lists.fields, id, value_lists.entity_options); new_value_lists.fields = ([key_field].concat value_lists.fields) end if value_lists.respond_to? :fields; new_value_lists }
|
188
169
|
end
|
189
170
|
end
|
190
171
|
|
@@ -195,6 +176,7 @@ module RbbtRESTHelpers
|
|
195
176
|
|
196
177
|
field = "key" if field.nil? or field.empty?
|
197
178
|
size = PAGE_SIZE if size.nil? or size.empty?
|
179
|
+
num = 1 if num.nil? || num.empty?
|
198
180
|
|
199
181
|
[num, size, field]
|
200
182
|
end
|
@@ -214,11 +196,7 @@ module RbbtRESTHelpers
|
|
214
196
|
|
215
197
|
field = CGI.unescapeHTML(Entity::REST.restore_element(field))
|
216
198
|
|
217
|
-
|
218
|
-
entity = object.entity_templates[field].annotation_types.last
|
219
|
-
else
|
220
|
-
entity = Entity.formats[field]
|
221
|
-
end
|
199
|
+
entity = Entity.formats[field]
|
222
200
|
|
223
201
|
if num == 'all'
|
224
202
|
num = 1
|
@@ -235,9 +213,9 @@ module RbbtRESTHelpers
|
|
235
213
|
|
236
214
|
object.with_unnamed do
|
237
215
|
if entity and entity.respond_to? :tsv_sort
|
238
|
-
object.page(num, size, field, false, reverse, &entity.method(:tsv_sort))
|
216
|
+
object.page(num, size, field, false, reverse, &entity.method(:tsv_sort)).tap{|o| o.unnamed = false }
|
239
217
|
else
|
240
|
-
object.page(num, size, field, false, reverse)
|
218
|
+
object.page(num, size, field, false, reverse).tap{|o| o.unnamed = false }
|
241
219
|
end
|
242
220
|
end
|
243
221
|
end
|
@@ -389,19 +367,7 @@ module RbbtRESTHelpers
|
|
389
367
|
|
390
368
|
def self.save_tsv(tsv, path)
|
391
369
|
Open.write(path, tsv.to_s)
|
392
|
-
table_options = {:tsv_entity_options => tsv.entity_options
|
393
|
-
if tsv.entity_templates and tsv.entity_templates.any?
|
394
|
-
table_options[:headers] ||= {}
|
395
|
-
tsv.entity_templates.each do |field,template|
|
396
|
-
next if template.nil?
|
397
|
-
next if table_options[:headers].include? field
|
398
|
-
info = template.info
|
399
|
-
info.delete :format
|
400
|
-
info.delete :annotation_types
|
401
|
-
info.delete :annotated_array
|
402
|
-
table_options[:headers][field] = [template.annotation_types.last.to_s, info]
|
403
|
-
end
|
404
|
-
end
|
370
|
+
table_options = {:tsv_entity_options => tsv.entity_options}
|
405
371
|
Open.write(path + '.table_options', table_options.to_yaml )
|
406
372
|
end
|
407
373
|
|
@@ -442,7 +408,7 @@ module RbbtRESTHelpers
|
|
442
408
|
if @step
|
443
409
|
table_file = @step.file(table_code) if @step
|
444
410
|
|
445
|
-
url = add_GET_param(@
|
411
|
+
url = add_GET_param(@fullpath, "_fragment", File.basename(table_file))
|
446
412
|
url = remove_GET_param(url, "_update")
|
447
413
|
url = remove_GET_param(url, "_layout")
|
448
414
|
url = remove_GET_param(url, "_")
|
@@ -63,7 +63,7 @@ module EntityRESTHelpers
|
|
63
63
|
locals = {}
|
64
64
|
info = {:inputs => inputs, :input_descriptions => input_descriptions, :input_defaults => input_defaults, :input_options => input_options, :input_types => input_types, :values => values}
|
65
65
|
locals[:id] = action_parameters_id
|
66
|
-
locals[:action] = @
|
66
|
+
locals[:action] = @fullpath
|
67
67
|
locals[:klass] = 'action_parameter_form'
|
68
68
|
locals[:info] = info
|
69
69
|
#locals[:description] = description
|
@@ -223,11 +223,8 @@ module EntityRESTHelpers
|
|
223
223
|
|
224
224
|
field = map.key_field
|
225
225
|
|
226
|
-
|
227
|
-
|
228
|
-
else
|
229
|
-
types = [Entity.formats[field]].compact
|
230
|
-
end
|
226
|
+
types = [Entity.formats[field]].compact
|
227
|
+
|
231
228
|
types += ["Default"]
|
232
229
|
|
233
230
|
path = nil
|
@@ -248,11 +245,8 @@ module EntityRESTHelpers
|
|
248
245
|
|
249
246
|
field = map.key_field
|
250
247
|
|
251
|
-
|
252
|
-
|
253
|
-
else
|
254
|
-
types = [Entity.formats[field]].compact
|
255
|
-
end
|
248
|
+
types = [Entity.formats[field]].compact
|
249
|
+
|
256
250
|
types += ["Default"]
|
257
251
|
|
258
252
|
paths = types.inject([]) do |acc,type|
|
@@ -28,8 +28,7 @@ module EntityRESTHelpers
|
|
28
28
|
entity_annotations[annotation] = value
|
29
29
|
end
|
30
30
|
|
31
|
-
entity
|
32
|
-
entity_class.setup_hash(entity, entity_annotations)
|
31
|
+
entity_class.setup(entity, entity_annotations)
|
33
32
|
entity.format = format if format and entity.respond_to? :format
|
34
33
|
|
35
34
|
entity
|
@@ -122,7 +122,6 @@ module Entity
|
|
122
122
|
#{{{ LINKS
|
123
123
|
|
124
124
|
def link(text = nil, options = {})
|
125
|
-
#return self.tap{|a| a.extend AnnotatedArray}.collect{|e| e.link(text, options) } if Array === self
|
126
125
|
return self.collect{|e| e.nil? ? nil : e.link(text, options) } if Array === self
|
127
126
|
return self.split(";").collect{|e| self.annotate(e).link(text, options) } * ", " if self.include? ";"
|
128
127
|
return nil if self.empty?
|
@@ -187,7 +186,7 @@ module Entity
|
|
187
186
|
|
188
187
|
reuse = options.delete(:reuse)
|
189
188
|
reuse = options.delete("reuse") if reuse.nil?
|
190
|
-
reuse =
|
189
|
+
reuse = false if reuse.nil?
|
191
190
|
|
192
191
|
Entity::List.save_list(entity_type.to_s, id, self) unless reuse and File.exist?(Entity::List.list_file(entity_type.to_s, id))
|
193
192
|
|
data/lib/rbbt/rest/entity.rb
CHANGED
@@ -201,8 +201,10 @@ module Sinatra
|
|
201
201
|
|
202
202
|
annotations[:annotation_types] ||= [type]
|
203
203
|
|
204
|
+
annotations.delete_if{|k,v| v.empty? }
|
205
|
+
|
204
206
|
mod = Kernel.const_get(type)
|
205
|
-
list = mod.setup(entities.reject{|e| e.empty?}, annotations)
|
207
|
+
list = mod.setup(entities.reject{|e| e.empty? }, annotations)
|
206
208
|
|
207
209
|
Entity::List.save_list(type, list_id, list, user)
|
208
210
|
|
data/lib/rbbt/rest/main.rb
CHANGED
@@ -18,6 +18,7 @@ require 'nakayoshi_fork'
|
|
18
18
|
|
19
19
|
Rbbt.add_version(__FILE__)
|
20
20
|
|
21
|
+
Path.add_path :rbbt_rest, File.join(Path.caller_lib_dir(__FILE__), "{TOPLEVEL}/{SUBPATH}")
|
21
22
|
module Sinatra
|
22
23
|
module RbbtRESTMain
|
23
24
|
|
@@ -133,7 +134,7 @@ module Sinatra
|
|
133
134
|
Log.info{ "Profile saved at #{ dir }: #{@uri}" }
|
134
135
|
end
|
135
136
|
|
136
|
-
|
137
|
+
headers "URI" => @uri
|
137
138
|
end
|
138
139
|
|
139
140
|
add_sass_load_path Rbbt.views.compass.find
|
@@ -269,7 +269,7 @@ module WorkflowRESTHelpers
|
|
269
269
|
|
270
270
|
begin
|
271
271
|
# $rest_cache_semaphore is defined in rbbt-util etc/app.d/semaphores.rb
|
272
|
-
job.fork($rest_cache_semaphore) unless job.started?
|
272
|
+
job.fork(true, $rest_cache_semaphore) unless job.started?
|
273
273
|
|
274
274
|
if @format == :jobname
|
275
275
|
job.soft_grace
|
@@ -311,7 +311,11 @@ module WorkflowRESTHelpers
|
|
311
311
|
end
|
312
312
|
|
313
313
|
def abort_job(workflow, job)
|
314
|
-
|
314
|
+
begin
|
315
|
+
job.abort
|
316
|
+
rescue Exception
|
317
|
+
Log.exception $!
|
318
|
+
end
|
315
319
|
halt 200, "Aborted #{ job.path }"
|
316
320
|
end
|
317
321
|
|
@@ -6,7 +6,7 @@ module WorkflowRESTHelpers
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def workflow_resources
|
9
|
-
[Rbbt.www.views.find(:lib)] + WorkflowRESTHelpers.workflow_resources
|
9
|
+
@workflow_resources ||= [Rbbt.www.views.find(:lib)] + WorkflowRESTHelpers.workflow_resources
|
10
10
|
end
|
11
11
|
|
12
12
|
def locate_workflow_template(template, workflow = nil, task = nil)
|
data/lib/rbbt/rest/workflow.rb
CHANGED
@@ -235,7 +235,7 @@ module Sinatra
|
|
235
235
|
task_inputs = task_info[:inputs]
|
236
236
|
TmpFile.with_file do |basedir|
|
237
237
|
dir = File.join(basedir, 'inputs')
|
238
|
-
|
238
|
+
workflow.tasks[task].save_inputs(dir, job.recursive_inputs)
|
239
239
|
filename = File.join(basedir, job.clean_name + '.input_bundle.tar.gz')
|
240
240
|
content_type "application/tar+gzip"
|
241
241
|
Misc.consume_stream(Misc.tarize(dir), false, filename)
|
@@ -317,6 +317,7 @@ module Sinatra
|
|
317
317
|
# end
|
318
318
|
#end
|
319
319
|
mime = file_mimetype(path)
|
320
|
+
mime = 'html' if path.ends_with?('.html')
|
320
321
|
content_type mime if mime
|
321
322
|
send_file path
|
322
323
|
end
|
@@ -25,7 +25,7 @@
|
|
25
25
|
- controller.actions.each do |action, text, resource, params|
|
26
26
|
-#.ui.item.button(class="#{last_resource and last_resource != resource ? "new_resource" : ""}" attr-resource="#{resource}")
|
27
27
|
- case
|
28
|
-
- when AnnotatedArray === entity
|
28
|
+
- when (AnnotatedArray === entity) && (Array === entity)
|
29
29
|
- id = params.delete :id if Hash === params
|
30
30
|
- id = controller.id if id.nil?
|
31
31
|
= entity.list_action_link action, text, id, params.merge(:reuse => true, :class => 'ui item button')
|
data/share/views/error.haml
CHANGED
@@ -13,30 +13,31 @@
|
|
13
13
|
- else
|
14
14
|
- if ! job.updated?
|
15
15
|
%pre.error_message.ui.basic.segment.content
|
16
|
-
Job out of date. Dependencies: #{job.
|
16
|
+
Job out of date. Dependencies: #{job.newer_dependencies.collect{|d| d.path} * ", "}
|
17
17
|
- else
|
18
18
|
%pre.error_message.ui.basic.segment.content
|
19
19
|
Unknown Error (status: #{job.status})
|
20
20
|
|
21
21
|
|
22
22
|
|
23
|
-
- if defined? job.info_file and Open.exists? job.info_file and @
|
24
|
-
- clean_url = add_GET_param(remove_GET_param(@
|
23
|
+
- if defined? job.info_file and Open.exists? job.info_file and @path_info.include? job.name
|
24
|
+
- clean_url = add_GET_param(remove_GET_param(@path_info, "_layout"), "_update", "clean")
|
25
25
|
%a.ui.button.blue.clean(href=clean_url) Clean
|
26
26
|
- else
|
27
|
-
- clean_url = add_GET_param(remove_GET_param(@
|
27
|
+
- clean_url = add_GET_param(remove_GET_param(@path_info, "_layout"), "_update", "reload")
|
28
28
|
%a.ui.blue.button.reload(href=clean_url) Reload
|
29
29
|
|
30
|
-
- info_url = @
|
31
|
-
- if @
|
30
|
+
- info_url = @path_info.sub(/\?.*/,'') + '/info'
|
31
|
+
- if @path_info.include? job.name
|
32
32
|
%a.ui.blue.button.reload(href=info_url) Info
|
33
33
|
|
34
|
-
- if job.files.any? and @
|
35
|
-
- files_url = @
|
34
|
+
- if job.files.any? and @path_info.include? job.name
|
35
|
+
- files_url = @path_info.sub(/\?.*/,'') + '/files'
|
36
36
|
%a.ui.blue.button.reload(href=files_url) Files
|
37
37
|
|
38
38
|
|
39
39
|
- backtrace = job.info[:backtrace]
|
40
|
+
- backtrace ||= job.info[:exception].backtrace if Exception === job.info[:exception]
|
40
41
|
- if backtrace and backtrace.any?
|
41
42
|
|
42
43
|
.error_backtrace.clean_list.ui.segment
|
data/share/views/job_info.haml
CHANGED
@@ -49,7 +49,8 @@
|
|
49
49
|
overflow: auto
|
50
50
|
border: 1px solid #EEE
|
51
51
|
|
52
|
-
- inputs.
|
52
|
+
- input_fields = Hash === inputs ? inputs.keys : inputs.fields
|
53
|
+
- input_fields.each_with_index do |f, ix|
|
53
54
|
- i = inputs[ix]
|
54
55
|
- next unless task_inputs.include?(f)
|
55
56
|
%dt= f
|
@@ -73,7 +74,7 @@
|
|
73
74
|
- if exception
|
74
75
|
- tab.active "Exception"
|
75
76
|
- tab.add "Exception" do
|
76
|
-
- backtrace = exception[:backtrace]
|
77
|
+
- backtrace = exception.respond_to?(:backtrace) ? exception.backtrace : exception[:backtrace]
|
77
78
|
.error_backtrace.clean_list
|
78
79
|
.ui.header Backtrace
|
79
80
|
%pre.ui.content
|
data/share/views/job_result.haml
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
.job_control
|
3
3
|
= workflow_partial('job_result/job_control', workflow, task, locals)
|
4
4
|
|
5
|
-
- type ||= job.info[:result_type]
|
5
|
+
- type ||= job.info[:result_type] || job.info[:type]
|
6
6
|
- case type
|
7
7
|
- when :tsv
|
8
8
|
= workflow_partial('job_result/tsv', workflow, task, locals)
|
@@ -11,18 +11,32 @@
|
|
11
11
|
%input(type="search" name="term" placeholder='Search')
|
12
12
|
|
13
13
|
#aesthetics.item
|
14
|
+
- main_actions = glob_all_server_files("main/*.haml", RbbtRESTHelpers.template_resources)
|
15
|
+
- if main_actions.any?
|
16
|
+
- main_actions = main_actions.collect do |file|
|
17
|
+
- _, _, filename = file.partition("main/")
|
18
|
+
- filename.sub('.haml','')
|
19
|
+
.main.ui.simple.dropdown.item.right
|
20
|
+
%i.icon.dropdown
|
21
|
+
Main pages
|
22
|
+
.menu
|
23
|
+
- main_actions.each do |action|
|
24
|
+
%a.item(href='#{'/main/' + action}')
|
25
|
+
= action.to_s
|
26
|
+
|
27
|
+
|
14
28
|
- if defined? Sinatra::RbbtRESTWorkflow and Sinatra::RbbtRESTWorkflow::WORKFLOWS
|
15
|
-
-
|
29
|
+
- exported_workflows = Sinatra::RbbtRESTWorkflow::WORKFLOWS.collect do |workflow|
|
16
30
|
- next if workflow.asynchronous_exports.empty? and workflow.synchronous_exports.empty? and workflow.exec_exports.empty?
|
17
31
|
- workflow
|
18
32
|
|
19
|
-
-
|
20
|
-
- if
|
33
|
+
- exported_workflows.compact!
|
34
|
+
- if exported_workflows.any?
|
21
35
|
.workflow.ui.simple.dropdown.item.right
|
22
36
|
%i.icon.dropdown
|
23
37
|
Workflows
|
24
38
|
.menu
|
25
|
-
-
|
39
|
+
- exported_workflows.each do |workflow|
|
26
40
|
%a.item(href='#{'/' + workflow.to_s}')
|
27
41
|
- if production?
|
28
42
|
= workflow.to_s
|
@@ -1,88 +1,89 @@
|
|
1
1
|
|
2
2
|
- cache = {} if not defined?(cache) or cache.nil?
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
4
|
+
- if job.dependencies
|
5
|
+
%ul.dependencies
|
6
|
+
- job.dependencies.reverse.each do |dep|
|
7
|
+
- dep_workflow = dep.workflow
|
8
|
+
- dep_workflow = nil if dep_workflow == ""
|
9
|
+
- dep_workflow ||= dep.task.workflow if dep.task
|
10
|
+
- dep_workflow = nil if dep_workflow == ""
|
11
|
+
- dep_workflow ||= File.basename(File.dirname(File.dirname(dep.path)))
|
12
|
+
- dep_workflow = nil if dep_workflow == ""
|
13
|
+
- str = [dep_workflow, dep.task_name, dep.name].compact * " - "
|
14
|
+
- remote = true if Open.remote?(dep.path) || Open.ssh?(dep.path)
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
- if remote
|
17
|
+
- dep_status = "done" if dep.done?
|
18
|
+
- else
|
19
|
+
- dep_status = "done" if Open.exists?(dep.path)
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
- dep_status ||= dep.status
|
22
|
+
- if ! remote && ! dep_status == 'done' && dep.file(:progress).exists?
|
23
|
+
- pgr = dep.file(:progress).yaml
|
24
|
+
- if pgr and pgr[:last_percent]
|
25
|
+
- start = pgr[:start]
|
26
|
+
- last_time = pgr[:last_time]
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
28
|
+
- ellapsed = last_time - start
|
29
|
+
- if pgr[:mean]
|
30
|
+
- missing = pgr[:max].to_f - pgr[:ticks].to_f
|
31
|
+
- eta = missing / pgr[:mean].to_f
|
32
|
+
- else
|
33
|
+
- ratio = pgr[:ticks].to_f/pgr[:max].to_f
|
34
|
+
- eta = ellapsed * (1 - ratio)
|
35
|
+
- eta = Misc.format_seconds(eta)
|
36
|
+
- ellapsed = Misc.format_seconds(ellapsed)
|
37
|
+
- pgr_str = " - " + pgr[:last_percent].to_s + "%" + " " + eta
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
39
|
+
:deferjs
|
40
|
+
var percent = '#{pgr[:last_percent]}';
|
41
|
+
var task = '#{dep.task_name}';
|
42
|
+
var title = $('head title');
|
43
|
+
var current = title.text();
|
44
|
+
var newtext;
|
45
|
+
var pos = current.indexOf('%');
|
46
|
+
if (pos == -1){
|
47
|
+
newtext = task + " - " + percent + "% " + current
|
48
|
+
}else{
|
49
|
+
newtext = task + " - " + percent + "% " + current.slice(pos+1)
|
50
|
+
}
|
51
|
+
title.text(newtext)
|
51
52
|
|
53
|
+
- else
|
54
|
+
- pgr_str = " - " + pgr[:ticks].to_s
|
55
|
+
- status = dep_status.to_s + pgr_str
|
52
56
|
- else
|
53
|
-
-
|
54
|
-
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
-
|
64
|
-
-
|
65
|
-
- rescue
|
66
|
-
- elsif Module === dep_workflow
|
67
|
-
- wf = dep_workflow
|
57
|
+
- status = dep_status
|
58
|
+
- name = dep.name
|
59
|
+
%li
|
60
|
+
%span.workflow= dep_workflow
|
61
|
+
%span.task= dep.task_name
|
62
|
+
%span.name
|
63
|
+
- if String === dep_workflow
|
64
|
+
- wf ||= begin
|
65
|
+
- Kernel.const_get dep_workflow
|
66
|
+
- rescue
|
67
|
+
- elsif Module === dep_workflow
|
68
|
+
- wf = dep_workflow
|
68
69
|
|
69
|
-
|
70
|
-
|
71
|
-
|
70
|
+
- if remote
|
71
|
+
- url = dep.path.split("?").first
|
72
|
+
%a(href=url) #{ name }
|
72
73
|
|
73
|
-
|
74
|
-
|
75
|
-
|
74
|
+
- elsif wf and Sinatra::RbbtRESTWorkflow::WORKFLOWS.include?(wf) and wf.task_exports.include? dep.task_name.to_sym
|
75
|
+
- url = "/" + [dep_workflow.to_s, dep.task_name.to_s, dep.name.to_s] * "/"
|
76
|
+
%a(href=url) #{ name }
|
76
77
|
|
77
|
-
|
78
|
-
|
78
|
+
- else
|
79
|
+
= name
|
79
80
|
|
80
81
|
|
81
|
-
|
82
|
+
%span.status(class="#{dep_status}") [#{status}]
|
82
83
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
84
|
+
- if dep.dependencies && dep.dependencies.any?
|
85
|
+
- if cache[dep.path]
|
86
|
+
= reveal "(deps)", nil, :title => "Dependencies already shown above", "attr-reveal_title" => "#{[dep_workflow, dep.task_name, dep.name] * " # "}" do
|
87
|
+
= cache[dep.path]
|
88
|
+
- else
|
89
|
+
= cache[dep.path] ||= partial_render('partials/dependencies', :job => dep, :cache => cache)
|
@@ -60,7 +60,7 @@
|
|
60
60
|
- if uses
|
61
61
|
- uses.each do |workflow, tasks|
|
62
62
|
- tasks.each do |task|
|
63
|
-
- use_tags << [workflow, task] * "#"
|
63
|
+
- use_tags << [workflow.to_s, task.to_s] * "#"
|
64
64
|
- input_id = id.nil? ? nil : id + "__" << input.to_s
|
65
65
|
- hide = (options[input] != nil and options[input][:hide])
|
66
66
|
%div(class="field #{types[input]} #{input} #{hide ? 'hide' : ''}" attr-use_tags='#{use_tags * " "}')
|
@@ -72,7 +72,8 @@
|
|
72
72
|
- uses.each do |workflow, tasks|
|
73
73
|
- tasks.each do |task|
|
74
74
|
- description << " * " << [workflow.to_s, task] * "#" << "\n"
|
75
|
-
|
75
|
+
- value = values[input].nil? ? locals[input] : values[input]
|
76
|
+
!~ form_input(input, types[input], defaults[input], value, description, input_id, input_options)
|
76
77
|
|
77
78
|
|
78
79
|
- if bundle && inputs.any?
|
@@ -50,8 +50,13 @@
|
|
50
50
|
|
51
51
|
%tr(id=row_id)
|
52
52
|
- row.each_with_index do |value, i|
|
53
|
-
- list_id = "#{ Misc.humanize(table_id) }: #{header[i]} for #{row.first}" if list_links and table_id and header and AnnotatedArray === value
|
54
53
|
- field = header ? header[i] : nil
|
54
|
+
- if entity_headers && entity_headers[field]
|
55
|
+
- entity_field, entity_options = entity_headers[field]
|
56
|
+
- value = Entity.prepare_entity(value, entity_field, entity_options)
|
57
|
+
- else
|
58
|
+
- value = Entity.prepare_entity(value, field)
|
59
|
+
- list_id = "#{ Misc.humanize(table_id) }: #{header[i]} for #{row.first}" if list_links and table_id and header and AnnotatedArray === value
|
55
60
|
- val = table_value(value, field, :list_id => list_id, :unnamed => unnamed, :entity_options => entity_options, :span => span)
|
56
61
|
- case val.to_s
|
57
62
|
- when 'TRUE', 'true', 'Yes', 'yes'
|
@@ -130,7 +130,7 @@ body.on('click', '.edit_list input[type=submit]', function(){
|
|
130
130
|
|
131
131
|
if (undefined !== format){ entity_type = entity_type + ':' + clean_element(format) }
|
132
132
|
|
133
|
-
var url = '/entity_list/' + clean_element(entity_type) + '/' + clean_element(new_list_id
|
133
|
+
var url = '/entity_list/' + clean_element(entity_type) + '/' + clean_element(new_list_id)
|
134
134
|
|
135
135
|
url = rbbt.url_add_script_name(url)
|
136
136
|
get_ajax({url: url, type: 'POST', async: false, data: {annotations: JSON.stringify(annotations), entities: entities}}, function(){ window.location = url })
|
data/share/views/tasks.haml
CHANGED
@@ -20,9 +20,7 @@
|
|
20
20
|
|
21
21
|
- tasks.sort.each do |task|
|
22
22
|
%li
|
23
|
-
//%a(href="#{to(File.join("/", workflow.to_s, task.to_s))}")= task
|
24
23
|
%a(href="#{File.join("/", workflow.to_s, task.to_s)}")= task
|
25
|
-
-
|
26
|
-
|
27
|
-
%span= info[:description].split(/\n\s*\n/).first
|
24
|
+
- if workflow.tasks[task].description
|
25
|
+
%span= workflow.tasks[task].description.split(/\n\s*\n/).first
|
28
26
|
|
@@ -4,12 +4,16 @@
|
|
4
4
|
- size = 3 unless defined? size and size
|
5
5
|
- width = size unless defined? width and width
|
6
6
|
- height = size unless defined? height and height
|
7
|
+
- svg = true unless defined? svg
|
7
8
|
- plot = block.call unless (defined? plot and plot) or not defined? block
|
8
9
|
- plot_options = {} unless defined? plot_options and plot_options
|
9
10
|
|
10
11
|
- filename += '.png' unless filename =~ /\.png$/i
|
11
12
|
- require 'rbbt/util/R'
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
- if svg
|
15
|
+
= R::SVG.ggplot(data, plot, width, height, plot_options)
|
16
|
+
- else
|
17
|
+
= resource filename, text, :image do |filename|
|
18
|
+
- R::PNG.ggplot(filename, data, plot, width, height, plot_options)
|
15
19
|
|
data/share/views/wait.haml
CHANGED
@@ -7,13 +7,17 @@
|
|
7
7
|
overflow: auto
|
8
8
|
text-overflow: ellipsis
|
9
9
|
|
10
|
+
- title = "#{job.status} #{File.basename(job.name)}"
|
11
|
+
:deferjs
|
12
|
+
$('head title').text("#{title}")
|
13
|
+
|
14
|
+
|
10
15
|
- progress = false
|
11
16
|
.wait.ui.segment.info.message
|
12
17
|
%h3.ui.header Waiting on #{format_name File.basename(job.name)}
|
13
18
|
|
14
19
|
%span.ui.basic.segment.content.status= job.status
|
15
20
|
|
16
|
-
|
17
21
|
- if job.file(:progress).exists?
|
18
22
|
.footer.ui.basic.segment
|
19
23
|
- progress = job.file(:progress).yaml
|
@@ -65,22 +69,24 @@
|
|
65
69
|
:deferjs
|
66
70
|
$('.step.progress').progress({label: 'ratio',text:{ratio: '{value}'}})
|
67
71
|
|
72
|
+
|
68
73
|
%hr
|
69
|
-
|
70
|
-
|
74
|
+
|
75
|
+
- if defined?(job.info_file) and File.exist?(job.info_file) and @fullpath.include?(job.name)
|
76
|
+
- abort_url = add_GET_param(remove_GET_param(@fullpath, "_layout"), "_update", "abort")
|
71
77
|
%a.ui.button.red.abort(href=abort_url) Abort
|
72
78
|
-#- clean_url = add_GET_param(remove_GET_param(@uri, "_layout"), "_update", "clean")
|
73
79
|
-#%a.ui.button.blue.clean(href=clean_url) Clean
|
74
80
|
- else
|
75
|
-
- clean_url = add_GET_param(remove_GET_param(@
|
81
|
+
- clean_url = add_GET_param(remove_GET_param(@fullpath, "_layout"), "_update", "reload")
|
76
82
|
%a.ui.blue.button.reload(href=clean_url) Reload
|
77
83
|
|
78
|
-
- if @
|
79
|
-
- info_url = @
|
80
|
-
%a.ui.blue.button.reload(href
|
84
|
+
- if @fullpath.include?(job.name)
|
85
|
+
- info_url = @fullpath.sub(/\?.*/,'') + '/info'
|
86
|
+
%a.ui.blue.button.reload(href=@fullpath) Info
|
81
87
|
|
82
|
-
- if job.files.any? and @
|
83
|
-
- files_url = @
|
88
|
+
- if job.files.any? and @fullpath.include? job.name
|
89
|
+
- files_url = @fullpath.sub(/\?.*/,'') + '/files'
|
84
90
|
%a.ui.blue.button.reload(href=files_url) Files
|
85
91
|
|
86
92
|
- if ! progress
|
@@ -95,14 +101,15 @@
|
|
95
101
|
}
|
96
102
|
|
97
103
|
|
98
|
-
.
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
-
|
103
|
-
|
104
|
+
- if job.messages
|
105
|
+
.ui.segment
|
106
|
+
%h3.ui.header Log
|
107
|
+
%ul.step_messages.clean_list
|
108
|
+
- job.messages.reverse.each do |line|
|
109
|
+
- next if line.nil? or line.strip.empty?
|
110
|
+
%li= line
|
104
111
|
|
105
|
-
- if job.dependencies.any?
|
112
|
+
- if job.dependencies && job.dependencies.any?
|
106
113
|
|
107
114
|
.ui.segment
|
108
115
|
%h3.ui.header Dependencies
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbbt-rest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miguel Vazquez
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: modular-scale
|
@@ -1853,7 +1853,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
1853
1853
|
- !ruby/object:Gem::Version
|
1854
1854
|
version: '0'
|
1855
1855
|
requirements: []
|
1856
|
-
rubygems_version: 3.5.
|
1856
|
+
rubygems_version: 3.5.23
|
1857
1857
|
signing_key:
|
1858
1858
|
specification_version: 4
|
1859
1859
|
summary: Rbbt Web and REST interfaces
|