chef-server-api 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +201 -0
- data/README.rdoc +92 -0
- data/Rakefile +59 -0
- data/app/controllers/application.rb +289 -0
- data/app/controllers/clients.rb +111 -0
- data/app/controllers/cookbooks.rb +213 -0
- data/app/controllers/data.rb +75 -0
- data/app/controllers/data_item.rb +108 -0
- data/app/controllers/exceptions.rb +40 -0
- data/app/controllers/main.rb +18 -0
- data/app/controllers/nodes.rb +102 -0
- data/app/controllers/roles.rb +73 -0
- data/app/controllers/search.rb +60 -0
- data/app/controllers/users.rb +77 -0
- data/app/helpers/application_helper.rb +163 -0
- data/app/helpers/exceptions_helper.rb +6 -0
- data/app/helpers/global_helpers.rb +25 -0
- data/app/helpers/nodes_helper.rb +26 -0
- data/app/helpers/roles_helper.rb +5 -0
- data/app/helpers/tarball_helper.rb +82 -0
- data/app/views/exceptions/bad_request.json.erb +1 -0
- data/app/views/exceptions/internal_server_error.html.erb +216 -0
- data/app/views/exceptions/not_acceptable.html.haml +5 -0
- data/app/views/exceptions/not_found.html.erb +47 -0
- data/app/views/exceptions/standard_error.html.erb +217 -0
- data/app/views/layout/chef_server_api.html.haml +23 -0
- data/app/views/main/index.html.haml +5 -0
- data/config/init.rb +45 -0
- data/config/router.rb +6 -0
- data/lib/chef-server-api.rb +158 -0
- data/lib/chef-server-api/merbtasks.rb +103 -0
- data/lib/chef-server-api/slicetasks.rb +20 -0
- data/lib/chef-server-api/spectasks.rb +53 -0
- data/public/images/avatar.png +0 -0
- data/public/images/indicator.gif +0 -0
- data/public/images/merb.jpg +0 -0
- data/public/stylesheets/base.css +336 -0
- data/public/stylesheets/chef.css +157 -0
- data/public/stylesheets/themes/bec-green/style.css +290 -0
- data/public/stylesheets/themes/bec/style.css +301 -0
- data/public/stylesheets/themes/blue/style.css +280 -0
- data/public/stylesheets/themes/default/style.css +267 -0
- data/public/stylesheets/themes/djime-cerulean/style.css +298 -0
- data/public/stylesheets/themes/kathleene/style.css +272 -0
- data/public/stylesheets/themes/orange/style.css +263 -0
- data/public/stylesheets/themes/reidb-greenish/style.css +301 -0
- data/stubs/app/controllers/application.rb +2 -0
- data/stubs/app/controllers/main.rb +2 -0
- metadata +193 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
3
|
+
# Author:: Christopher Brown (<cb@opscode.com>)
|
4
|
+
# Copyright:: Copyright (c) 2008 Opscode, Inc.
|
5
|
+
# License:: Apache License, Version 2.0
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
#
|
19
|
+
|
20
|
+
class Exceptions < ChefServerApi::Application
|
21
|
+
|
22
|
+
provides :json
|
23
|
+
|
24
|
+
def not_acceptable
|
25
|
+
if request.accept =~ /application\/json/
|
26
|
+
display({ "error" => request.exceptions })
|
27
|
+
else
|
28
|
+
render
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def standard_error
|
33
|
+
if request.accept =~ /application\/json/
|
34
|
+
display({ "error" => request.exceptions })
|
35
|
+
else
|
36
|
+
raise request.exceptions.first
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class ChefServerApi::Main < ChefServerApi::Application
|
2
|
+
|
3
|
+
before :authenticate_every
|
4
|
+
provides :html, :json
|
5
|
+
|
6
|
+
def index
|
7
|
+
display(
|
8
|
+
{
|
9
|
+
absolute_slice_url(:nodes) => "Manage Nodes",
|
10
|
+
absolute_slice_url(:roles) => "Manage Roles",
|
11
|
+
absolute_slice_url(:cookbooks) => "Manage Cookbooks",
|
12
|
+
absolute_slice_url(:data) => "Manage Data Bags",
|
13
|
+
absolute_slice_url(:search) => "Search"
|
14
|
+
}
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
3
|
+
# Author:: Christopher Brown (<cb@opscode.com>)
|
4
|
+
# Copyright:: Copyright (c) 2008 Opscode, Inc.
|
5
|
+
# License:: Apache License, Version 2.0
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'chef' / 'node'
|
21
|
+
|
22
|
+
class ChefServerApi::Nodes < ChefServerApi::Application
|
23
|
+
|
24
|
+
provides :json
|
25
|
+
|
26
|
+
before :authenticate_every
|
27
|
+
before :is_correct_node, :only => [ :update, :destroy, :cookbooks ]
|
28
|
+
|
29
|
+
def index
|
30
|
+
@node_list = Chef::Node.cdb_list
|
31
|
+
display(@node_list.inject({}) do |r,n|
|
32
|
+
r[n] = absolute_slice_url(:node, n); r
|
33
|
+
end)
|
34
|
+
end
|
35
|
+
|
36
|
+
def show
|
37
|
+
begin
|
38
|
+
@node = Chef::Node.cdb_load(params[:id])
|
39
|
+
rescue Chef::Exceptions::CouchDBNotFound => e
|
40
|
+
raise NotFound, "Cannot load node #{params[:id]}"
|
41
|
+
end
|
42
|
+
@node.couchdb_rev = nil
|
43
|
+
recipes, default, override = @node.run_list.expand("couchdb")
|
44
|
+
@node.default_attrs = default
|
45
|
+
@node.override_attrs = override
|
46
|
+
display @node
|
47
|
+
end
|
48
|
+
|
49
|
+
def create
|
50
|
+
@node = params["inflated_object"]
|
51
|
+
exists = true
|
52
|
+
begin
|
53
|
+
Chef::Node.cdb_load(@node.name)
|
54
|
+
rescue Chef::Exceptions::CouchDBNotFound
|
55
|
+
exists = false
|
56
|
+
end
|
57
|
+
raise Conflict, "Node already exists" if exists
|
58
|
+
self.status = 201
|
59
|
+
@node.cdb_save
|
60
|
+
display({ :uri => absolute_slice_url(:node, @node.name) })
|
61
|
+
end
|
62
|
+
|
63
|
+
def update
|
64
|
+
begin
|
65
|
+
@node = Chef::Node.cdb_load(params[:id])
|
66
|
+
rescue Chef::Exceptions::CouchDBNotFound => e
|
67
|
+
raise NotFound, "Cannot load node #{params[:id]}"
|
68
|
+
end
|
69
|
+
|
70
|
+
updated = params['inflated_object']
|
71
|
+
@node.run_list.reset!(updated.run_list)
|
72
|
+
@node.attribute = updated.attribute
|
73
|
+
@node.override_attrs = updated.override_attrs
|
74
|
+
@node.default_attrs = updated.default_attrs
|
75
|
+
@node.cdb_save
|
76
|
+
@node.couchdb_rev = nil
|
77
|
+
display(@node)
|
78
|
+
end
|
79
|
+
|
80
|
+
def destroy
|
81
|
+
begin
|
82
|
+
@node = Chef::Node.cdb_load(params[:id])
|
83
|
+
rescue Chef::Exceptions::CouchDBNotFound => e
|
84
|
+
raise NotFound, "Cannot load node #{params[:id]}"
|
85
|
+
end
|
86
|
+
@node.cdb_destroy
|
87
|
+
@node.couchdb_rev = nil
|
88
|
+
display @node
|
89
|
+
end
|
90
|
+
|
91
|
+
def cookbooks
|
92
|
+
begin
|
93
|
+
@node = Chef::Node.cdb_load(params[:id])
|
94
|
+
rescue Chef::Exceptions::CouchDBNotFound => e
|
95
|
+
raise NotFound, "Cannot load node #{params[:id]}"
|
96
|
+
end
|
97
|
+
|
98
|
+
display(load_all_files(params[:id]))
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'chef/role'
|
2
|
+
|
3
|
+
class ChefServerApi::Roles < ChefServerApi::Application
|
4
|
+
provides :json
|
5
|
+
|
6
|
+
before :authenticate_every
|
7
|
+
before :is_admin, :only => [ :create, :update, :destroy ]
|
8
|
+
|
9
|
+
# GET /roles
|
10
|
+
def index
|
11
|
+
@role_list = Chef::Role.cdb_list(true)
|
12
|
+
display(@role_list.inject({}) { |r,role| r[role.name] = absolute_slice_url(:role, role.name); r })
|
13
|
+
end
|
14
|
+
|
15
|
+
# GET /roles/:id
|
16
|
+
def show
|
17
|
+
begin
|
18
|
+
@role = Chef::Role.cdb_load(params[:id])
|
19
|
+
rescue Chef::Exceptions::CouchDBNotFound => e
|
20
|
+
raise NotFound, "Cannot load role #{params[:id]}"
|
21
|
+
end
|
22
|
+
@role.couchdb_rev = nil
|
23
|
+
display @role
|
24
|
+
end
|
25
|
+
|
26
|
+
# POST /roles
|
27
|
+
def create
|
28
|
+
@role = params["inflated_object"]
|
29
|
+
exists = true
|
30
|
+
begin
|
31
|
+
Chef::Role.cdb_load(@role.name)
|
32
|
+
rescue Chef::Exceptions::CouchDBNotFound
|
33
|
+
exists = false
|
34
|
+
end
|
35
|
+
raise Conflict, "Role already exists" if exists
|
36
|
+
|
37
|
+
@role.cdb_save
|
38
|
+
|
39
|
+
self.status = 201
|
40
|
+
display({ :uri => absolute_slice_url(:role, :id => @role.name) })
|
41
|
+
end
|
42
|
+
|
43
|
+
# PUT /roles/:id
|
44
|
+
def update
|
45
|
+
begin
|
46
|
+
@role = Chef::Role.cdb_load(params[:id])
|
47
|
+
rescue Chef::Exceptions::CouchDBNotFound => e
|
48
|
+
raise NotFound, "Cannot load role #{params[:id]}"
|
49
|
+
end
|
50
|
+
|
51
|
+
@role.description(params["inflated_object"].description)
|
52
|
+
@role.recipes(params["inflated_object"].recipes) if defined?(params["inflated_object"].recipes)
|
53
|
+
@role.run_list(params["inflated_object"].run_list)
|
54
|
+
@role.default_attributes(params["inflated_object"].default_attributes)
|
55
|
+
@role.override_attributes(params["inflated_object"].override_attributes)
|
56
|
+
@role.cdb_save
|
57
|
+
self.status = 200
|
58
|
+
@role.couchdb_rev = nil
|
59
|
+
display(@role)
|
60
|
+
end
|
61
|
+
|
62
|
+
# DELETE /roles/:id
|
63
|
+
def destroy
|
64
|
+
begin
|
65
|
+
@role = Chef::Role.cdb_load(params[:id])
|
66
|
+
rescue Chef::Exceptions::CouchDBNotFound => e
|
67
|
+
raise NotFound, "Cannot load role #{params[:id]}"
|
68
|
+
end
|
69
|
+
@role.cdb_destroy
|
70
|
+
display @role
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
3
|
+
# Author:: Christopher Brown (<cb@opscode.com>)
|
4
|
+
# Copyright:: Copyright (c) 2008 Opscode, Inc.
|
5
|
+
# License:: Apache License, Version 2.0
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
19
|
+
|
20
|
+
require 'chef/solr/query'
|
21
|
+
|
22
|
+
class ChefServerApi::Search < ChefServerApi::Application
|
23
|
+
provides :json
|
24
|
+
|
25
|
+
before :authenticate_every
|
26
|
+
before :is_admin, :only => [:reindex]
|
27
|
+
|
28
|
+
def index
|
29
|
+
indexes = valid_indexes
|
30
|
+
display(indexes.inject({}) { |r,i| r[i] = absolute_slice_url(:search, i); r })
|
31
|
+
end
|
32
|
+
|
33
|
+
def valid_indexes
|
34
|
+
indexes = Chef::DataBag.cdb_list(false)
|
35
|
+
indexes += %w{ role node client }
|
36
|
+
end
|
37
|
+
|
38
|
+
def show
|
39
|
+
unless valid_indexes.include?(params[:id])
|
40
|
+
raise NotFound, "I don't know how to search for #{params[:id]} data objects."
|
41
|
+
end
|
42
|
+
|
43
|
+
query = Chef::Solr::Query.new(Chef::Config[:solr_url], Chef::Config[:couchdb_database])
|
44
|
+
params[:q] ||= "*:*"
|
45
|
+
params[:sort] ||= nil
|
46
|
+
params[:start] ||= 0
|
47
|
+
params[:rows] ||= 20
|
48
|
+
objects, start, total = query.search(params[:id], params[:q], params[:sort], params[:start], params[:rows])
|
49
|
+
display({
|
50
|
+
"rows" => objects,
|
51
|
+
"start" => start,
|
52
|
+
"total" => total
|
53
|
+
})
|
54
|
+
end
|
55
|
+
|
56
|
+
def reindex
|
57
|
+
display(Chef::Solr.new.rebuild_index)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Nuo Yan (<nuo@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2009 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
|
18
|
+
|
19
|
+
require File.join("chef", "webui_user")
|
20
|
+
|
21
|
+
class ChefServerApi::Users < ChefServerApi::Application
|
22
|
+
provides :json
|
23
|
+
|
24
|
+
before :authenticate_every
|
25
|
+
|
26
|
+
# GET to /users
|
27
|
+
def index
|
28
|
+
@user_list = Chef::WebUIUser.cdb_list
|
29
|
+
display(@user_list.inject({}) { |r,n| r[n] = absolute_slice_url(:user, n); r })
|
30
|
+
end
|
31
|
+
|
32
|
+
# GET to /users/:id
|
33
|
+
def show
|
34
|
+
begin
|
35
|
+
@user = Chef::WebUIUser.cdb_load(params[:id])
|
36
|
+
rescue Chef::Exceptions::CouchDBNotFound => e
|
37
|
+
raise NotFound, "Cannot load user #{params[:id]}"
|
38
|
+
end
|
39
|
+
display @user
|
40
|
+
end
|
41
|
+
|
42
|
+
# PUT to /users/:id
|
43
|
+
def update
|
44
|
+
begin
|
45
|
+
Chef::WebUIUser.cdb_load(params[:id])
|
46
|
+
rescue Chef::Exceptions::CouchDBNotFound => e
|
47
|
+
raise NotFound, "Cannot load user #{params[:id]}"
|
48
|
+
end
|
49
|
+
@user = params['inflated_object']
|
50
|
+
@user.cdb_save
|
51
|
+
display(@user)
|
52
|
+
end
|
53
|
+
|
54
|
+
# POST to /users
|
55
|
+
def create
|
56
|
+
@user = params["inflated_object"]
|
57
|
+
begin
|
58
|
+
Chef::WebUIUser.cdb_load(@user.name)
|
59
|
+
rescue Chef::Exceptions::CouchDBNotFound
|
60
|
+
@user.cdb_save
|
61
|
+
self.status = 201
|
62
|
+
else
|
63
|
+
raise Conflict, "User already exists"
|
64
|
+
end
|
65
|
+
display({ :uri => absolute_slice_url(:user, @user.name) })
|
66
|
+
end
|
67
|
+
|
68
|
+
def destroy
|
69
|
+
begin
|
70
|
+
@user = Chef::WebUIUser.cdb_load(params[:id])
|
71
|
+
rescue Chef::Exceptions::CouchDBNotFound => e
|
72
|
+
raise NotFound, "Cannot load user #{params[:id]}"
|
73
|
+
end
|
74
|
+
@user.cdb_destroy
|
75
|
+
display @user
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
module Merb
|
2
|
+
module ChefServerApi
|
3
|
+
module ApplicationHelper
|
4
|
+
|
5
|
+
# Generate the absolute url for a slice - takes the slice's :path_prefix into account.
|
6
|
+
#
|
7
|
+
# @param slice_name<Symbol>
|
8
|
+
# The name of the slice - in identifier_sym format (underscored).
|
9
|
+
# @param *args<Array[Symbol,Hash]>
|
10
|
+
# There are several possibilities regarding arguments:
|
11
|
+
# - when passing a Hash only, the :default route of the current
|
12
|
+
# slice will be used
|
13
|
+
# - when a Symbol is passed, it's used as the route name
|
14
|
+
# - a Hash with additional params can optionally be passed
|
15
|
+
#
|
16
|
+
# @return <String> A uri based on the requested slice.
|
17
|
+
#
|
18
|
+
# @example absolute_slice_url(:awesome, :format => 'html')
|
19
|
+
# @example absolute_slice_url(:forum, :posts, :format => 'xml')
|
20
|
+
def absolute_slice_url(slice_name, *args)
|
21
|
+
options = extract_options_from_args!(args) || {}
|
22
|
+
protocol = options.delete(:protocol) || request.protocol
|
23
|
+
host = options.delete(:host) || request.host
|
24
|
+
|
25
|
+
protocol + "://" + host + slice_url(slice_name,*args)
|
26
|
+
end
|
27
|
+
|
28
|
+
# @param *segments<Array[#to_s]> Path segments to append.
|
29
|
+
#
|
30
|
+
# @return <String>
|
31
|
+
# A path relative to the public directory, with added segments.
|
32
|
+
def image_path(*segments)
|
33
|
+
public_path_for(:image, *segments)
|
34
|
+
end
|
35
|
+
|
36
|
+
# @param *segments<Array[#to_s]> Path segments to append.
|
37
|
+
#
|
38
|
+
# @return <String>
|
39
|
+
# A path relative to the public directory, with added segments.
|
40
|
+
def javascript_path(*segments)
|
41
|
+
public_path_for(:javascript, *segments)
|
42
|
+
end
|
43
|
+
|
44
|
+
# @param *segments<Array[#to_s]> Path segments to append.
|
45
|
+
#
|
46
|
+
# @return <String>
|
47
|
+
# A path relative to the public directory, with added segments.
|
48
|
+
def stylesheet_path(*segments)
|
49
|
+
public_path_for(:stylesheet, *segments)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Construct a path relative to the public directory
|
53
|
+
#
|
54
|
+
# @param <Symbol> The type of component.
|
55
|
+
# @param *segments<Array[#to_s]> Path segments to append.
|
56
|
+
#
|
57
|
+
# @return <String>
|
58
|
+
# A path relative to the public directory, with added segments.
|
59
|
+
def public_path_for(type, *segments)
|
60
|
+
::ChefServerApi.public_path_for(type, *segments)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Construct an app-level path.
|
64
|
+
#
|
65
|
+
# @param <Symbol> The type of component.
|
66
|
+
# @param *segments<Array[#to_s]> Path segments to append.
|
67
|
+
#
|
68
|
+
# @return <String>
|
69
|
+
# A path within the host application, with added segments.
|
70
|
+
def app_path_for(type, *segments)
|
71
|
+
::ChefServerApi.app_path_for(type, *segments)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Construct a slice-level path.
|
75
|
+
#
|
76
|
+
# @param <Symbol> The type of component.
|
77
|
+
# @param *segments<Array[#to_s]> Path segments to append.
|
78
|
+
#
|
79
|
+
# @return <String>
|
80
|
+
# A path within the slice source (Gem), with added segments.
|
81
|
+
def slice_path_for(type, *segments)
|
82
|
+
::ChefServerApi.slice_path_for(type, *segments)
|
83
|
+
end
|
84
|
+
|
85
|
+
def build_tree(name, node, default={}, override={})
|
86
|
+
node = Chef::Mixin::DeepMerge.merge(default, node)
|
87
|
+
node = Chef::Mixin::DeepMerge.merge(node, override)
|
88
|
+
html = "<table id='#{name}' class='tree table'>"
|
89
|
+
html << "<tr><th class='first'>Attribute</th><th class='last'>Value</th></tr>"
|
90
|
+
count = 0
|
91
|
+
parent = 0
|
92
|
+
append_tree(name, html, node, count, parent, override)
|
93
|
+
html << "</table>"
|
94
|
+
html
|
95
|
+
end
|
96
|
+
|
97
|
+
def append_tree(name, html, node, count, parent, override)
|
98
|
+
node.sort{ |a,b| a[0] <=> b[0] }.each do |key, value|
|
99
|
+
to_send = Array.new
|
100
|
+
count += 1
|
101
|
+
is_parent = false
|
102
|
+
local_html = ""
|
103
|
+
local_html << "<tr id='#{name}-#{count}' class='collapsed #{name}"
|
104
|
+
if parent != 0
|
105
|
+
local_html << " child-of-#{name}-#{parent}' style='display: none;'>"
|
106
|
+
else
|
107
|
+
local_html << "'>"
|
108
|
+
end
|
109
|
+
local_html << "<td class='table-key'><span toggle='#{name}-#{count}'/>#{key}</td>"
|
110
|
+
case value
|
111
|
+
when Hash
|
112
|
+
is_parent = true
|
113
|
+
local_html << "<td></td>"
|
114
|
+
p = count
|
115
|
+
to_send << Proc.new { append_tree(name, html, value, count, p, override) }
|
116
|
+
when Array
|
117
|
+
is_parent = true
|
118
|
+
local_html << "<td></td>"
|
119
|
+
as_hash = {}
|
120
|
+
value.each_index { |i| as_hash[i] = value[i] }
|
121
|
+
p = count
|
122
|
+
to_send << Proc.new { append_tree(name, html, as_hash, count, p, override) }
|
123
|
+
else
|
124
|
+
local_html << "<td><div class='json-attr'>#{value}</div></td>"
|
125
|
+
end
|
126
|
+
local_html << "</tr>"
|
127
|
+
local_html.sub!(/class='collapsed/, 'class=\'collapsed parent') if is_parent
|
128
|
+
local_html.sub!(/<span/, "<span class='expander'") if is_parent
|
129
|
+
html << local_html
|
130
|
+
to_send.each { |s| count = s.call }
|
131
|
+
count += to_send.length
|
132
|
+
end
|
133
|
+
count
|
134
|
+
end
|
135
|
+
|
136
|
+
# Recursively build a tree of lists.
|
137
|
+
#def build_tree(node)
|
138
|
+
# list = "<dl>"
|
139
|
+
# list << "\n<!-- Beginning of Tree -->"
|
140
|
+
# walk = lambda do |key,value|
|
141
|
+
# case value
|
142
|
+
# when Hash, Array
|
143
|
+
# list << "\n<!-- Beginning of Enumerable obj -->"
|
144
|
+
# list << "\n<dt>#{key}</dt>"
|
145
|
+
# list << "<dd>"
|
146
|
+
# list << "\t<dl>\n"
|
147
|
+
# value.each(&walk)
|
148
|
+
# list << "\t</dl>\n"
|
149
|
+
# list << "</dd>"
|
150
|
+
# list << "\n<!-- End of Enumerable obj -->"
|
151
|
+
#
|
152
|
+
# else
|
153
|
+
# list << "\n<dt>#{key}</dt>"
|
154
|
+
# list << "<dd>#{value}</dd>"
|
155
|
+
# end
|
156
|
+
# end
|
157
|
+
# node.sort{ |a,b| a[0] <=> b[0] }.each(&walk)
|
158
|
+
# list << "</dl>"
|
159
|
+
#end
|
160
|
+
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|