omf_web 0.9.7 → 0.9.8
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/README.md +1 -1
- data/bin/omf_web_demo +3 -0
- data/bin/omf_web_demo.sh +0 -0
- data/doc/tutorial/tut01/hello_world.rb +27 -0
- data/doc/tutorial/tut02/hello_graph.rb +85 -0
- data/doc/tutorial/tut03/hello_database.rb +69 -0
- data/doc/tutorial/tut03/nmetric.sq3 +0 -0
- data/example/bridge/config.ru +2 -1
- data/example/demo/data_sources/downloads.csv +96 -1
- data/example/demo/demo_viz_server.rb +46 -28
- data/example/openflow-gec15/README.md +2 -0
- data/example/openflow-gec15/doc/gec15_topo.png +0 -0
- data/example/openflow-gec15/exp_source.rb +48 -9
- data/example/openflow-gec15/of_viz_server.rb +1 -1
- data/example/openflow-gec15/repository/of-exp.rb +117 -12
- data/example/openflow-gec15/repository/trema-ctl6.rb +2 -2
- data/example/simple/README.md +29 -1
- data/example/simple/data_sources/ping_source.rb +2 -2
- data/lib/irods4r/directory.rb +49 -0
- data/lib/irods4r/file.rb +53 -0
- data/lib/irods4r/icommands.rb +63 -0
- data/lib/irods4r.rb +34 -0
- data/lib/omf-web/content/content_proxy.rb +14 -5
- data/lib/omf-web/content/file_repository.rb +36 -75
- data/lib/omf-web/content/git_repository.rb +39 -35
- data/lib/omf-web/content/irods_repository.rb +191 -0
- data/lib/omf-web/content/repository.rb +84 -21
- data/lib/omf-web/content/static_repository.rb +61 -0
- data/lib/omf-web/data_source_proxy.rb +3 -3
- data/lib/omf-web/rack/session_authenticator.rb +67 -35
- data/lib/omf-web/rack/tab_mapper.rb +2 -1
- data/lib/omf-web/rack/websocket_handler.rb +49 -10
- data/lib/omf-web/session_store.rb +9 -8
- data/lib/omf-web/theme/bright/page.rb +1 -1
- data/lib/omf-web/thin/runner.rb +18 -5
- data/lib/omf-web/version.rb +1 -1
- data/lib/omf-web/widget/text/maruku/output/to_html.rb +8 -2
- data/lib/omf_web.rb +17 -2
- data/omf_web.gemspec +0 -1
- data/share/htdocs/graph/js/abstract_widget.js +3 -1
- data/share/htdocs/graph/js/barchart_brush.js +240 -0
- data/share/htdocs/js/data_source2.js +4 -1
- data/share/htdocs/js/mustache.js +17 -11
- data/share/htdocs/theme/bright/css/bright.css +1 -1
- data/share/htdocs/vendor/{bootstrap-2.1.1 → bootstrap-2.3.1}/css/bootstrap-responsive.css +56 -5
- data/share/htdocs/vendor/bootstrap-2.3.1/css/bootstrap-responsive.min.css +9 -0
- data/share/htdocs/vendor/{bootstrap-2.1.1 → bootstrap-2.3.1}/css/bootstrap.css +856 -472
- data/share/htdocs/vendor/bootstrap-2.3.1/css/bootstrap.min.css +9 -0
- data/share/htdocs/vendor/{bootstrap-2.1.1 → bootstrap-2.3.1}/img/glyphicons-halflings-white.png +0 -0
- data/share/htdocs/vendor/{bootstrap-2.1.1 → bootstrap-2.3.1}/img/glyphicons-halflings.png +0 -0
- data/share/htdocs/vendor/{bootstrap-2.1.1 → bootstrap-2.3.1}/js/bootstrap.js +427 -178
- data/share/htdocs/vendor/bootstrap-2.3.1/js/bootstrap.min.js +6 -0
- data/share/htdocs/vendor/jquery-tipsy/css/tipsy.css +25 -0
- data/share/htdocs/vendor/jquery-tipsy/js/jquery.tipsy.js +258 -0
- metadata +27 -14
- data/bin/omf-web-basic +0 -235
- data/share/htdocs/vendor/.DS_Store +0 -0
- data/share/htdocs/vendor/bootstrap-2.1.1/css/bootstrap-responsive.min.css +0 -9
- data/share/htdocs/vendor/bootstrap-2.1.1/css/bootstrap.min.css +0 -9
- data/share/htdocs/vendor/bootstrap-2.1.1/js/bootstrap.min.js +0 -6
- data/share/htdocs/vendor/jquery-ui-1.8.23/index.html +0 -383
@@ -14,17 +14,17 @@ module OMF::Web
|
|
14
14
|
#
|
15
15
|
class GitContentRepository < ContentRepository
|
16
16
|
|
17
|
-
@@git_repositories = {}
|
18
|
-
|
19
|
-
# Return the repository which is referenced to by elements in 'opts'.
|
20
|
-
#
|
21
|
-
#
|
22
|
-
def self.[](name)
|
23
|
-
unless repo = @@git_repositories[name.to_sym]
|
24
|
-
raise "Unknown git repo '#{name}'"
|
25
|
-
end
|
26
|
-
repo
|
27
|
-
end
|
17
|
+
# @@git_repositories = {}
|
18
|
+
#
|
19
|
+
# # Return the repository which is referenced to by elements in 'opts'.
|
20
|
+
# #
|
21
|
+
# #
|
22
|
+
# def self.[](name)
|
23
|
+
# unless repo = @@git_repositories[name.to_sym]
|
24
|
+
# raise "Unknown git repo '#{name}'"
|
25
|
+
# end
|
26
|
+
# repo
|
27
|
+
# end
|
28
28
|
|
29
29
|
# Register an existing GIT repo to the system. It will be
|
30
30
|
# consulted for all content url's strarting with
|
@@ -32,17 +32,17 @@ module OMF::Web
|
|
32
32
|
# become the default repo for all newly created content
|
33
33
|
# in this app.
|
34
34
|
#
|
35
|
-
def self.register_git_repo(name, top_dir, is_primary = false)
|
36
|
-
name = name.to_sym
|
37
|
-
if @@git_repositories[name]
|
38
|
-
warn "Ignoring repeated registration of git rep '#{name}'"
|
39
|
-
return
|
40
|
-
end
|
41
|
-
repo = @@git_repositories[name] = GitContentRepository.new(name, top_dir)
|
42
|
-
if is_primary
|
43
|
-
@@primary_repository = repo
|
44
|
-
end
|
45
|
-
end
|
35
|
+
# def self.register_git_repo(name, top_dir, is_primary = false)
|
36
|
+
# name = name.to_sym
|
37
|
+
# if @@git_repositories[name]
|
38
|
+
# warn "Ignoring repeated registration of git rep '#{name}'"
|
39
|
+
# return
|
40
|
+
# end
|
41
|
+
# repo = @@git_repositories[name] = GitContentRepository.new(name, top_dir)
|
42
|
+
# if is_primary
|
43
|
+
# @@primary_repository = repo
|
44
|
+
# end
|
45
|
+
# end
|
46
46
|
|
47
47
|
# def self.read_content(url, opts)
|
48
48
|
# unless (a = url.split(':')).length == 3
|
@@ -57,23 +57,21 @@ module OMF::Web
|
|
57
57
|
|
58
58
|
attr_reader :name, :top_dir
|
59
59
|
|
60
|
-
def initialize(name,
|
61
|
-
|
62
|
-
@
|
63
|
-
@
|
64
|
-
@url_prefix = "git:#{name}:"
|
65
|
-
#@@git_repositories['git:foo'] = self
|
60
|
+
def initialize(name, opts)
|
61
|
+
super
|
62
|
+
@repo = Grit::Repo.new(@top_dir)
|
63
|
+
@url_prefix = "git:#{@name}:"
|
66
64
|
end
|
67
65
|
|
68
66
|
#
|
69
67
|
# Create a URL for a file with 'path' in.
|
70
68
|
# If 'strictly_new' is true, returns nil if 'path' already exists.
|
71
69
|
#
|
72
|
-
def create_url(path, strictly_new = true)
|
73
|
-
return "git:"
|
74
|
-
# TODO: Need to add code to select proper repository
|
75
|
-
return GitContentRepository.create_url(path, strictly_new)
|
76
|
-
end
|
70
|
+
# def create_url(path, strictly_new = true)
|
71
|
+
# return "git:"
|
72
|
+
# # TODO: Need to add code to select proper repository
|
73
|
+
# return GitContentRepository.create_url(path, strictly_new)
|
74
|
+
# end
|
77
75
|
|
78
76
|
|
79
77
|
# Load content described by either a hash or a straightforward path
|
@@ -87,9 +85,9 @@ module OMF::Web
|
|
87
85
|
def create_content_proxy_for(content_descr)
|
88
86
|
path = _get_path(content_descr)
|
89
87
|
# TODO: Make sure that key is really unique across multiple repositories
|
90
|
-
descr = descr ? descr.dup : {}
|
91
88
|
url = @url_prefix + path
|
92
89
|
key = Digest::MD5.hexdigest(url)
|
90
|
+
descr = {}
|
93
91
|
descr[:url] = url
|
94
92
|
descr[:url_key] = key
|
95
93
|
descr[:path] = path
|
@@ -119,6 +117,12 @@ module OMF::Web
|
|
119
117
|
end
|
120
118
|
end
|
121
119
|
|
120
|
+
# Return a URL for a path in this repo
|
121
|
+
#
|
122
|
+
def get_url_for_path(path)
|
123
|
+
@url_prefix + path
|
124
|
+
end
|
125
|
+
|
122
126
|
|
123
127
|
|
124
128
|
#
|
@@ -148,7 +152,7 @@ module OMF::Web
|
|
148
152
|
if long_name.match(search_pattern)
|
149
153
|
mt = mime_type_for_file(e.name)
|
150
154
|
path = @url_prefix + long_name
|
151
|
-
res << {:path => path, :name => e.name,
|
155
|
+
res << {:path => path, url => url_for_path(path), :name => e.name,
|
152
156
|
:mime_type => mt,
|
153
157
|
#:id => Base64.encode64(long_name).gsub("\n", ''),
|
154
158
|
:size => e.size, :blob => e.id}
|
@@ -0,0 +1,191 @@
|
|
1
|
+
|
2
|
+
require 'find'
|
3
|
+
require 'omf_common/lobject'
|
4
|
+
require 'omf_web'
|
5
|
+
require 'omf-web/content/content_proxy'
|
6
|
+
require 'omf-web/content/repository'
|
7
|
+
require 'irods4r'
|
8
|
+
|
9
|
+
module OMF::Web
|
10
|
+
|
11
|
+
# This class provides an interface to a directory based repository
|
12
|
+
# It retrieves, archives and versions content.
|
13
|
+
#
|
14
|
+
class IRodsContentRepository < ContentRepository
|
15
|
+
|
16
|
+
@@irods_repositories = {}
|
17
|
+
|
18
|
+
# Return the repository which is referenced to by elements in 'opts'.
|
19
|
+
#
|
20
|
+
#
|
21
|
+
def self.[](name)
|
22
|
+
unless repo = @@irods_repositories[name.to_sym]
|
23
|
+
raise "Unknown iRODS repo '#{name}'"
|
24
|
+
end
|
25
|
+
repo
|
26
|
+
end
|
27
|
+
|
28
|
+
# Register an existing directory to the system. It will be
|
29
|
+
# consulted for all content url's starting with
|
30
|
+
# 'irods:_top_dir_:'. If 'is_primary' is set to true, it will
|
31
|
+
# become the default repo for all newly created content
|
32
|
+
# in this app.
|
33
|
+
#
|
34
|
+
def self.register_file_repo(name, top_dir, is_primary = false)
|
35
|
+
name = name.to_sym
|
36
|
+
if @@irods_repositories[name]
|
37
|
+
warn "Ignoring repeated registration of iRODS rep '#{name}'"
|
38
|
+
return
|
39
|
+
end
|
40
|
+
repo = @@irods_repositories[name] = self.new(name, top_dir)
|
41
|
+
if is_primary
|
42
|
+
@@primary_repository = repo
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
attr_reader :name, :top_dir
|
47
|
+
|
48
|
+
def initialize(name, opts)
|
49
|
+
super
|
50
|
+
unless @top_dir
|
51
|
+
raise "No top_dir defined (#{opts.keys.inspect})"
|
52
|
+
end
|
53
|
+
@url_prefix = "irods:#{name}:"
|
54
|
+
end
|
55
|
+
|
56
|
+
# Load content described by either a hash or a straightforward path
|
57
|
+
# and return a 'ContentProxy' holding it.
|
58
|
+
#
|
59
|
+
# If descr[:strictly_new] is true, return nil if file for which proxy is requested
|
60
|
+
# already exists.
|
61
|
+
#
|
62
|
+
# @return: Content proxy
|
63
|
+
#
|
64
|
+
def create_content_proxy_for(content_descr)
|
65
|
+
path = _get_path(content_descr)
|
66
|
+
# TODO: Make sure that key is really unique across multiple repositories
|
67
|
+
descr = descr ? descr.dup : {}
|
68
|
+
url = get_url_for_path(path)
|
69
|
+
key = Digest::MD5.hexdigest(url)
|
70
|
+
descr[:url] = url
|
71
|
+
descr[:url_key] = key
|
72
|
+
descr[:path] = path
|
73
|
+
descr[:name] = url # Should be something human digestable
|
74
|
+
if (descr[:strictly_new])
|
75
|
+
return nil if IRODS4r.exists?(path)
|
76
|
+
end
|
77
|
+
proxy = ContentProxy.create(descr, self)
|
78
|
+
return proxy
|
79
|
+
end
|
80
|
+
|
81
|
+
def write(content_descr, content, message)
|
82
|
+
path = _get_path(content_descr)
|
83
|
+
#puts "WRITE PATHS>>> #{path}"
|
84
|
+
f = IRODS4r::File.create(path, false)
|
85
|
+
f.write(content)
|
86
|
+
end
|
87
|
+
|
88
|
+
def read(content_descr)
|
89
|
+
path = _get_path(content_descr)
|
90
|
+
#puts "READ PATHS>>> #{path}"
|
91
|
+
f = IRODS4r::File.create(path, false)
|
92
|
+
f.read()
|
93
|
+
end
|
94
|
+
|
95
|
+
#
|
96
|
+
# Return an array of file names which are in the repository and
|
97
|
+
# match 'search_pattern'
|
98
|
+
#
|
99
|
+
def find_files(search_pattern, opts = {})
|
100
|
+
begin
|
101
|
+
dir = IRODS4r.find(@top_dir)
|
102
|
+
rescue IRODS4r::IRODS4rException
|
103
|
+
return []
|
104
|
+
end
|
105
|
+
res = []
|
106
|
+
_find_files(search_pattern, dir, res, opts[:mime_type])
|
107
|
+
res
|
108
|
+
end
|
109
|
+
|
110
|
+
def _find_files(search_pattern, dir, res, mime_type)
|
111
|
+
dir.list.each do |e|
|
112
|
+
if e.directory?
|
113
|
+
_find_files(search_pattern, e, res, mime_type)
|
114
|
+
else
|
115
|
+
path = e.path
|
116
|
+
if path.match(search_pattern)
|
117
|
+
mt = mime_type_for_file(path)
|
118
|
+
next if mime_type != nil && mime_type != mt
|
119
|
+
res << {:url => get_url_for_path(path), :path => path, #:name => 'foo',
|
120
|
+
:mime_type => mt}
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
res
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
# Return a URL for a path in this repo
|
129
|
+
#
|
130
|
+
def get_url_for_path(path)
|
131
|
+
puts "PATH>>>>> '#{path}:#{path.class}'-'#{@top_dir}:#{@top_dir.class}'"
|
132
|
+
if m = path.match("#{@top_dir}(.*)")
|
133
|
+
path = m[1]
|
134
|
+
end
|
135
|
+
url = @url_prefix + path
|
136
|
+
end
|
137
|
+
|
138
|
+
# HACK ALERT!!!
|
139
|
+
#
|
140
|
+
# This method may be called by an entity which wants to access the content
|
141
|
+
# directly through the file system. In the absence of a FUSE mounted iRODS
|
142
|
+
# repo, we 'iget' the resource to a temporary directory and return that
|
143
|
+
# path. The calling entity needs to be aware that any changes to that file
|
144
|
+
# will NOT show up in iRODS without an iput.
|
145
|
+
#
|
146
|
+
# This should really NOT be necessary. Use FUSE
|
147
|
+
#
|
148
|
+
def absolute_path(content_descr)
|
149
|
+
path = _get_path(content_descr)
|
150
|
+
|
151
|
+
require 'etc'
|
152
|
+
tmp_dir = "#{Dir::tmpdir}/LabWiki-#{Etc.getlogin}"
|
153
|
+
# unless Dir.exists? tmp_dir
|
154
|
+
# Dir.mkdir tmp_dir, 0700
|
155
|
+
# end
|
156
|
+
|
157
|
+
target = File.join(tmp_dir, path)
|
158
|
+
IRODS4r::ICommands.export(path, target)
|
159
|
+
target
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
def _get_path(content_descr)
|
164
|
+
#puts ">>>GET PATH #{content_descr.inspect}"
|
165
|
+
if content_descr.is_a? String
|
166
|
+
path = content_descr.to_s
|
167
|
+
if path.start_with? 'irods:'
|
168
|
+
path = File.join(@top_dir, path.split(':')[2])
|
169
|
+
end
|
170
|
+
elsif content_descr.is_a? Hash
|
171
|
+
descr = content_descr
|
172
|
+
unless path = descr[:path]
|
173
|
+
if url = descr[:url]
|
174
|
+
path = File.join(@top_dir, url.split(':')[2]) # irods:repo_name:path
|
175
|
+
end
|
176
|
+
end
|
177
|
+
unless path
|
178
|
+
raise "Missing 'path' or 'url' in content description (#{descr.inspect})"
|
179
|
+
end
|
180
|
+
path = path.to_s
|
181
|
+
else
|
182
|
+
raise "Unsupported type '#{content_descr.class}'"
|
183
|
+
end
|
184
|
+
unless path
|
185
|
+
raise "Can't find path information in '#{content_descr.inspect}'"
|
186
|
+
end
|
187
|
+
return path
|
188
|
+
end
|
189
|
+
|
190
|
+
end # class
|
191
|
+
end # module
|
@@ -22,8 +22,48 @@ module OMF::Web
|
|
22
22
|
:txt => 'text'
|
23
23
|
}
|
24
24
|
|
25
|
+
REPO_PLUGINS = {
|
26
|
+
git: lambda do |name, opts|
|
27
|
+
require 'omf-web/content/git_repository'
|
28
|
+
return GitContentRepository.new(name, opts)
|
29
|
+
end,
|
30
|
+
file: lambda do |name, opts|
|
31
|
+
require 'omf-web/content/file_repository'
|
32
|
+
return FileContentRepository.new(name, opts)
|
33
|
+
end,
|
34
|
+
irods: lambda do |name, opts|
|
35
|
+
require 'omf-web/content/irods_repository'
|
36
|
+
return IRodsContentRepository.new(name, opts)
|
37
|
+
end,
|
38
|
+
static: lambda do |name, opts|
|
39
|
+
require 'omf-web/content/static_repository'
|
40
|
+
return StaticContentRepository.new(name, opts)
|
41
|
+
end
|
42
|
+
}
|
43
|
+
|
25
44
|
# Repo to be used for all newly created content
|
26
45
|
@@primary_repository = nil
|
46
|
+
@@repositories = {}
|
47
|
+
|
48
|
+
def self.register_repo(name, opts)
|
49
|
+
raise "ArgumentMismatch: Expected Hash, but got #{opts}" unless opts.is_a? Hash
|
50
|
+
|
51
|
+
name = name.to_sym
|
52
|
+
if @@repositories[name]
|
53
|
+
warn "Ignoring repeated registration of repo '#{name}'"
|
54
|
+
return
|
55
|
+
end
|
56
|
+
|
57
|
+
unless type = opts[:type]
|
58
|
+
raise "Missing type in repo opts (#{opts})"
|
59
|
+
end
|
60
|
+
unless repo_creator = REPO_PLUGINS[type.to_sym]
|
61
|
+
raise "Unknown repository type '#{type}'"
|
62
|
+
end
|
63
|
+
@@repositories[name] = r = repo_creator.call(name, opts)
|
64
|
+
@@primary_repository = r if opts[:is_primary]
|
65
|
+
end
|
66
|
+
|
27
67
|
|
28
68
|
# Load content described by either a hash or a straightforward url
|
29
69
|
# and return a 'ContentProxy' holding it.
|
@@ -39,7 +79,13 @@ module OMF::Web
|
|
39
79
|
if url_or_descr.is_a? String
|
40
80
|
url = url_or_descr
|
41
81
|
else
|
42
|
-
|
82
|
+
if (text = url_or_descr[:text])
|
83
|
+
# a bit of a hack for small static text blocks
|
84
|
+
# Much better for maintenance is to use a separate file
|
85
|
+
url = "static:-"
|
86
|
+
else
|
87
|
+
url = url_or_descr[:url]
|
88
|
+
end
|
43
89
|
end
|
44
90
|
unless url
|
45
91
|
throw "Can't find url in '#{url_or_descr.inspect}"
|
@@ -49,19 +95,6 @@ module OMF::Web
|
|
49
95
|
repo.create_content_proxy_for(url_or_descr)
|
50
96
|
end
|
51
97
|
|
52
|
-
def self.find_repo_for(url)
|
53
|
-
parts = url.split(':')
|
54
|
-
case type = parts[0]
|
55
|
-
when 'git'
|
56
|
-
require 'omf-web/content/git_repository'
|
57
|
-
return GitContentRepository[parts[1]]
|
58
|
-
when 'file'
|
59
|
-
require 'omf-web/content/file_repository'
|
60
|
-
return FileContentRepository[parts[1]]
|
61
|
-
else
|
62
|
-
raise "Unknown repo type '#{type}'"
|
63
|
-
end
|
64
|
-
end
|
65
98
|
|
66
99
|
def self.absolute_path_for(url)
|
67
100
|
find_repo_for(url).absolute_path(url)
|
@@ -71,6 +104,16 @@ module OMF::Web
|
|
71
104
|
find_repo_for(url).read(url)
|
72
105
|
end
|
73
106
|
|
107
|
+
def self.find_repo_for(url)
|
108
|
+
parts = url.split(':')
|
109
|
+
name = parts[1]
|
110
|
+
unless repo = @@repositories[name.to_sym]
|
111
|
+
raise "Unknown repo '#{name}'"
|
112
|
+
end
|
113
|
+
return repo
|
114
|
+
end
|
115
|
+
|
116
|
+
|
74
117
|
# Find files whose file name matches 'selector'.
|
75
118
|
#
|
76
119
|
# Supported options:
|
@@ -96,16 +139,29 @@ module OMF::Web
|
|
96
139
|
end
|
97
140
|
|
98
141
|
|
99
|
-
|
100
|
-
|
142
|
+
attr_reader :name, :top_dir
|
143
|
+
|
144
|
+
def initialize(name, opts)
|
145
|
+
@name = name
|
146
|
+
if @top_dir = opts[:top_dir]
|
147
|
+
@top_dir = File.expand_path(@top_dir)
|
148
|
+
end
|
149
|
+
end
|
101
150
|
|
102
|
-
|
103
|
-
|
104
|
-
|
151
|
+
#
|
152
|
+
# Return an array of file names which are in the repository and
|
153
|
+
# match 'search_pattern'
|
154
|
+
#
|
155
|
+
def find_files(search_pattern, opts = {})
|
156
|
+
raise "Missing implementation"
|
105
157
|
end
|
106
158
|
|
107
159
|
|
108
|
-
def mime_type_for_file(
|
160
|
+
def mime_type_for_file(content_descriptor)
|
161
|
+
fname = content_descriptor
|
162
|
+
if content_descriptor.is_a? Hash
|
163
|
+
fname = content_descriptor[:path]
|
164
|
+
end
|
109
165
|
ext = fname.split('.')[-1]
|
110
166
|
mt = MIME_TYPE[ext.to_sym] || 'text'
|
111
167
|
end
|
@@ -126,7 +182,14 @@ module OMF::Web
|
|
126
182
|
File.join(@top_dir, path)
|
127
183
|
end
|
128
184
|
|
185
|
+
def path(content_descr)
|
186
|
+
path = _get_path(content_descr)
|
187
|
+
end
|
129
188
|
|
130
|
-
|
189
|
+
# Return a URL for a path in this repo
|
190
|
+
#
|
191
|
+
def get_url_for_path(path)
|
192
|
+
raise "Missing implementation"
|
193
|
+
end
|
131
194
|
end # class
|
132
195
|
end # module
|
@@ -0,0 +1,61 @@
|
|
1
|
+
|
2
|
+
require 'omf_common/lobject'
|
3
|
+
require 'omf_web'
|
4
|
+
require 'omf-web/content/content_proxy'
|
5
|
+
require 'omf-web/content/repository'
|
6
|
+
require 'singleton'
|
7
|
+
|
8
|
+
module OMF::Web
|
9
|
+
|
10
|
+
# This class provides an interface to a repository of static,
|
11
|
+
# preloaded content.
|
12
|
+
#
|
13
|
+
class StaticContentRepository < ContentRepository
|
14
|
+
|
15
|
+
|
16
|
+
# Load content described by either a hash or a straightforward path
|
17
|
+
# and return a 'ContentProxy' holding it.
|
18
|
+
#
|
19
|
+
# @return: Content proxy
|
20
|
+
#
|
21
|
+
def create_content_proxy_for(content_descr)
|
22
|
+
debug content_descr
|
23
|
+
if content_descr.is_a? String
|
24
|
+
content_descr = {text: content_descr}
|
25
|
+
end
|
26
|
+
descr = content_descr.dup
|
27
|
+
unless text = descr.delete(:text)
|
28
|
+
raise "Missing ':text' declaraton for static content"
|
29
|
+
end
|
30
|
+
|
31
|
+
key = Digest::MD5.hexdigest(text)
|
32
|
+
@content[key] = text
|
33
|
+
descr[:url] = url = "static:" + key
|
34
|
+
descr[:url_key] = key
|
35
|
+
descr[:name] = content_descr[:name] || url # Should be something human digestable
|
36
|
+
proxy = ContentProxy.create(descr, self)
|
37
|
+
return proxy
|
38
|
+
end
|
39
|
+
|
40
|
+
def read(content_descr)
|
41
|
+
debug "READ: #{content_descr}"
|
42
|
+
@content[content_descr[:url_key]] || 'Unknown'
|
43
|
+
end
|
44
|
+
|
45
|
+
def write(content_descr, content, message)
|
46
|
+
raise "READ ONLY"
|
47
|
+
end
|
48
|
+
|
49
|
+
def mime_type_for_file(content_descriptor)
|
50
|
+
content_descriptor[:mime_type] || 'text'
|
51
|
+
end
|
52
|
+
|
53
|
+
def initialize(name, opts)
|
54
|
+
super
|
55
|
+
@content = {}
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
end # class
|
61
|
+
end # module
|
@@ -124,7 +124,7 @@ module OMF::Web
|
|
124
124
|
block.call :added, rows
|
125
125
|
end
|
126
126
|
@data_source.on_content_changed(block.object_id) do |action, rows|
|
127
|
-
debug "on_changed: #{action}: #{rows.inspect}"
|
127
|
+
#debug "on_changed: #{action}: #{rows.inspect}"
|
128
128
|
block.call action, rows
|
129
129
|
end
|
130
130
|
end
|
@@ -142,7 +142,7 @@ module OMF::Web
|
|
142
142
|
sid = Thread.current["sessionID"]
|
143
143
|
opts = opts.dup
|
144
144
|
opts[:name] = @name
|
145
|
-
opts[:schema] = @data_source.schema
|
145
|
+
opts[:schema] = @data_source.schema.describe
|
146
146
|
opts[:update_url] = "/_update/#{@name}?sid=#{sid}"
|
147
147
|
opts[:sid] = sid
|
148
148
|
unless opts[:slice] # don't send any data if this is a sliced one
|
@@ -150,7 +150,7 @@ module OMF::Web
|
|
150
150
|
opts[:rows] = []
|
151
151
|
opts[:offset] = @data_source.offset
|
152
152
|
end
|
153
|
-
#puts "to_java2>>>>> #{opts.
|
153
|
+
#puts "to_java2>>>>> #{opts.inspect}"
|
154
154
|
|
155
155
|
%{
|
156
156
|
OML.data_sources.register(#{opts.to_json});
|