rbbt-rest 1.9.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|