rbbt-views 1.0.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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|