rrd-grapher 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.
Files changed (122) hide show
  1. data/.gitignore +9 -0
  2. data/.rvmrc +1 -0
  3. data/Gemfile +11 -0
  4. data/Guardfile +123 -0
  5. data/README.md +91 -0
  6. data/Rakefile +42 -0
  7. data/example_app/Gemfile +9 -0
  8. data/example_app/Guardfile +18 -0
  9. data/example_app/app.rb +38 -0
  10. data/example_app/assets/javascripts/available_rrds.coffee +13 -0
  11. data/example_app/assets/javascripts/collectd.coffee +48 -0
  12. data/example_app/config.ru +9 -0
  13. data/example_app/public/.gitignore +1 -0
  14. data/example_app/public/chosen/chosen-sprite.png +0 -0
  15. data/example_app/public/chosen/chosen.css +340 -0
  16. data/example_app/public/chosen/chosen.jquery.js +786 -0
  17. data/example_app/public/chosen/chosen.jquery.min.js +10 -0
  18. data/example_app/public/javascripts/available_rrds.js +16 -0
  19. data/example_app/public/javascripts/collectd.js +64 -0
  20. data/example_app/public/javascripts/jquery.timeago.js +148 -0
  21. data/example_app/public/stylesheets/Aristo/images/bg_fallback.png +0 -0
  22. data/example_app/public/stylesheets/Aristo/images/icon_sprite.png +0 -0
  23. data/example_app/public/stylesheets/Aristo/images/progress_bar.gif +0 -0
  24. data/example_app/public/stylesheets/Aristo/images/slider_handles.png +0 -0
  25. data/example_app/public/stylesheets/Aristo/images/ui-icons_222222_256x240.png +0 -0
  26. data/example_app/public/stylesheets/Aristo/images/ui-icons_454545_256x240.png +0 -0
  27. data/example_app/public/stylesheets/Aristo/theme.css +738 -0
  28. data/example_app/views/available_rrds.haml +26 -0
  29. data/example_app/views/collectd.haml +30 -0
  30. data/example_app/views/layout.haml +19 -0
  31. data/example_app/views/stylesheets/available_rrds.scss +7 -0
  32. data/example_notifier/Gemfile +2 -0
  33. data/example_notifier/notifier.rb +25 -0
  34. data/lib/rrd-grapher/assets/javascripts/app-dev.js +20 -0
  35. data/lib/rrd-grapher/assets/javascripts/app.js +20 -0
  36. data/lib/rrd-grapher/assets/javascripts/classes/format.coffee +35 -0
  37. data/lib/rrd-grapher/assets/javascripts/classes/graph.coffee +306 -0
  38. data/lib/rrd-grapher/assets/javascripts/classes/graph_definition.coffee +216 -0
  39. data/lib/rrd-grapher/assets/javascripts/classes/serie.coffee +13 -0
  40. data/lib/rrd-grapher/assets/javascripts/classes/size.coffee +5 -0
  41. data/lib/rrd-grapher/assets/javascripts/classes/static_line.coffee +44 -0
  42. data/lib/rrd-grapher/assets/javascripts/classes/time.coffee +17 -0
  43. data/lib/rrd-grapher/notifier/alarm_manager.rb +190 -0
  44. data/lib/rrd-grapher/notifier/alarm_trigger.rb +187 -0
  45. data/lib/rrd-grapher/notifier/alarms.rb +79 -0
  46. data/lib/rrd-grapher/notifier/collectdrb.rb +86 -0
  47. data/lib/rrd-grapher/notifier/data_struct.rb +46 -0
  48. data/lib/rrd-grapher/notifier/default_user_handler.rb +36 -0
  49. data/lib/rrd-grapher/notifier/parsers/bindata_parser.rb +144 -0
  50. data/lib/rrd-grapher/notifier/parsers/ruby_parser.rb +134 -0
  51. data/lib/rrd-grapher/notifier/structures.rb +80 -0
  52. data/lib/rrd-grapher/notifier.rb +87 -0
  53. data/lib/rrd-grapher/public/favicon.ico +0 -0
  54. data/lib/rrd-grapher/public/javascripts/app-dev.js +13709 -0
  55. data/lib/rrd-grapher/public/javascripts/app.js +4057 -0
  56. data/lib/rrd-grapher/public/javascripts/backbone/backbone.js +1155 -0
  57. data/lib/rrd-grapher/public/javascripts/backbone/backbone.min.js +32 -0
  58. data/lib/rrd-grapher/public/javascripts/backbone/underscore.js +841 -0
  59. data/lib/rrd-grapher/public/javascripts/backbone/underscore.min.js +27 -0
  60. data/lib/rrd-grapher/public/javascripts/classes/format.js +42 -0
  61. data/lib/rrd-grapher/public/javascripts/classes/graph.js +360 -0
  62. data/lib/rrd-grapher/public/javascripts/classes/graph_definition.js +298 -0
  63. data/lib/rrd-grapher/public/javascripts/classes/serie.js +32 -0
  64. data/lib/rrd-grapher/public/javascripts/classes/size.js +7 -0
  65. data/lib/rrd-grapher/public/javascripts/classes/static_line.js +48 -0
  66. data/lib/rrd-grapher/public/javascripts/classes/time.js +17 -0
  67. data/lib/rrd-grapher/public/javascripts/flot/.gitignore +4 -0
  68. data/lib/rrd-grapher/public/javascripts/flot/excanvas.min.js +1 -0
  69. data/lib/rrd-grapher/public/javascripts/flot/jquery.colorhelpers.min.js +1 -0
  70. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.crosshair.min.js +1 -0
  71. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.fillbetween.min.js +1 -0
  72. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.image.min.js +1 -0
  73. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.js +2604 -0
  74. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.navigate.min.js +1 -0
  75. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.pie.min.js +1 -0
  76. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.resize.min.js +1 -0
  77. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.selection.js +345 -0
  78. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.selection.min.js +1 -0
  79. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.stack.min.js +1 -0
  80. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.symbol.min.js +1 -0
  81. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.threshold.min.js +1 -0
  82. data/lib/rrd-grapher/public/javascripts/jquery/jquery-1.6.2.js +8981 -0
  83. data/lib/rrd-grapher/public/javascripts/jquery/jquery-1.6.2.min.js +18 -0
  84. data/lib/rrd-grapher/public/javascripts/jquery/jquery-ui-1.8.11.min.js +783 -0
  85. data/lib/rrd-grapher/public/javascripts/jquery/jquery.showtime.js +63 -0
  86. data/lib/rrd-grapher/public/javascripts/jquery/jquery.tpl.min.js +10 -0
  87. data/lib/rrd-grapher/resources.rb +14 -0
  88. data/lib/rrd-grapher/rrd.rb +238 -0
  89. data/lib/rrd-grapher/rrd_server.rb +78 -0
  90. data/lib/rrd-grapher/version.rb +4 -0
  91. data/lib/rrd-grapher/views/stylesheets/app.scss +111 -0
  92. data/lib/rrd-grapher.rb +12 -0
  93. data/rrd-grapher.gemspec +47 -0
  94. data/spec/common.rb +70 -0
  95. data/spec/data/myrouter.rrd +0 -0
  96. data/spec/data/subdata.rrd +0 -0
  97. data/spec/data/test.rrd +0 -0
  98. data/spec/factories.rb +23 -0
  99. data/spec/javascripts/helpers/jasmine-jquery-1.3.0.js +283 -0
  100. data/spec/javascripts/source/format_spec.coffee +18 -0
  101. data/spec/javascripts/source/graph_def_spec.coffee +27 -0
  102. data/spec/javascripts/source/graph_spec.coffee +63 -0
  103. data/spec/javascripts/source/serie_spec.coffee +28 -0
  104. data/spec/javascripts/source/static_line_spec.coffee +13 -0
  105. data/spec/javascripts/source/time_spec.coffee +26 -0
  106. data/spec/javascripts/support/jasmine.yml +78 -0
  107. data/spec/javascripts/support/jasmine_config.rb +23 -0
  108. data/spec/javascripts/support/jasmine_runner.rb +32 -0
  109. data/spec/unit/alarm_manager_spec.rb +252 -0
  110. data/spec/unit/alarm_trigger_spec.rb +26 -0
  111. data/spec/unit/data_struct_spec.rb +55 -0
  112. data/spec/unit/notifier_spec.rb +45 -0
  113. data/spec/unit/parsers/bindata_parser_spec.rb +184 -0
  114. data/spec/unit/parsers/ruby_parser_spec.rb +184 -0
  115. data/spec/unit/rrd_spec.rb +50 -0
  116. data/spec/unit/structures_spec.rb +28 -0
  117. data/tests/4series.rrd +0 -0
  118. data/tests/analyze_rrd.rb +62 -0
  119. data/tests/exact.rrd +0 -0
  120. data/tests/exact2.rrd +0 -0
  121. data/tests/filler.rb +46 -0
  122. metadata +414 -0
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ gems/
2
+ doc/
3
+ coverage/
4
+ .bundle/
5
+ public/javascripts/generated/*.js
6
+ spec/javascripts/*.js
7
+ .sass-cache/
8
+ .yardoc/
9
+ Gemfile.lock
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.2-p290
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+
2
+ source :rubygems
3
+
4
+ # underscore.js makes sprockets raise an error wil latest 1.x version..
5
+ #gem 'sprockets', :git => 'git://github.com/matehat/sprockets.git'
6
+ gem 'sprockets', :git => 'git://github.com/salbito/sprockets.git', :branch => '1.0.x'
7
+ # gem 'bacon', :git => 'git://github.com/schmurfy/bacon.git'
8
+ gem 'schmurfy-bacon'
9
+ gem "bindata", "~> 1.4.2"
10
+
11
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,123 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ require 'sprockets'
5
+
6
+ guard 'yard' do
7
+ watch(%r{lib/.+\.rb})
8
+ end
9
+
10
+
11
+ # for the grapher
12
+ guard 'coffeescript',
13
+ :input => 'lib/rrd-grapher/assets/javascripts',
14
+ :output => 'lib/rrd-grapher/public/javascripts'
15
+
16
+ guard 'coffeescript',
17
+ :input => 'spec/javascripts/source',
18
+ :output => 'spec/javascripts'
19
+
20
+ guard 'sprockets', :destination => "lib/rrd-grapher/public/javascripts" do
21
+ watch (%r{lib/rrd-grapher/assets/javascripts/app.js})
22
+ watch (%r{lib/rrd-grapher/assets/javascripts/app-dev.js})
23
+ end
24
+
25
+
26
+ guard 'livereload', :apply_js_live => false do
27
+ watch(%r{^spec/javascripts/.+\.js$})
28
+ watch(%r{^lib/rrd-grapher/public/javascripts/.+\.js$})
29
+ watch(%r{^lib/rrd-grapher/views/stylesheets/.+\.scss$})
30
+ end
31
+
32
+
33
+
34
+
35
+
36
+ require 'bacon'
37
+ require 'guard/guard'
38
+
39
+ module ::Guard
40
+ class Bacon < Guard
41
+
42
+ def initialize(watchers=[], options={})
43
+ super
44
+ ::Bacon.extend(::Bacon::TestUnitOutput)
45
+ end
46
+
47
+ def start
48
+ puts "Guard::Bacon started."
49
+ true
50
+ end
51
+
52
+ # Called on Ctrl-C signal (when Guard quits)
53
+ def stop
54
+ true
55
+ end
56
+
57
+ # Called on Ctrl-Z signal
58
+ def reload
59
+ true
60
+ end
61
+
62
+ # Called on Ctrl-\ signal
63
+ # This method should be principally used for long action like running all specs/tests/...
64
+ def run_all
65
+ true
66
+ end
67
+
68
+ SPEC_FILE ||= /_spec\.rb$/.freeze
69
+ FILE_REG ||= %r{^lib/rrd-grapher/(?:[^/]+/)?(.*)\.rb$}.freeze
70
+
71
+ def run_spec(path)
72
+ if File.exists?(path)
73
+ pid = Kernel.fork do
74
+ puts " *** Running spec: #{path} ***"
75
+ counters = ::Bacon.run_file(path)
76
+ # system "bundle exec bacon -o TestUnit #{path}"
77
+ # {:installed_summary=>1, :specifications=>19, :depth=>0, :requirements=>30, :failed=>2}
78
+
79
+ all_specs = counters[:specifications]
80
+ failed = counters[:failed]
81
+
82
+ if counters[:failed] > 0
83
+ Notifier.notify("Specs: #{failed} Failures (#{all_specs} specs)",
84
+ :image => :failed,
85
+ :title => File.basename(path)
86
+ )
87
+ else
88
+ Notifier.notify("Specs: OK (#{all_specs} specs)",
89
+ :image => :success,
90
+ :title => File.basename(path)
91
+ )
92
+ end
93
+ end
94
+
95
+ Process.wait(pid)
96
+ end
97
+ end
98
+
99
+ def file_changed(path)
100
+ case
101
+ when path =~ SPEC_FILE then run_spec(path)
102
+ when path =~ FILE_REG then run_spec("spec/unit/#{$1}_spec.rb")
103
+ end
104
+
105
+ puts ""
106
+ end
107
+
108
+ # Called on file(s) modifications
109
+ def run_on_change(paths)
110
+ paths.each do |path|
111
+ file_changed(path)
112
+ end
113
+ end
114
+
115
+ end
116
+ end
117
+
118
+
119
+ guard 'bacon' do
120
+ watch(%r{^spec/([^/]/)?.*_spec.rb$})
121
+ watch(%r{^lib/rrd-grapher/(?:[^/]+/)?(.*)\.rb$})
122
+ end
123
+
data/README.md ADDED
@@ -0,0 +1,91 @@
1
+
2
+ ![screenshot](http://dl.dropbox.com/u/1313066/github/rrd-grapher.png "Screenshot")
3
+
4
+ # What is this ?
5
+
6
+ RRDGrapher is my attempt at designing an application capable of drawing meaningful
7
+ dynamic graphs from RRD files.
8
+
9
+ This project is built as a Rack middleware providing you the with the tools you need to
10
+ build you own views as you see fit, the middleware will provide:
11
+
12
+ - a REST inerface to your rrd files
13
+ - a javascript framework to create graphs easily (built on top of jQuery and Flot)
14
+ - some basic css to get you started (everything can then be overloaded in your application)
15
+
16
+ You can have a look at the example_app folder which is a fully working application.
17
+
18
+ # My goals
19
+
20
+ The main goal of this project is to allow easy creation of graphs from rrd files stored
21
+ by any tool capable of it (the source really does not matter). Here is a features list:
22
+
23
+ # Features
24
+
25
+ - you should be able to able to add a new graph in minutes
26
+ - the zoom (with mouse drag and drop) load new fresh data so your graph is as exact as possible
27
+ - you can decide if the zoom will affect every graph on the page or just one
28
+
29
+
30
+ # Notifier Demon
31
+
32
+ This one may go into another gem but lives there for now, I made a monitoring demon to receive
33
+ collectd packets and trigger alerts by reacting on the data received.
34
+
35
+ ## What can be monitored ?
36
+
37
+ Here s what the demon can monitor:
38
+
39
+ - min/max value : raise an alarm if the value go above or below a <X>
40
+ - missing data : raise an alarm if no data was received for <X> seconds
41
+ - clock drift : raise an alarm if the absolute difference between the timestamp
42
+ inside the packet and the local time is higher then <X> (this suppose that both
43
+ hosts have an UTC clock)
44
+
45
+ ## How to use it
46
+
47
+ The demon is desgined as a library and require an eventmachine reactor to run, here is a minimal
48
+ application using it (check the documentation or the source code for more informations):
49
+
50
+ ``` ruby
51
+ require 'rubygems'
52
+ require 'bundler/setup'
53
+ require 'rrd-grapher/notifier'
54
+
55
+ puts "Notifier started."
56
+
57
+ EM::run do
58
+ RRDNotifier::Server.start do |s|
59
+ s.register_alarm("*", "ping", "ping_droprate", :max => 5)
60
+ s.register_alarm("*", "uptime", "uptime", :monitor_presence => 2*60)
61
+
62
+ s.register_alarm("*", "load", "load", :max => 1, :index => 1)
63
+ s.register_alarm("*", "memory/*", "memory/active", :monitor_presence => 1)
64
+ end
65
+
66
+ end
67
+ ```
68
+
69
+
70
+
71
+ # Development
72
+
73
+ If you wan to contribute to this project, here how to do it (in the root folder):
74
+
75
+ $ bundle
76
+
77
+ Now you have all the require gems run guard, it will monitor the sources files
78
+ and rebuild the results as you change them (coffeescript, sass).
79
+ It will also package all the js files with sprockets in one file.
80
+
81
+ $ bundle exec guard (will take one console)
82
+
83
+ You can also force a full rebuild of everything with (coffeescript + sprockets):
84
+
85
+ $ rake build
86
+
87
+ Last thing you will certainly need is to start a webserver, any should do but
88
+ I currently use unicorn
89
+
90
+ $ unicorn
91
+
data/Rakefile ADDED
@@ -0,0 +1,42 @@
1
+ require "bundler/gem_tasks"
2
+ require 'sprockets'
3
+
4
+ def pack_js(src_file)
5
+ secretary = ::Sprockets::Secretary.new(
6
+ :asset_root => "lib",
7
+ :source_files => ["lib/rrd-grapher/assets/javascripts/#{src_file}"],
8
+ :interpolate_constants => false
9
+ )
10
+
11
+ concatenation = secretary.concatenation
12
+ concatenation.save_to("lib/rrd-grapher/public/javascripts/#{src_file}")
13
+ secretary.install_assets
14
+ end
15
+
16
+ # compile and pack coffee files
17
+ task :build do
18
+ # core
19
+ sh "coffee -c -o lib/rrd-grapher/public/javascripts lib/rrd-grapher/assets/javascripts/"
20
+
21
+ # example_app
22
+ sh "coffee -c -o example_app/public/javascripts example_app/assets/javascripts/"
23
+
24
+ # sprockets
25
+ pack_js("app-dev.js")
26
+ pack_js("app.js")
27
+ end
28
+
29
+ task :test do
30
+ system("COVERAGE=1 bundle exec bacon spec/**/*_spec.rb")
31
+ end
32
+
33
+
34
+
35
+ begin
36
+ require 'jasmine'
37
+ load 'jasmine/tasks/jasmine.rake'
38
+ rescue LoadError
39
+ task :jasmine do
40
+ abort "Jasmine is not available. In order to run jasmine, you must: (sudo) gem install jasmine"
41
+ end
42
+ end
@@ -0,0 +1,9 @@
1
+
2
+ gem 'rrd-grapher', :path => File.expand_path('../..', __FILE__)
3
+ gem 'sinatra'
4
+ gem 'sinatra-content-for'
5
+ gem 'haml'
6
+
7
+ group(:dev) do
8
+ gem 'guard-coffeescript'
9
+ end
@@ -0,0 +1,18 @@
1
+
2
+ guard 'coffeescript',
3
+ :input => 'assets/javascripts',
4
+ :output => 'public/javascripts'
5
+
6
+ # guard 'coffeescript',
7
+ # :input => 'spec/javascripts/source',
8
+ # :output => 'spec/javascripts'
9
+
10
+
11
+
12
+ # guard 'livereload', :apply_js_live => false do
13
+ # watch(%r{^spec/javascripts/.+\.js$})
14
+ # watch(%r{^public/javascripts/.+\.js$})
15
+ # watch(%r{^views/stylesheets/.+\.scss$})
16
+ # watch(%r{^views/.+\.haml$})
17
+ # end
18
+
@@ -0,0 +1,38 @@
1
+ require 'rest-client'
2
+ require 'sinatra/base'
3
+ require 'sinatra/content_for'
4
+
5
+ class TestApp < Sinatra::Base
6
+ helpers Sinatra::ContentFor
7
+
8
+ set :haml, :format => :html5
9
+
10
+ # set :markdown, :layout_engine => :haml, :layout => :post
11
+ set :root, File.dirname(__FILE__)
12
+
13
+ get '/available_rrds' do
14
+ haml :available_rrds
15
+ end
16
+
17
+ get '/graph' do
18
+ haml :graph
19
+ end
20
+
21
+
22
+ get '/collectd' do
23
+ haml :collectd
24
+ end
25
+
26
+ # css
27
+
28
+ def self.dynamic_css(path)
29
+ get "/stylesheets/#{path}.css" do
30
+ content_type :css
31
+ scss "stylesheets/#{path}".to_sym
32
+ end
33
+ end
34
+
35
+ dynamic_css('available_rrds')
36
+ dynamic_css('graph')
37
+
38
+ end
@@ -0,0 +1,13 @@
1
+
2
+ list_rrd = (callback) ->
3
+ jQuery.get "/rrd", (o) ->
4
+ callback(o)
5
+
6
+ $ ->
7
+ list_rrd (data) ->
8
+ # $("#template").tmpl(data).appendTo("#target")
9
+ tmp = $("#template").tmpl(data)
10
+ tmp.appendTo("#data_list")
11
+ # $("#time").showTime( { div_hours: "h ", div_minutes: "m ", div_seconds: "s " } )
12
+ $(".time").timeago()
13
+
@@ -0,0 +1,48 @@
1
+
2
+ class window.TestGraph extends GraphDefinition
3
+ constructor: (container, host, @interface, ymin = null) ->
4
+ super(host, container, "Test Traffic (#{interface})", [ Format.size, Format.size ], ymin)
5
+
6
+ @graph.addSerie("#{@host}/interface/if_octets-#{@interface}", "rx", "(#{@interface}) Bytes Received")
7
+ @graph.addSerie("#{@host}/interface/if_octets-#{@interface}", "tx", "(#{@interface}) Bytes Sent", 2)
8
+
9
+
10
+
11
+ class CollectdPage extends GraphPage
12
+ constructor: (container, panel_container, host) ->
13
+ super(container, panel_container, host)
14
+
15
+ # @addGraph("NetworkGraph", "en0", 1 * Size.megabyte )
16
+ @addGraph("TestGraph", "en1", [20 * Size.kilobyte, 100 * Size.kilobyte ] )
17
+ @addGraph("MemoryGraph", "osx")
18
+ @addGraph("LoadGraph", 2.0)
19
+
20
+ $ ->
21
+ graphs = []
22
+
23
+ container = $("#graphs")
24
+ panel_container = $("#config_panel")
25
+
26
+ page = new CollectdPage(container, panel_container, "pomme.local")
27
+ # page.set_simple_interval(30)
28
+
29
+ $("#dateselect").datepicker().change ->
30
+ date_string = $(this).val()
31
+ time = Date.parse(date_string) / 1000
32
+
33
+ page.set_autorefresh(null)
34
+ page.set_interval(time, time + 24*60*60)
35
+
36
+ $("#rangeselect").chosen().change ->
37
+ page.set_autorefresh(null)
38
+ page.set_simple_interval( $(this).val() )
39
+
40
+ $("#linkedzoom").change (event) =>
41
+ if $(event.currentTarget).attr("checked")
42
+ page.refresh()
43
+
44
+ $("#autorefresh").change (event) =>
45
+ if $(event.currentTarget).attr("checked")
46
+ page.set_autorefresh(5000)
47
+ else
48
+ page.set_autorefresh(null)
@@ -0,0 +1,9 @@
1
+ require 'bundler/setup'
2
+ require 'rrd-grapher'
3
+
4
+ require File.expand_path('../app', __FILE__)
5
+
6
+ use RRDGrapher::RRDServer, :root_path => "/usr/local/var/lib/collectd/"
7
+ use RRDGrapher::ResourcesServer
8
+
9
+ run TestApp
@@ -0,0 +1 @@
1
+ javascripts/wijmo-open/