omf_web 0.9.6 → 0.9.7

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 (91) hide show
  1. data/README.md +168 -13
  2. data/bin/omf-web-basic +3 -3
  3. data/doc/index.md +205 -0
  4. data/example/NOT_WORKING/brooklyn/brooklyn_server.rb +2 -2
  5. data/example/NOT_WORKING/frisbee/data_sources/parse_log.rb +1 -1
  6. data/example/NOT_WORKING/frisbee/viz_server.rb +1 -1
  7. data/example/NOT_WORKING/gec12/gec12_demo_server.rb +1 -1
  8. data/example/NOT_WORKING/gec12/visualization.rb +2 -2
  9. data/example/NOT_WORKING/network/network_server.rb +2 -2
  10. data/example/NOT_WORKING/wimax/test.rb +2 -2
  11. data/example/NOT_WORKING/wimax/viz_server.rb +2 -2
  12. data/example/bridge/auth_basic.rb +75 -0
  13. data/example/bridge/config.ru +101 -0
  14. data/example/bridge/configure/configure_widget.rb +32 -0
  15. data/example/bridge/data_sources/sensor-sqlite.rb +28 -6
  16. data/example/bridge/data_sources/test31.sq3 +0 -0
  17. data/example/bridge/htdocs/{js/graph → graph/js}/bridge.js +2 -2
  18. data/example/bridge/htdocs/{js/graph → graph/js}/event_line_chart.js +7 -6
  19. data/example/bridge/htdocs/{js/graph → graph/js}/event_table.js +13 -5
  20. data/example/bridge/htdocs/template/login.html +23 -0
  21. data/example/bridge/viz_server.rb +3 -5
  22. data/example/bridge/widgets/configure.yaml +12 -0
  23. data/example/bridge/widgets/login.yaml +16 -0
  24. data/example/bridge/{overview.yaml → widgets/overview.yaml} +7 -4
  25. data/example/demo/data_sources/animals.rb +1 -1
  26. data/example/demo/data_sources/downloads.rb +1 -1
  27. data/example/demo/data_sources/generator.rb +1 -1
  28. data/example/demo/data_sources/histogram.rb +1 -1
  29. data/example/demo/data_sources/mobile_network.rb +4 -3
  30. data/example/demo/data_sources/movies.rb +1 -1
  31. data/example/demo/data_sources/network.rb +4 -3
  32. data/example/demo/data_sources/returns.rb +1 -1
  33. data/example/demo/data_sources/static_network.rb +4 -3
  34. data/example/demo/data_sources/walk.rb +1 -1
  35. data/example/demo/demo_viz_server.rb +1 -1
  36. data/example/demo/widgets/linked_graphs_tab.yaml +1 -1
  37. data/example/openflow-gec15/README.md +21 -0
  38. data/example/openflow-gec15/code_tab.yaml +36 -0
  39. data/example/openflow-gec15/dashboard_tab.yaml +72 -0
  40. data/example/openflow-gec15/doc/screenshot.png +0 -0
  41. data/example/openflow-gec15/exp_source.rb +104 -0
  42. data/example/openflow-gec15/of_viz_server.rb +63 -0
  43. data/example/openflow-gec15/openflow-demo.sq3 +0 -0
  44. data/example/openflow-gec15/raw_tab.yaml +37 -0
  45. data/example/openflow-gec15/repository/of-exp.rb +12 -0
  46. data/example/openflow-gec15/repository/sample.md +52 -0
  47. data/example/openflow-gec15/repository/trema-ctl6.rb +148 -0
  48. data/example/simple/README.md +2 -0
  49. data/example/simple/data_sources/gimi31.sq3 +0 -0
  50. data/example/simple/data_sources/ping_source.rb +56 -0
  51. data/example/simple/simple_viz_server.rb +39 -0
  52. data/example/simple/widgets/charts_tab.yaml +38 -0
  53. data/lib/omf-web/config.ru +31 -3
  54. data/lib/omf-web/data_source_proxy.rb +29 -26
  55. data/lib/omf-web/rack/session_authenticator.rb +93 -0
  56. data/lib/omf-web/rack/tab_mapper.rb +10 -5
  57. data/lib/omf-web/rack/websocket_handler.rb +17 -6
  58. data/lib/omf-web/theme/abstract_page.rb +1 -1
  59. data/lib/omf-web/theme/bright/flow_renderer.rb +2 -2
  60. data/lib/omf-web/theme/bright/layout_renderer.rb +15 -0
  61. data/lib/omf-web/theme/bright/mustache_renderer.rb +29 -0
  62. data/lib/omf-web/theme/bright/one_column_renderer.rb +2 -2
  63. data/lib/omf-web/theme/bright/page.rb +33 -8
  64. data/lib/omf-web/theme/bright/tabbed_renderer.rb +2 -3
  65. data/lib/omf-web/theme/bright/two_columns_renderer.rb +3 -4
  66. data/lib/omf-web/version.rb +1 -1
  67. data/lib/omf-web/widget/code_widget.rb +0 -7
  68. data/lib/omf-web/widget/layout/two_columns_layout.rb +3 -2
  69. data/lib/omf-web/widget/mustache_widget.rb +44 -0
  70. data/lib/omf-web/widget.rb +14 -1
  71. data/lib/omf_common/lobject.rb +6 -3
  72. data/omf_web.gemspec +3 -1
  73. data/share/htdocs/graph/js/abstract_nv_chart.js +14 -4
  74. data/share/htdocs/graph/js/abstract_widget.js +5 -4
  75. data/share/htdocs/graph/js/line_chart3.js +2 -0
  76. data/share/htdocs/graph/js/map2.js +3 -3
  77. data/share/htdocs/graph/js/network2.js +51 -19
  78. data/share/htdocs/graph/js/scatter_plot.js +6 -2
  79. data/share/htdocs/graph/js/table2.js +5 -2
  80. data/share/htdocs/js/data_source2.js +40 -8
  81. data/share/htdocs/js/mustache.js +29 -0
  82. data/share/htdocs/theme/abstract/abstract.js +10 -3
  83. data/share/htdocs/vendor/mustache-0.7.0/CHANGES +21 -0
  84. data/share/htdocs/vendor/mustache-0.7.0/LICENSE +10 -0
  85. data/share/htdocs/vendor/mustache-0.7.0/README.md +374 -0
  86. data/share/htdocs/vendor/mustache-0.7.0/jquery.mustache.js +635 -0
  87. data/share/htdocs/vendor/mustache-0.7.0/mustache.js +612 -0
  88. data/share/htdocs/vendor/nv_d3/js/nv.d3.js +9 -1
  89. data/share/htdocs/vendor/raphael-2.1.0/raphael.js +5815 -0
  90. metadata +74 -9
  91. data/DESIGN_NOTES.txt +0 -56
@@ -1,7 +1,7 @@
1
1
 
2
2
 
3
3
  require 'omf_common/lobject'
4
- require 'omf-oml/network'
4
+ require 'omf_oml/network'
5
5
 
6
6
  module OMF::Web
7
7
 
@@ -25,11 +25,14 @@ module OMF::Web
25
25
  raise "Repeated try to register data source '#{name}'"
26
26
  end
27
27
  if data_source.is_a? OMF::OML::OmlNetwork
28
- dsh = data_source.to_tables(opts)
29
- @@datasources[name] = dsh
30
- else
31
- @@datasources[name] = data_source
28
+ raise "Register link and node table separately "
32
29
  end
30
+ # dsh = data_source.to_tables(opts)
31
+ # @@datasources[name] = dsh
32
+ # else
33
+ # @@datasources[name] = data_source
34
+ # end
35
+ @@datasources[name] = data_source
33
36
  end
34
37
 
35
38
  def self.[](name)
@@ -63,36 +66,35 @@ module OMF::Web
63
66
  ds_name = ds_name.to_sym
64
67
  ds = @@datasources[ds_name]
65
68
  unless ds
66
- # let's check for sub table, such as network/nodes
67
- main, sub = ds_descr[:name].split('/')
68
- if (sub)
69
- if ds_top = @@datasources[main.to_sym]
70
- ds = ds_top[sub.to_sym]
69
+ top = "#{ds_name}/"
70
+ names = @@datasources.keys.find_all { |ds_name| ds_name.to_s.start_with? top }
71
+ unless names.empty?
72
+ return names.map do |ds_name|
73
+ OMF::Web::SessionStore[ds_name, :dsp] ||= self.new(ds_name, @@datasources[ds_name])
71
74
  end
72
75
  end
76
+ # debug ">>>> #{dsa}"
77
+ # # let's check for sub table, such as network/nodes
78
+ # main, sub = ds_descr[:name].split('/')
79
+ # if (sub)
80
+ # if ds_top = @@datasources[main.to_sym]
81
+ # ds = ds_top[sub.to_sym]
82
+ # end
83
+ # end
73
84
  unless ds
74
85
  raise "Unknown data source '#{ds_name}' (#{@@datasources.keys.inspect})"
75
86
  end
76
87
  end
77
88
  if ds.is_a? Hash
89
+ raise "Is this actually used anywhere?"
78
90
  proxies = ds.map do |name, ds|
79
91
  id = "#{ds_name}_#{name}".to_sym
80
92
  proxy = OMF::Web::SessionStore[id, :dsp] ||= self.new(id, ds)
81
93
  end
82
94
  return proxies
83
-
84
- # n_name = "#{ds_name}_nodes".to_sym
85
- # l_name = "#{ds_name}_links".to_sym
86
- # if (nodes = OMF::Web::SessionStore[n_name, :dsp])
87
- # # assume links exist as well
88
- # links = OMF::Web::SessionStore[l_name, :dsp]
89
- # else
90
- # nodes = OMF::Web::SessionStore[n_name, :dsp] = self.new(n_name, ds[:nodes])
91
- # links = OMF::Web::SessionStore[l_name, :dsp] = self.new(l_name, ds[:links])
92
- # end
93
- # return [nodes, links]
94
95
  end
95
96
 
97
+ #debug ">>>>> DS: #{ds_descr.inspect} - #{ds}"
96
98
  proxy = OMF::Web::SessionStore[ds_name, :dsp] ||= self.new(ds_name, ds)
97
99
  return [proxy]
98
100
  end
@@ -119,11 +121,11 @@ module OMF::Web
119
121
  rows = ds.rows[(offset - ds.offset) .. -1]
120
122
  if rows && rows.length > 0
121
123
  debug "on_changed: sending #{rows.length}"
122
- block.call rows, ds.offset
124
+ block.call :added, rows
123
125
  end
124
- @data_source.on_row_added(block.object_id) do |row, offset|
125
- debug "on_changed: more data: #{row.inspect}"
126
- block.call [row], offset
126
+ @data_source.on_content_changed(block.object_id) do |action, rows|
127
+ debug "on_changed: #{action}: #{rows.inspect}"
128
+ block.call action, rows
127
129
  end
128
130
  end
129
131
 
@@ -144,7 +146,8 @@ module OMF::Web
144
146
  opts[:update_url] = "/_update/#{@name}?sid=#{sid}"
145
147
  opts[:sid] = sid
146
148
  unless opts[:slice] # don't send any data if this is a sliced one
147
- opts[:rows] = @data_source.rows[0 .. 20]
149
+ #opts[:rows] = @data_source.rows[0 .. 20]
150
+ opts[:rows] = []
148
151
  opts[:offset] = @data_source.offset
149
152
  end
150
153
  #puts "to_java2>>>>> #{opts.to_json.inspect}"
@@ -0,0 +1,93 @@
1
+
2
+ require 'omf_common/lobject'
3
+ require 'rack'
4
+ require 'omf-web/session_store'
5
+
6
+
7
+ module OMF::Web::Rack
8
+ class SessionAuthenticator < OMF::Common::LObject
9
+
10
+ def self.active?
11
+ @@active
12
+ end
13
+
14
+ def self.authenticated?
15
+ self[:authenticated]
16
+ end
17
+
18
+ def self.authenticate
19
+ self[:authenticated] = true
20
+ self[:valid_until] = Time.now + @@expire_after
21
+ end
22
+
23
+ def self.logout
24
+ self[:authenticated] = false
25
+ end
26
+
27
+ def self.[](key)
28
+ OMF::Web::SessionStore[key, :authenticator]
29
+ end
30
+
31
+ def self.[]=(key, value)
32
+ OMF::Web::SessionStore[key, :authenticator] = value
33
+ end
34
+
35
+ @@active = false
36
+ # Expire authenticated session after being idle for that many seconds
37
+ @@expire_after = 2592000
38
+
39
+ #
40
+ # opts -
41
+ # :no_session - Array of regexp to ignore
42
+ #
43
+ def initialize(app, opts = {})
44
+ @app = app
45
+ @opts = opts
46
+ @opts[:no_session] = (@opts[:no_session] || []).map { |s| Regexp.new(s) }
47
+ if @opts[:expire_after]
48
+ @@expire_after = @opts[:expire_after]
49
+ end
50
+ @@active = true
51
+ end
52
+
53
+
54
+ def call(env)
55
+ #puts env.keys.inspect
56
+ req = ::Rack::Request.new(env)
57
+ sid = nil
58
+ path_info = req.path_info
59
+ #puts "REQUEST: #{path_info}"
60
+ unless @opts[:no_session].find {|rx| rx.match(path_info) }
61
+ sid = req.cookies['sid'] || "s#{(rand * 10000000).to_i}_#{(rand * 10000000).to_i}"
62
+ debug "Setting session for '#{req.path_info}' to '#{sid}'"
63
+ Thread.current["sessionID"] = sid
64
+ # If 'login_url' is defined, check if this session is authenticated
65
+ login_url = @opts[:login_url]
66
+ if login_url && login_url != req.path_info
67
+ if authenticated = self.class[:authenticated]
68
+ # Check if it hasn't imed out
69
+ if self.class[:valid_until] < Time.now
70
+ debug "Session '#{sid}' expired"
71
+ authenticated = false
72
+ end
73
+ end
74
+ unless authenticated
75
+ return [301, {'Location' => login_url, "Content-Type" => ""}, ['Login first']]
76
+ end
77
+ end
78
+ self.class[:valid_until] = Time.now + @@expire_after
79
+ end
80
+
81
+ status, headers, body = @app.call(env)
82
+ if sid
83
+ headers['Set-Cookie'] = "sid=#{sid}" ##: name2=value2; Expires=Wed, 09-Jun-2021 ]
84
+ end
85
+ [status, headers, body]
86
+ end
87
+ end # class
88
+
89
+ end # module
90
+
91
+
92
+
93
+
@@ -32,12 +32,17 @@ module OMF::Web::Rack
32
32
  end
33
33
 
34
34
  def call(env)
35
+ #puts env.keys.inspect
36
+
35
37
  req = ::Rack::Request.new(env)
36
- sessionID = req.params['sid']
37
- if sessionID.nil? || sessionID.empty?
38
- sessionID = "s#{(rand * 10000000).to_i}"
39
- end
40
- Thread.current["sessionID"] = sessionID
38
+ #puts "COOKIES>>>> #{req.cookies.inspect}"
39
+ #req.cookies['user'] = 'booo'
40
+
41
+ # sessionID = req.params['sid']
42
+ # if sessionID.nil? || sessionID.empty?
43
+ # sessionID = "s#{(rand * 10000000).to_i}"
44
+ # end
45
+ # Thread.current["sessionID"] = sessionID
41
46
 
42
47
  OMF::Web::Theme.require 'page'
43
48
  body, headers = render_page(req)
@@ -53,12 +53,13 @@ module OMF::Web::Rack
53
53
  dsp = find_data_source(args)
54
54
  return unless dsp # should define appropriate exception
55
55
  debug "Received registration for datasource proxy '#{dsp}'"
56
- dsp.on_changed(args['offset']) do |new_rows, offset|
56
+ dsp.on_changed(args['offset']) do |action, rows|
57
57
  msg = {
58
58
  type: 'datasource_update',
59
59
  datasource: dsp.name,
60
- rows: new_rows,
61
- offset: offset
60
+ rows: rows,
61
+ action: action
62
+ #offset: offset
62
63
  }
63
64
  send_data(msg.to_json)
64
65
  end
@@ -81,14 +82,24 @@ module OMF::Web::Rack
81
82
  end
82
83
  sdsp = dsp.create_slice(col_name, col_value)
83
84
  context[:sliced_datasource] = {:col_name => col_name, :dsp => sdsp}
84
- sdsp.on_changed(0) do |new_rows, offset|
85
+ sdsp.on_changed(0) do |action, rows|
85
86
  msg = {
86
87
  type: 'datasource_update',
87
88
  datasource: args['ds_name'],
88
- rows: new_rows,
89
- offset: offset
89
+ rows: rows,
90
+ action: action
91
+ #offset: offset
90
92
  }
91
93
  send_data(msg.to_json)
94
+ #
95
+ # do |new_rows, offset|
96
+ # msg = {
97
+ # type: 'datasource_update',
98
+ # datasource: args['ds_name'],
99
+ # rows: new_rows,
100
+ # offset: offset
101
+ # }
102
+ # send_data(msg.to_json)
92
103
  end
93
104
  end
94
105
 
@@ -70,7 +70,7 @@ module OMF::Web::Theme
70
70
  def render_data_sources
71
71
  return unless @widget
72
72
 
73
- require 'omf-oml/table'
73
+ require 'omf_oml/table'
74
74
  require 'set'
75
75
 
76
76
  dss = Set.new
@@ -1,9 +1,9 @@
1
1
 
2
- require 'omf-web/theme/bright/widget_chrome'
2
+ require 'omf-web/theme/bright/layout_renderer'
3
3
 
4
4
  module OMF::Web::Theme
5
5
 
6
- class FlowRenderer < Erector::Widget
6
+ class FlowRenderer < LayoutRenderer
7
7
 
8
8
  def initialize(layout_widget, widgets, opts)
9
9
  super opts
@@ -0,0 +1,15 @@
1
+
2
+ require 'omf-web/theme/bright/widget_chrome'
3
+
4
+ module OMF::Web::Theme
5
+
6
+ class LayoutRenderer < Erector::Widget
7
+
8
+ def render? partial
9
+ a = (@opts[:render] ||= {})[partial]
10
+ a != false
11
+ end
12
+
13
+ end # class
14
+
15
+ end # OMF::Web::Theme
@@ -0,0 +1,29 @@
1
+
2
+ require 'omf-web/theme/abstract_page'
3
+
4
+ module OMF::Web::Theme
5
+
6
+ class MustacheRenderer < Erector::Widget
7
+
8
+ def initialize(widget, opts)
9
+ super opts
10
+ @widget = widget
11
+ @opts = opts
12
+ end
13
+
14
+ def content()
15
+ base_id = "mr#{self.object_id}"
16
+ opts = @opts.dup
17
+ opts[:base_id] = base_id
18
+ div :id => base_id, :class => "mustache_widget" do
19
+ javascript(%{
20
+ L.require('#OML.mustache', 'js/mustache', function() {
21
+ OML.mustache(#{opts.to_json});
22
+ });
23
+ })
24
+ end
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -1,9 +1,9 @@
1
1
 
2
- require 'omf-web/theme/bright/widget_chrome'
2
+ require 'omf-web/theme/bright/layout_renderer'
3
3
 
4
4
  module OMF::Web::Theme
5
5
 
6
- class OneColumnRenderer < Erector::Widget
6
+ class OneColumnRenderer < LayoutRenderer
7
7
 
8
8
  def initialize(widgets, opts)
9
9
  super opts
@@ -1,4 +1,5 @@
1
1
  require 'omf-web/theme/abstract_page'
2
+ require 'omf-web/rack/session_authenticator'
2
3
 
3
4
  module OMF::Web::Theme
4
5
  class Page < OMF::Web::Theme::AbstractPage
@@ -33,16 +34,25 @@ module OMF::Web::Theme
33
34
 
34
35
  def content
35
36
  super
37
+ @renderer = @widget.content
36
38
  div :id => 'doc3' do
37
- div :id => 'hd' do
38
- render_top_line
39
- h1 @page_title || 'Missing :page_title'
39
+ if @renderer.render? :header
40
+ div :id => 'hd' do
41
+ if @renderer.render? :top_line
42
+ render_top_line
43
+ end
44
+ if @renderer.render? :title
45
+ h1 @page_title || 'Missing :page_title'
46
+ end
47
+ end
40
48
  end
41
49
  div :id => 'bd' do
42
50
  render_body
43
51
  end
44
- div :id => 'ft' do
45
- render_footer
52
+ if @renderer.render? :footer
53
+ div :id => 'ft' do
54
+ render_footer
55
+ end
46
56
  end
47
57
  end
48
58
  end
@@ -59,7 +69,8 @@ module OMF::Web::Theme
59
69
  @tabs.each do |h|
60
70
  lopts = h[:id] == @tab ? {:class => :current} : {}
61
71
  li lopts do
62
- a :href => "#{@prefix}/#{h[:id]}?sid=#{Thread.current["sessionID"]}" do
72
+ #a :href => "#{@prefix}/#{h[:id]}?sid=#{Thread.current["sessionID"]}" do
73
+ a :href => "#{@prefix}/#{h[:id]}" do
63
74
  span h[:name], :class => :tab_text
64
75
  end
65
76
  end
@@ -69,8 +80,22 @@ module OMF::Web::Theme
69
80
 
70
81
  def render_tools_menu
71
82
  div :id => :tools_menu do
72
- a 'Log in', :href => '/login'
83
+ render_authentication
84
+ end
85
+ end
86
+
87
+ def render_authentication
88
+ if OMF::Web::Rack::SessionAuthenticator.active?
89
+ if OMF::Web::Rack::SessionAuthenticator.authenticated?
90
+ # text OMF::Web::Rack::Session[:name]
91
+ # text ' | '
92
+ a 'Log out', :href => '/logout'
93
+ else
94
+ a 'Log in', :href => '/tab/login'
95
+ end
73
96
  end
97
+
98
+
74
99
  end
75
100
 
76
101
  def render_body
@@ -81,7 +106,7 @@ module OMF::Web::Theme
81
106
  def render_card_body
82
107
  return unless @widget
83
108
  Thread.current["top_renderer"] = self
84
- rawtext @widget.content.to_html
109
+ rawtext @renderer.to_html
85
110
  end
86
111
 
87
112
  def render_footer
@@ -1,9 +1,8 @@
1
-
2
- require 'omf-web/theme/bright/widget_chrome'
1
+ require 'omf-web/theme/bright/layout_renderer'
3
2
 
4
3
  module OMF::Web::Theme
5
4
 
6
- class TabbedRenderer < Erector::Widget
5
+ class TabbedRenderer < LayoutRenderer
7
6
 
8
7
  def initialize(layout_widget, widgets, opts)
9
8
  super opts
@@ -1,10 +1,9 @@
1
-
2
- require 'omf-web/theme/bright/widget_chrome'
1
+ require 'omf-web/theme/bright/layout_renderer'
3
2
 
4
3
  module OMF::Web::Theme
5
4
 
6
- class TwoColumnsRenderer < Erector::Widget
7
-
5
+ class TwoColumnsRenderer < LayoutRenderer
6
+
8
7
  DEFAULT_LAYOUT = '66_33'
9
8
 
10
9
  @@layout2class = {
@@ -1,7 +1,7 @@
1
1
 
2
2
  module OMF
3
3
  module Web
4
- VERSION = '0.9.6'
4
+ VERSION = '0.9.7'
5
5
  # Used for finding the example directory
6
6
  TOP_DIR = File.dirname(File.dirname(File.dirname(__FILE__)))
7
7
  end
@@ -19,12 +19,6 @@ module OMF::Web::Widget
19
19
  unless (content_descr = opts[:content])
20
20
  raise "Missing 'content' option in '#{opts.describe}'"
21
21
  end
22
- # if content_descr.is_a? OMF::Web::ContentProxy
23
- # @content_proxy = content_descr
24
- # else
25
- # #@content_proxy = OMF::Web::ContentRepository[opts].load(content_descr)
26
- # @content_proxy = OMF::Web::Repository.create_content_proxy_for(content_descr, opts)
27
- # end
28
22
  @content_proxy = OMF::Web::ContentRepository.create_content_proxy_for(content_descr, opts)
29
23
  end
30
24
 
@@ -36,7 +30,6 @@ module OMF::Web::Widget
36
30
  @content_proxy.mime_type
37
31
  end
38
32
 
39
-
40
33
  def update_url
41
34
  @content_proxy.content_url
42
35
  end
@@ -8,8 +8,9 @@ module OMF::Web::Widget::Layout
8
8
 
9
9
  def initialize(type, opts)
10
10
  super opts
11
- @left = (opts[:left] || []).map {|w| OMF::Web::Widget.create_widget(w)}
12
- @right = (opts[:right] || []).map {|w| OMF::Web::Widget.create_widget(w)}
11
+ wt = opts[:widgets] || opts # support opts[:left] as well as opts[:widgets][:left]
12
+ @left = (wt[:left] || []).map {|w| OMF::Web::Widget.create_widget(w)}
13
+ @right = (wt[:right] || []).map {|w| OMF::Web::Widget.create_widget(w)}
13
14
  end
14
15
 
15
16
  def content()
@@ -0,0 +1,44 @@
1
+
2
+ require 'omf-web/widget/abstract_widget'
3
+ require 'omf-web/content/repository'
4
+
5
+ module OMF::Web::Widget
6
+
7
+ # Renders the content of a moustache file in the context of a data source
8
+ #
9
+ class MustacheWidget < AbstractWidget
10
+
11
+ def self.create_mustache_widget(type, wdescr)
12
+ return self.new(wdescr)
13
+ end
14
+
15
+ attr_accessor :content_proxy
16
+
17
+ def initialize(opts)
18
+ super opts
19
+ # if (content_descr = opts[:content])
20
+ # opts[:content_proxy] = OMF::Web::ContentRepository.create_content_proxy_for(content_descr, opts)
21
+ # end
22
+ end
23
+
24
+ def title
25
+ @opts[:title] || 'No Title'
26
+ end
27
+
28
+ def content()
29
+ OMF::Web::Theme.require 'mustache_renderer'
30
+ OMF::Web::Theme::MustacheRenderer.new(self, @opts)
31
+ end
32
+
33
+ def collect_data_sources(ds_set)
34
+ if @opts[:data_sources]
35
+ @opts[:data_sources].each do |ds|
36
+ ds_set.add(ds[:stream])
37
+ end
38
+ end
39
+ ds_set
40
+ end
41
+
42
+ end # class
43
+
44
+ end
@@ -5,7 +5,8 @@ module OMF::Web::Widget
5
5
 
6
6
 
7
7
  @@widgets = {}
8
- @@descriptions = {}
8
+ @@descriptions = {}
9
+ @@type2class = {}
9
10
 
10
11
  def self.register_widget(wdescr)
11
12
  unless id = wdescr[:id]
@@ -22,6 +23,15 @@ module OMF::Web::Widget
22
23
  @@descriptions
23
24
  end
24
25
 
26
+ def self.register_widget_type(id, widget_class)
27
+ id = id.to_sym
28
+ if (@@type2class.key? id)
29
+ raise "Repeated try to register widget type '#{id}'"
30
+ end
31
+ @@type2class[id] = widget_class
32
+ end
33
+
34
+
25
35
  # Return the number of top level widgets. If 'restrict_to' is an
26
36
  # array, only return those.
27
37
  #
@@ -82,6 +92,9 @@ module OMF::Web::Widget
82
92
  when /^code/
83
93
  require 'omf-web/widget/code_widget'
84
94
  w = OMF::Web::Widget::CodeWidget.create_code_widget(type, wdescr)
95
+ when /^moustache/
96
+ require 'omf-web/widget/mustache_widget'
97
+ w = OMF::Web::Widget::MustacheWidget.create_mustache_widget(type, wdescr)
85
98
  else
86
99
  raise "Unknown widget type '#{type}' (#{wdescr.inspect})"
87
100
  end
@@ -150,9 +150,12 @@ module OMF::Common
150
150
  end
151
151
 
152
152
  def _logger(category = nil)
153
- unless @logger && category.nil?
154
- category ||= self.class.to_s
155
- @logger = OMF::Common::Loggable.logger(category)
153
+ unless @logger #&& category.nil?
154
+ cat = self.class.to_s
155
+ if category
156
+ cat = "#{cat}-#{category}"
157
+ end
158
+ @logger = OMF::Common::Loggable.logger(cat)
156
159
  end
157
160
  return @logger
158
161
  end
data/omf_web.gemspec CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
21
21
 
22
22
  # specify any dependencies here; for example:
23
23
  # s.add_development_dependency "minitest", "~> 2.11.3"
24
- s.add_runtime_dependency "omf-oml", "~> 0.9"
24
+ s.add_runtime_dependency "omf_oml", "~> 0.9"
25
25
  s.add_runtime_dependency "erector", "~> 0.8.3"
26
26
  s.add_runtime_dependency "activesupport", "~> 3.0.0" # required by erector:table
27
27
  s.add_runtime_dependency "rack", "~> 1.3.5"
@@ -33,4 +33,6 @@ Gem::Specification.new do |s|
33
33
  s.add_runtime_dependency "json", "~> 1.7.3"
34
34
  s.add_runtime_dependency "grit", "~> 2.5.0"
35
35
  s.add_runtime_dependency "sqlite3", "~> 1.3.6"
36
+ s.add_runtime_dependency "postgres-pr", "~> 0.6.3"
37
+ s.add_runtime_dependency "websocket-rack", "~> 0.4.0"
36
38
  end
@@ -26,7 +26,14 @@ L.provide('OML.abstract_nv_chart', ["graph/js/abstract_chart", "#OML.abstract_ch
26
26
  margin: {
27
27
  top: 0, right: 0, bottom: 0, left: 50 // not sure what impact this really has?
28
28
  }
29
+ },
30
+
31
+ defaults: function() {
32
+ return this.deep_defaults({
33
+ transition_duration: 500
34
+ }, OML.abstract_nv_chart.__super__.defaults.call(this));
29
35
  },
36
+
30
37
 
31
38
  configure_base_layer: function(vis) {
32
39
  this.base_layer = vis;
@@ -116,10 +123,13 @@ L.provide('OML.abstract_nv_chart', ["graph/js/abstract_chart", "#OML.abstract_ch
116
123
  },
117
124
 
118
125
  redraw: function(data) {
119
- this.base_layer//.select(".chart_layer")
120
- .datum(this._datum(data, this.chart))
121
- .transition().duration(500)
122
- .call(this.chart);
126
+ var bl = this.base_layer//.select(".chart_layer")
127
+ .datum(this._datum(data, this.chart))
128
+ ;
129
+ if (this.opts.transition_duration > 0) {
130
+ bl = bl.transition().duration(500)
131
+ }
132
+ bl.call(this.chart);
123
133
  },
124
134
 
125
135
  })
@@ -282,6 +282,7 @@ L.provide('OML.abstract_widget', ["vendor/d3/d3.js"], function () {
282
282
  switch (type) {
283
283
  case 'int':
284
284
  case 'float':
285
+ case 'key' :
285
286
  var scale = descr.scale;
286
287
  var min_value = descr.min;
287
288
  var max_value = descr.max;
@@ -311,10 +312,10 @@ L.provide('OML.abstract_widget', ["vendor/d3/d3.js"], function () {
311
312
  var color = color_f(v);
312
313
  return color;
313
314
  };
314
- case 'key' :
315
- return function(d) {
316
- return d[index];
317
- }
315
+ // case 'key' :
316
+ // return function(d) {
317
+ // return d[index];
318
+ // }
318
319
  default:
319
320
  throw "Unknown mapping type '" + type + "'";
320
321
  }