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
@@ -0,0 +1,62 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
|
4
|
+
# Simple tab showing a line chart with supporting table
|
5
|
+
#
|
6
|
+
|
7
|
+
server:
|
8
|
+
name: 'Simple Demo'
|
9
|
+
port: 4050
|
10
|
+
|
11
|
+
data_sources:
|
12
|
+
- id: signal
|
13
|
+
table: wave
|
14
|
+
database:
|
15
|
+
id: sample
|
16
|
+
url: sqlite://sample.sq3
|
17
|
+
|
18
|
+
repositories:
|
19
|
+
- id: simple
|
20
|
+
type: file
|
21
|
+
top_dir: .
|
22
|
+
|
23
|
+
widgets:
|
24
|
+
- id: main
|
25
|
+
name: Main
|
26
|
+
top_level: true
|
27
|
+
priority: 900
|
28
|
+
type: layout/two_columns/33_66
|
29
|
+
left:
|
30
|
+
- name: Introduction
|
31
|
+
type: text
|
32
|
+
content:
|
33
|
+
url: file:simple:introduction.md
|
34
|
+
right:
|
35
|
+
- type: layout/stacked
|
36
|
+
info: This widget shows the output measurements of three stacked generators.
|
37
|
+
widgets:
|
38
|
+
- name: Signal
|
39
|
+
type: data/line_chart3
|
40
|
+
data_source:
|
41
|
+
name: signal
|
42
|
+
mapping:
|
43
|
+
x_axis:
|
44
|
+
property: t
|
45
|
+
y_axis:
|
46
|
+
property: y
|
47
|
+
max: 2.0
|
48
|
+
group_by: oml_sender
|
49
|
+
axis:
|
50
|
+
x:
|
51
|
+
legend: Time (sec)
|
52
|
+
y:
|
53
|
+
legend: V
|
54
|
+
ticks:
|
55
|
+
format: ".1f"
|
56
|
+
|
57
|
+
- name: Table
|
58
|
+
type: data/table2
|
59
|
+
data_source:
|
60
|
+
name: signal
|
61
|
+
|
62
|
+
|
@@ -0,0 +1,66 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
|
4
|
+
# Simple tab showing a line chart with supporting table
|
5
|
+
#
|
6
|
+
|
7
|
+
server:
|
8
|
+
name: 'Simple Demo'
|
9
|
+
port: 4050
|
10
|
+
|
11
|
+
data_sources:
|
12
|
+
- id: signal
|
13
|
+
table: wave
|
14
|
+
dynamic: 2 # Check every 2 seconds
|
15
|
+
limit: 5 # Fetch 5 rows each time
|
16
|
+
database:
|
17
|
+
id: sample
|
18
|
+
url: sqlite://sample.sq3
|
19
|
+
|
20
|
+
repositories:
|
21
|
+
- id: simple
|
22
|
+
type: file
|
23
|
+
top_dir: .
|
24
|
+
|
25
|
+
widgets:
|
26
|
+
- id: main
|
27
|
+
name: Main
|
28
|
+
top_level: true
|
29
|
+
priority: 900
|
30
|
+
type: layout/two_columns/33_66
|
31
|
+
left:
|
32
|
+
- name: Introduction
|
33
|
+
type: text
|
34
|
+
content:
|
35
|
+
url: file:simple:introduction.md
|
36
|
+
right:
|
37
|
+
- type: layout/stacked
|
38
|
+
info: This widget shows the output measurements of three stacked generators.
|
39
|
+
widgets:
|
40
|
+
- name: Signal
|
41
|
+
type: data/line_chart3
|
42
|
+
data_source:
|
43
|
+
name: signal
|
44
|
+
dynamic: 2
|
45
|
+
mapping:
|
46
|
+
x_axis:
|
47
|
+
property: t
|
48
|
+
y_axis:
|
49
|
+
property: y
|
50
|
+
max: 2.0
|
51
|
+
group_by: oml_sender
|
52
|
+
axis:
|
53
|
+
x:
|
54
|
+
legend: Time (sec)
|
55
|
+
y:
|
56
|
+
legend: V
|
57
|
+
ticks:
|
58
|
+
format: ".1f"
|
59
|
+
|
60
|
+
- name: Table
|
61
|
+
type: data/table2
|
62
|
+
data_source:
|
63
|
+
name: signal
|
64
|
+
dynamic: 2
|
65
|
+
|
66
|
+
|
data/lib/irods4r/file.rb
CHANGED
@@ -2,15 +2,15 @@
|
|
2
2
|
require 'irods4r/directory'
|
3
3
|
|
4
4
|
module IRODS4r
|
5
|
-
|
5
|
+
|
6
6
|
#class NotFoundException < Exception; end
|
7
|
-
class NoFileException < Exception; end
|
8
|
-
class FileExistsException < Exception; end
|
9
|
-
|
7
|
+
class NoFileException < Exception; end
|
8
|
+
class FileExistsException < Exception; end
|
9
|
+
|
10
10
|
# This class proxies a file in an iRODS environment
|
11
11
|
#
|
12
12
|
class File
|
13
|
-
|
13
|
+
|
14
14
|
# Create a file resource 'path'. If 'must_not_exist' is true,
|
15
15
|
# throw exception if resource already exists.
|
16
16
|
#
|
@@ -20,34 +20,35 @@ module IRODS4r
|
|
20
20
|
end
|
21
21
|
self.new(path, opts)
|
22
22
|
end
|
23
|
-
|
24
|
-
|
23
|
+
|
24
|
+
|
25
25
|
# Return the content of this file
|
26
26
|
def read()
|
27
|
-
ICommands.read(@path)
|
27
|
+
ICommands.read(@path, @ticket)
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
# Write content to this file.
|
31
31
|
#
|
32
32
|
# WARN: This will overwrite any previous content
|
33
33
|
#
|
34
34
|
def write(content)
|
35
|
-
ICommands.write(@path, content)
|
35
|
+
ICommands.write(@path, content, @ticket)
|
36
36
|
end
|
37
37
|
|
38
38
|
def file?
|
39
39
|
return true
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
def directory?
|
43
43
|
return false
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
attr_reader :path
|
47
|
-
|
47
|
+
|
48
48
|
private
|
49
49
|
def initialize(path, opts = {})
|
50
50
|
@path = path
|
51
|
+
@ticket = opts[:ticket]
|
51
52
|
end
|
52
53
|
end
|
53
|
-
end
|
54
|
+
end
|
data/lib/irods4r/icommands.rb
CHANGED
@@ -2,62 +2,62 @@
|
|
2
2
|
require 'irods4r'
|
3
3
|
|
4
4
|
module IRODS4r
|
5
|
-
|
5
|
+
|
6
6
|
# This module interfaces directly with the IRODS system
|
7
7
|
#
|
8
8
|
module ICommands
|
9
9
|
class ICommandException < IRODS4rException; end
|
10
|
-
|
11
|
-
# Return the list of files found at 'path'.
|
12
|
-
def self.ls(path)
|
13
|
-
r = `ils #{path}`
|
10
|
+
|
11
|
+
# Return the list of files found at 'path'.
|
12
|
+
def self.ls(path, ticket = nil)
|
13
|
+
r = `ils #{"-t #{ticket}" if ticket} #{path}`
|
14
14
|
#raise ICommandException.new($?) unless $?.exitstatus == 0
|
15
15
|
if r.empty?
|
16
16
|
raise NotFoundException.new("Can't find resource '#{path}'")
|
17
|
-
end
|
17
|
+
end
|
18
18
|
r.lines
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
# Return content of resource at 'path'
|
22
22
|
#
|
23
|
-
def self.read(path)
|
23
|
+
def self.read(path, ticket = nil)
|
24
24
|
f = Tempfile.new('irods4r')
|
25
|
-
`iget -f #{path} #{f.path}`
|
25
|
+
`iget -f #{"-t #{ticket}" if ticket} #{path} #{f.path}`
|
26
26
|
raise ICommandException.new($?) unless $?.exitstatus == 0
|
27
27
|
content = f.read
|
28
28
|
f.close
|
29
29
|
f.unlink
|
30
30
|
content
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
# Return content of resource at 'path'
|
34
34
|
#
|
35
|
-
def self.write(path, content)
|
35
|
+
def self.write(path, content, ticket = nil)
|
36
36
|
f = Tempfile.new('irods4r')
|
37
37
|
f.write(content)
|
38
38
|
f.close
|
39
|
-
`iput -f #{f.path} #{path}`
|
39
|
+
`iput -f #{"-t #{ticket}" if ticket} #{f.path} #{path}`
|
40
40
|
raise ICommandException.new($?) unless $?.exitstatus == 0
|
41
41
|
f.unlink
|
42
42
|
end
|
43
43
|
|
44
|
-
def self.exist?(path)
|
45
|
-
`ils #{path}`
|
44
|
+
def self.exist?(path, ticket = nil)
|
45
|
+
`ils #{"-t #{ticket}" if ticket} #{path}`
|
46
46
|
$?.exitstatus == 0
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
# Copy the resource at 'path' in iRODS to 'file_path'
|
50
50
|
# in the local file system.
|
51
51
|
#
|
52
|
-
def self.export(path, file_path, create_parent_path = true)
|
52
|
+
def self.export(path, file_path, create_parent_path = true, ticket = nil)
|
53
53
|
#puts ">>>> #{path} -> #{file_path}"
|
54
54
|
if create_parent_path
|
55
55
|
require 'fileutils'
|
56
56
|
FileUtils.mkpath ::File.dirname(file_path)
|
57
57
|
end
|
58
|
-
`iget -f #{path} #{file_path}`
|
58
|
+
`iget -f #{"-t #{ticket}" if ticket} #{path} #{file_path}`
|
59
59
|
raise ICommandException.new($?) unless $?.exitstatus == 0
|
60
60
|
end
|
61
61
|
end #module
|
62
62
|
end # module
|
63
|
-
|
63
|
+
|
data/lib/irods4r.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
|
2
2
|
|
3
3
|
module IRODS4r
|
4
|
-
|
4
|
+
|
5
5
|
class IRODS4rException < Exception; end
|
6
6
|
class NotFoundException < IRODS4rException; end
|
7
|
-
class NoDirectoryException < IRODS4rException; end
|
7
|
+
class NoDirectoryException < IRODS4rException; end
|
8
8
|
|
9
9
|
# Return a IRODS4r object for 'irodsPath' if it exists.
|
10
10
|
#
|
@@ -12,23 +12,23 @@ module IRODS4r
|
|
12
12
|
# @param [Hash] opts Options to use for establishing context
|
13
13
|
# @return [Directory|File]
|
14
14
|
#
|
15
|
-
def self.find(irodsPath = ".", opts = {})
|
16
|
-
r = ICommands.ls(irodsPath)
|
15
|
+
def self.find(irodsPath = ".", opts = {}, ticket = nil)
|
16
|
+
r = ICommands.ls(irodsPath, ticket)
|
17
17
|
name = r.to_a[0].strip
|
18
18
|
if name.end_with? ':'
|
19
19
|
Directory.new(name[0 ... -1])
|
20
20
|
else
|
21
21
|
File.new(name)
|
22
|
-
end
|
22
|
+
end
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
# Return true if 'path' exists
|
26
|
-
def self.exists?(path)
|
27
|
-
ICommands.exist?(path)
|
26
|
+
def self.exists?(path, ticket = nil)
|
27
|
+
ICommands.exist?(path, ticket)
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
31
|
require 'irods4r/directory'
|
32
32
|
require 'irods4r/file'
|
33
33
|
require 'irods4r/icommands'
|
34
|
-
|
34
|
+
|
data/lib/omf-web/config.ru
CHANGED
@@ -1,16 +1,19 @@
|
|
1
1
|
|
2
2
|
require 'omf_common/lobject'
|
3
|
+
require 'rack/accept'
|
3
4
|
|
4
5
|
use ::Rack::ShowExceptions
|
5
6
|
#use ::Rack::Lint
|
7
|
+
use Rack::Accept
|
6
8
|
|
7
9
|
OMF::Web::Runner.instance.life_cycle(:pre_rackup)
|
8
10
|
options = OMF::Web::Runner.instance.options
|
11
|
+
auth_opts = options[:authentication] || {required: false}
|
9
12
|
|
10
13
|
require 'omf-web/rack/session_authenticator'
|
11
14
|
use OMF::Web::Rack::SessionAuthenticator, #:expire_after => 10,
|
12
|
-
|
13
|
-
:
|
15
|
+
login_page_url: auth_opts[:required] ? (auth_opts[:login_url] || '/content/login') : nil,
|
16
|
+
no_session: ['^/resource/', '^/auth']
|
14
17
|
|
15
18
|
map "/resource/vendor/" do
|
16
19
|
require 'omf-web/rack/multi_file'
|
@@ -52,25 +55,47 @@ end
|
|
52
55
|
# run OMF::Web::Rack::WidgetMapper.new(options)
|
53
56
|
# end
|
54
57
|
|
55
|
-
map '/login' do
|
58
|
+
map '/auth/login' do
|
56
59
|
handler = Proc.new do |env|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
60
|
+
req = ::Rack::Request.new(env)
|
61
|
+
accept = env['rack-accept.request']
|
62
|
+
begin
|
63
|
+
OMF::Web::Rack::SessionAuthenticator.authenticate_with(req)
|
64
|
+
rescue OMF::Web::Rack::AuthenticationFailedException => ax
|
65
|
+
if accept.media_type?('application/json')
|
66
|
+
body = {authenticated: false, message: ax.to_s}
|
67
|
+
next [200, {"Content-Type" => "application/json"}, body.to_json]
|
68
|
+
else
|
69
|
+
url = auth_opts[:login_url] || '/content/login'
|
70
|
+
url = "#{url}?error=#{URI.encode ax.to_s}"
|
71
|
+
next [307, {'Location' => url, "Content-Type" => ""}, ['Next window!']]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
accept = env['rack-accept.request']
|
76
|
+
redirect_url = "/?#{rand(10e15)}" # avoid some ugly URL caching
|
77
|
+
if accept.media_type?('application/json')
|
78
|
+
body = {authenticated: true, redirect: redirect_url}
|
79
|
+
[200, {"Content-Type" => "application/json"}, body.to_json]
|
80
|
+
else
|
81
|
+
[307, {'Location' => redirect_url, "Content-Type" => ""}, ['Next window!']]
|
82
|
+
end
|
66
83
|
end
|
67
84
|
run handler
|
68
85
|
end
|
69
86
|
|
70
|
-
map '/logout' do
|
87
|
+
map '/auth/logout' do
|
71
88
|
handler = Proc.new do |env|
|
72
89
|
OMF::Web::Rack::SessionAuthenticator.logout
|
73
|
-
|
90
|
+
|
91
|
+
accept = env['rack-accept.request']
|
92
|
+
redirect_url = "/?#{rand(10e15)}" # avoid some ugly URL caching
|
93
|
+
if accept.media_type?('application/json')
|
94
|
+
body = {authenticated: false, redirect: redirect_url}
|
95
|
+
[200, {"Content-Type" => "application/json"}, body.to_json]
|
96
|
+
else
|
97
|
+
[307, {'Location' => redirect_url, "Content-Type" => ""}, ['Next window!']]
|
98
|
+
end
|
74
99
|
end
|
75
100
|
run handler
|
76
101
|
end
|
@@ -80,9 +105,9 @@ map "/" do
|
|
80
105
|
req = ::Rack::Request.new(env)
|
81
106
|
case req.path_info
|
82
107
|
when '/'
|
83
|
-
[
|
108
|
+
[307, {'Location' => '/tab', "Content-Type" => ""}, ['Next window!']]
|
84
109
|
when '/favicon.ico'
|
85
|
-
[
|
110
|
+
[307, {'Location' => '/resource/image/favicon.ico', "Content-Type" => ""}, ['Next window!']]
|
86
111
|
else
|
87
112
|
OMF::Common::Loggable.logger('rack').warn "Can't handle request '#{req.path_info}'"
|
88
113
|
[401, {"Content-Type" => ""}, "Sorry!"]
|
@@ -12,10 +12,10 @@ module OMF::Web
|
|
12
12
|
# This class provides an interface to a GIT repository
|
13
13
|
# It retrieves, archives and versions content.
|
14
14
|
#
|
15
|
-
class GitContentRepository < ContentRepository
|
16
|
-
|
15
|
+
class GitContentRepository < ContentRepository
|
16
|
+
|
17
17
|
# @@git_repositories = {}
|
18
|
-
#
|
18
|
+
#
|
19
19
|
# # Return the repository which is referenced to by elements in 'opts'.
|
20
20
|
# #
|
21
21
|
# #
|
@@ -25,8 +25,8 @@ module OMF::Web
|
|
25
25
|
# end
|
26
26
|
# repo
|
27
27
|
# end
|
28
|
-
|
29
|
-
# Register an existing GIT repo to the system. It will be
|
28
|
+
|
29
|
+
# Register an existing GIT repo to the system. It will be
|
30
30
|
# consulted for all content url's strarting with
|
31
31
|
# 'git:_top_dir_:'. If 'is_primary' is set to true, it will
|
32
32
|
# become the default repo for all newly created content
|
@@ -43,7 +43,7 @@ module OMF::Web
|
|
43
43
|
# @@primary_repository = repo
|
44
44
|
# end
|
45
45
|
# end
|
46
|
-
|
46
|
+
|
47
47
|
# def self.read_content(url, opts)
|
48
48
|
# unless (a = url.split(':')).length == 3
|
49
49
|
# raise "Expected 'git:some_name:some_path', but got '#{url}'"
|
@@ -56,13 +56,13 @@ module OMF::Web
|
|
56
56
|
# end
|
57
57
|
|
58
58
|
attr_reader :name, :top_dir
|
59
|
-
|
59
|
+
|
60
60
|
def initialize(name, opts)
|
61
61
|
super
|
62
62
|
@repo = Grit::Repo.new(@top_dir)
|
63
63
|
@url_prefix = "git:#{@name}:"
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
#
|
67
67
|
# Create a URL for a file with 'path' in.
|
68
68
|
# If 'strictly_new' is true, returns nil if 'path' already exists.
|
@@ -72,8 +72,8 @@ module OMF::Web
|
|
72
72
|
# # TODO: Need to add code to select proper repository
|
73
73
|
# return GitContentRepository.create_url(path, strictly_new)
|
74
74
|
# end
|
75
|
-
|
76
|
-
|
75
|
+
|
76
|
+
|
77
77
|
# Load content described by either a hash or a straightforward path
|
78
78
|
# and return a 'ContentProxy' holding it.
|
79
79
|
#
|
@@ -88,9 +88,9 @@ module OMF::Web
|
|
88
88
|
url = @url_prefix + path
|
89
89
|
key = Digest::MD5.hexdigest(url)
|
90
90
|
descr = {}
|
91
|
-
descr[:url] = url
|
91
|
+
descr[:url] = url
|
92
92
|
descr[:url_key] = key
|
93
|
-
descr[:path] = path
|
93
|
+
descr[:path] = path
|
94
94
|
descr[:name] = url # Should be something human digestable
|
95
95
|
if (descr[:strictly_new])
|
96
96
|
Dir.chdir(@top_dir) do
|
@@ -100,31 +100,31 @@ module OMF::Web
|
|
100
100
|
proxy = ContentProxy.create(descr, self)
|
101
101
|
return proxy
|
102
102
|
end
|
103
|
-
|
103
|
+
|
104
104
|
def write(content_descr, content, message)
|
105
105
|
path = _get_path(content_descr)
|
106
106
|
Dir.chdir(@top_dir) do
|
107
|
-
unless File.writable?(path)
|
107
|
+
unless File.writable?(path) || File.writable?(File.dirname(path))
|
108
108
|
raise "Cannot write to file '#{path}'"
|
109
109
|
end
|
110
110
|
f = File.open(path, 'w')
|
111
111
|
f.write(content)
|
112
112
|
f.close
|
113
|
-
|
113
|
+
|
114
114
|
@repo.add(path)
|
115
115
|
# TODO: Should set info about committing user which should be in thread context
|
116
|
-
@repo.commit_index(message || 'no message')
|
116
|
+
@repo.commit_index(message || 'no message')
|
117
117
|
end
|
118
118
|
end
|
119
|
-
|
119
|
+
|
120
120
|
# Return a URL for a path in this repo
|
121
|
-
#
|
121
|
+
#
|
122
122
|
def get_url_for_path(path)
|
123
123
|
@url_prefix + path
|
124
124
|
end
|
125
|
-
|
126
|
-
|
127
|
-
|
125
|
+
|
126
|
+
|
127
|
+
|
128
128
|
#
|
129
129
|
# Return an array of file names which are in the repository and
|
130
130
|
# match 'search_pattern'
|
@@ -134,13 +134,13 @@ module OMF::Web
|
|
134
134
|
tree = @repo.tree
|
135
135
|
res = []
|
136
136
|
fs = _find_files(search_pattern, tree, nil, res)
|
137
|
-
|
137
|
+
|
138
138
|
if (mt = opts[:mime_type])
|
139
139
|
fs = fs.select { |f| f[:mime_type] == mt }
|
140
140
|
end
|
141
141
|
fs
|
142
142
|
end
|
143
|
-
|
143
|
+
|
144
144
|
def _find_files(search_pattern, tree, dir_path, res)
|
145
145
|
tree.contents.each do |e|
|
146
146
|
d = e.name
|
@@ -151,11 +151,12 @@ module OMF::Web
|
|
151
151
|
else
|
152
152
|
if long_name.match(search_pattern)
|
153
153
|
mt = mime_type_for_file(e.name)
|
154
|
-
path = @url_prefix + long_name
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
154
|
+
#path = @url_prefix + long_name
|
155
|
+
path = long_name
|
156
|
+
res << {path: path, url: get_url_for_path(path), name: e.name,
|
157
|
+
mime_type: mt,
|
158
|
+
#:id => Base64.encode64(long_name).gsub("\n", ''),
|
159
|
+
size: e.size, blob: e.id}
|
159
160
|
end
|
160
161
|
# name = e.name
|
161
162
|
# if File.fnmatch(search_pattern, long_name)
|
@@ -165,7 +166,7 @@ module OMF::Web
|
|
165
166
|
end
|
166
167
|
res
|
167
168
|
end
|
168
|
-
|
169
|
+
|
169
170
|
def _get_path(content_descr)
|
170
171
|
if content_descr.is_a? String
|
171
172
|
path = content_descr.to_s
|
@@ -191,6 +192,6 @@ module OMF::Web
|
|
191
192
|
end
|
192
193
|
return path
|
193
194
|
end
|
194
|
-
|
195
|
+
|
195
196
|
end # class
|
196
|
-
end # module
|
197
|
+
end # module
|