omf_web 1.2.1 → 1.2.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.
- data/.gitignore +2 -0
- data/doc/tutorial/tut01/hello_world.yaml +12 -0
- data/doc/tutorial/tut02/gen.csv +1 -0
- data/doc/tutorial/tut02/simple_graph.yaml +28 -0
- data/doc/tutorial/tut03/stacked.yaml +37 -0
- data/doc/tutorial/tut04/create_db.rb +56 -0
- data/doc/tutorial/tut04/gen.sq3 +0 -0
- data/doc/tutorial/tut04/realtime_graph.yaml +47 -0
- data/doc/tutorial/tut05/gen_maxs-laptop-3.local-35511_foo_2013-12-19t19.20.46+1100 +125 -0
- data/doc/tutorial/tut05/monitor_generator_oml.rb +36 -0
- data/doc/tutorial/tut05/realtime_graph_omsp.yaml +47 -0
- data/lib/omf-web/content/git_repository.rb +3 -3
- data/lib/omf-web/content/irods_repository.rb +2 -1
- data/lib/omf-web/content/repository.rb +5 -0
- data/lib/omf-web/content/static_repository.rb +1 -1
- data/lib/omf-web/data_source_proxy.rb +18 -10
- data/lib/omf-web/session_store.rb +18 -0
- data/lib/omf-web/theme/bright/code_renderer.rb +1 -1
- data/lib/omf-web/thin/server.rb +100 -34
- data/lib/omf-web/version.rb +1 -1
- data/omf_web.gemspec +1 -0
- data/share/htdocs/graph/js/abstract_chart.js +8 -1
- data/share/htdocs/graph/js/abstract_multiple_datasource_chart.js +82 -0
- data/share/htdocs/graph/js/abstract_widget.js +13 -11
- data/share/htdocs/js/data_source3.js +6 -6
- data/share/htdocs/js/data_source_repo.js +2 -2
- metadata +211 -216
- data/doc/tutorial/tut01/hello_world.rb +0 -27
- data/doc/tutorial/tut02/hello_graph.rb +0 -85
- data/doc/tutorial/tut03/hello_database.rb +0 -69
- data/doc/tutorial/tut03/nmetric.sq3 +0 -0
data/lib/omf-web/thin/server.rb
CHANGED
@@ -41,12 +41,12 @@ module OMF::Web
|
|
41
41
|
|
42
42
|
def load_environment(opts)
|
43
43
|
unless cf = opts[:omf_config_file]
|
44
|
-
|
44
|
+
fatal "Missing config file"
|
45
45
|
abort
|
46
46
|
end
|
47
47
|
|
48
48
|
unless File.readable? cf
|
49
|
-
|
49
|
+
fatal "Can't read config file '#{cf}'"
|
50
50
|
abort
|
51
51
|
end
|
52
52
|
|
@@ -75,18 +75,32 @@ module OMF::Web
|
|
75
75
|
load_repository(repo)
|
76
76
|
end
|
77
77
|
|
78
|
-
|
79
|
-
|
78
|
+
widgets = cfg[:widgets] || []
|
79
|
+
if (tabs = cfg[:tabs])
|
80
|
+
tabs.each {|t| t[:top_level] = true}
|
81
|
+
widgets += tabs
|
82
|
+
end
|
83
|
+
if widgets.empty?
|
84
|
+
fatal "Can't find 'widgets' or 'tabs' section in config file '#{cf}' - #{cfg.keys}"
|
80
85
|
abort
|
81
86
|
end
|
82
|
-
|
83
|
-
|
87
|
+
widgets.each do |w|
|
88
|
+
register_widget w
|
89
|
+
end
|
90
|
+
|
91
|
+
# Any other file to load before opening shop
|
92
|
+
if init = cfg[:init]
|
93
|
+
unless init.is_a? Enumerable
|
94
|
+
init = [init]
|
95
|
+
end
|
96
|
+
init.each {|f| load_ruby_file(f) }
|
84
97
|
end
|
98
|
+
|
85
99
|
end
|
86
100
|
|
87
101
|
def load_datasource(config)
|
88
102
|
unless id = config[:id]
|
89
|
-
|
103
|
+
fatal "Missing id in datasource configuration"
|
90
104
|
abort
|
91
105
|
end
|
92
106
|
if config[:database]
|
@@ -95,6 +109,8 @@ module OMF::Web
|
|
95
109
|
load_datasource_file(id, config)
|
96
110
|
elsif config[:omsp]
|
97
111
|
load_omsp_endpoint(id, config)
|
112
|
+
elsif config[:generator]
|
113
|
+
load_generator(id, config[:generator])
|
98
114
|
else
|
99
115
|
abort "Unknown datasource type - #{config}"
|
100
116
|
end
|
@@ -102,13 +118,13 @@ module OMF::Web
|
|
102
118
|
|
103
119
|
def load_database(id, config)
|
104
120
|
unless db_cfg = config[:database]
|
105
|
-
|
121
|
+
fatal "Missing database configuration in datasource '#{config}'"
|
106
122
|
abort
|
107
123
|
end
|
108
124
|
db = get_database(db_cfg)
|
109
125
|
if query_s = config[:query]
|
110
126
|
unless schema = config[:schema]
|
111
|
-
|
127
|
+
fatal "Missing schema configuration in datasource '#{config}'"
|
112
128
|
abort
|
113
129
|
end
|
114
130
|
require 'omf_oml/schema'
|
@@ -116,12 +132,12 @@ module OMF::Web
|
|
116
132
|
table = db.create_table(id, config)
|
117
133
|
else
|
118
134
|
unless table_name = config.delete(:table)
|
119
|
-
|
135
|
+
fatal "Missing 'table' in datasource configuration '#{config}'"
|
120
136
|
abort
|
121
137
|
end
|
122
138
|
config[:name] = id
|
123
139
|
unless table = db.create_table(table_name, config)
|
124
|
-
|
140
|
+
fatal "Can't find table '#{table_name}' in database '#{db_cfg}'"
|
125
141
|
abort
|
126
142
|
end
|
127
143
|
end
|
@@ -136,23 +152,21 @@ module OMF::Web
|
|
136
152
|
if db = @databases[config]
|
137
153
|
return db
|
138
154
|
end
|
139
|
-
|
140
|
-
abort
|
141
|
-
end
|
142
|
-
unless id = config.delete(:id)
|
143
|
-
puts "Missing id in database configuration"
|
155
|
+
fatal "Database '#{config}' not defined - (#{@databases.keys})"
|
144
156
|
abort
|
145
157
|
end
|
146
|
-
if
|
147
|
-
|
158
|
+
if id = config.delete(:id)
|
159
|
+
if db = @databases[id.to_s] # already known
|
160
|
+
return db
|
161
|
+
end
|
148
162
|
end
|
149
163
|
|
150
164
|
# unless id = config[:id]
|
151
|
-
#
|
165
|
+
# fatal "Database '#{config}' not defined - (#{@databases.keys})"
|
152
166
|
# abort
|
153
167
|
# end
|
154
168
|
unless url = config.delete(:url)
|
155
|
-
|
169
|
+
fatal "Missing URL for database '#{id}'"
|
156
170
|
abort
|
157
171
|
end
|
158
172
|
if url.start_with?('sqlite:') && ! url.start_with?('sqlite:/')
|
@@ -162,9 +176,11 @@ module OMF::Web
|
|
162
176
|
config[:check_interval] ||= 3.0
|
163
177
|
puts "URL: #{url} - #{config}"
|
164
178
|
begin
|
165
|
-
|
179
|
+
db = OMF::OML::OmlSqlSource.new(url, config)
|
180
|
+
@databases[id] = db if id
|
181
|
+
return db
|
166
182
|
rescue Exception => ex
|
167
|
-
|
183
|
+
fatal "Can't connect to database '#{id}' - #{ex}"
|
168
184
|
abort
|
169
185
|
end
|
170
186
|
end
|
@@ -175,24 +191,27 @@ module OMF::Web
|
|
175
191
|
#
|
176
192
|
def load_datasource_file(name, opts)
|
177
193
|
unless file = opts[:file]
|
178
|
-
|
194
|
+
fatal "Data source file is not defined in '#{opts}'"
|
179
195
|
abort
|
180
196
|
end
|
181
197
|
unless file.start_with? '/'
|
182
|
-
|
198
|
+
File.absolute_path(file, @cfg_dir)
|
183
199
|
end
|
184
200
|
unless File.readable? file
|
185
|
-
|
201
|
+
fatal "Can't read file '#{file}'"
|
186
202
|
abort
|
187
203
|
end
|
188
|
-
|
204
|
+
unless content_type = opts[:content_type]
|
205
|
+
content_type = File.extname(file)[1 .. -1]
|
206
|
+
end
|
207
|
+
case content_type.to_s
|
189
208
|
when 'json'
|
190
209
|
ds = JSONDataSource.new(file)
|
191
210
|
when 'csv'
|
192
211
|
require 'omf_oml/csv_table'
|
193
212
|
ds = OMF::OML::OmlCsvTable.create name, file, has_csv_header: true
|
194
213
|
else
|
195
|
-
|
214
|
+
fatal "Unknown content type '#{content_type}'"
|
196
215
|
abort
|
197
216
|
end
|
198
217
|
OMF::Web.register_datasource ds, name: name
|
@@ -201,21 +220,57 @@ module OMF::Web
|
|
201
220
|
def load_omsp_endpoint(id, config)
|
202
221
|
oconfig = config[:omsp]
|
203
222
|
unless port = oconfig[:port]
|
204
|
-
|
223
|
+
fatal "Need port in OMSP definition '#{oconfig}' - datasource '#{id}'"
|
205
224
|
abort
|
206
225
|
end
|
207
226
|
ep = @omsp_endpoints[port] ||= OmspEndpointProxy.new(port)
|
208
227
|
ep.add_datasource(id, config)
|
209
228
|
end
|
210
229
|
|
230
|
+
def load_generator(id, config)
|
231
|
+
if file = config[:load]
|
232
|
+
load_ruby_file(file)
|
233
|
+
end
|
234
|
+
unless klass_name = config[:class]
|
235
|
+
fatal "Missing 'class' options for generator '#{id}'"
|
236
|
+
abort
|
237
|
+
end
|
238
|
+
klass = nil
|
239
|
+
begin
|
240
|
+
klass = Kernel.const_get(klass_name)
|
241
|
+
rescue
|
242
|
+
fatal "Can't find class '#{klass_name}' referenced in generator '#{id}'"
|
243
|
+
abort
|
244
|
+
end
|
245
|
+
opts = config[:opts] || {}
|
246
|
+
debug "Creating new generator '#{id}' from '#{klass_name}' with '#{opts}'"
|
247
|
+
unless klass.respond_to? :create_data_source
|
248
|
+
fatal "Class '#{klass_name}' doesn't have a 'create_data_source' class method."
|
249
|
+
abort
|
250
|
+
end
|
251
|
+
klass.create_data_source(id, opts)
|
252
|
+
end
|
253
|
+
|
254
|
+
def load_ruby_file(file)
|
255
|
+
unless file.start_with? '/'
|
256
|
+
file = File.absolute_path(file, @cfg_dir)
|
257
|
+
end
|
258
|
+
unless File.readable? file
|
259
|
+
fatal "Can't read file '#{file}'"
|
260
|
+
abort
|
261
|
+
end
|
262
|
+
debug "Loading #{file}"
|
263
|
+
load(file)
|
264
|
+
end
|
265
|
+
|
211
266
|
|
212
267
|
def load_repository(config)
|
213
268
|
unless id = config[:id]
|
214
|
-
|
269
|
+
fatal "Missing id in respository configuration"
|
215
270
|
abort
|
216
271
|
end
|
217
272
|
unless type = config[:type]
|
218
|
-
|
273
|
+
fatal "Missing 'type' in respository configuration '#{id}'"
|
219
274
|
abort
|
220
275
|
end
|
221
276
|
|
@@ -223,20 +278,31 @@ module OMF::Web
|
|
223
278
|
case type
|
224
279
|
when 'file'
|
225
280
|
unless top_dir = config[:top_dir]
|
226
|
-
|
281
|
+
fatal "Missing 'top_dir' in respository configuration '#{id}'"
|
227
282
|
abort
|
228
283
|
end
|
229
284
|
unless top_dir.start_with? '/'
|
230
|
-
top_dir = File.join(@
|
285
|
+
top_dir = File.join(@cfg_dir, top_dir)
|
231
286
|
end
|
287
|
+
#puts "TOP>>> #{File.absolute_path top_dir}"
|
232
288
|
OMF::Web::ContentRepository.register_repo(id, type: :file, top_dir: top_dir)
|
233
289
|
else
|
234
|
-
|
290
|
+
fatal "Unknown repository type '#{type}'. Only supporting 'file'."
|
235
291
|
abort
|
236
292
|
end
|
237
293
|
|
238
294
|
end
|
239
295
|
|
296
|
+
def register_widget(w)
|
297
|
+
unless w[:id]
|
298
|
+
require 'digest/md5'
|
299
|
+
w[:id] = Digest::MD5.hexdigest(w[:name] || "tab#{rand(10000)}")[0, 8]
|
300
|
+
end
|
301
|
+
w[:top_level] = true
|
302
|
+
w[:type] ||= 'layout/one_column'
|
303
|
+
OMF::Web.register_widget w
|
304
|
+
end
|
305
|
+
|
240
306
|
# Recusively Symbolize keys of hash
|
241
307
|
#
|
242
308
|
def _rec_sym_keys(hash)
|
@@ -330,4 +396,4 @@ module OMF::Web
|
|
330
396
|
end # class OmspEndpointProxy
|
331
397
|
|
332
398
|
end # class
|
333
|
-
end # module
|
399
|
+
end # module
|
data/lib/omf-web/version.rb
CHANGED
data/omf_web.gemspec
CHANGED
@@ -34,6 +34,7 @@ Gem::Specification.new do |s|
|
|
34
34
|
s.add_runtime_dependency "websocket-rack", "~> 0.4.0"
|
35
35
|
s.add_runtime_dependency "rack-accept", "~> 0.4.0"
|
36
36
|
s.add_runtime_dependency "i18n"
|
37
|
+
s.add_runtime_dependency "rake"
|
37
38
|
|
38
39
|
# Do we need the next two dependencies?
|
39
40
|
#s.add_runtime_dependency "sqlite3", "~> 1.3.6"
|
@@ -77,6 +77,13 @@ define(["graph/abstract_widget"], function (abstract_widget) {
|
|
77
77
|
this.update();
|
78
78
|
},
|
79
79
|
|
80
|
+
configure_base_layer: function(vis) {
|
81
|
+
this.base_layer = vis.append("svg:g");
|
82
|
+
if (this.base_css_class) {
|
83
|
+
this.base_layer.attr("class", this.base_css_class);
|
84
|
+
}
|
85
|
+
},
|
86
|
+
|
80
87
|
_resize_base_el: function(w, h) {
|
81
88
|
// Do not add margins to the base_el, but to the inside of the SVG panes
|
82
89
|
this.w = w;
|
@@ -290,4 +297,4 @@ define(["graph/abstract_widget"], function (abstract_widget) {
|
|
290
297
|
});
|
291
298
|
|
292
299
|
return abstract_chart;
|
293
|
-
});
|
300
|
+
});
|
@@ -0,0 +1,82 @@
|
|
1
|
+
|
2
|
+
define(["graph/abstract_chart"], function(abstract_chart) {
|
3
|
+
|
4
|
+
var graph = abstract_chart.extend({
|
5
|
+
// MAKE SURE THIS IS DEFINED IN SUB CLASS
|
6
|
+
data_source_names: ['change', 'me'],
|
7
|
+
|
8
|
+
initialize: function(opts) {
|
9
|
+
graph.__super__.initialize.call(this, opts);
|
10
|
+
},
|
11
|
+
|
12
|
+
// Find the appropriate data source and bind to it
|
13
|
+
//
|
14
|
+
init_data_source: function() {
|
15
|
+
var self = this;
|
16
|
+
var o = self.opts;
|
17
|
+
var sources = o.data_sources;
|
18
|
+
var ds_names = self.data_source_names;
|
19
|
+
|
20
|
+
if (! (sources instanceof Array)) {
|
21
|
+
throw "Expected an array";
|
22
|
+
}
|
23
|
+
if (sources.length != ds_names.length) {
|
24
|
+
throw "Expected '" + ds_names.length + "' data source, but only found '" + sources.length + "'.";
|
25
|
+
}
|
26
|
+
|
27
|
+
var dsh = self.data_source = {};
|
28
|
+
_.map(sources, function(s) {
|
29
|
+
dsh[s.name] = self.init_single_data_source(s);
|
30
|
+
});
|
31
|
+
_.each(ds_names, function(ds_name) {
|
32
|
+
if (dsh[ds_name] == undefined) {
|
33
|
+
throw "Missing data source '" + ds_name + "'. Check for spelling of name.";
|
34
|
+
}
|
35
|
+
});
|
36
|
+
},
|
37
|
+
|
38
|
+
process_schema: function() {
|
39
|
+
var self = this;
|
40
|
+
var ds_names = self.data_source_names;
|
41
|
+
|
42
|
+
var schemas = self.schema = {};
|
43
|
+
_.each(ds_names, function(ds_name) {
|
44
|
+
schemas[ds_name] = self.process_single_schema(self.data_source[ds_name]);
|
45
|
+
});
|
46
|
+
|
47
|
+
var om = self.opts.mapping;
|
48
|
+
if (om == undefined) {
|
49
|
+
throw "Missing mapping instructions in 'options'.";
|
50
|
+
}
|
51
|
+
self.mapping = {};
|
52
|
+
_.each(ds_names, function(ds_name) {
|
53
|
+
var mapping = om[ds_name];
|
54
|
+
if (mapping == undefined) {
|
55
|
+
throw "Missing mapping instructions in 'options' for '" + ds_name + "'.";
|
56
|
+
}
|
57
|
+
self.mapping[ds_name] = self.process_single_mapping(ds_name, mapping, self.decl_properties[ds_name]);
|
58
|
+
});
|
59
|
+
},
|
60
|
+
|
61
|
+
/*
|
62
|
+
* Return schema for +stream+.
|
63
|
+
*/
|
64
|
+
schema_for_stream: function(stream) {
|
65
|
+
var schema = this.schema[stream];
|
66
|
+
return schema;
|
67
|
+
},
|
68
|
+
|
69
|
+
update: function() {
|
70
|
+
var data = {};
|
71
|
+
var self = this;
|
72
|
+
|
73
|
+
_.each(self.data_source_names, function(ds_name) {
|
74
|
+
data[ds_name] = self.data_source[ds_name].rows();
|
75
|
+
}, self);
|
76
|
+
self.redraw(data);
|
77
|
+
},
|
78
|
+
|
79
|
+
}); // end of graph
|
80
|
+
|
81
|
+
return graph;
|
82
|
+
});
|
@@ -31,7 +31,7 @@ define(['omf/data_source_repo', 'vendor/d3/d3'], function(ds_repo) {
|
|
31
31
|
x: 0,
|
32
32
|
y: 0
|
33
33
|
},
|
34
|
-
}
|
34
|
+
};
|
35
35
|
},
|
36
36
|
|
37
37
|
//base_css_class: 'oml-chart',
|
@@ -93,6 +93,8 @@ define(['omf/data_source_repo', 'vendor/d3/d3'], function(ds_repo) {
|
|
93
93
|
}
|
94
94
|
this._resize_base_el(w,h);
|
95
95
|
|
96
|
+
OHUB.trigger(o.id + '.resize', {width: w, height: h});
|
97
|
+
|
96
98
|
return this;
|
97
99
|
},
|
98
100
|
|
@@ -120,10 +122,10 @@ define(['omf/data_source_repo', 'vendor/d3/d3'], function(ds_repo) {
|
|
120
122
|
var self = this;
|
121
123
|
|
122
124
|
if (! (sources instanceof Array)) {
|
123
|
-
throw "Expected an array"
|
125
|
+
throw "Expected an array";
|
124
126
|
}
|
125
127
|
if (sources.length != 1) {
|
126
|
-
throw "Can only process a SINGLE source"
|
128
|
+
throw "Can only process a SINGLE source";
|
127
129
|
}
|
128
130
|
this.data_source = this.init_single_data_source(sources[0]);
|
129
131
|
},
|
@@ -136,7 +138,7 @@ define(['omf/data_source_repo', 'vendor/d3/d3'], function(ds_repo) {
|
|
136
138
|
var self = this;
|
137
139
|
OHUB.bind(ds.event_name, function() {
|
138
140
|
self.update();;
|
139
|
-
})
|
141
|
+
});
|
140
142
|
return ds;
|
141
143
|
},
|
142
144
|
|
@@ -166,7 +168,7 @@ define(['omf/data_source_repo', 'vendor/d3/d3'], function(ds_repo) {
|
|
166
168
|
_.map(properties_decl, function(a) {
|
167
169
|
var pname = a[0]; var type = a[1]; var def = a[2];
|
168
170
|
var descr = om[pname];
|
169
|
-
m[pname] = self.create_mapping(pname, descr, source_name, type, def)
|
171
|
+
m[pname] = self.create_mapping(pname, descr, source_name, type, def);
|
170
172
|
});
|
171
173
|
return m;
|
172
174
|
},
|
@@ -194,7 +196,7 @@ define(['omf/data_source_repo', 'vendor/d3/d3'], function(ds_repo) {
|
|
194
196
|
create_mapping: function(mname, descr, stream, type, def) {
|
195
197
|
var self = this;
|
196
198
|
if (descr == undefined && typeof(def) == 'object') {
|
197
|
-
descr = def
|
199
|
+
descr = def;
|
198
200
|
}
|
199
201
|
if (descr == undefined || typeof(descr) != 'object' ) {
|
200
202
|
if (type == 'index') {
|
@@ -208,7 +210,7 @@ define(['omf/data_source_repo', 'vendor/d3/d3'], function(ds_repo) {
|
|
208
210
|
var cf_i = cf();
|
209
211
|
value = function(x) {
|
210
212
|
return cf_i(x);
|
211
|
-
}
|
213
|
+
};
|
212
214
|
}
|
213
215
|
return value;
|
214
216
|
}
|
@@ -256,7 +258,7 @@ define(['omf/data_source_repo', 'vendor/d3/d3'], function(ds_repo) {
|
|
256
258
|
var t = index_f(join);
|
257
259
|
//var r = t[join];
|
258
260
|
return t;
|
259
|
-
}
|
261
|
+
};
|
260
262
|
} else {
|
261
263
|
if (descr.values) {
|
262
264
|
// provided custom mapping for values
|
@@ -264,7 +266,7 @@ define(['omf/data_source_repo', 'vendor/d3/d3'], function(ds_repo) {
|
|
264
266
|
var def_value = descr['default'];
|
265
267
|
return function(x) {
|
266
268
|
return values[x] || def_value;
|
267
|
-
}
|
269
|
+
};
|
268
270
|
}
|
269
271
|
var pname = descr.property;
|
270
272
|
if (pname == undefined) {
|
@@ -331,7 +333,7 @@ define(['omf/data_source_repo', 'vendor/d3/d3'], function(ds_repo) {
|
|
331
333
|
if (source[prop] == null) {
|
332
334
|
source[prop] = defaults[prop];
|
333
335
|
} else if((typeof(source[prop]) == 'object') && defaults[prop]) {
|
334
|
-
this.deep_defaults(source[prop], defaults[prop])
|
336
|
+
this.deep_defaults(source[prop], defaults[prop]);
|
335
337
|
}
|
336
338
|
}
|
337
339
|
return source;
|
@@ -341,4 +343,4 @@ define(['omf/data_source_repo', 'vendor/d3/d3'], function(ds_repo) {
|
|
341
343
|
});
|
342
344
|
|
343
345
|
return abstract_widget;
|
344
|
-
})
|
346
|
+
});
|
@@ -13,11 +13,11 @@ function omf_web_data_source(opts) {
|
|
13
13
|
version: "0.1",
|
14
14
|
name: name,
|
15
15
|
schema: schema,
|
16
|
-
rows: function() {return rows},
|
16
|
+
rows: function() { return rows; },
|
17
17
|
index_for_column: index_for_column,
|
18
18
|
is_dynamic: is_dynamic,
|
19
19
|
event_name: event_name,
|
20
|
-
}
|
20
|
+
};
|
21
21
|
|
22
22
|
var indexes = {};
|
23
23
|
var unique_index_check = null;
|
@@ -30,18 +30,18 @@ function omf_web_data_source(opts) {
|
|
30
30
|
var index = indexes[i];
|
31
31
|
if (!index) {
|
32
32
|
index = indexes[i] = {};
|
33
|
-
_.each(rows, function(r) { index[r[i]] = r; })
|
33
|
+
_.each(rows, function(r) { index[r[i]] = r; });
|
34
34
|
}
|
35
35
|
return function(key) {
|
36
36
|
return indexes[i][key]; // need fresh lookup as we may redo index
|
37
|
-
}
|
37
|
+
};
|
38
38
|
}
|
39
39
|
|
40
40
|
function update_indexes() {
|
41
41
|
// This can most likley be done more efficiently if we consider what has changed
|
42
42
|
_.each(indexes, function(ignore, i) {
|
43
43
|
var index = indexes[i] = {};
|
44
|
-
_.each(rows, function(r) { index[r[i]] = r; })
|
44
|
+
_.each(rows, function(r) { index[r[i]] = r; });
|
45
45
|
});
|
46
46
|
}
|
47
47
|
|
@@ -53,7 +53,7 @@ function omf_web_data_source(opts) {
|
|
53
53
|
var opts = _;
|
54
54
|
var interval = -1;
|
55
55
|
if (typeof(opts) == 'number') {
|
56
|
-
interval = opts
|
56
|
+
interval = opts;
|
57
57
|
} else if (opts == true) {
|
58
58
|
interval = 3;
|
59
59
|
}
|
@@ -7,7 +7,7 @@ define(['omf/data_source3'], function(data_source) {
|
|
7
7
|
function context() {};
|
8
8
|
|
9
9
|
context.register = function(opts) {
|
10
|
-
var id = opts.id || opts.name;
|
10
|
+
var id = opts.id || opts.stream || opts.name;
|
11
11
|
if (sources[id] == null) {
|
12
12
|
sources[id] = data_source(opts);
|
13
13
|
}
|
@@ -19,7 +19,7 @@ define(['omf/data_source3'], function(data_source) {
|
|
19
19
|
var dynamic = false;
|
20
20
|
|
21
21
|
if (typeof(ds_descr) == 'object') {
|
22
|
-
name = ds_descr.id || ds_descr.name;
|
22
|
+
name = ds_descr.id || ds_descr.stream || ds_descr.name;
|
23
23
|
dynamic = ds_descr.dynamic;
|
24
24
|
} else {
|
25
25
|
name = ds_descr;
|