neo-viz 1.0.1
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 +9 -0
- data/.livereload +20 -0
- data/.rspec +2 -0
- data/.rvmrc +3 -0
- data/Gemfile +6 -0
- data/LICENSE +19 -0
- data/README.md +120 -0
- data/Rakefile +12 -0
- data/bin/neo-viz +12 -0
- data/config.ru +35 -0
- data/lib/neo-viz.rb +185 -0
- data/lib/neo-viz/version.rb +6 -0
- data/neo-viz.gemspec +37 -0
- data/public/coffeescripts/app_context.coffee +89 -0
- data/public/coffeescripts/canvas_util.coffee +68 -0
- data/public/coffeescripts/event_broker.coffee +16 -0
- data/public/coffeescripts/filters.coffee +113 -0
- data/public/coffeescripts/main.coffee.erb +132 -0
- data/public/coffeescripts/neo4j.coffee +90 -0
- data/public/coffeescripts/renderer.coffee +141 -0
- data/public/coffeescripts/space.coffee +81 -0
- data/public/images/ajax-loader.gif +0 -0
- data/public/javascripts/data.js +45 -0
- data/public/javascripts/data2.js +1287 -0
- data/public/javascripts/main.sprockets.js +9 -0
- data/public/lib/arbor/arbor-tween.js +86 -0
- data/public/lib/arbor/arbor.js +67 -0
- data/public/lib/jQuery/jquery-1.6.1.min.js +18 -0
- data/public/lib/jasmine-1.1.0/MIT.LICENSE +20 -0
- data/public/lib/jasmine-1.1.0/jasmine-html.js +190 -0
- data/public/lib/jasmine-1.1.0/jasmine.css +166 -0
- data/public/lib/jasmine-1.1.0/jasmine.js +2476 -0
- data/public/lib/jasmine-1.1.0/jasmine_favicon.png +0 -0
- data/public/lib/stdlib/stdlib.js +115 -0
- data/public/lib/sylvester-0.1.3/CHANGELOG.txt +29 -0
- data/public/lib/sylvester-0.1.3/sylvester.js +1 -0
- data/public/lib/sylvester-0.1.3/sylvester.js.gz +0 -0
- data/public/lib/sylvester-0.1.3/sylvester.src.js +1254 -0
- data/public/scss/main.scss +152 -0
- data/public/scss/mixins.scss +37 -0
- data/spec/coffeescripts/canvas_util_spec.coffee +4 -0
- data/spec/coffeescripts/filters_spec.coffee +37 -0
- data/spec/coffeescripts/neo4j_spec.coffee +76 -0
- data/spec/neo_viz_spec.rb +48 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/support/struct_matcher.rb +117 -0
- data/views/_filters.haml +22 -0
- data/views/_partial.haml +39 -0
- data/views/embedded.haml +15 -0
- data/views/index.haml +19 -0
- data/views/jasmine_specs_runner.haml +50 -0
- metadata +236 -0
data/.gitignore
ADDED
data/.livereload
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# Lines starting with pound sign (#) are ignored.
|
2
|
+
|
3
|
+
# additional extensions to monitor
|
4
|
+
config.exts << 'scss'
|
5
|
+
config.exts << 'haml'
|
6
|
+
|
7
|
+
# exclude files with NAMES matching this mask
|
8
|
+
#config.exclusions << '~*'
|
9
|
+
# exclude files with PATHS matching this mask (if the mask contains a slash)
|
10
|
+
#config.exclusions << '/excluded_dir/*'
|
11
|
+
# exclude files with PATHS matching this REGEXP
|
12
|
+
#config.exclusions << /somedir.*(ab){2,4}.(css|js)$/
|
13
|
+
|
14
|
+
# reload the whole page when .js changes
|
15
|
+
#config.apply_js_live = false
|
16
|
+
# reload the whole page when .css changes
|
17
|
+
#config.apply_css_live = false
|
18
|
+
|
19
|
+
# wait 100ms for more changes before reloading a page
|
20
|
+
#config.grace_period = 0.1
|
data/.rspec
ADDED
data/.rvmrc
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2011 AmanziTel
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
# Neo-Viz
|
2
|
+
|
3
|
+
Neo-Viz is a tool for visualizing Neo data in the browser. It is
|
4
|
+
a Sinatra application that uses Neo4j.rb to read data from a Neo
|
5
|
+
database directory. It shows the data using Javascript in a browser.
|
6
|
+
|
7
|
+
|
8
|
+
## Installing
|
9
|
+
|
10
|
+
The visualizer can be used stand-alone or embedded in a Rails application.
|
11
|
+
|
12
|
+
### External Dependencies
|
13
|
+
|
14
|
+
The visualizer has an external dependency on coffee-script. It can be
|
15
|
+
installed by:
|
16
|
+
|
17
|
+
# OS X
|
18
|
+
$ brew install coffee-script
|
19
|
+
|
20
|
+
# Linux
|
21
|
+
$ apt-get install coffee-script
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
### Standalone
|
26
|
+
|
27
|
+
To use it standalone you must first get the code from the repository.
|
28
|
+
|
29
|
+
$ git clone git@github.com:AmanziTel/neo-viz.git
|
30
|
+
$ cd neo-viz
|
31
|
+
|
32
|
+
# To use it as is
|
33
|
+
$ rackup
|
34
|
+
[2011-06-23 07:48:34] INFO WEBrick 1.3.1
|
35
|
+
[2011-06-23 07:48:34] INFO ruby 1.8.7 (2011-05-23) [java]
|
36
|
+
[2011-06-23 07:48:34] INFO WEBrick::HTTPServer#start: pid=64743 port=9292
|
37
|
+
|
38
|
+
|
39
|
+
# To install it as a gem
|
40
|
+
$ rake install
|
41
|
+
neo-viz 1.0.0 built to pkg/neo-viz-1.0.0.gem
|
42
|
+
neo-viz (1.0.0) installed
|
43
|
+
|
44
|
+
$ neo-viz
|
45
|
+
[2011-06-23 07:51:10] INFO WEBrick 1.3.1
|
46
|
+
[2011-06-23 07:51:10] INFO ruby 1.8.7 (2011-05-23) [java]
|
47
|
+
[2011-06-23 07:51:10] INFO WEBrick::HTTPServer#start: pid=64864 port=1666
|
48
|
+
|
49
|
+
### Embedding in Rails
|
50
|
+
|
51
|
+
To embed the visualizer in Rails, you first have to add it to your `Gemfile`.
|
52
|
+
|
53
|
+
# Gemfile
|
54
|
+
gem 'neo-viz', :git => 'git@github.com:AmanziTel/neo-viz.git'
|
55
|
+
|
56
|
+
Then you have to mount the route in `routes.rb`
|
57
|
+
|
58
|
+
# config/routes.rb
|
59
|
+
mount Neo::Viz::App => '/neo-viz'
|
60
|
+
|
61
|
+
You can now access it at e.g. http://localhost:3000/neo-viz.
|
62
|
+
|
63
|
+
## Neo4j Database
|
64
|
+
|
65
|
+
The standalone version expects a `db` directory containing the usual
|
66
|
+
Neo4j database files.
|
67
|
+
|
68
|
+
The embedded version uses the Neo4j database that has been configured
|
69
|
+
for the embedding project.
|
70
|
+
|
71
|
+
## Known issues
|
72
|
+
|
73
|
+
There is a problem running the Jasmine specs (/run-specs) on Windows if the "therubyrhino" gem is installed
|
74
|
+
and you are using JRuby. On Windows we want to use the built-in JScript runtime but ExecJS chooses Rhino if it
|
75
|
+
is installed.
|
76
|
+
|
77
|
+
Typical errors returned over HTTP when requesting a .coffee file:
|
78
|
+
|
79
|
+
throw Error("NativeException: org.mozilla.javascript.JavaScriptException:
|
80
|
+
Error: too many ) on line 2 (<eval>#8)\n (in c:/..../neo-viz/public/coffeescripts/canvas_util.coffee)")
|
81
|
+
|
82
|
+
A workaround is to uninstall the therubyrhino gem, but ofcourse it will be re-installed on every call to bundle.
|
83
|
+
I can't figure out how to tell bundler not to load a specific gem when I'm on JRuby and Windows.
|
84
|
+
|
85
|
+
## To do
|
86
|
+
|
87
|
+
### Server
|
88
|
+
|
89
|
+
* Make it possible to choose where that data comes from
|
90
|
+
* Implement a command line interface for starting the server and
|
91
|
+
selecting the data source.
|
92
|
+
|
93
|
+
|
94
|
+
### Client
|
95
|
+
|
96
|
+
* Group nodes, if there are too many to show.
|
97
|
+
* bind and trigger with custom events
|
98
|
+
|
99
|
+
|
100
|
+
### License
|
101
|
+
|
102
|
+
MIT, see LICENSE file
|
103
|
+
|
104
|
+
### Changes
|
105
|
+
|
106
|
+
* 2011-09-28 Added relationship filter
|
107
|
+
* 2001-09-28 Enabled embedding from AJAX-call (/embedded)
|
108
|
+
* 2011-06-23 Changed the namespace.
|
109
|
+
* 2011-06-23 Added depth to the traversal algorithm
|
110
|
+
* 2011-06-20 A query protocol for selecting only the relevant nodes
|
111
|
+
* 2011-06-20 Query protocol editor to select the relevant nodes to ask
|
112
|
+
* 2011-06-16 Views for showing only the relevant properties.
|
113
|
+
* 2011-06-16 Node filter
|
114
|
+
* 2011-06-16 Select number of nodes to show.
|
115
|
+
* 2011-06-14 Click to show detailed information.
|
116
|
+
* Connect with the Server to get the data.
|
117
|
+
* Fetch new data from the Server when a node is selected.
|
118
|
+
* Limit the amount of nodes shown on the screen.
|
119
|
+
* Show the properties of the nodes and relations.
|
120
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jasmine'
|
6
|
+
load 'jasmine/tasks/jasmine.rake'
|
7
|
+
rescue LoadError
|
8
|
+
task :jasmine do
|
9
|
+
abort "Jasmine is not available. In order to run jasmine, you must: (sudo) gem install jasmine"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
data/bin/neo-viz
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rack'
|
4
|
+
|
5
|
+
rackup_file = File.expand_path('../../config.ru', __FILE__)
|
6
|
+
|
7
|
+
ARGV.concat(["-p", "1666"]) unless ARGV.include?("-p")
|
8
|
+
ARGV.concat(["-E", "production"]) unless ARGV.include?("-E")
|
9
|
+
ARGV << rackup_file unless ARGV.include?(/\.ru/)
|
10
|
+
|
11
|
+
Rack::Server.start
|
12
|
+
|
data/config.ru
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/lib'
|
2
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/views'
|
3
|
+
|
4
|
+
require 'sprockets'
|
5
|
+
require 'neo-viz'
|
6
|
+
require 'find'
|
7
|
+
|
8
|
+
map '/' do
|
9
|
+
run Neo::Viz::App
|
10
|
+
end
|
11
|
+
|
12
|
+
map '/assets' do
|
13
|
+
environment = Sprockets::Environment.new
|
14
|
+
|
15
|
+
# map all dirs under /public to /assets
|
16
|
+
Find.find(File.join(Neo::Viz.install_path, "public")) do |path|
|
17
|
+
environment.append_path(path) if FileTest.directory?(path)
|
18
|
+
end
|
19
|
+
|
20
|
+
environment.instance_eval do
|
21
|
+
@context_class.instance_eval do
|
22
|
+
define_method :root_url do
|
23
|
+
'.'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
run environment
|
29
|
+
end
|
30
|
+
|
31
|
+
map '/specs' do
|
32
|
+
environment = Sprockets::Environment.new
|
33
|
+
environment.append_path 'spec/coffeescripts'
|
34
|
+
run environment
|
35
|
+
end
|
data/lib/neo-viz.rb
ADDED
@@ -0,0 +1,185 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
|
3
|
+
require 'haml'
|
4
|
+
require 'sass'
|
5
|
+
require 'coffee-script'
|
6
|
+
require 'neo4j'
|
7
|
+
require 'sprockets'
|
8
|
+
require 'execjs'
|
9
|
+
|
10
|
+
module Neo; module Viz; end; end
|
11
|
+
|
12
|
+
|
13
|
+
module Neo::Viz
|
14
|
+
|
15
|
+
def self.install_path
|
16
|
+
return File.expand_path('../..', __FILE__)
|
17
|
+
end
|
18
|
+
|
19
|
+
class App < Sinatra::Base
|
20
|
+
|
21
|
+
include Neo4j
|
22
|
+
|
23
|
+
configure do
|
24
|
+
set :public, File.expand_path('../../public/', __FILE__)
|
25
|
+
set :views, File.expand_path('../../views/', __FILE__)
|
26
|
+
end
|
27
|
+
|
28
|
+
configure(:development) do
|
29
|
+
require 'sinatra/reloader'
|
30
|
+
register Sinatra::Reloader
|
31
|
+
also_reload "lib/**/*.rb"
|
32
|
+
end
|
33
|
+
|
34
|
+
get '/' do
|
35
|
+
redirect to('/index')
|
36
|
+
end
|
37
|
+
|
38
|
+
get '/index' do
|
39
|
+
@assets_url_prefix = ''
|
40
|
+
haml :index
|
41
|
+
end
|
42
|
+
|
43
|
+
# Consumers of /embedded have to redefine this method inside
|
44
|
+
# the Sprockets environment. See config.ru.
|
45
|
+
def root_url
|
46
|
+
'.'
|
47
|
+
end
|
48
|
+
|
49
|
+
get '/embedded' do
|
50
|
+
@assets_url_prefix = request.env["rack.mount.prefix"] || ''
|
51
|
+
haml :embedded
|
52
|
+
end
|
53
|
+
|
54
|
+
get '/node-count' do
|
55
|
+
Neo4j.management.get_number_of_node_ids_in_use.to_s
|
56
|
+
end
|
57
|
+
|
58
|
+
get '/tree' do
|
59
|
+
Neo4j.ref_node.rels.map { |rel| rel.end_node.attributes }.inspect
|
60
|
+
end
|
61
|
+
|
62
|
+
get '/env' do
|
63
|
+
#p ExecJS::runtime
|
64
|
+
p request.env
|
65
|
+
request.env.inspect
|
66
|
+
end
|
67
|
+
|
68
|
+
get '/run-specs' do
|
69
|
+
haml :jasmine_specs_runner
|
70
|
+
end
|
71
|
+
|
72
|
+
get '/eval' do
|
73
|
+
code = params[:code]
|
74
|
+
p code
|
75
|
+
ret = eval_code code, depth
|
76
|
+
if node_data?(ret)
|
77
|
+
ret.to_json
|
78
|
+
else
|
79
|
+
# Hallberg: is seems 'to_s' does not alias 'inspect' for Hash and Array
|
80
|
+
# on JRuby 1.6.4 on Windows. Instead {:foo => :bar}.to_s = "foobar".
|
81
|
+
# So special case them here.
|
82
|
+
if ret.kind_of?(Hash) || ret.kind_of?(Array)
|
83
|
+
{ :result => ret.inspect}.to_json
|
84
|
+
else
|
85
|
+
{ :result => "#{ret}" }.to_json
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def node_data?(ret)
|
94
|
+
ret.kind_of?(Hash) && ret.length == 2 && ret.key?(:nodes) && ret.key?(:rels)
|
95
|
+
end
|
96
|
+
|
97
|
+
def depth
|
98
|
+
params[:depth].try(:to_i) || 1
|
99
|
+
end
|
100
|
+
|
101
|
+
def eval_code(code, depth)
|
102
|
+
code = underscore code
|
103
|
+
|
104
|
+
begin
|
105
|
+
$Depth = depth
|
106
|
+
tx = Neo4j::Transaction.new
|
107
|
+
begin
|
108
|
+
result = eval <<-EOT
|
109
|
+
#{code}
|
110
|
+
EOT
|
111
|
+
rescue SyntaxError => e
|
112
|
+
return e
|
113
|
+
end
|
114
|
+
tx.success
|
115
|
+
result
|
116
|
+
rescue => e
|
117
|
+
e
|
118
|
+
ensure
|
119
|
+
tx.finish
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
# This changes the code to use the internal versions that
|
125
|
+
# don't use classes, but just pure nodes and relations.
|
126
|
+
def underscore code
|
127
|
+
code.
|
128
|
+
gsub(/\bload\b/, '_load').
|
129
|
+
gsub(/\brels\b/, '_rels').
|
130
|
+
gsub(/\bnode\b/, '_node')
|
131
|
+
end
|
132
|
+
|
133
|
+
def viz(*args)
|
134
|
+
depth = $Depth
|
135
|
+
data = { :nodes => [], :rels => [] }
|
136
|
+
args.each do |arg|
|
137
|
+
data_for(data, arg, depth)
|
138
|
+
end
|
139
|
+
data
|
140
|
+
end
|
141
|
+
|
142
|
+
def data_for(data, obj, depth)
|
143
|
+
if obj.class.to_s == 'Neo4j::Relationship'
|
144
|
+
populate_data(data, arg.start_node, depth, [])
|
145
|
+
elsif obj.class.to_s == 'Neo4j::Node'
|
146
|
+
populate_data(data, obj, depth, [])
|
147
|
+
elsif obj.respond_to? :each
|
148
|
+
obj.each do |o|
|
149
|
+
data_for(data, o, depth)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
data
|
153
|
+
end
|
154
|
+
|
155
|
+
def populate_data(data, node, depth, navigatedRels)
|
156
|
+
data[:nodes] << node_data(node)
|
157
|
+
return if depth == 0
|
158
|
+
node._rels.each do |rel|
|
159
|
+
# Make sure we don't walk the same rel path more than once
|
160
|
+
if !navigatedRels.include?(rel)
|
161
|
+
data[:rels] << rel_data(rel)
|
162
|
+
navigatedRels << rel
|
163
|
+
populate_data(data, rel._other_node(node), depth-1, navigatedRels)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def node_data(node)
|
169
|
+
{
|
170
|
+
:id => node.props['_neo_id'],
|
171
|
+
:data => node.props,
|
172
|
+
}
|
173
|
+
end
|
174
|
+
|
175
|
+
def rel_data(rel)
|
176
|
+
{
|
177
|
+
:id => rel.props['_neo_id'],
|
178
|
+
:start_node => rel._start_node.props['_neo_id'],
|
179
|
+
:end_node => rel._end_node.props['_neo_id'],
|
180
|
+
:data => rel.props.merge(:rel_type => rel.rel_type)
|
181
|
+
}
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|