rbbt-rest 1.1.4 → 1.1.5
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 +8 -8
- data/config.ru +3 -0
- data/lib/rbbt/rest/client.rb +9 -10
- data/lib/rbbt/rest/common/cache.rb +32 -7
- data/lib/rbbt/rest/common/forms.rb +33 -0
- data/lib/rbbt/rest/common/locate.rb +4 -0
- data/lib/rbbt/rest/common/misc.rb +24 -0
- data/lib/rbbt/rest/common/render.rb +26 -9
- data/lib/rbbt/rest/common/resources.rb +1 -1
- data/lib/rbbt/rest/common/table.rb +87 -26
- data/lib/rbbt/rest/common/users.rb +5 -1
- data/lib/rbbt/rest/entity.rb +300 -95
- data/lib/rbbt/rest/entity/action_controller.rb +6 -1
- data/lib/rbbt/rest/entity/entity_list_card.rb +1 -1
- data/lib/rbbt/rest/entity/entity_map_card.rb +15 -0
- data/lib/rbbt/rest/entity/favourites.rb +57 -1
- data/lib/rbbt/rest/entity/finder.rb +1 -1
- data/lib/rbbt/rest/entity/helpers.rb +40 -7
- data/lib/rbbt/rest/entity/list.rb +8 -0
- data/lib/rbbt/rest/entity/locate.rb +114 -0
- data/lib/rbbt/rest/entity/map.rb +99 -0
- data/lib/rbbt/rest/entity/render.rb +25 -0
- data/lib/rbbt/rest/entity/rest.rb +33 -4
- data/lib/rbbt/rest/main.rb +27 -4
- data/lib/rbbt/rest/workflow.rb +7 -1
- data/lib/rbbt/rest/workflow/jobs.rb +21 -1
- data/share/views/compass/app.sass +17 -9
- data/share/views/compass/entity_card.sass +16 -3
- data/share/views/compass/favourites.sass +44 -2
- data/share/views/compass/form.sass +11 -0
- data/share/views/compass/list_container.sass +1 -1
- data/share/views/compass/reveal.sass +31 -0
- data/share/views/compass/style.sass +29 -1
- data/share/views/compass/style_mixins.sass +18 -6
- data/share/views/compass/table.sass +19 -3
- data/share/views/compass/topbar.sass +8 -2
- data/share/views/entity_map/Default.haml +5 -0
- data/share/views/entity_partials/action_card.haml +2 -0
- data/share/views/entity_partials/action_controller.haml +8 -1
- data/share/views/entity_partials/entity_list_card.haml +8 -6
- data/share/views/entity_partials/entity_map_card.haml +63 -0
- data/share/views/entity_partials/list_container.haml +3 -2
- data/share/views/error.haml +14 -10
- data/share/views/help.haml +34 -0
- data/share/views/help/entity.haml +193 -0
- data/share/views/help/workflow.haml +77 -0
- data/share/views/job_result/tsv.haml +3 -2
- data/share/views/layout.haml +33 -3
- data/share/views/layout/favourites.haml +14 -4
- data/share/views/layout/header.haml +4 -0
- data/share/views/partials/form.haml +3 -1
- data/share/views/partials/table.haml +16 -52
- data/share/views/partials/table/column.haml +10 -0
- data/share/views/partials/table/files.haml +4 -0
- data/share/views/partials/table/filters.haml +11 -0
- data/share/views/partials/table/page.haml +37 -0
- data/share/views/public/favicon.gif +0 -0
- data/share/views/public/js/_ajax_replace.js +76 -4
- data/share/views/public/js/_fix_tablesorter_science.js +13 -0
- data/share/views/public/js/actions.js +8 -2
- data/share/views/public/js/base.js +12 -1
- data/share/views/public/js/entities.js +39 -7
- data/share/views/public/js/favourites.js +308 -77
- data/share/views/public/js/helpers.js +9 -5
- data/share/views/public/js/lists.js +12 -12
- data/share/views/public/js/maps.js +17 -0
- data/share/views/public/js/reveal.js +48 -0
- data/share/views/public/js/tables.js +110 -51
- data/share/views/public/js/workflow.js +4 -16
- data/share/views/public/plugins/underscore/js/underscore.js +1227 -0
- data/share/views/tasks.haml +12 -1
- data/share/views/wait.haml +7 -0
- metadata +17 -2
@@ -20,6 +20,7 @@ module EntityRESTHelpers
|
|
20
20
|
entity_annotations = {}
|
21
21
|
entity_class.annotations.each do |annotation|
|
22
22
|
value = consume_parameter annotation, params
|
23
|
+
value = Entity::REST.restore_element(value) if String === value
|
23
24
|
value = false if value == "false"
|
24
25
|
value = true if value == "true"
|
25
26
|
entity_annotations[annotation] = value
|
@@ -71,6 +72,30 @@ module EntityRESTHelpers
|
|
71
72
|
|
72
73
|
render(template_file, locals, layout_file, "Entity list #{ action }: #{ id }")
|
73
74
|
end
|
75
|
+
|
76
|
+
def entity_map_render(map_id, type, column)
|
77
|
+
template_file = locate_entity_map_template(type, column)
|
78
|
+
|
79
|
+
map = Entity::Map.load_map(type, column, map_id, user)
|
80
|
+
locals = {:map => map, :map_id => map_id}
|
81
|
+
|
82
|
+
layout_file = layout ? locate_template("layout") : nil
|
83
|
+
|
84
|
+
render(template_file, locals, layout_file, "Entity map: #{ map_id }")
|
85
|
+
end
|
86
|
+
|
87
|
+
def entity_map_action_render(map, action, id, params = {})
|
88
|
+
template_file = locate_entity_map_action_template(map, action)
|
89
|
+
|
90
|
+
locals = params.merge({:map => map, :map_id => id})
|
91
|
+
|
92
|
+
layout_file = layout ? locate_template("layout") : nil
|
93
|
+
|
94
|
+
render(template_file, locals, layout_file, "Entity map #{ action }: #{ id }")
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
|
74
99
|
end
|
75
100
|
|
76
101
|
|
@@ -14,15 +14,15 @@ module Entity
|
|
14
14
|
#{{{ MISC
|
15
15
|
|
16
16
|
def self.clean_element(elem)
|
17
|
-
elem.gsub('/', '--')
|
17
|
+
elem.gsub('/', '--').gsub('%', 'o-o')
|
18
18
|
end
|
19
19
|
|
20
20
|
def self.restore_element(elem)
|
21
|
-
CGI.unescape(elem.gsub('--', '/'))
|
21
|
+
CGI.unescape(CGI.unescape(elem.gsub('--', '/').gsub('o-o', '%')))
|
22
22
|
end
|
23
23
|
|
24
24
|
def entity_link_params
|
25
|
-
info = self.info
|
25
|
+
info = self.info.dup
|
26
26
|
info.delete :format
|
27
27
|
info.delete :annotation_types
|
28
28
|
info.delete :annotated_array
|
@@ -65,7 +65,21 @@ module Entity
|
|
65
65
|
|
66
66
|
#{{{ URLS
|
67
67
|
|
68
|
-
def self.entity_url(entity, type, params =
|
68
|
+
def self.entity_url(entity, type = nil, params = nil)
|
69
|
+
if type.nil?
|
70
|
+
type = entity.annotation_types.last.to_s
|
71
|
+
type << ":" << entity.format if entity.respond_to? :format
|
72
|
+
end
|
73
|
+
|
74
|
+
if params.nil?
|
75
|
+
if entity.respond_to? :entity_link_params
|
76
|
+
params = entity.entity_link_params
|
77
|
+
else
|
78
|
+
params = {}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
params ||= entity.info if entity.respond_to? :info
|
69
83
|
url = File.join('/', 'entity', Entity::REST.clean_element(type.to_s), entity)
|
70
84
|
url << "?" << Misc.hash2GET_params(params) if params.any?
|
71
85
|
url
|
@@ -87,6 +101,20 @@ module Entity
|
|
87
101
|
url
|
88
102
|
end
|
89
103
|
|
104
|
+
def self.entity_map_url(map, type, column)
|
105
|
+
type = Entity::REST.clean_element(type.to_s)
|
106
|
+
column = Entity::REST.clean_element(column)
|
107
|
+
map = Entity::REST.clean_element(map)
|
108
|
+
File.join('/', 'entity_map', type, column, map)
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.entity_map_action_url(map, type, column, action)
|
112
|
+
type = Entity::REST.clean_element(type.to_s)
|
113
|
+
column = Entity::REST.clean_element(column)
|
114
|
+
map = Entity::REST.clean_element(map)
|
115
|
+
File.join('/', 'entity_map_action', type, column, action, map)
|
116
|
+
end
|
117
|
+
|
90
118
|
|
91
119
|
#{{{ LINKS
|
92
120
|
|
@@ -101,6 +129,7 @@ module Entity
|
|
101
129
|
|
102
130
|
attributes[:class] << klasses
|
103
131
|
attributes[:href] = Entity::REST.entity_url(self, entity_type.to_s, link_params)
|
132
|
+
attributes["attr-entity_id"] = self.to_s
|
104
133
|
|
105
134
|
text = self.respond_to?(:name)? self.name || self : self if text.nil?
|
106
135
|
attributes[:title] = text if attributes[:title].nil?
|
data/lib/rbbt/rest/main.rb
CHANGED
@@ -4,6 +4,7 @@ require 'rbbt/rest/common/users'
|
|
4
4
|
require 'ruby-prof'
|
5
5
|
|
6
6
|
require 'sinatra/base'
|
7
|
+
require 'sinatra/cross_origin'
|
7
8
|
require 'json'
|
8
9
|
|
9
10
|
module Sinatra
|
@@ -21,18 +22,25 @@ module Sinatra
|
|
21
22
|
|
22
23
|
set :cache_dir, Rbbt.var.sinatra.cache.find unless settings.respond_to? :cache_dir and settings.cache_dir != nil
|
23
24
|
set :file_dir, Rbbt.var.sinatra.files.find unless settings.respond_to? :file_dir and settings.file_dir != nil
|
25
|
+
set :permalink_dir, Rbbt.var.sinatra.permalink.find unless settings.respond_to? :permalink_dir and settings.permalink_dir != nil
|
24
26
|
|
25
27
|
set :public_folder, Rbbt.share.views.public.find
|
26
28
|
|
27
29
|
attr_accessor :ajax, :layout, :format, :size, :update, :cache_type, :_, :profile
|
28
30
|
|
29
|
-
set :haml, { :ugly => true }
|
30
31
|
if production?
|
31
32
|
set :haml, { :ugly => true }
|
32
33
|
set :clean_trace, true
|
33
34
|
set :static_cache_control , [:public, {:max_age => 360000}]
|
34
35
|
end
|
35
36
|
|
37
|
+
enable :cross_origin
|
38
|
+
set :allow_origin, :any
|
39
|
+
set :allow_methods, [:get, :post, :options]
|
40
|
+
set :allow_credentials, true
|
41
|
+
set :max_age, "1728000"
|
42
|
+
set :allow_headers, ['URI']
|
43
|
+
|
36
44
|
before do
|
37
45
|
Log.info("IP #{request.ip}: " << request.path_info << ". Params: " << Misc.remove_long_items(params).inspect)
|
38
46
|
process_common_parameters
|
@@ -52,8 +60,7 @@ module Sinatra
|
|
52
60
|
printer.print(:path => dir, :profile => 'profile')
|
53
61
|
Log.info("Profile saved at #{ dir }")
|
54
62
|
end
|
55
|
-
|
56
|
-
request
|
63
|
+
response.header["URI"] = request.env["REQUEST_URI"]
|
57
64
|
end
|
58
65
|
|
59
66
|
add_sass_load_path Rbbt.views.compass.find
|
@@ -92,9 +99,25 @@ module Sinatra
|
|
92
99
|
end
|
93
100
|
|
94
101
|
get '/' do
|
95
|
-
template_render('main', params)
|
102
|
+
template_render('main', params, 'main', :cache_type => :asynchronous)
|
96
103
|
end
|
97
104
|
|
105
|
+
get '/help/?:section?' do
|
106
|
+
if params[:section]
|
107
|
+
section = params[:section]
|
108
|
+
template_render('help/' << section, params, section, :cache_type => :asynchronous)
|
109
|
+
else
|
110
|
+
template_render('help', params, 'help', :cache_type => :asynchronous)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
get '/permalink/:id' do
|
115
|
+
content_type "text/html"
|
116
|
+
layout_file = locate_template('layout')
|
117
|
+
Haml::Engine.new(Open.read(layout_file), :filename => layout_file).render(self) do
|
118
|
+
Open.read(File.join(settings.permalink_dir, params[:id]))
|
119
|
+
end
|
120
|
+
end
|
98
121
|
end
|
99
122
|
end
|
100
123
|
end
|
data/lib/rbbt/rest/workflow.rb
CHANGED
@@ -16,6 +16,7 @@ require 'json'
|
|
16
16
|
|
17
17
|
module Sinatra
|
18
18
|
module RbbtRESTWorkflow
|
19
|
+
WORKFLOWS = []
|
19
20
|
|
20
21
|
def add_workflow_resource(workflow)
|
21
22
|
views_dir = workflow.libdir.www.views.find(:lib)
|
@@ -32,12 +33,13 @@ module Sinatra
|
|
32
33
|
|
33
34
|
def add_workflow(workflow, add_resource = false)
|
34
35
|
raise "Provided workflow is not of type Workflow" unless Workflow === workflow or WorkflowRESTClient === workflow
|
36
|
+
RbbtRESTWorkflow::WORKFLOWS.push workflow unless RbbtRESTWorkflow::WORKFLOWS.include? workflow
|
35
37
|
|
36
38
|
add_workflow_resource(workflow) if add_resource
|
37
39
|
|
38
40
|
Log.debug("Adding #{ workflow } to REST server")
|
39
41
|
|
40
|
-
self.instance_eval workflow.libdir.lib['sinatra.rb'].read if File.exists? workflow.libdir.lib['sinatra.rb']
|
42
|
+
self.instance_eval workflow.libdir.lib['sinatra.rb'].read, workflow.libdir.lib['sinatra.rb'].find if File.exists? workflow.libdir.lib['sinatra.rb']
|
41
43
|
|
42
44
|
get "/#{workflow.to_s}" do
|
43
45
|
case format
|
@@ -79,6 +81,10 @@ module Sinatra
|
|
79
81
|
end
|
80
82
|
end
|
81
83
|
|
84
|
+
get "/#{workflow.to_s}/description" do
|
85
|
+
halt 200, workflow.workflow_description
|
86
|
+
end
|
87
|
+
|
82
88
|
|
83
89
|
get "/#{workflow.to_s}/:task" do
|
84
90
|
task = consume_parameter(:task)
|
@@ -90,9 +90,29 @@ module WorkflowRESTHelpers
|
|
90
90
|
end
|
91
91
|
|
92
92
|
def show_result(job, workflow, task)
|
93
|
-
case format
|
93
|
+
case format.to_sym
|
94
94
|
when :html
|
95
95
|
show_result_html job.load, workflow, task, job.name, job
|
96
|
+
when :table
|
97
|
+
halt 200, tsv2html(job.path, :url => "/" << [workflow.to_s, task, job.name] * "/")
|
98
|
+
when :entities
|
99
|
+
tsv = tsv_process(load_tsv(job.path).first)
|
100
|
+
list = tsv.values.flatten
|
101
|
+
if not AnnotatedArray === list and Annotated === list.first
|
102
|
+
list.first.annotate list
|
103
|
+
list.extend AnnotatedArray
|
104
|
+
end
|
105
|
+
type = list.annotation_types.last
|
106
|
+
list_id = "TMP #{type} in #{ [workflow.to_s, task, job.name] * " - " }"
|
107
|
+
Entity::List.save_list(type.to_s, list_id, list, user)
|
108
|
+
redirect to(Entity::REST.entity_list_url(list_id, type))
|
109
|
+
when :map
|
110
|
+
tsv = tsv_process(load_tsv(job.path).first)
|
111
|
+
type = tsv.keys.annotation_types.last
|
112
|
+
column = tsv.fields.first
|
113
|
+
map_id = "MAP #{type}-#{column} in #{ [workflow.to_s, task, job.name] * " - " }"
|
114
|
+
Entity::Map.save_map(type.to_s, column, map_id, tsv, user)
|
115
|
+
redirect to(Entity::REST.entity_map_url(map_id, type, column))
|
96
116
|
when :json
|
97
117
|
content_type "application/json"
|
98
118
|
halt 200, job.load.to_json
|
@@ -1,4 +1,6 @@
|
|
1
1
|
@import _foundation_setup
|
2
|
+
@import style_mixins
|
3
|
+
|
2
4
|
@import lists
|
3
5
|
@import list_container
|
4
6
|
@import dom
|
@@ -7,8 +9,6 @@
|
|
7
9
|
@import tabs
|
8
10
|
@import responsive_table
|
9
11
|
|
10
|
-
@import style_mixins
|
11
|
-
|
12
12
|
@import topbar
|
13
13
|
@import favourites
|
14
14
|
@import footer
|
@@ -17,6 +17,7 @@
|
|
17
17
|
@import offcanvas
|
18
18
|
@import fragment
|
19
19
|
@import workflow
|
20
|
+
@import reveal
|
20
21
|
@import style
|
21
22
|
|
22
23
|
body
|
@@ -26,13 +27,6 @@ body
|
|
26
27
|
#body
|
27
28
|
min-height: 900px
|
28
29
|
|
29
|
-
|
30
|
-
//.main
|
31
|
-
dl
|
32
|
-
@extend dl.details
|
33
|
-
@extend .column
|
34
|
-
@extend .large-4
|
35
|
-
|
36
30
|
ul.entities
|
37
31
|
@extend .inline-list
|
38
32
|
li
|
@@ -40,3 +34,17 @@ ul.entities
|
|
40
34
|
|
41
35
|
dl.details
|
42
36
|
@extend dl.indented
|
37
|
+
|
38
|
+
|
39
|
+
.filter_controls
|
40
|
+
@media #{$medium}
|
41
|
+
div.input
|
42
|
+
@include grid-column(4)
|
43
|
+
&.submit, &.submit > input
|
44
|
+
float: right
|
45
|
+
clear: both
|
46
|
+
label
|
47
|
+
@include ellipsis_text()
|
48
|
+
|
49
|
+
.map_management ul
|
50
|
+
@include button-group-list()
|
@@ -1,5 +1,5 @@
|
|
1
1
|
// GRID LAYOUT
|
2
|
-
.entity_card, .entity_list_card, .action_card
|
2
|
+
.entity_card, .entity_list_card, .action_card, .entity_map_card
|
3
3
|
|
4
4
|
& > .title
|
5
5
|
@include grid-row(collapse)
|
@@ -49,9 +49,8 @@
|
|
49
49
|
clear: left
|
50
50
|
|
51
51
|
|
52
|
-
.entity_card, .entity_list_card, .action_card
|
52
|
+
.entity_card, .entity_list_card, .action_card, .entity_map_card
|
53
53
|
& > .title
|
54
|
-
padding-top: 1em
|
55
54
|
margin-bottom: 1em
|
56
55
|
|
57
56
|
.name
|
@@ -98,3 +97,17 @@
|
|
98
97
|
p
|
99
98
|
text-align: justify
|
100
99
|
max-width: 50em
|
100
|
+
|
101
|
+
|
102
|
+
@media #{$not-small}
|
103
|
+
.reveal-modal
|
104
|
+
.entity_card, .entity_list_card, .action_card, .entity_map_card
|
105
|
+
&> .card
|
106
|
+
&>.sidebar
|
107
|
+
width: 33%
|
108
|
+
&>.content
|
109
|
+
width: 67%
|
110
|
+
|
111
|
+
form.rename
|
112
|
+
input[name=rename]
|
113
|
+
width: 100%
|
@@ -1,5 +1,9 @@
|
|
1
|
-
a
|
2
|
-
|
1
|
+
.reveal-modal a.toggle_favourite
|
2
|
+
&:not(.active)
|
3
|
+
i
|
4
|
+
color: black !important
|
5
|
+
|
6
|
+
a#toggle_favourite, .reveal-modal a.toggle_favourite
|
3
7
|
&.inactive
|
4
8
|
span.remove
|
5
9
|
display: none !important
|
@@ -26,6 +30,44 @@ a#toggle_favourite
|
|
26
30
|
font-size: 0.5em
|
27
31
|
margin-left: 1em
|
28
32
|
|
33
|
+
ul.favourite_entity_lists
|
34
|
+
li
|
35
|
+
ul
|
36
|
+
li:not(.title)
|
37
|
+
+clearfix()
|
38
|
+
position: relative
|
39
|
+
width: 100%
|
40
|
+
padding-right: 3em
|
41
|
+
a
|
42
|
+
min-height: 1em
|
43
|
+
display: inline-block !important
|
44
|
+
&.highlight
|
45
|
+
width: 3em !important
|
46
|
+
position: absolute
|
47
|
+
left: 0
|
48
|
+
&.active
|
49
|
+
i
|
50
|
+
color: yellow
|
51
|
+
&:not(.highlight)
|
52
|
+
position: relative
|
53
|
+
margin-left: 3em
|
54
|
+
|
55
|
+
|
56
|
+
ul.favourite_entities, ul.favourite_entity_lists, ul.favourite_entity_maps
|
57
|
+
ul.dropdown
|
58
|
+
li
|
59
|
+
@media #{ $not-small }
|
60
|
+
background: none repeat scroll 0 0 #00434C
|
61
|
+
a
|
62
|
+
@media #{ $not-small }
|
63
|
+
+ellipsis_text()
|
64
|
+
max-width: 400px
|
65
|
+
z-index: 9
|
66
|
+
&:not(.highlight):hover
|
67
|
+
white-space: normal !important
|
68
|
+
z-index: 10
|
69
|
+
|
70
|
+
|
29
71
|
//@media only screen and (max-width: 767px)
|
30
72
|
#find_wrapper
|
31
73
|
top: 9em
|
@@ -18,6 +18,13 @@
|
|
18
18
|
margin-bottom: 2em
|
19
19
|
label
|
20
20
|
margin-bottom: 1em
|
21
|
+
&.inline
|
22
|
+
+ellipsis_text()
|
23
|
+
display: inline-block
|
24
|
+
clear: top
|
25
|
+
padding: 0
|
26
|
+
margin-bottom: 0
|
27
|
+
margin-left: 0.5em
|
21
28
|
|
22
29
|
.input.submit
|
23
30
|
clear: both
|
@@ -26,5 +33,9 @@
|
|
26
33
|
select.favourite_lists
|
27
34
|
width: 175px
|
28
35
|
|
36
|
+
span.choice
|
37
|
+
margin-right: 1em
|
38
|
+
white-space: nowrap
|
39
|
+
|
29
40
|
.action_parameters form
|
30
41
|
+clearfix()
|
@@ -0,0 +1,31 @@
|
|
1
|
+
.rbbt_reveal_content
|
2
|
+
display: none !important
|
3
|
+
|
4
|
+
.reveal-modal a.toggle_favourite
|
5
|
+
&.active
|
6
|
+
i
|
7
|
+
color: #dd1 !important
|
8
|
+
&:not(.active)
|
9
|
+
i
|
10
|
+
color: black !important
|
11
|
+
|
12
|
+
.reveal-modal .header
|
13
|
+
bottom-border: 1px solid grey
|
14
|
+
.close
|
15
|
+
float: right
|
16
|
+
.title
|
17
|
+
float: left
|
18
|
+
|
19
|
+
.reveal-modal
|
20
|
+
.controls
|
21
|
+
a.link-reveal-modal
|
22
|
+
@include reveal-close()
|
23
|
+
right: 3em
|
24
|
+
font-size: 1em
|
25
|
+
top: 1.1em
|
26
|
+
|
27
|
+
&:not(.url)
|
28
|
+
.controls
|
29
|
+
a.link-reveal-modal
|
30
|
+
display: none
|
31
|
+
|