omf_web 0.9.9 → 1.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.
- checksums.yaml +7 -0
- data/README.md +31 -0
- data/bin/omf_web_server.rb +157 -0
- data/doc/screenshot2.png +0 -0
- data/doc/widget_detail.png +0 -0
- data/example/demo/data_sources/downloads.rb +2 -1
- data/example/simple/README.md +12 -13
- data/example/simple/create_waveform.rb +29 -0
- data/example/simple/introduction.md +17 -0
- data/example/simple/sample.sq3 +0 -0
- data/example/simple/sample.sql +1008 -0
- data/example/simple/simple.yaml +62 -0
- data/example/simple/simple_dynamic.yaml +66 -0
- data/lib/irods4r/file.rb +15 -14
- data/lib/irods4r/icommands.rb +18 -18
- data/lib/irods4r.rb +9 -9
- data/lib/omf-web/config.ru +41 -16
- data/lib/omf-web/content/git_repository.rb +32 -31
- data/lib/omf-web/content/irods_repository.rb +34 -33
- data/lib/omf-web/content/repository.rb +48 -44
- data/lib/omf-web/data_source_proxy.rb +33 -22
- data/lib/omf-web/rack/session_authenticator.rb +48 -12
- data/lib/omf-web/rack/tab_mapper.rb +30 -36
- data/lib/omf-web/rack/websocket_handler.rb +26 -25
- data/lib/omf-web/session_store.rb +16 -13
- data/lib/omf-web/theme/abstract_page.rb +26 -22
- data/lib/omf-web/theme/bright/page.rb +84 -34
- data/lib/omf-web/theme/bright/stacked_renderer.rb +20 -19
- data/lib/omf-web/theme.rb +14 -9
- data/lib/omf-web/thin/runner.rb +38 -36
- data/lib/omf-web/thin/server.rb +255 -0
- data/lib/omf-web/version.rb +1 -1
- data/lib/omf-web/widget/data_widget.rb +6 -6
- data/lib/omf-web/widget/text/maruku/helpers.rb +33 -30
- data/lib/omf-web/widget/text/maruku/input/parse_block.rb +117 -117
- data/lib/omf-web/widget/text/maruku/output/to_html.rb +155 -154
- data/lib/omf-web/widget/text/maruku.rb +17 -16
- data/omf_web.gemspec +6 -2
- data/sample.sq3 +0 -0
- data/share/htdocs/graph/js/gauge.js +524 -0
- data/share/htdocs/vendor/VERSION_MAP.yaml +3 -3
- data/share/htdocs/vendor/backbone-1.0.0/backbone.js +1571 -0
- data/share/htdocs/vendor/d3-3.0/LICENSE.brewer.txt +38 -0
- data/share/htdocs/vendor/d3-3.0/colorbrewer.js +1 -0
- data/share/htdocs/vendor/d3-3.0/d3.js +8810 -0
- data/share/htdocs/vendor/d3-3.0/d3.min.js +5 -0
- data/share/htdocs/vendor/geo_json/Readme.txt +71 -0
- data/share/htdocs/vendor/geo_json/regions.json +41 -0
- data/share/htdocs/vendor/geo_json/switzerland.json +24 -0
- data/share/htdocs/vendor/geo_json/world.json +497 -0
- data/share/htdocs/vendor/nv_d3/js/nv.d3.js +8801 -4447
- data/share/htdocs/vendor/spin/jquery.spin.js +46 -0
- data/share/htdocs/vendor/spin/spin.js +349 -0
- data/share/htdocs/vendor/spin/spin.min.js +1 -0
- data/share/htdocs/vendor/underscore-1.4.4/underscore.js +1227 -0
- metadata +63 -48
- data/example/simple/data_sources/gimi31.sq3 +0 -0
- data/example/simple/data_sources/ping_source.rb +0 -56
- data/example/simple/simple_viz_server.rb +0 -39
- data/example/simple/widgets/charts_tab.yaml +0 -38
- data/share/.DS_Store +0 -0
- data/share/htdocs/.DS_Store +0 -0
- data/share/htdocs/vendor/backbone-0.5.3/backbone.js +0 -1158
- data/share/htdocs/vendor/underscore-1.2.1/underscore.js +0 -958
@@ -1,58 +1,59 @@
|
|
1
1
|
|
2
2
|
require 'omf-web/theme/bright/widget_chrome'
|
3
|
+
require 'omf-web/theme/bright/layout_renderer'
|
3
4
|
|
4
5
|
module OMF::Web::Theme
|
5
|
-
|
6
|
-
class StackedRenderer
|
7
|
-
|
6
|
+
|
7
|
+
class StackedRenderer < LayoutRenderer
|
8
|
+
|
8
9
|
def initialize(stacked_widget, widgets, active_index, opts)
|
9
10
|
@stacked_widget = stacked_widget
|
10
11
|
@widgets = widgets
|
11
12
|
@active_index = active_index
|
12
13
|
@helper = StackedRendererHelper.new(widgets, active_index, opts)
|
13
14
|
@opts = opts
|
14
|
-
end
|
15
|
-
|
15
|
+
end
|
16
|
+
|
16
17
|
def to_html()
|
17
18
|
wp = "w#{@helper.object_id}"
|
18
19
|
@opts[:menu] = @widgets.each_with_index.map do |w, i|
|
19
|
-
wc = w.widget_type.split('/').inject([]) do |a, e|
|
20
|
-
a << (a.empty? ? e : "#{a[-1]}_#{e}")
|
20
|
+
wc = w.widget_type.split('/').inject([]) do |a, e|
|
21
|
+
a << (a.empty? ? e : "#{a[-1]}_#{e}")
|
21
22
|
end
|
22
23
|
{
|
23
|
-
:name => w.name,
|
24
|
-
:class => wc.join(' '),
|
25
|
-
:is_active => (@active_index == i),
|
24
|
+
:name => w.name,
|
25
|
+
:class => wc.join(' '),
|
26
|
+
:is_active => (@active_index == i),
|
26
27
|
:id => "#{wp}_l_#{i}",
|
27
28
|
:js_function => 'OML.show_widget',
|
28
29
|
:inner_class => wp,
|
29
30
|
:index => i,
|
30
31
|
:widget_id => w.dom_id
|
31
32
|
}
|
32
|
-
end
|
33
|
+
end
|
33
34
|
WidgetChrome.new(@stacked_widget, @helper, @opts).to_html
|
34
|
-
end
|
35
|
-
end
|
35
|
+
end
|
36
|
+
end
|
36
37
|
|
37
38
|
class StackedRendererHelper < Erector::Widget
|
38
|
-
|
39
|
+
|
39
40
|
def initialize(widgets, active_index, opts)
|
40
41
|
super opts
|
41
42
|
@widgets = widgets
|
42
43
|
@active_index = active_index
|
43
|
-
end
|
44
|
+
end
|
44
45
|
|
45
46
|
def content()
|
46
47
|
#widget @active_widget
|
47
|
-
widgets = @widgets
|
48
|
+
widgets = @widgets
|
48
49
|
prefix = "w#{self.object_id}"
|
49
50
|
@widgets.each_with_index do |w, i|
|
50
51
|
style = i == @active_index ? '' : 'display:none'
|
51
52
|
div :id => "#{prefix}_#{i}", :class => prefix, :style => style do
|
52
|
-
rawtext w.content.to_html
|
53
|
+
rawtext w.content.to_html
|
53
54
|
end
|
54
|
-
end
|
55
|
+
end
|
55
56
|
end
|
56
|
-
|
57
|
+
|
57
58
|
end
|
58
59
|
end
|
data/lib/omf-web/theme.rb
CHANGED
@@ -2,29 +2,34 @@
|
|
2
2
|
|
3
3
|
module OMF::Web::Theme
|
4
4
|
extend OMF::Common::Loggable
|
5
|
-
|
5
|
+
|
6
6
|
DEFAULT_THEME = 'omf-web/theme/bright'
|
7
7
|
@@search_order = [DEFAULT_THEME] # default theme
|
8
8
|
@@loaded = {}
|
9
9
|
@@additional_renderers = {}
|
10
|
-
|
10
|
+
|
11
11
|
def self.theme=(theme)
|
12
12
|
if theme
|
13
13
|
unless theme.match '.*/'
|
14
14
|
theme = "omf-web/theme/#{theme}" # add default name space
|
15
15
|
end
|
16
16
|
@@loaded = {}
|
17
|
-
@@search_order = [theme]
|
17
|
+
@@search_order = [theme]
|
18
18
|
Kernel::require "#{theme}/init"
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
|
+
def self.include_css(css_file)
|
23
|
+
::Kernel.require 'omf-web/theme/abstract_page'
|
24
|
+
OMF::Web::Theme::AbstractPage.add_depends_on(:css, "/resource/#{css_file}")
|
25
|
+
end
|
26
|
+
|
22
27
|
def self.register_renderer(name, klass, theme = DEFAULT_THEME)
|
23
28
|
tr = @@additional_renderers[theme.to_s] ||= {}
|
24
29
|
tr[name] = klass
|
25
30
|
end
|
26
|
-
|
27
|
-
# Set additional themes to search in the given order for
|
31
|
+
|
32
|
+
# Set additional themes to search in the given order for
|
28
33
|
# implementations of renderes. Allows for partial override
|
29
34
|
# in new themes.
|
30
35
|
#
|
@@ -32,8 +37,8 @@ module OMF::Web::Theme
|
|
32
37
|
@@loaded = {}
|
33
38
|
@@search_order = search_order if search_order
|
34
39
|
end
|
35
|
-
|
36
|
-
|
40
|
+
|
41
|
+
|
37
42
|
def self.require(name)
|
38
43
|
name = name.to_sym
|
39
44
|
return if @@loaded[name]
|
@@ -45,7 +50,7 @@ module OMF::Web::Theme
|
|
45
50
|
Kernel::require "#{theme}/#{name}"
|
46
51
|
end
|
47
52
|
@@loaded[name] = true
|
48
|
-
debug "Using renderer '#{theme}/#{name}'"
|
53
|
+
debug "Using renderer '#{theme}/#{name}'"
|
49
54
|
return
|
50
55
|
rescue LoadError => le
|
51
56
|
# Move on to the next one
|
data/lib/omf-web/thin/runner.rb
CHANGED
@@ -11,26 +11,27 @@ module Thin
|
|
11
11
|
true # will be verified later
|
12
12
|
end
|
13
13
|
end
|
14
|
-
end
|
14
|
+
end
|
15
15
|
|
16
16
|
module OMF::Web
|
17
17
|
class Runner < Thin::Runner
|
18
18
|
include OMF::Common::Loggable
|
19
|
-
|
19
|
+
|
20
20
|
@@instance = nil
|
21
|
-
|
21
|
+
|
22
22
|
def self.instance
|
23
23
|
@@instance
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
attr_reader :options
|
27
|
-
|
27
|
+
|
28
28
|
def initialize(argv, opts = {})
|
29
29
|
raise "SINGLETON" if @@instance
|
30
|
-
|
30
|
+
@@instance = self
|
31
|
+
|
31
32
|
@argv = argv
|
32
33
|
sopts = opts.delete(:ssl) # runner has it's own idea of ssl options
|
33
|
-
|
34
|
+
|
34
35
|
# Default options values
|
35
36
|
app_name = opts[:app_name] || 'omf_web_app'
|
36
37
|
@options = {
|
@@ -46,68 +47,70 @@ module OMF::Web
|
|
46
47
|
:max_persistent_conns => Thin::Server::DEFAULT_MAXIMUM_PERSISTENT_CONNECTIONS,
|
47
48
|
:require => [],
|
48
49
|
:wait => Thin::Controllers::Cluster::DEFAULT_WAIT_TIME,
|
49
|
-
|
50
|
+
|
50
51
|
:rackup => File.dirname(__FILE__) + '/../config.ru',
|
51
52
|
:static_dirs => ["#{File.dirname(__FILE__)}/../../../share/htdocs"],
|
52
53
|
:static_dirs_pre => ["./resources"], # directories to prepend to 'static_dirs'
|
53
|
-
|
54
|
+
|
54
55
|
:handlers => {} # procs to call at various times of the server's life cycle
|
55
56
|
}.merge(opts)
|
56
57
|
# Search path for resource files is concatination of 'pre' and 'standard' static dirs
|
57
58
|
@options[:static_dirs] = @options[:static_dirs_pre].concat(@options[:static_dirs])
|
58
|
-
|
59
|
-
|
60
|
-
|
59
|
+
|
60
|
+
|
61
|
+
|
61
62
|
print_options = false
|
62
63
|
p = parser
|
63
64
|
p.separator ""
|
64
|
-
p.separator "OMF options:"
|
65
|
-
p.on("--theme THEME", "Select web theme") do |t| OMF::Web::Theme.theme = t end
|
66
|
-
|
67
|
-
p.separator ""
|
68
|
-
p.separator "Testing options:"
|
69
|
-
p.on("--disable-https", "Run server without SSL") do sopts = nil end
|
70
|
-
p.on("--print-options", "Print option settings after parsing command lines args") do print_options = true end
|
71
|
-
|
65
|
+
p.separator "OMF Web options:"
|
66
|
+
p.on("--theme THEME", "Select web theme") do |t| OMF::Web::Theme.theme = t end
|
67
|
+
|
72
68
|
# Allow application to add it's own parsing options
|
73
69
|
if ph = @options[:handlers][:pre_parse]
|
74
|
-
ph.call(p)
|
70
|
+
ph.arity == 1 ? ph.call(p) : ph.call(p, self)
|
75
71
|
end
|
76
72
|
|
73
|
+
p.separator ""
|
74
|
+
p.separator "Testing options:"
|
75
|
+
p.on("--disable-https", "Run server without SSL") do sopts = nil end
|
76
|
+
p.on("--print-options", "Print option settings after parsing command lines args") do print_options = true end
|
77
|
+
p.separator ""
|
78
|
+
|
77
79
|
parse!
|
78
|
-
|
79
|
-
# unless life_cycle(:post_parse)
|
80
|
-
# puts p.to_s
|
81
|
-
# abort()
|
82
|
-
# end
|
80
|
+
|
83
81
|
if sopts
|
84
82
|
@options[:ssl] = true
|
85
83
|
@options[:ssl_key_file] ||= sopts[:key_file]
|
86
84
|
@options[:ssl_cert_file] ||= sopts[:cert_file]
|
87
85
|
@options[:ssl_verify] ||= sopts[:verify_peer]
|
88
86
|
end
|
87
|
+
life_cycle(:post_parse)
|
89
88
|
|
90
89
|
# Change the name of the root logger so we can apply different logging
|
91
|
-
# policies depending on environment.
|
90
|
+
# policies depending on environment.
|
92
91
|
#
|
93
92
|
OMF::Common::Loggable.set_environment @options[:environment]
|
94
93
|
|
94
|
+
if css = opts[:include_css]
|
95
|
+
require 'omf-web/theme'
|
96
|
+
OMF::Web::Theme.include_css(css)
|
97
|
+
end
|
98
|
+
|
95
99
|
if print_options
|
96
100
|
require 'pp'
|
97
101
|
pp @options
|
98
|
-
end
|
99
|
-
|
100
|
-
@@instance = self
|
102
|
+
end
|
103
|
+
|
101
104
|
end
|
102
|
-
|
105
|
+
|
103
106
|
def life_cycle(step, &exception_block)
|
104
107
|
begin
|
105
108
|
if (p = @options[:handlers][step])
|
106
|
-
p.call()
|
109
|
+
p.arity == 0 ? p.call() : p.call(self)
|
107
110
|
end
|
108
111
|
rescue => ex
|
109
112
|
if exception_block
|
110
|
-
begin
|
113
|
+
begin
|
111
114
|
exception_block.call(ex)
|
112
115
|
rescue => ex2
|
113
116
|
error ex2
|
@@ -118,8 +121,8 @@ module OMF::Web
|
|
118
121
|
debug "#{ex.backtrace.join("\n")}"
|
119
122
|
end
|
120
123
|
end
|
121
|
-
end
|
122
|
-
|
124
|
+
end
|
125
|
+
|
123
126
|
def run!
|
124
127
|
if theme = @options[:theme]
|
125
128
|
require 'omf-web/theme'
|
@@ -131,4 +134,3 @@ module OMF::Web
|
|
131
134
|
end
|
132
135
|
|
133
136
|
|
134
|
-
|
@@ -0,0 +1,255 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'omf_common/lobject'
|
3
|
+
require 'omf_web'
|
4
|
+
|
5
|
+
module OMF::Web
|
6
|
+
|
7
|
+
# Most of the code to run an OMF Web server from a configuration file
|
8
|
+
#
|
9
|
+
# USAGE:
|
10
|
+
#
|
11
|
+
#
|
12
|
+
class Server < OMF::Common::LObject
|
13
|
+
|
14
|
+
def self.start(server_name, description, top_dir, opts = {})
|
15
|
+
self.new(server_name, description, top_dir, opts)
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(server_name, description, top_dir, opts)
|
19
|
+
OMF::Common::Loggable.init_log server_name
|
20
|
+
|
21
|
+
opts = {
|
22
|
+
static_dirs_pre: ["#{top_dir}/htdocs"],
|
23
|
+
handlers: {
|
24
|
+
pre_parse: lambda do |p, runner|
|
25
|
+
p.on("--config CONF_FILE", "File holding description of web site") {|f| runner.options[:omf_config_file] = f}
|
26
|
+
p.on("--top-dir DIR", "Directory to start from for relative data paths [directory of config file]") {|td| @top_dir = td }
|
27
|
+
end,
|
28
|
+
post_parse: lambda { |r| load_environment(r.options) },
|
29
|
+
},
|
30
|
+
authentication: {
|
31
|
+
required: false
|
32
|
+
}
|
33
|
+
}.merge(opts)
|
34
|
+
|
35
|
+
@top_dir = top_dir
|
36
|
+
@databases = {}
|
37
|
+
|
38
|
+
OMF::Web.start(opts)
|
39
|
+
end
|
40
|
+
|
41
|
+
def load_environment(opts)
|
42
|
+
unless cf = opts[:omf_config_file]
|
43
|
+
puts "Missing config file"
|
44
|
+
abort
|
45
|
+
end
|
46
|
+
|
47
|
+
unless File.readable? cf
|
48
|
+
puts "Can't read config file '#{cf}'"
|
49
|
+
abort
|
50
|
+
end
|
51
|
+
|
52
|
+
@top_dir ||= File.dirname(cf)
|
53
|
+
cfg = _rec_sym_keys(YAML.load_file(cf))
|
54
|
+
|
55
|
+
(cfg[:server] || {}).each do |k, v|
|
56
|
+
k = k.to_sym
|
57
|
+
case k
|
58
|
+
when :port
|
59
|
+
opts[:port] = v.to_i
|
60
|
+
else
|
61
|
+
opts[k] = v
|
62
|
+
end
|
63
|
+
end
|
64
|
+
(cfg[:data_sources] || []).each do |ds|
|
65
|
+
load_datasource(ds)
|
66
|
+
end
|
67
|
+
(cfg[:repositories] || []).each do |repo|
|
68
|
+
load_repository(repo)
|
69
|
+
end
|
70
|
+
|
71
|
+
unless wa = cfg[:widgets]
|
72
|
+
puts "Can't find 'widgets' section in config file '#{cf}' - #{cfg.keys}"
|
73
|
+
abort
|
74
|
+
end
|
75
|
+
wa.each do |w|
|
76
|
+
OMF::Web.register_widget w
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def load_datasource(config)
|
81
|
+
unless id = config[:id]
|
82
|
+
puts "Missing id in datasource configuration"
|
83
|
+
abort
|
84
|
+
end
|
85
|
+
case type = config[:type] || 'database'
|
86
|
+
when 'database'
|
87
|
+
load_database(config)
|
88
|
+
when 'file'
|
89
|
+
load_datasource_file(id, config)
|
90
|
+
else
|
91
|
+
abort "Unknown datasource type '#{type}'."
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def load_database(config)
|
96
|
+
unless table_name = config[:table]
|
97
|
+
puts "Missing 'table' in datasource configuration '#{id}'"
|
98
|
+
abort
|
99
|
+
end
|
100
|
+
unless db_cfg = config[:database]
|
101
|
+
puts "Missing database configuration in datasource '#{id}'"
|
102
|
+
abort
|
103
|
+
end
|
104
|
+
db = get_database(db_cfg)
|
105
|
+
unless table = db.create_table(table_name)
|
106
|
+
puts "Can't find table '#{table_name}' in database '#{db}'"
|
107
|
+
abort
|
108
|
+
end
|
109
|
+
OMF::Web.register_datasource table, name: id
|
110
|
+
end
|
111
|
+
|
112
|
+
def get_database(config)
|
113
|
+
require 'omf_oml/table'
|
114
|
+
require 'omf_oml/sql_source'
|
115
|
+
|
116
|
+
if config.is_a? String
|
117
|
+
if db = @databases[config]
|
118
|
+
return db
|
119
|
+
end
|
120
|
+
puts "Database '#{config}' not defined - (#{@databases.keys})"
|
121
|
+
abort
|
122
|
+
end
|
123
|
+
unless id = config[:id]
|
124
|
+
puts "Missing id in database configuration"
|
125
|
+
abort
|
126
|
+
end
|
127
|
+
# unless id = config[:id]
|
128
|
+
# puts "Database '#{config}' not defined - (#{@databases.keys})"
|
129
|
+
# abort
|
130
|
+
# end
|
131
|
+
unless url = config[:url]
|
132
|
+
puts "Missing URL for database '#{id}'"
|
133
|
+
abort
|
134
|
+
end
|
135
|
+
if url.start_with?('sqlite://') && ! url.start_with?('sqlite:///')
|
136
|
+
# inject top dir
|
137
|
+
url.insert('sqlite://'.length, @top_dir + '/')
|
138
|
+
end
|
139
|
+
puts "URL: #{url}"
|
140
|
+
begin
|
141
|
+
return @databases[id] = OMF::OML::OmlSqlSource.new(url, :check_interval => 3.0)
|
142
|
+
rescue Exception => ex
|
143
|
+
puts "Can't connect to database '#{id}' - #{ex}"
|
144
|
+
abort
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# The data to be served as a datasource is contained in a file. We
|
149
|
+
# currently support CSV with headers, and JSON which turns into a
|
150
|
+
# 1 col by 1 row datasource.
|
151
|
+
#
|
152
|
+
def load_datasource_file(name, opts)
|
153
|
+
unless file = opts[:file]
|
154
|
+
puts "Data source file is not defined in '#{opts}'"
|
155
|
+
abort
|
156
|
+
end
|
157
|
+
unless file.start_with? '/'
|
158
|
+
file = File.join(@top_dir, file)
|
159
|
+
end
|
160
|
+
unless File.readable? file
|
161
|
+
puts "Can't read file '#{file}'"
|
162
|
+
abort
|
163
|
+
end
|
164
|
+
case content_type = opts[:content_type].to_s
|
165
|
+
when 'json'
|
166
|
+
ds = JSONDataSource.new(file)
|
167
|
+
when 'csv'
|
168
|
+
require 'omf_oml/csv_table'
|
169
|
+
ds = OMF::OML::OmlCsvTable.create name, file, has_csv_header: true
|
170
|
+
else
|
171
|
+
puts "Unknown content type '#{content_type}'"
|
172
|
+
abort
|
173
|
+
end
|
174
|
+
OMF::Web.register_datasource ds, name: name
|
175
|
+
end
|
176
|
+
|
177
|
+
def load_repository(config)
|
178
|
+
unless id = config[:id]
|
179
|
+
puts "Missing id in respository configuration"
|
180
|
+
abort
|
181
|
+
end
|
182
|
+
unless type = config[:type]
|
183
|
+
puts "Missing 'type' in respository configuration '#{id}'"
|
184
|
+
abort
|
185
|
+
end
|
186
|
+
|
187
|
+
require 'omf-web/content/repository'
|
188
|
+
case type
|
189
|
+
when 'file'
|
190
|
+
unless top_dir = config[:top_dir]
|
191
|
+
puts "Missing 'top_dir' in respository configuration '#{id}'"
|
192
|
+
abort
|
193
|
+
end
|
194
|
+
unless top_dir.start_with? '/'
|
195
|
+
top_dir = File.join(@top_dir, top_dir)
|
196
|
+
end
|
197
|
+
OMF::Web::ContentRepository.register_repo(id, type: :file, top_dir: top_dir)
|
198
|
+
else
|
199
|
+
puts "Unknown repository type '#{type}'. Only supporting 'file'."
|
200
|
+
abort
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
204
|
+
|
205
|
+
# Recusively Symbolize keys of hash
|
206
|
+
#
|
207
|
+
def _rec_sym_keys(hash)
|
208
|
+
h = {}
|
209
|
+
hash.each do |k, v|
|
210
|
+
if v.is_a? Hash
|
211
|
+
v = _rec_sym_keys(v)
|
212
|
+
elsif v.is_a? Array
|
213
|
+
v = v.map {|e| e.is_a?(Hash) ? _rec_sym_keys(e) : e }
|
214
|
+
end
|
215
|
+
h[k.to_sym] = v
|
216
|
+
end
|
217
|
+
h
|
218
|
+
end
|
219
|
+
|
220
|
+
|
221
|
+
# This class simulates a DataSource to transfer a JSON file as a database with one row and column
|
222
|
+
|
223
|
+
|
224
|
+
class JSONDataSource < OMF::Common::LObject
|
225
|
+
|
226
|
+
def initialize(file)
|
227
|
+
raw = File.read(file)
|
228
|
+
@content = [[JSON.parse(raw)]]
|
229
|
+
end
|
230
|
+
|
231
|
+
# * rows Returns an array of rows
|
232
|
+
# * on_content_changed(lambda{action, rows}) Call provided block with actions :added, :removed
|
233
|
+
# * create_sliced_table (optional)
|
234
|
+
# * release Not exactly sure when that is being used
|
235
|
+
# * schema Schema of row
|
236
|
+
# * offset
|
237
|
+
def rows
|
238
|
+
@content
|
239
|
+
end
|
240
|
+
|
241
|
+
def offset
|
242
|
+
0
|
243
|
+
end
|
244
|
+
|
245
|
+
def schema
|
246
|
+
require 'omf_oml/schema'
|
247
|
+
OMF::OML::OmlSchema.create([[:content]])
|
248
|
+
end
|
249
|
+
|
250
|
+
def on_content_changed(*args)
|
251
|
+
# do nothing
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end # class
|
255
|
+
end # module
|
data/lib/omf-web/version.rb
CHANGED
@@ -28,8 +28,8 @@ module OMF::Web::Widget
|
|
28
28
|
opts[:js_url] = "graph/js/#{vizType}.js"
|
29
29
|
opts[:js_class] = "OML.#{vizType}"
|
30
30
|
opts[:base_el] = "\##{dom_id}"
|
31
|
-
super opts
|
32
|
-
|
31
|
+
super opts
|
32
|
+
|
33
33
|
if (ds = opts.delete(:data_source))
|
34
34
|
# single source
|
35
35
|
data_sources = {:default => ds}
|
@@ -49,10 +49,10 @@ module OMF::Web::Widget
|
|
49
49
|
end
|
50
50
|
#puts "DTA_WIDGTE>>> #{opts[:data_sources].inspect}"
|
51
51
|
end
|
52
|
-
|
53
|
-
# This is the DOM id which should be used by the renderer for this widget.
|
52
|
+
|
53
|
+
# This is the DOM id which should be used by the renderer for this widget.
|
54
54
|
# We need to keep this here as various renderes at various levels may need
|
55
|
-
# to get a reference to it to allow for such functionalities as
|
55
|
+
# to get a reference to it to allow for such functionalities as
|
56
56
|
# hiding, stacking, ...
|
57
57
|
def dom_id
|
58
58
|
"w#{object_id.abs}"
|
@@ -86,7 +86,7 @@ module OMF::Web::Widget
|
|
86
86
|
# end
|
87
87
|
# end
|
88
88
|
# end
|
89
|
-
#
|
89
|
+
#
|
90
90
|
# def on_ws_close(ws)
|
91
91
|
# raise "ARE WE STILL NEEDING THIS"
|
92
92
|
# @ws = nil
|