rbbt-rest 1.1.0 → 1.1.2

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 (34) hide show
  1. data/lib/rbbt/rest/common/cache.rb +3 -1
  2. data/lib/rbbt/rest/common/misc.rb +14 -7
  3. data/lib/rbbt/rest/common/resources.rb +0 -1
  4. data/lib/rbbt/rest/common/table.rb +46 -5
  5. data/lib/rbbt/rest/entity.rb +7 -0
  6. data/lib/rbbt/rest/entity/helpers.rb +3 -2
  7. data/lib/rbbt/rest/main.rb +3 -1
  8. data/lib/rbbt/rest/web_tool.rb +8 -0
  9. data/lib/rbbt/rest/workflow.rb +2 -1
  10. data/lib/rbbt/rest/workflow/jobs.rb +2 -0
  11. data/share/views/compass/_foundation_setup.sass +1 -6
  12. data/share/views/compass/actions.sass +1 -3
  13. data/share/views/compass/app.sass +8 -6
  14. data/share/views/compass/dom.sass +0 -10
  15. data/share/views/compass/form.sass +2 -0
  16. data/share/views/compass/list_container.sass +4 -2
  17. data/share/views/compass/offcanvas.sass +2 -2
  18. data/share/views/compass/style.sass +5 -17
  19. data/share/views/compass/style_mixins.sass +19 -1
  20. data/share/views/compass/table.sass +3 -0
  21. data/share/views/compass/tabs.sass +9 -16
  22. data/share/views/job_result.haml +4 -0
  23. data/share/views/job_result/integer.haml +1 -0
  24. data/share/views/job_result/text.haml +1 -0
  25. data/share/views/layout.haml +5 -2
  26. data/share/views/partials/table.haml +10 -0
  27. data/share/views/public/js/helpers.js +14 -0
  28. data/share/views/public/js/lists.js +16 -2
  29. data/share/views/public/js/offcanvas.js +2 -0
  30. data/share/views/public/js/tables.js +89 -27
  31. data/share/views/public/js/workflow.js +29 -0
  32. data/share/views/public/plugins/jquery/js/jquery-1.9.1.js +9597 -0
  33. data/share/views/public/plugins/jquery/js/jquery-2.0.0.js +8755 -0
  34. metadata +8 -2
@@ -39,7 +39,9 @@ module RbbtRESTHelpers
39
39
  content_type "text/tab-separated-values"
40
40
  send_file fragment_file
41
41
  when "table"
42
- tsv2html fragment_file
42
+ halt 200, tsv2html(fragment_file)
43
+ when "json"
44
+ halt 200, tsv_process(TSV.open(fragment_file)).to_json
43
45
  when "excel"
44
46
  require 'rbbt/tsv/excel'
45
47
  tsv = TSV.open(Open.open(fragment_file))
@@ -52,8 +52,10 @@ module RbbtRESTHelpers
52
52
  @splat = consume_parameter :splat
53
53
  @captures = consume_parameter :captures
54
54
 
55
- # Pagination
55
+ # TSV table pagination, filtering, and slicing
56
56
  @page = consume_parameter :_page
57
+ @filter = consume_parameter :_filter
58
+ @column = consume_parameter :_column
57
59
 
58
60
  # Fix boolean inputs sumbitted using checkboxes
59
61
  params.keys.each do |param|
@@ -106,14 +108,19 @@ module RbbtRESTHelpers
106
108
  value
107
109
  end
108
110
 
109
- if Array === text
111
+ case
112
+ when Array === text
110
113
  text
111
- else
112
- if text =~ /\[.*\]/
114
+ when text =~ /^list:([^:]+):(.+)$/
115
+ Entity::List.load_list($1, $2, user)
116
+ when text =~ /\[.*\]/
113
117
  JSON.parse(text)
114
- else
115
- text.split(/\r?\n|\|/).collect{|l| l.strip}
116
- end
118
+ when text =~ /\n/
119
+ text.split(/\r?\n/).collect{|l| l.strip}
120
+ when text =~ /\|/
121
+ text.split(/\|/).collect{|l| l.strip}
122
+ else
123
+ text.split(/,/).collect{|l| l.strip}
117
124
  end
118
125
 
119
126
  when :tsv
@@ -49,7 +49,6 @@ module RbbtRESTHelpers
49
49
  } * "\n"
50
50
 
51
51
  FileUtils.mkdir_p File.dirname(filename) unless File.exists? File.dirname(filename)
52
- #Open.write(filename, YUI::JavaScriptCompressor.new(:munge => false).compress(text))
53
52
  Open.write(filename, Uglifier.compile(text))
54
53
  end
55
54
 
@@ -94,7 +94,31 @@ module RbbtRESTHelpers
94
94
  end
95
95
  end
96
96
 
97
- def tsv_rows(tsv, page = nil)
97
+ def tsv_process(tsv, filter = nil, column = nil)
98
+ filter = @filter if filter.nil?
99
+ column = @column if column.nil?
100
+
101
+ if filter and filter.to_s != "false"
102
+ filter.split("|").each do |f|
103
+ key, value = f.split("~")
104
+ case
105
+ when value =~ /^([<>]=?)(.*)/
106
+ tsv = tsv.select(key){|k| k.send($1, $2)}
107
+ when value =~ /^\/.*\/$/
108
+ tsv = tsv.select(key => Regexp.new(value))
109
+ else
110
+ tsv = tsv.select(key => value)
111
+ end
112
+ end
113
+ end
114
+
115
+ tsv = tsv.column(column) if column and not column.empty?
116
+
117
+ tsv
118
+ end
119
+
120
+ def tsv_rows(tsv, page = nil, filter = nil, column = nil)
121
+ tsv = tsv_process(tsv, filter, column)
98
122
  page = @page if page.nil?
99
123
  if page.nil? or page.to_s == "false"
100
124
  tsv_rows_full(tsv)
@@ -122,6 +146,11 @@ module RbbtRESTHelpers
122
146
  @table_headers[field] = [entity_type, entity_options]
123
147
  end
124
148
 
149
+ def filter(field, type = :string)
150
+ @table_filters ||= {}
151
+ @table_filters[field] = type
152
+ end
153
+
125
154
  def table(options = {})
126
155
  options = {} if options.nil?
127
156
 
@@ -146,24 +175,36 @@ module RbbtRESTHelpers
146
175
  @table_headers = {}
147
176
  end
148
177
 
178
+ if @table_filters and @table_filters.any?
179
+ options[:filters] = @table_filters
180
+ @table_filters = {}
181
+ end
182
+
149
183
  Open.write table_file, tsv.to_s
150
184
  Open.write table_file + '.table_options', options.to_yaml if defined? options.any?
151
185
 
152
186
  total_size = tsv.size
153
187
  if options[:page].nil? and total_size > PAGE_SIZE * 1.2
154
- page = "1"
188
+ @page = "1"
155
189
  end
156
190
 
157
- partial_render('partials/table', {:page => page, :total_size => total_size, :rows => tsv_rows(tsv, page), :header => tsv.all_fields, :url => url, :table_class => table_class * " ", :table_options => options.dup})
191
+ tsv2html(table_file)
192
+ end
193
+
194
+ def load_tsv(file)
195
+ tsv
158
196
  end
159
197
 
160
198
  def tsv2html(file)
161
199
  tsv = TSV.open(Open.open(file))
162
- table_options = YAML.load_file(file + '.table_options') if File.exists? file + '.table_options'
200
+
201
+ table_options = File.exists?(file + '.table_options') ? YAML.load_file(file + '.table_options') : {}
163
202
  tsv.entity_options = table_options[:tsv_entity_options]
164
203
  headers = table_options[:headers]
204
+ filters = table_options[:filters]
165
205
  headers.each{|field,p| tsv.entity_templates[field] = Misc.prepare_entity("TEMPLATE", p.first, p.last) } unless headers.nil?
206
+
166
207
  content_type "text/html"
167
- halt 200, partial_render('partials/table', {:total_size => tsv.size, :rows => tsv_rows(tsv), :header => tsv.all_fields, :table_options => table_options})
208
+ partial_render('partials/table', {:filters => filters, :total_size => tsv.size, :rows => tsv_rows(tsv), :header => tsv.all_fields, :table_options => table_options})
168
209
  end
169
210
  end
@@ -110,6 +110,13 @@ module Sinatra
110
110
  send_file global_file if File.exists? global_file
111
111
 
112
112
  raise "List file not found: #{ list_id }"
113
+ when :json
114
+ list = Entity::List.load_list(entity_type.split(":").first, list_id, user)
115
+ list_info = {:entities => list, :info => list.info}
116
+ halt 200, list_info.to_json
117
+ when :info
118
+ list = Entity::List.load_list(entity_type.split(":").first, list_id, user)
119
+ halt 200, list.info.to_json
113
120
  when :list
114
121
  list = Entity::List.load_list(entity_type.split(":").first, list_id, user)
115
122
 
@@ -14,7 +14,7 @@ module EntityRESTHelpers
14
14
  end
15
15
  end
16
16
 
17
- def action_parameters(values = nil, &block)
17
+ def action_parameters(values = nil, action_options = {}, form_options = {}, &block)
18
18
  o = Object.new
19
19
  o.extend AnnotatedModule
20
20
 
@@ -46,8 +46,9 @@ module EntityRESTHelpers
46
46
  locals[:action] = @ajax_url
47
47
  locals[:klass] = 'action_parameter_form'
48
48
  locals[:info] = info
49
+ locals = locals.merge(form_options)
49
50
 
50
- html_tag :div, partial_render('partials/form', locals), :class => 'action_parameters'
51
+ html_tag :div, partial_render('partials/form', locals), {:class => 'action_parameters'}.merge(action_options)
51
52
  end
52
53
 
53
54
  def page_type(path = nil)
@@ -17,6 +17,8 @@ module Sinatra
17
17
  helpers RbbtRESTHelpers
18
18
  register Sinatra::RbbtAuth
19
19
 
20
+ add_sass_load_path Rbbt.share.views.compass.find(:lib)
21
+
20
22
  set :cache_dir, Rbbt.var.sinatra.cache.find unless settings.respond_to? :cache_dir and settings.cache_dir != nil
21
23
  set :file_dir, Rbbt.var.sinatra.files.find unless settings.respond_to? :file_dir and settings.file_dir != nil
22
24
 
@@ -32,7 +34,7 @@ module Sinatra
32
34
  end
33
35
 
34
36
  before do
35
- Log.debug("IP #{request.ip}: " << request.path_info << ". Params: " << params.inspect)
37
+ Log.debug("IP #{request.ip}: " << request.path_info << ". Params: " << Misc.remove_long_items(params).inspect)
36
38
  process_common_parameters
37
39
 
38
40
  if profile
@@ -0,0 +1,8 @@
1
+
2
+ module Sinatra
3
+ module RbbtToolHelper
4
+ def tool(toolname, options = {})
5
+ partial_render("tools/#{toolname}", options)
6
+ end
7
+ end
8
+ end
@@ -26,6 +26,7 @@ module Sinatra
26
26
  add_sass_load_path views_dir.compass if views_dir.compass.exists?
27
27
 
28
28
  RbbtRESTHelpers.javascript_resources.unshift views_dir.public.js if views_dir.public.js.exists?
29
+ RbbtRESTHelpers.sass_resources.unshift views_dir.compass if views_dir.compass.exists?
29
30
  end
30
31
  end
31
32
 
@@ -36,7 +37,7 @@ module Sinatra
36
37
 
37
38
  Log.debug("Adding #{ workflow } to REST server")
38
39
 
39
- load workflow.libdir.lib['sinatra.rb'] if File.exists? workflow.libdir.lib['sinatra.rb']
40
+ self.instance_eval workflow.libdir.lib['sinatra.rb'].read if File.exists? workflow.libdir.lib['sinatra.rb']
40
41
 
41
42
  get "/#{workflow.to_s}" do
42
43
  case format
@@ -129,12 +129,14 @@ module WorkflowRESTHelpers
129
129
  job.clean if update == :reload
130
130
  job.run
131
131
  job_url = to(File.join("/", workflow.to_s, task, job.name))
132
+ job_url += "?_format=#{@format}" if @format
132
133
  halt 200, job.name if format === :jobname
133
134
  redirect job_url
134
135
  when :asynchronous, :async, nil
135
136
  job.clean if update == :reload
136
137
  job.fork
137
138
  job_url = to(File.join("/", workflow.to_s, task, job.name))
139
+ job_url += "?_format=#{@format}" if @format
138
140
  halt 200, job.name if format === :jobname
139
141
  redirect job_url
140
142
  else
@@ -1,14 +1,10 @@
1
- // Make sure the charset is set appropriately
2
1
  @charset "UTF-8"
3
2
 
4
- // This includes all of the foundation global elements that are needed to work with any of the other files.
5
- //
6
- // RENAME THIS TO _foundation-global.scss ONCE ALL THE OLD VARIABLES ARE OUT OF THE FILE.
7
-
8
3
  @import "normalize"
9
4
  @import "foundation/_variables"
10
5
  @import "foundation/components/global"
11
6
  @import "colors"
7
+
12
8
  $breakpoint: 1050px
13
9
 
14
10
  $small-screen: emCalc($breakpoint)
@@ -40,7 +36,6 @@ $indent: 15px
40
36
  $vindent: 22px
41
37
  $white: #EEEEEE
42
38
 
43
-
44
39
  // Foundation Components
45
40
  @import foundation/components/grid
46
41
  @import foundation/components/visibility
@@ -1,9 +1,7 @@
1
1
  .action_controller
2
2
  ul.controls, ul.actions
3
- @include inline-list()
4
- @include button-group-container()
5
3
 
6
- #body .action_parameters
4
+ .action_controller .action_parameters
7
5
  @extend .offcanvas
8
6
 
9
7
  .action_loader
@@ -1,18 +1,20 @@
1
1
  @import _foundation_setup
2
+ @import lists
3
+ @import list_container
4
+ @import dom
5
+ @import form
6
+ @import table
7
+ @import tabs
8
+
2
9
  @import style_mixins
10
+
3
11
  @import topbar
4
12
  @import favourites
5
13
  @import footer
6
14
  @import entity_card
7
15
  @import actions
8
- @import lists
9
- @import list_container
10
- @import form
11
- @import dom
12
- @import table
13
16
  @import offcanvas
14
17
  @import fragment
15
- @import tabs
16
18
  @import workflow
17
19
  @import style
18
20
 
@@ -11,9 +11,6 @@
11
11
  display: inline-block
12
12
  padding: 0px 10px
13
13
 
14
- .embedded
15
- // @include transition(1.25s height ease-in)
16
-
17
14
  .hide
18
15
  display: none
19
16
 
@@ -30,13 +27,6 @@ dl.float
30
27
  dt dd
31
28
  float: left
32
29
 
33
- //dl.meta
34
- dt, dd
35
- font-size: 0.7em
36
- display: inline
37
- dd
38
- margin-right: 1em
39
-
40
30
  i[class*="foundicon-"]
41
31
  display: inline-block
42
32
 
@@ -26,3 +26,5 @@
26
26
  select.favourite_lists
27
27
  width: 175px
28
28
 
29
+ .action_parameters form
30
+ +clearfix()
@@ -24,9 +24,11 @@ dl.list_container
24
24
  a.entity_list
25
25
  display: block
26
26
  z-index: 15
27
- margin-right: 2em
27
+ margin-right: 1em
28
28
  color: $primary-color
29
29
  width: 1.5em
30
30
  float: left
31
- padding: 2 0 0 5
31
+ padding-top: 0.2em
32
+ padding-bottom: 0px
33
+ padding-right: 20px
32
34
 
@@ -3,7 +3,7 @@
3
3
  min-height: 2em
4
4
 
5
5
  .offcanvas_button
6
- position: absolute
6
+ position: absolute !important
7
7
  top: - 30px
8
8
  height: 1em
9
9
  right: 14px
@@ -63,4 +63,4 @@
63
63
 
64
64
  @media #{$not_small}
65
65
  .offcanvas_button
66
- display: none
66
+ display: none !important
@@ -1,9 +1,10 @@
1
1
  @import "colors"
2
2
  @import url(http://fonts.googleapis.com/css?family=Noticia+Text)
3
+ @import url(http://fonts.googleapis.com/css?family=Open+Sans)
3
4
 
4
5
  body, p, h1, h2, h3, h4, h5, h6
5
- font-family: Arial,Liberation Sans,DejaVu Sans,sans-serif
6
- font-family: "Noticia Text", Verdana, Arial, "Helvetica Neue", Helvetica, sans-serif
6
+ //font-family: Arial, Liberation Sans,DejaVu Sans,sans-serif
7
+ font-family: "Open Sans", "Trebuchet MS", "Noticia Text", Verdana, Arial, "Helvetica Neue", Helvetica, sans-serif
7
8
  line-height: 1.4em
8
9
 
9
10
  body
@@ -26,21 +27,8 @@ footer
26
27
  background-color: darken($primary-color, 30%)
27
28
 
28
29
  ul.controls, ul.actions
29
- margin: 0
30
- margin-top: 5px
31
- margin-bottom: 5px
32
- li
33
- margin: 0 2px 0 0
34
-
35
- a
36
- @include button-base
37
- @include button-size
38
- @include button-style
39
- @include radius
40
- @include single-transition
41
- margin-bottom: 2px
42
- font-size: 0.8em
43
-
30
+ @extend .button-group-list
31
+
44
32
  ul.controls
45
33
  li.parameters:not(.active), li.reload:not(.active)
46
34
  a
@@ -1,3 +1,4 @@
1
+ @import foundation/components/inline-lists
1
2
  =dl_indented()
2
3
  dt
3
4
  font-weight: bold
@@ -9,4 +10,21 @@
9
10
  //border: solid 1px darken($white, 10%)
10
11
  @extend .panel
11
12
 
12
-
13
+ .button-group-list
14
+ @include inline-list()
15
+ @include button-group-container()
16
+ margin: 0
17
+ margin-top: 5px
18
+ margin-bottom: 5px
19
+ li
20
+ margin: 0 2px 0 0
21
+
22
+ a
23
+ @include button-base
24
+ @include button-size
25
+ @include button-style
26
+ @include radius
27
+ @include single-transition
28
+ margin-bottom: 2px
29
+ font-size: 0.8em
30
+
@@ -19,6 +19,9 @@ table
19
19
  @include button-group-container()
20
20
  margin-bottom: 0
21
21
  float: right
22
+ li.filter
23
+ .filter_controls
24
+ display: none
22
25
 
23
26
 
24
27
  &.sorted
@@ -1,8 +1,12 @@
1
1
  dl.tabs
2
2
  position: relative
3
- dd:not(.selected)
4
- display: none
5
- dt
3
+ & > dd:not(.selected)
4
+ visibility: hidden
5
+ height: 0px
6
+ margin: 0px
7
+ padding: 0px
8
+ border: none
9
+ & > dt
6
10
  margin: 0px
7
11
  padding: 5px
8
12
  padding-bottom: 2px
@@ -14,21 +18,10 @@ dl.tabs
14
18
  background: $tab-active-color-bg
15
19
 
16
20
  &:not(.selected)
21
+ cursor: pointer
17
22
  border: none
18
23
  background: $tab-color-bg
19
-
20
- //
21
- float: left
22
- line-height: 2
23
- height: 2em
24
- border-bottom: 0
25
- padding: 0 1em
26
- position: relative
27
- left: 35px
28
- margin-right: 1px
29
- cursor: pointer
30
-
31
- dd
24
+ & > dd
32
25
  float: right
33
26
  width: 100%
34
27
  padding: 5px