omf_web 0.9.6 → 0.9.7

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