rbbt-rest 1.1.0 → 1.1.2

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