rbbt-views 1.0.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (177) hide show
  1. data/lib/rbbt/workflow/rest.rb +365 -95
  2. data/lib/rbbt/workflow/rest/client.rb +2 -0
  3. data/lib/rbbt/workflow/rest/entity.rb +82 -76
  4. data/lib/rbbt/workflow/rest/finder.rb +78 -0
  5. data/lib/rbbt/workflow/rest/helpers.rb +288 -47
  6. data/lib/rbbt/workflow/rest/notes.rb +125 -0
  7. data/lib/rbbt/workflow/rest/render.rb +280 -240
  8. data/lib/rbbt/workflow/rest/util.rb +47 -31
  9. data/share/views/compass/_base.sass +0 -8
  10. data/share/views/compass/colors.sass +10 -0
  11. data/share/views/compass/colors/ventana_azul.sass +5 -0
  12. data/share/views/compass/compass.config +2 -1
  13. data/share/views/compass/details.sass +50 -0
  14. data/share/views/compass/dom.sass +64 -0
  15. data/share/views/compass/embedded.sass +111 -0
  16. data/share/views/compass/entities.sass +8 -0
  17. data/share/views/compass/error.sass +13 -0
  18. data/share/views/compass/finder.sass +42 -0
  19. data/share/views/compass/fonts.sass +8 -0
  20. data/share/views/compass/form.sass +49 -1
  21. data/share/views/compass/header.sass +68 -0
  22. data/share/views/compass/{main.sass → helpers.sass} +53 -21
  23. data/share/views/compass/layout.sass +31 -199
  24. data/share/views/compass/lists.sass +128 -0
  25. data/share/views/compass/menu.sass +35 -0
  26. data/share/views/compass/notes.sass +52 -0
  27. data/share/views/compass/sizes.sass +8 -0
  28. data/share/views/compass/tables.sass +22 -0
  29. data/share/views/compass/wait.sass +9 -0
  30. data/share/views/edit_list.haml +41 -30
  31. data/share/views/entity/GOTerm.haml +4 -3
  32. data/share/views/entity/Gene.haml +8 -1
  33. data/share/views/entity/GenomicMutation.haml +4 -1
  34. data/share/views/entity/KeggPathway.haml +1 -1
  35. data/share/views/entity/MutatedIsoform.haml +68 -11
  36. data/share/views/entity/NCIBioCartaPathway.haml +2 -3
  37. data/share/views/entity/NCINaturePathway.haml +3 -3
  38. data/share/views/entity/NCIReactomePathway.haml +2 -3
  39. data/share/views/entity/PfamDomain.haml +2 -0
  40. data/share/views/entity/Transcript.haml +10 -0
  41. data/share/views/entity_list/Default.haml +4 -0
  42. data/share/views/entity_list/Default/compare_to_other_lists.haml +41 -0
  43. data/share/views/entity_list/Default/entity_links.haml +6 -0
  44. data/share/views/entity_list/Default/find_in_other_lists.haml +36 -0
  45. data/share/views/error.haml +6 -1
  46. data/share/views/find.haml +10 -0
  47. data/share/views/form.haml +1 -1
  48. data/share/views/info.haml +1 -1
  49. data/share/views/js/_action_setup.js +250 -0
  50. data/share/views/js/_basic.js +269 -0
  51. data/share/views/js/_cytoscape.js +44 -0
  52. data/share/views/js/_details.js +239 -0
  53. data/share/views/js/_dom_updates.js +384 -0
  54. data/share/views/js/_embedded.js +95 -0
  55. data/share/views/js/_images.js +20 -0
  56. data/share/views/js/_layout.js +21 -0
  57. data/share/views/js/_lists.js +224 -0
  58. data/share/views/js/_table.js +36 -0
  59. data/share/views/js/_workflow.js +42 -0
  60. data/share/views/js/app.js +0 -570
  61. data/share/views/js/fix_tablesorter_scientific.js +25 -0
  62. data/share/views/js/json2.js +487 -0
  63. data/share/views/layout.haml +8 -98
  64. data/share/views/notes.haml +15 -0
  65. data/share/views/partials/_form.haml +22 -7
  66. data/share/views/partials/_job_control.haml +8 -8
  67. data/share/views/partials/_list_control.haml +32 -0
  68. data/share/views/partials/_list_header.haml +6 -0
  69. data/share/views/partials/_note_list.haml +64 -0
  70. data/share/views/partials/_result_table.haml +12 -7
  71. data/share/views/partials/_result_table_controls.haml +11 -5
  72. data/share/views/partials/_table.haml +24 -6
  73. data/share/views/partials/layout/_coda.haml +10 -0
  74. data/share/views/partials/layout/_details.haml +25 -0
  75. data/share/views/partials/layout/_head.haml +22 -0
  76. data/share/views/partials/layout/_header.haml +29 -0
  77. data/share/views/partials/layout/_menu.haml +20 -0
  78. data/share/views/partials/layout/_resources.haml +41 -0
  79. data/share/views/public/background.png +0 -0
  80. data/share/views/public/plugins/cytoscape-web/LICENSE.txt +504 -0
  81. data/share/views/public/plugins/cytoscape-web/README.txt +213 -0
  82. data/share/views/public/plugins/cytoscape-web/js/AC_OETags.js +1 -0
  83. data/share/views/public/plugins/cytoscape-web/js/cytoscapeweb.js +1 -0
  84. data/share/views/public/plugins/cytoscape-web/js/json2.js +1 -0
  85. data/share/views/public/plugins/cytoscape-web/swf/CytoscapeWeb.swf +0 -0
  86. data/share/views/public/plugins/cytoscape-web/swf/playerProductInstall.swf +0 -0
  87. data/share/views/public/plugins/fancybox/CHANGELOG.md +68 -0
  88. data/share/views/public/plugins/fancybox/README.md +220 -0
  89. data/share/views/public/plugins/fancybox/css/blank.gif +0 -0
  90. data/share/views/public/plugins/fancybox/css/fancybox_loading.gif +0 -0
  91. data/share/views/public/plugins/fancybox/css/fancybox_sprite.png +0 -0
  92. data/share/views/public/plugins/fancybox/css/jquery.fancybox.css +234 -0
  93. data/share/views/public/plugins/fancybox/helpers/fancybox_buttons.png +0 -0
  94. data/share/views/public/plugins/fancybox/helpers/jquery.fancybox-buttons.css +85 -0
  95. data/share/views/public/plugins/fancybox/helpers/jquery.fancybox-buttons.js +115 -0
  96. data/share/views/public/plugins/fancybox/helpers/jquery.fancybox-media.js +85 -0
  97. data/share/views/public/plugins/fancybox/helpers/jquery.fancybox-thumbs.css +54 -0
  98. data/share/views/public/plugins/fancybox/helpers/jquery.fancybox-thumbs.js +157 -0
  99. data/share/views/public/plugins/fancybox/js/jquery.fancybox.js +1463 -0
  100. data/share/views/public/plugins/fancybox/js/jquery.mousewheel-3.0.6.pack.js +13 -0
  101. data/share/views/public/plugins/fancybox/lib/jquery-1.7.2.min.js +4 -0
  102. data/share/views/public/plugins/featuredimagezoomer/css/featuredimagezoomer.css +8 -0
  103. data/share/views/public/plugins/featuredimagezoomer/images/spinningred.gif +0 -0
  104. data/share/views/public/plugins/featuredimagezoomer/js/featuredimagezoomer.js +245 -0
  105. data/share/views/public/plugins/jquery-ui.hitarea.js +173 -0
  106. data/share/views/public/plugins/jquery/js/jquery-1.8.0.min.js +2 -0
  107. data/share/views/public/plugins/tablesorter/addons/pager/jquery.tablesorter.pager.css +25 -0
  108. data/share/views/public/plugins/tablesorter/addons/pager/jquery.tablesorter.pager.js +184 -0
  109. data/share/views/public/plugins/tablesorter/build.xml +26 -0
  110. data/share/views/public/plugins/tablesorter/build/ParseMaster.js +106 -0
  111. data/share/views/public/plugins/tablesorter/build/js.jar +0 -0
  112. data/share/views/public/plugins/tablesorter/build/jsmin.js +316 -0
  113. data/share/views/public/plugins/tablesorter/build/min.js +5 -0
  114. data/share/views/public/plugins/tablesorter/build/pack.js +5 -0
  115. data/share/views/public/plugins/tablesorter/build/packer.js +316 -0
  116. data/share/views/public/plugins/tablesorter/build/writeFile.js +19 -0
  117. data/share/views/public/plugins/tablesorter/changelog +41 -0
  118. data/share/views/public/plugins/tablesorter/docs/assets/ajax-content.html +43 -0
  119. data/share/views/public/plugins/tablesorter/docs/css/jq.css +29 -0
  120. data/share/views/public/plugins/tablesorter/docs/example-ajax.html +119 -0
  121. data/share/views/public/plugins/tablesorter/docs/example-empty-table.html +75 -0
  122. data/share/views/public/plugins/tablesorter/docs/example-extending-defaults.html +109 -0
  123. data/share/views/public/plugins/tablesorter/docs/example-meta-headers.html +108 -0
  124. data/share/views/public/plugins/tablesorter/docs/example-meta-parsers.html +105 -0
  125. data/share/views/public/plugins/tablesorter/docs/example-meta-sort-list.html +107 -0
  126. data/share/views/public/plugins/tablesorter/docs/example-option-debug.html +116 -0
  127. data/share/views/public/plugins/tablesorter/docs/example-option-digits.html +106 -0
  128. data/share/views/public/plugins/tablesorter/docs/example-option-sort-force.html +107 -0
  129. data/share/views/public/plugins/tablesorter/docs/example-option-sort-key.html +108 -0
  130. data/share/views/public/plugins/tablesorter/docs/example-option-sort-list.html +108 -0
  131. data/share/views/public/plugins/tablesorter/docs/example-option-sort-order.html +108 -0
  132. data/share/views/public/plugins/tablesorter/docs/example-option-text-extraction.html +85 -0
  133. data/share/views/public/plugins/tablesorter/docs/example-options-headers.html +118 -0
  134. data/share/views/public/plugins/tablesorter/docs/example-pager.html +329 -0
  135. data/share/views/public/plugins/tablesorter/docs/example-parsers.html +112 -0
  136. data/share/views/public/plugins/tablesorter/docs/example-trigger-sort.html +113 -0
  137. data/share/views/public/plugins/tablesorter/docs/example-triggers.html +336 -0
  138. data/share/views/public/plugins/tablesorter/docs/example-update-cell.html +118 -0
  139. data/share/views/public/plugins/tablesorter/docs/example-widgets.html +383 -0
  140. data/share/views/public/plugins/tablesorter/docs/img/external.png +0 -0
  141. data/share/views/public/plugins/tablesorter/docs/index.html +576 -0
  142. data/share/views/public/plugins/tablesorter/docs/js/docs.js +23 -0
  143. data/share/views/public/plugins/tablesorter/docs/js/examples.js +29 -0
  144. data/share/views/public/plugins/tablesorter/jquery-latest.js +154 -0
  145. data/share/views/public/plugins/tablesorter/jquery.metadata.js +122 -0
  146. data/share/views/public/plugins/tablesorter/jquery.tablesorter.js +1031 -0
  147. data/share/views/public/plugins/tablesorter/jquery.tablesorter.min.js +4 -0
  148. data/share/views/public/plugins/tablesorter/tests/assets/ajax-content.html +28 -0
  149. data/share/views/public/plugins/tablesorter/tests/cell.metadata.html +112 -0
  150. data/share/views/public/plugins/tablesorter/tests/checkbox.html +117 -0
  151. data/share/views/public/plugins/tablesorter/tests/colspan.html +149 -0
  152. data/share/views/public/plugins/tablesorter/tests/demo.html +353 -0
  153. data/share/views/public/plugins/tablesorter/tests/index.html +22 -0
  154. data/share/views/public/plugins/tablesorter/tests/large.html +30 -0
  155. data/share/views/public/plugins/tablesorter/tests/lockedOrder.html +355 -0
  156. data/share/views/public/plugins/tablesorter/tests/metadata.html +320 -0
  157. data/share/views/public/plugins/tablesorter/tests/multiple-headers.html +67 -0
  158. data/share/views/public/plugins/tablesorter/tests/pager.html +553 -0
  159. data/share/views/public/plugins/tablesorter/themes/blue/asc.gif +0 -0
  160. data/share/views/public/plugins/tablesorter/themes/blue/bg.gif +0 -0
  161. data/share/views/public/plugins/tablesorter/themes/blue/blue.zip +0 -0
  162. data/share/views/public/plugins/tablesorter/themes/blue/desc.gif +0 -0
  163. data/share/views/public/plugins/tablesorter/themes/blue/style.css +39 -0
  164. data/share/views/public/plugins/tablesorter/themes/green/asc.png +0 -0
  165. data/share/views/public/plugins/tablesorter/themes/green/bg.png +0 -0
  166. data/share/views/public/plugins/tablesorter/themes/green/desc.png +0 -0
  167. data/share/views/public/plugins/tablesorter/themes/green/green.zip +0 -0
  168. data/share/views/public/plugins/tablesorter/themes/green/style.css +39 -0
  169. data/share/views/public/plugins/wz_jsgraphics.js +1108 -0
  170. data/share/views/public/tmp/foo +0 -0
  171. data/share/views/result.haml +6 -1
  172. data/share/views/step_error.haml +5 -0
  173. data/share/views/user_lists.haml +8 -7
  174. data/share/views/wait.haml +40 -2
  175. metadata +302 -106
  176. data/share/views/compass/screen.sass +0 -8
  177. data/share/views/public/plugins/jquery/js/jquery-1.6.2.min.js +0 -18
@@ -13,23 +13,26 @@ require 'rbbt/workflow/rest/auth.rb'
13
13
  require 'rbbt/workflow/rest/email.rb'
14
14
  require 'rbbt/workflow/rest/helpers.rb'
15
15
  require 'rbbt/workflow/rest/entity.rb'
16
+ require 'rbbt/workflow/rest/notes.rb'
16
17
 
17
18
  module WorkflowREST
18
-
19
19
  class << self
20
20
  attr_accessor :workflows
21
21
  self
22
22
  end
23
23
  self.workflows = []
24
24
 
25
-
26
25
  def self.setup
27
26
  configure do
28
27
  Compass.add_project_configuration(Rbbt.share.views.compass["compass.config"].find.dup.to_s)
29
28
  end
30
29
 
31
30
  Sinatra.module_eval do
31
+
32
32
  helpers Sinatra::SinatraRbbt
33
+
34
+ use Rack::Deflater
35
+
33
36
  enable :static
34
37
 
35
38
  # This would make random secrets that would make the server hang after reload by old cookies.
@@ -38,19 +41,41 @@ module WorkflowREST
38
41
  use Rack::Session::Cookie, :key => 'rack.session',
39
42
  :path => '/',
40
43
  :expire_after => 2592000,
41
- :secret => 'rbbt_default_secret. Please CHANGE!'
44
+ :secret => 'rbbt_default_secret. Please CHANGE! ' + WorkflowREST.workflows.collect{|w| w.to_s} * ", "
45
+
46
+ set :root, ENV["PWD"]
47
+ set :cache_dir, "var/cache" unless settings.respond_to? :cache_dir and settings.cache_dir
48
+ set :persistence_dir, "var/cache/persistence" unless settings.respond_to? :persistence_dir and settings.persistence_dir
49
+ set :file_dir, "var/files" unless settings.respond_to? :file_dir and settings.file_dir
50
+ set :note_dir, "var/notes" unless settings.respond_to? :note_dir and settings.note_dir
51
+ set :user_action_defaults, "var/user_defaults" unless settings.respond_to? :user_action_defaults and settings.user_action_defaults
42
52
 
43
- set :cache_dir, "cache"
53
+ # To allow crossorigin with json
54
+ # http://trevorpower.com/blog/faiiure-to-access-json-on-a-remote-domain
55
+ set :protection, :except => :json_csrf
44
56
 
45
57
  before do
46
58
  @file_cache = {}
47
59
  @result_cache = {}
60
+ @js_files = []
61
+ @css_files = []
62
+
48
63
  headers "AJAX-URL" => request.env["REQUEST_URI"]
64
+
65
+ params.delete "_"
66
+ params.delete :_
67
+ cache_control :public, :must_revalidate, :max_age => 60
68
+
69
+ # CrossOrigin
70
+ headers 'Access-Control-Allow-Origin' => request.env['HTTP_ORIGIN'],
71
+ 'Access-Control-Allow-Methods' => %w(GET POST OPTIONS),
72
+ 'Access-Control-Allow-Credentials' => "true",
73
+ 'Access-Control-Max-Age' => "1728000"
49
74
  end
50
75
 
51
76
  after do
52
- @file_cache.clear
53
- @result_cache.clear
77
+ @file_cache.clear if @file_cache
78
+ @result_cache.clear if @result_cache
54
79
  end
55
80
 
56
81
  helpers do
@@ -78,45 +103,94 @@ module WorkflowREST
78
103
  end
79
104
  end
80
105
 
81
- if production?
82
- before do
83
- params.delete "_"
84
- params.delete :_
85
- cache_control :public, :must_revalidate, :max_age => 60
106
+ followed_users = {}
107
+ all_users = settings.users.keys
108
+ all_users.each do |user|
109
+ followed_users[user] = all_users - [user]
110
+ end
111
+ set :followed_users, followed_users
112
+
113
+ error do
114
+ error = request.env['sinatra.error']
115
+ workflow_render('error', :message => error.message)
116
+ end
117
+
118
+ #{{{ Files, CSS, and JS
119
+
120
+ get '/files/:filename' do
121
+ cache_control :public, :max_age => 36000 if production?
122
+ file = File.join(settings.file_dir, params[:filename])
123
+ send_file file
124
+ end
125
+
126
+ get '/stylesheets/entity/:type/:entity/:name.css' do
127
+
128
+ entity_type, format = params["type"].split ":"
129
+ entity = setup_entity(entity_type, format, params["entity"])
130
+
131
+ file = locate_file(WorkflowREST.workflows.last, nil, File.join("compass", params[:name] + '.sass'), entity)
132
+
133
+ content_type 'text/css', :charset => 'utf-8'
134
+ cache_control :public, :max_age => 36000 if production?
135
+ cache_type = production? ? :sync : :none
136
+ cache('css', params.merge(:cache_type => cache_type)) do
137
+ renderer = Sass::Engine.new(file.read, :filename => file.find)
138
+ css_text = renderer.render
139
+ YUI::CssCompressor.new.compress(css_text)
86
140
  end
87
- Log.severity = 0
88
141
  end
89
142
 
90
143
  get '/stylesheets/:name.css' do
91
144
  file = locate_file(WorkflowREST.workflows.last, nil, File.join("compass", params[:name] + '.sass'))
92
145
 
93
146
  content_type 'text/css', :charset => 'utf-8'
94
- cache('css', params.merge(:cache_type => :sync)) do
95
- renderer = Sass::Engine.new(file.read)
96
- renderer.render
147
+ cache_control :public, :max_age => 36000 if production?
148
+ cache_type = production? ? :sync : :none
149
+ cache('css', params.merge(:cache_type => cache_type)) do
150
+ renderer = Sass::Engine.new(file.read, :filename => file.find)
151
+ css_text = renderer.render
152
+ YUI::CssCompressor.new.compress(css_text)
97
153
  end
98
154
  end
99
155
 
156
+ get '/js/entity/:type/:entity/:name.js' do
157
+ content_type 'text/css', :charset => 'utf-8'
158
+ cache_control :public, :max_age => 36000 if production?
159
+
160
+ entity_type, format = params["type"].split ":"
161
+ entity = setup_entity(entity_type, format, params["entity"])
162
+
163
+ send_file locate_file(WorkflowREST.workflows.last, nil, File.join("js", params[:name] + '.js'), entity)
164
+ end
165
+
100
166
  get '/js/:name.js' do
101
167
  content_type 'text/css', :charset => 'utf-8'
102
- send_file locate_file(nil, nil, File.join("js", params[:name] + '.js')).find
168
+ cache_control :public, :max_age => 36000 if production?
169
+ send_file locate_file(WorkflowREST.workflows.last, nil, File.join("js", params[:name] + '.js')).find
103
170
  end
104
171
 
105
- get '/entity/:type/:entity' do
106
- type = params[:type]
172
+ #{{{ entity
173
+
174
+ get '/entity/:entity_type/:entity' do
175
+ params.delete "captures"
176
+ params.delete "splat"
177
+ entity_type = params[:entity_type]
107
178
 
108
179
  visualization_parameters = get_visualization_parameters(params)
109
180
 
110
- cache_type = params.delete(:_cache_type) || params.delete("_cache_type") || :sync
181
+ cache_type = params.delete(:_cache_type) || params.delete("_cache_type") || :async
182
+ update = params.delete(:_update) || params.delete("_update") || nil
111
183
 
112
- cache("Entity:", :params => params, :visualization_params => visualization_parameters, :user => user) do
113
- entity_render(type, params.merge(visualization_parameters))
184
+ cache("Entity [#{ params[:entity] }]:", :update => update, :cache_type => cache_type, :params => params, :visualization_params => visualization_parameters, :user => user) do
185
+ entity_render(entity_type, params.merge(visualization_parameters))
114
186
  end
115
187
  end
116
188
 
117
189
  #{{{ entity_list
118
190
 
119
191
  get '/entity_list/:user' do
192
+ params.delete "captures"
193
+ params.delete "splat"
120
194
  list_user = params.delete(:user) || params.delete("user")
121
195
 
122
196
  list_user = user if list_user.to_s == "user"
@@ -129,124 +203,208 @@ module WorkflowREST
129
203
  workflow_render('user_lists', params.merge(:lists => lists))
130
204
  end
131
205
 
132
- get '/entity_list/:type/:id' do
133
- type = params.delete "type"
206
+ get '/entity_list/:entity_type/:id' do
207
+ params.delete "captures"
208
+ params.delete "splat"
209
+ entity_type = params.delete "entity_type"
134
210
  visualization_parameters = get_visualization_parameters(params)
211
+ list_id = params[:id] = CGI.unescape(params[:id])
135
212
 
136
- cache_type = params.delete(:_cache_type) || params.delete("_cache_type") || :sync
213
+ cache_type = params.delete(:_cache_type) || params.delete("_cache_type") || :async
137
214
  update = params.delete(:_update) || params.delete("_update") || nil
138
215
 
139
- check = Entity::REST.list_file(type, params[:id], user)
140
- check = Entity::REST.list_file(type, params[:id]) unless not check.nil? and File.exists? check
141
-
142
- raise "List of type #{ type } not found for #{params[:id]}: #{ check.inspect }" if check.nil? or not File.exists?(check)
143
-
144
- cache("Entity List:", :check => [check], :update => update, :cache_type => cache_type, :params => params, :type => type, :visualization_params => visualization_parameters, :user => user) do
145
- if visualization_parameters[:_format] == 'json'
146
- list = Entity::REST.load_list(type, params[:id], user)
147
- list.collect{|elem| [elem.clean_annotations, elem.info]}.to_json
216
+ check = Entity::REST.list_file(entity_type, list_id, user)
217
+ check = Entity::REST.list_file(entity_type, list_id, :public) if check.nil? or not File.exists? check
218
+ check = Entity::REST.list_file(entity_type, list_id) if check.nil? or not File.exists? check
219
+
220
+ raise "List of type #{ entity_type } not found for #{list_id}: #{ check.inspect }" if check.nil? or not File.exists?(check)
221
+
222
+ content_type "text/plain" if visualization_parameters[:_format] == 'literal' or visualization_parameters[:_format] == 'tsv' or visualization_parameters[:_format] == 'bed'
223
+ content_type "application/json" if visualization_parameters[:_format] == 'json'
224
+
225
+ cache("Entity List:", :check => [check], :update => update, :cache_type => cache_type, :params => params, :entity_type => entity_type, :visualization_params => visualization_parameters, :user => user) do
226
+ case (visualization_parameters[:_format] || 'html').to_s
227
+ when 'json'
228
+ list = Entity::REST.load_list(entity_type, list_id, user)
229
+ list.collect{|elem| [elem.clean_annotations, elem.info.merge(:id => elem.id)]}.to_json
230
+ when 'bed'
231
+ list = Entity::REST.load_list(entity_type, list_id, user)
232
+ type = entity_type.split(":").first
233
+ case type
234
+ when "GenomicMutation"
235
+ list.collect{|elem| ['chr' + elem.chromosome, elem.position, elem.position+1] * "\t"} * "\n"
236
+ else
237
+ raise "Don't know how to produce bed file for entity type: #{ entity_type }"
238
+ end
239
+ when 'tsv'
240
+ list = Entity::REST.load_list(entity_type, list_id, user)
241
+ Annotated.tsv(list, :all).to_s
242
+ when 'literal'
243
+ list = Entity::REST.load_list(entity_type, list_id, user)
244
+ list * "\n"
148
245
  else
149
- entity_list_render(type, params.merge(visualization_parameters))
246
+ entity_list_render(entity_type, params.merge(visualization_parameters))
150
247
  end
151
248
  end
152
249
  end
153
250
 
154
- post '/entity_list/:type/copy/:id' do
155
- type = params.delete "type"
251
+ post '/entity_list/:entity_type/create/:id' do
252
+ params.delete "captures"
253
+ params.delete "splat"
254
+
255
+ list_id = params.delete("id")
256
+ list_id = CGI.unescape(list_id)
257
+
258
+ entity_type = params.delete "entity_type"
259
+ entities = params.delete("entities")
260
+
261
+ raise "No entities" unless (entities and not entities.empty?)
262
+
263
+ entities = entities.split(/[,;|]/)
264
+
265
+ options = IndiferentHash.setup(params.dup)
266
+ entities = Misc.prepare_entity(entities, entity_type, options)
267
+
268
+ Entity::REST.save_list(entity_type, list_id, entities, user)
269
+
270
+ redirect "/entity_list/#{ entity_type }/#{list_id}"
271
+ end
272
+
273
+ post '/entity_list/:entity_type/copy/:id' do
274
+ params.delete "captures"
275
+ params.delete "splat"
276
+ entity_type = params.delete "entity_type"
156
277
 
157
- list = Entity::REST.load_list(type, params[:id], user)
158
- Entity::REST.save_list(type, params[:new_id], list, user)
278
+ list_id = params[:id] = CGI.unescape(params[:id])
279
+ list = Entity::REST.load_list(entity_type, list_id, user)
280
+ Entity::REST.save_list(entity_type, params[:new_id], list, user)
159
281
 
160
- redirect "/entity_list/#{ type }/#{params[:new_id]}"
282
+ redirect "/entity_list/#{ entity_type }/#{params[:new_id]}"
161
283
  end
162
284
 
163
- post '/entity_list/:type/add/:id' do
164
- type = params.delete "type"
285
+ post '/entity_list/:entity_type/add/:id' do
286
+ params.delete "captures"
287
+ params.delete "splat"
288
+ entity_type = params.delete "entity_type"
165
289
 
166
- list = Entity::REST.load_list(type, params[:id], user)
167
- other_list = Entity::REST.load_list(type, params[:other_list], user)
290
+ list_id = params[:id] = CGI.unescape(params[:id])
291
+ list = Entity::REST.load_list(entity_type, list_id, user)
292
+ other_list = Entity::REST.load_list(entity_type, params[:other_list], user)
168
293
  list.concat other_list
169
- Entity::REST.save_list(type, params[:id], list, user)
294
+ list.uniq!
295
+ Entity::REST.save_list(entity_type, list_id, list, user)
170
296
 
171
297
  redirect back
172
298
  end
173
299
 
174
- post '/entity_list/:type/remove/:id' do
175
- type = params.delete "type"
300
+ post '/entity_list/:entity_type/remove/:id' do
301
+ params.delete "captures"
302
+ params.delete "splat"
303
+ entity_type = params.delete "entity_type"
176
304
 
177
- list = Entity::REST.load_list(type, params[:id], user)
178
- other_list = Entity::REST.load_list(type, params[:other_list], user)
179
- Entity::REST.save_list(type, params[:id], list.remove(other_list), user)
305
+ list_id = params[:id] = CGI.unescape(params[:id])
306
+ list = Entity::REST.load_list(entity_type, list_id, user)
307
+ other_list = Entity::REST.load_list(entity_type, params[:other_list], user)
308
+ Entity::REST.save_list(entity_type, list_id, list.remove(other_list), user)
180
309
 
181
310
  redirect back
182
311
  end
183
312
 
184
- post '/entity_list/:type/subset/:id' do
185
- type = params.delete "type"
313
+ post '/entity_list/:entity_type/subset/:id' do
314
+ params.delete "captures"
315
+ params.delete "splat"
316
+ entity_type = params.delete "entity_type"
186
317
 
187
- list = Entity::REST.load_list(type, params[:id], user)
188
- other_list = Entity::REST.load_list(type, params[:other_list], user)
189
- Entity::REST.save_list(type, params[:id], list.subset(other_list), user)
318
+ list_id = params[:id] = CGI.unescape(params[:id])
319
+ list = Entity::REST.load_list(entity_type, list_id, user)
320
+ other_list = Entity::REST.load_list(entity_type, params[:other_list], user)
321
+ Entity::REST.save_list(entity_type, list_id, list.subset(other_list), user)
190
322
 
191
323
  redirect back
192
324
  end
193
325
 
194
- get '/entity_list/:type/edit/:id' do
195
- type = params[:type]
326
+ get '/entity_list/:entity_type/edit/:id' do
327
+ params.delete "captures"
328
+ params.delete "splat"
329
+ entity_type = params[:entity_type]
196
330
  visualization_parameters = get_visualization_parameters(params)
197
331
 
198
332
  workflow = WorkflowREST.workflows.last
199
- id = params[:id]
200
- list = Entity::REST.load_list(type, id, user)
333
+ list_id = params[:id] = CGI.unescape(params[:id])
334
+ id = list_id
335
+ list = Entity::REST.load_list(entity_type, id, user)
201
336
  workflow_render('edit_list', workflow, params.merge(:list => list))
202
337
  end
203
338
 
204
- delete '/entity_list/:type/:id' do
205
- Entity::REST.delete_list(params[:type], params[:id], user)
339
+ delete '/entity_list/:entity_type/:id' do
340
+ params.delete "captures"
341
+ params.delete "splat"
342
+ list_id = params[:id] = CGI.unescape(params[:id])
343
+ Entity::REST.delete_list(params[:entity_type], list_id, user)
206
344
  redirect '/'
207
345
  end
208
346
 
209
- # entities
210
- delete '/entity_list/:type/:entity/:id' do
211
- id = params[:id]
212
- Log.debug "Deleting #{params[:entity] } from #{params[:id]}"
347
+ delete '/entity_list/:entity_type/:entity/:id' do
348
+ params.delete "captures"
349
+ params.delete "splat"
350
+ id = params[:id] = CGI.unescape(params[:id])
351
+ Log.debug "Deleting #{params[:entity] } from #{id}"
213
352
 
214
- list = Entity::REST.load_list(params[:type], id, user)
353
+ list = Entity::REST.load_list(params[:entity_type], id, user)
215
354
 
216
355
  list.delete params[:entity]
217
356
 
218
- Entity::REST.save_list(params[:type], id, list, user)
357
+ Entity::REST.save_list(params[:entity_type], id, list, user)
219
358
 
220
359
  redirect back
221
360
  end
222
361
 
223
- post '/entity_list/:type/:entity/:id' do
224
- id = params.delete(:id) || params.delete("id")
225
- entity = params.delete(:entity) || params.delete("entity")
226
- type = params.delete(:type) || params.delete("type")
362
+ post '/entity_list/:entity_type/:entity/:list_id' do
363
+ params.delete "captures"
364
+ params.delete "splat"
365
+ list_id = params.delete(:list_id) || params.delete("list_id")
366
+ entity = params.delete(:entity) || params.delete("entity")
367
+ entity_type = params.delete(:entity_type) || params.delete("entity_type")
227
368
 
228
- info = {}
369
+ entity_type, entity_format = entity_type.split(":")
370
+ info = {:annotation_types => entity_type, :format => entity_format}
229
371
  params.each{|k,v| info[k] = begin JSON.parse(v) rescue v end}
230
372
  entity = Annotated.load_tsv_values(entity, [[info.to_json]], "JSON")
373
+ entity.id = params[:entity_id] if params.include? :entity_id
231
374
 
232
- list = Entity::REST.load_list(type, id, user)
233
-
375
+ list =
376
+ begin
377
+ Entity::REST.load_list(entity_type, list_id, user) || []
378
+ rescue
379
+ []
380
+ end
234
381
 
235
- different = entity.info.select{|k,v| not v.nil? and v != list_info[k]}.any?
382
+
383
+ different = Annotated === list ? entity.info.select{|k,v| not v.nil? and v != list.info[k]}.any? : true
236
384
 
385
+ if different
386
+ new = list.collect{|e| e}
387
+ else
388
+ new = list
389
+ end
237
390
 
238
- new = list.collect{|e| e} if different
239
- new.delete entity
391
+ new = new.reject{|e| e.id == entity.id}
240
392
  new << entity
241
- Entity::REST.save_list(type, id, new, user)
242
393
 
243
- redirect back
394
+
395
+ new.first.annotate new if new.collect{|e| e.info}.uniq.length == 1
396
+
397
+ Entity::REST.save_list(entity_type, list_id, new, user)
398
+
399
+ redirect back unless request.xhr?
244
400
  end
245
401
 
246
402
  #{{{ entity_action
247
403
 
248
- get '/entity_action/:type/:action/:entity' do
249
- type = params.delete "type"
404
+ get '/entity_action/:entity_type/:action/:entity' do
405
+ params.delete "captures"
406
+ params.delete "splat"
407
+ entity_type = params.delete "entity_type"
250
408
  action = params.delete "action"
251
409
 
252
410
  visualization_parameters = get_visualization_parameters(params)
@@ -254,13 +412,22 @@ module WorkflowREST
254
412
  cache_type = params.delete(:_cache_type) || params.delete("_cache_type") || :async
255
413
  update = params.delete(:_update) || params.delete("_update") || nil
256
414
 
257
- cache("Entity Action [#{action}][#{ params[:entity] }]", :update => update, :cache_type => cache_type, :params => params, :type => type, :action => action, :visualization_params => visualization_parameters, :user => user) do
258
- entity_action_render(type, action, params.merge(visualization_parameters))
415
+ add_user_defaults(user, entity_type, action, params) if authorized?
416
+
417
+ html = cache("Entity Action [#{action}][#{ params[:entity] }]", :update => update, :cache_type => cache_type, :params => params, :entity_type => entity_type, :action => action, :visualization_params => visualization_parameters, :user => user) do
418
+ entity_action_render(entity_type, action, params.merge(visualization_parameters))
259
419
  end
420
+
421
+ save_user_defaults(user, entity_type, action, params) if authorized? and response.status == 200
422
+ clear_user_defaults(user, entity_type, action) if authorized? and response.status == 500
423
+
424
+ html
260
425
  end
261
426
 
262
- get '/entity_list_action/:type/:action/:id' do
263
- type = params.delete "type"
427
+ get '/entity_list_action/:entity_type/:action/:id' do
428
+ params.delete "captures"
429
+ params.delete "splat"
430
+ entity_type = params.delete "entity_type"
264
431
  action = params.delete "action"
265
432
 
266
433
  visualization_parameters = get_visualization_parameters(params)
@@ -268,11 +435,78 @@ module WorkflowREST
268
435
  cache_type = params.delete(:_cache_type) || params.delete("_cache_type") || :async
269
436
  update = params.delete(:_update) || params.delete("_update") || nil
270
437
 
271
- cache("Entity List Action [#{action}] [#{ params[:id]}]", :update => update, :cache_type => cache_type, :params => params, :type => type, :action => action, :visualization_params => visualization_parameters, :user => user) do
272
- entity_list_action_render(type, action, params.merge(visualization_parameters))
438
+ add_user_defaults(user, entity_type, action, params) if authorized?
439
+
440
+ list_id = params[:id] = params[:id] = CGI.unescape(params[:id])
441
+ html = cache("Entity List Action [#{action}] [#{ list_id}]", :update => update, :cache_type => cache_type, :params => params, :entity_type => entity_type, :action => action, :visualization_params => visualization_parameters, :user => user) do
442
+ entity_list_action_render(entity_type, action, params.merge(visualization_parameters))
273
443
  end
444
+
445
+ save_user_defaults(user, entity_type, action, params) if authorized? and response.status == 200
446
+ clear_user_defaults(user, entity_type, action) if authorized? and response.status == 500
447
+
448
+ html
449
+ end
450
+
451
+ #{{{ Notes
452
+
453
+ get '/notes/edit/*' do
454
+ params.delete "captures"
455
+ path = params.delete("splat").last
456
+ markup = get_notes_markup(path, params, user)
457
+ workflow_render('notes', StudyExplorer, nil, :markup => markup)
458
+ end
459
+
460
+ post '/notes/edit/*' do
461
+ params.delete "captures"
462
+ path = params.delete("splat").last
463
+ path = path.sub("/notes/edit", "/notes")
464
+ markup = params.delete('markup')
465
+ save_notes(path, params, markup, user)
466
+ redirect request.env["REQUEST_URI"].sub('/notes/edit', '/notes')
274
467
  end
275
468
 
469
+ post '/notes/share/*' do
470
+ params.delete "captures"
471
+ path = params.delete("splat").last
472
+ path = path.sub("/notes/edit", "/notes")
473
+ markup = params.delete('markup')
474
+ params.delete("_method")
475
+ share_notes(path, params, markup, user)
476
+ redirect back unless request.xhr?
477
+ end
478
+
479
+ post '/notes/unshare/*' do
480
+ params.delete "captures"
481
+ path = params.delete("splat").last
482
+ path = path.sub("/notes/edit", "/notes")
483
+ markup = params.delete('markup')
484
+ params.delete("_method")
485
+ unshare_notes(path, params, markup, user)
486
+ redirect back unless request.xhr?
487
+ end
488
+
489
+
490
+ delete '/notes/*' do
491
+ params.delete "captures"
492
+ path = params.delete("splat").last
493
+ params.delete("_method")
494
+ markup = delete_notes_markup(path, params, user)
495
+ redirect File.join("/", path)
496
+ end
497
+
498
+ get '/notes/shared/:user/*' do
499
+ params.delete "captures"
500
+ path = params.delete("splat").last
501
+ sharing_user = params.delete('user')
502
+ render_notes(path, params, sharing_user, true)
503
+ end
504
+
505
+ get '/notes/*' do
506
+ params.delete "captures"
507
+ path = params.delete("splat").last
508
+ render_notes(path, params, user)
509
+ end
276
510
  end
277
511
 
278
512
  def self.add_task(workflow, task_name, type = nil)
@@ -301,8 +535,10 @@ module WorkflowREST
301
535
 
302
536
  case
303
537
  when visualization_parameters[:_format] == "json"
538
+ content_type "application/json"
304
539
  task_info.to_json
305
540
  when visualization_parameters[:_format] == "raw"
541
+ content_type "text/plain"
306
542
  task_info.collect{|k,v| [k,v] * "\t"} * "\n"
307
543
  when visualization_parameters[:_format] == "html"
308
544
  workflow_render("task_info", workflow, task_name, workflow.task_info(task_name).merge(visualization_parameters).merge(:task_info => task_info))
@@ -376,7 +612,7 @@ module WorkflowREST
376
612
 
377
613
  when :exec
378
614
  result = workflow.job(task_name, real_jobname, inputs.dup).exec
379
- workflow_render_result(result, workflow, task_name, visualization_parameters.merge(:inputs => inputs))
615
+ workflow_render_result(result, workflow, task_name, visualization_parameters.merge(:inputs => inputs).merge(workflow.task_info(task_name)))
380
616
 
381
617
  when :synchronous, :asynchronous
382
618
  job = workflow.job(task_name, real_jobname, inputs)
@@ -426,7 +662,11 @@ module WorkflowREST
426
662
 
427
663
  session[:jobname] = jobname
428
664
 
429
- step = workflow.load_id(File.join(task_name, real_jobname))
665
+ step = nil
666
+ [real_jobname, jobname].uniq.each do |jname|
667
+ step = workflow.load_id(File.join(task_name, jname))
668
+ break if File.exists? step.info_file
669
+ end
430
670
 
431
671
  case
432
672
 
@@ -436,7 +676,7 @@ module WorkflowREST
436
676
  if visualization_parameters[:_format] == "html"
437
677
  content_type "text/html"
438
678
  status 500
439
- return workflow_render("error", workflow, task_name, workflow.task_info(task_name).merge(visualization_parameters).merge(:jobname => jobname, :step => step, :inputs => step.info[:inputs]))
679
+ return workflow_render("step_error", workflow, task_name, workflow.task_info(task_name).merge(visualization_parameters).merge(:jobname => jobname, :step => step, :inputs => step.info[:inputs]))
440
680
  else
441
681
  status 500
442
682
  content_type "text/plain"
@@ -449,8 +689,13 @@ module WorkflowREST
449
689
  if visualization_parameters[:_format] == "html"
450
690
  content_type "text/html"
451
691
  status 202
452
- @rbbt_refresh = 30 unless step.error?
453
- return workflow_render("wait", workflow, task_name, workflow.task_info(task_name).merge(visualization_parameters).merge(:jobname => jobname, :step => step, :inputs => step.info[:inputs]))
692
+ if request.xhr?
693
+ visualization_parameters[:_layout] = false
694
+ return workflow_render("wait", workflow, task_name, workflow.task_info(task_name).merge(visualization_parameters).merge(:jobname => jobname, :step => step, :inputs => step.info[:inputs]))
695
+ else
696
+ @rbbt_refresh = 30 unless step.error?
697
+ return workflow_render("wait", workflow, task_name, workflow.task_info(task_name).merge(visualization_parameters).merge(:jobname => jobname, :step => step, :inputs => step.info[:inputs]))
698
+ end
454
699
  else
455
700
  status 202
456
701
  step.status
@@ -467,21 +712,45 @@ module WorkflowREST
467
712
  :user => user
468
713
  ) do
469
714
  case
715
+ when visualization_parameters[:_format].to_s == "excel"
716
+ require 'rbbt/tsv/excel'
717
+ data = nil
718
+ excel_file = TmpFile.tmp_file
719
+ result = step.load
720
+ result.excel(excel_file, :name => params[:_excel_use_name],:sort_by => params[:_excel_sort_by], :sort_by_cast => params[:_excel_sort_by_cast])
721
+ send_file excel_file, :type => 'application/vnd.ms-excel', :filename => step.clean_name + '.xls'
470
722
  when visualization_parameters[:_format] == "html"
471
723
  result = step.load
472
724
  workflow_render_result(result, workflow, task_name, workflow.task_info(task_name).merge(visualization_parameters).merge(:jobname => jobname, :step => step, :inputs => step.info[:inputs], :result => result))
473
725
 
474
- when visualization_parameters[:_format] == "json"
475
- content_type "application/json"
726
+ when visualization_parameters[:_format].to_s == "json"
476
727
  result = step.load
477
728
  result = paginate(result, visualization_parameters[:_page]) if visualization_parameters.include? "_page"
478
729
 
479
- if TSV === result
730
+ content_type "application/json"
731
+
732
+ case
733
+ when TSV === result
480
734
  result.dup.to_json
735
+ when workflow.task_info(task_name)[:result_type] == :annotations
736
+ Annotated.json(result, true)
481
737
  else
482
738
  result.to_json
483
739
  end
484
740
 
741
+ when visualization_parameters[:_format].to_s == "raw"
742
+ content_type "text/plain"
743
+ result = step.load
744
+
745
+ case
746
+ when workflow.task_info(task_name)[:result_type] == :annotations
747
+ Annotated.tsv(result, :all).to_s
748
+ when Array === result
749
+ result * "\n"
750
+ else
751
+ result.to_s
752
+ end
753
+
485
754
  else
486
755
  content_type "text/plain"
487
756
  result = step.load
@@ -636,7 +905,8 @@ module WorkflowREST
636
905
 
637
906
  get File.join("/plugins", workflow.to_s, "*") do
638
907
  file = params[:splat].first
639
- send_file RbbtHTMLHelpers.locate_file(workflow, nil, 'plugins/' + file)
908
+ path = RbbtHTMLHelpers.locate_file(workflow, nil, 'plugins/' + file)
909
+ send_file path
640
910
  end
641
911
 
642
912
  workflow.asynchronous_exports.each do |name|