chef-server-slice 0.7.10

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 (158) hide show
  1. data/LICENSE +201 -0
  2. data/README.rdoc +135 -0
  3. data/app/controllers/application.rb +228 -0
  4. data/app/controllers/cookbook_attributes.rb +59 -0
  5. data/app/controllers/cookbook_definitions.rb +60 -0
  6. data/app/controllers/cookbook_files.rb +94 -0
  7. data/app/controllers/cookbook_libraries.rb +60 -0
  8. data/app/controllers/cookbook_recipes.rb +59 -0
  9. data/app/controllers/cookbook_templates.rb +80 -0
  10. data/app/controllers/cookbooks.rb +63 -0
  11. data/app/controllers/exceptions.rb +33 -0
  12. data/app/controllers/main.rb +7 -0
  13. data/app/controllers/nodes.rb +144 -0
  14. data/app/controllers/openid_consumer.rb +133 -0
  15. data/app/controllers/openid_register.rb +113 -0
  16. data/app/controllers/openid_server.rb +252 -0
  17. data/app/controllers/roles.rb +138 -0
  18. data/app/controllers/search.rb +58 -0
  19. data/app/controllers/search_entries.rb +73 -0
  20. data/app/controllers/status.rb +34 -0
  21. data/app/helpers/application_helper.rb +144 -0
  22. data/app/helpers/cookbook_attributes_helper.rb +7 -0
  23. data/app/helpers/cookbook_definitions_helper.rb +8 -0
  24. data/app/helpers/cookbook_files_helper.rb +8 -0
  25. data/app/helpers/cookbook_libraries_helper.rb +7 -0
  26. data/app/helpers/cookbook_recipes_helper.rb +8 -0
  27. data/app/helpers/cookbook_templates_helper.rb +8 -0
  28. data/app/helpers/cookbooks_helper.rb +31 -0
  29. data/app/helpers/exceptions_helper.rb +6 -0
  30. data/app/helpers/global_helpers.rb +39 -0
  31. data/app/helpers/nodes_helper.rb +33 -0
  32. data/app/helpers/openid_consumer_helper.rb +8 -0
  33. data/app/helpers/openid_register_helper.rb +8 -0
  34. data/app/helpers/openid_server_helper.rb +6 -0
  35. data/app/helpers/openid_server_helpers.rb +29 -0
  36. data/app/helpers/roles_helper.rb +5 -0
  37. data/app/helpers/search_entries_helper.rb +8 -0
  38. data/app/helpers/search_helper.rb +38 -0
  39. data/app/helpers/status_helper.rb +26 -0
  40. data/app/views/cookbook_templates/index.html.haml +7 -0
  41. data/app/views/cookbooks/index.html.haml +10 -0
  42. data/app/views/cookbooks/show.html.haml +40 -0
  43. data/app/views/exceptions/bad_request.json.erb +1 -0
  44. data/app/views/exceptions/internal_server_error.html.erb +216 -0
  45. data/app/views/exceptions/not_acceptable.html.erb +63 -0
  46. data/app/views/exceptions/not_found.html.erb +47 -0
  47. data/app/views/exceptions/standard_error.html.erb +217 -0
  48. data/app/views/layout/chef_server_slice.html.haml +53 -0
  49. data/app/views/layout/login.html.haml +37 -0
  50. data/app/views/main/index.html.erb +1 -0
  51. data/app/views/nodes/_action.html.haml +13 -0
  52. data/app/views/nodes/_form.html.haml +56 -0
  53. data/app/views/nodes/_navigation.html.haml +9 -0
  54. data/app/views/nodes/_resource.html.haml +22 -0
  55. data/app/views/nodes/edit.html.haml +7 -0
  56. data/app/views/nodes/index.html.haml +25 -0
  57. data/app/views/nodes/new.html.haml +6 -0
  58. data/app/views/nodes/show.html.haml +60 -0
  59. data/app/views/openid_consumer/index.html.haml +23 -0
  60. data/app/views/openid_consumer/start.html.haml +4 -0
  61. data/app/views/openid_login/index.html.haml +5 -0
  62. data/app/views/openid_register/index.html.haml +19 -0
  63. data/app/views/openid_register/show.html.haml +7 -0
  64. data/app/views/openid_server/decide.html.haml +27 -0
  65. data/app/views/roles/_form.html.haml +48 -0
  66. data/app/views/roles/_navigation.html.haml +9 -0
  67. data/app/views/roles/edit.html.haml +6 -0
  68. data/app/views/roles/index.html.haml +22 -0
  69. data/app/views/roles/new.html.haml +6 -0
  70. data/app/views/roles/show.html.haml +29 -0
  71. data/app/views/search/_search_form.html.haml +6 -0
  72. data/app/views/search/index.html.haml +9 -0
  73. data/app/views/search/show.html.haml +14 -0
  74. data/app/views/search_entries/index.html.haml +8 -0
  75. data/app/views/search_entries/show.html.haml +7 -0
  76. data/app/views/status/index.html.haml +88 -0
  77. data/config/init.rb +48 -0
  78. data/config/router.rb +6 -0
  79. data/lib/chef-server-slice.rb +150 -0
  80. data/lib/chef-server-slice/merbtasks.rb +103 -0
  81. data/lib/chef-server-slice/slicetasks.rb +20 -0
  82. data/lib/chef-server-slice/spectasks.rb +53 -0
  83. data/public/facebox/README.txt +4 -0
  84. data/public/facebox/b.png +0 -0
  85. data/public/facebox/bl.png +0 -0
  86. data/public/facebox/br.png +0 -0
  87. data/public/facebox/closelabel.gif +0 -0
  88. data/public/facebox/facebox.css +95 -0
  89. data/public/facebox/facebox.js +319 -0
  90. data/public/facebox/loading.gif +0 -0
  91. data/public/facebox/tl.png +0 -0
  92. data/public/facebox/tr.png +0 -0
  93. data/public/images/avatar.png +0 -0
  94. data/public/images/black_big.png +0 -0
  95. data/public/images/indicator.gif +0 -0
  96. data/public/images/merb.jpg +0 -0
  97. data/public/images/toggle-collapse-dark.png +0 -0
  98. data/public/images/toggle-collapse-light.png +0 -0
  99. data/public/images/toggle-collapse.gif +0 -0
  100. data/public/images/toggle-expand-dark.png +0 -0
  101. data/public/images/toggle-expand-light.png +0 -0
  102. data/public/images/toggle-expand.gif +0 -0
  103. data/public/images/treeBuilderImages/Thumbs.db +0 -0
  104. data/public/images/treeBuilderImages/doc.gif +0 -0
  105. data/public/images/treeBuilderImages/docNode.gif +0 -0
  106. data/public/images/treeBuilderImages/docNodeLast.gif +0 -0
  107. data/public/images/treeBuilderImages/docNodeLastFirst.gif +0 -0
  108. data/public/images/treeBuilderImages/folder.gif +0 -0
  109. data/public/images/treeBuilderImages/folderNode.gif +0 -0
  110. data/public/images/treeBuilderImages/folderNodeFirst.gif +0 -0
  111. data/public/images/treeBuilderImages/folderNodeLast.gif +0 -0
  112. data/public/images/treeBuilderImages/folderNodeLastFirst.gif +0 -0
  113. data/public/images/treeBuilderImages/folderNodeOpen.gif +0 -0
  114. data/public/images/treeBuilderImages/folderNodeOpenFirst.gif +0 -0
  115. data/public/images/treeBuilderImages/folderNodeOpenLast.gif +0 -0
  116. data/public/images/treeBuilderImages/folderNodeOpenLastFirst.gif +0 -0
  117. data/public/images/treeBuilderImages/folderOpen.gif +0 -0
  118. data/public/images/treeBuilderImages/vertLine.gif +0 -0
  119. data/public/javascripts/JSONeditor.js +1171 -0
  120. data/public/javascripts/chef.js +126 -0
  121. data/public/javascripts/jquery-1.3.2.min.js +19 -0
  122. data/public/javascripts/jquery-ui-1.7.1.custom.min.js +65 -0
  123. data/public/javascripts/jquery.editinline.js +108 -0
  124. data/public/javascripts/jquery.jeditable.mini.js +30 -0
  125. data/public/javascripts/jquery.livequery.js +250 -0
  126. data/public/javascripts/jquery.localscroll.js +104 -0
  127. data/public/javascripts/jquery.scrollTo.js +150 -0
  128. data/public/javascripts/jquery.tools.min.js +17 -0
  129. data/public/javascripts/jquery.treeTable.min.js +165 -0
  130. data/public/stylesheets/base.css +336 -0
  131. data/public/stylesheets/chef.css +157 -0
  132. data/public/stylesheets/images/ui-bg_diagonals-small_0_aaaaaa_40x40.png +0 -0
  133. data/public/stylesheets/images/ui-bg_diagonals-thick_15_444444_40x40.png +0 -0
  134. data/public/stylesheets/images/ui-bg_glass_100_f0f0f0_1x400.png +0 -0
  135. data/public/stylesheets/images/ui-bg_glass_50_99c2ff_1x400.png +0 -0
  136. data/public/stylesheets/images/ui-bg_glass_55_fbf5d0_1x400.png +0 -0
  137. data/public/stylesheets/images/ui-bg_glass_80_e6e6e6_1x400.png +0 -0
  138. data/public/stylesheets/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  139. data/public/stylesheets/images/ui-bg_highlight-hard_100_f9f9f9_1x100.png +0 -0
  140. data/public/stylesheets/images/ui-bg_highlight-soft_100_e7eef3_1x100.png +0 -0
  141. data/public/stylesheets/images/ui-icons_222222_256x240.png +0 -0
  142. data/public/stylesheets/images/ui-icons_2694e8_256x240.png +0 -0
  143. data/public/stylesheets/images/ui-icons_2e83ff_256x240.png +0 -0
  144. data/public/stylesheets/images/ui-icons_72a7cf_256x240.png +0 -0
  145. data/public/stylesheets/images/ui-icons_888888_256x240.png +0 -0
  146. data/public/stylesheets/images/ui-icons_cd0a0a_256x240.png +0 -0
  147. data/public/stylesheets/images/ui-icons_ffffff_256x240.png +0 -0
  148. data/public/stylesheets/jquery-ui-1.7.1.custom.css +404 -0
  149. data/public/stylesheets/jquery.treeTable.css +43 -0
  150. data/public/stylesheets/themes/bec-green/style.css +290 -0
  151. data/public/stylesheets/themes/bec/style.css +301 -0
  152. data/public/stylesheets/themes/blue/style.css +280 -0
  153. data/public/stylesheets/themes/default/style.css +267 -0
  154. data/public/stylesheets/themes/djime-cerulean/style.css +298 -0
  155. data/public/stylesheets/themes/kathleene/style.css +272 -0
  156. data/public/stylesheets/themes/orange/style.css +263 -0
  157. data/public/stylesheets/themes/reidb-greenish/style.css +301 -0
  158. metadata +341 -0
@@ -0,0 +1,138 @@
1
+ require 'chef/role'
2
+
3
+ class ChefServerSlice::Roles < ChefServerSlice::Application
4
+
5
+ provides :html, :json
6
+ before :login_required
7
+
8
+ # GET /roles
9
+ def index
10
+ @role_list = Chef::Role.list(true)
11
+ display(@role_list.collect { |r| absolute_slice_url(:role, r.name) })
12
+ end
13
+
14
+ # GET /roles/:id
15
+ def show
16
+ begin
17
+ @role = Chef::Role.load(params[:id])
18
+ rescue Net::HTTPServerException => e
19
+ raise NotFound, "Cannot load role #{params[:id]}"
20
+ end
21
+ display @role
22
+ end
23
+
24
+ # GET /roles/new
25
+ def new
26
+ @available_recipes = get_available_recipes
27
+ @role = Chef::Role.new
28
+ @current_recipes = @role.recipes
29
+ render
30
+ end
31
+
32
+ # GET /roles/:id/edit
33
+ def edit
34
+ begin
35
+ @role = Chef::Role.load(params[:id])
36
+ rescue Net::HTTPServerException => e
37
+ raise NotFound, "Cannot load role #{params[:id]}"
38
+ end
39
+ @available_recipes = get_available_recipes
40
+ @current_recipes = @role.recipes
41
+ render
42
+ end
43
+
44
+ # GET /roles/:id/delete
45
+ def delete
46
+
47
+ end
48
+
49
+ # POST /roles
50
+ def create
51
+ if params.has_key?("inflated_object")
52
+ @role = params["inflated_object"]
53
+ exists = true
54
+ begin
55
+ Chef::Role.load(@role.name)
56
+ rescue Net::HTTPServerException
57
+ exists = false
58
+ end
59
+ raise Forbidden, "Role already exists" if exists
60
+
61
+ @role.save
62
+ self.status = 201
63
+ display({ :uri => absolute_slice_url(:role, @role.name) })
64
+ else
65
+ begin
66
+ @role = Chef::Role.new
67
+ @role.name(params[:name])
68
+ @role.recipes(params[:for_role] ? params[:for_role] : [])
69
+ @role.description(params[:description]) if params[:description] != ''
70
+ @role.default_attributes(JSON.parse(params[:default_attributes])) if params[:default_attributes] != ''
71
+ @role.override_attributes(JSON.parse(params[:override_attributes])) if params[:override_attributes] != ''
72
+ @role.save
73
+ redirect(slice_url(:roles), :message => { :notice => "Created Role #{@role.name}" })
74
+ rescue ArgumentError
75
+ @available_recipes = get_available_recipes
76
+ @role = Chef::Role.new
77
+ @role.default_attributes(JSON.parse(params[:default_attributes])) if params[:default_attributes] != ''
78
+ @role.override_attributes(JSON.parse(params[:override_attributes])) if params[:override_attributes] != ''
79
+ @current_recipes = params[:for_role] ? params[:for_role] : []
80
+ @_message = { :error => $! }
81
+ render :new
82
+ end
83
+ end
84
+ end
85
+
86
+ # PUT /roles/:id
87
+ def update
88
+ begin
89
+ @role = Chef::Role.load(params[:id])
90
+ rescue Net::HTTPServerException => e
91
+ raise NotFound, "Cannot load role #{params[:id]}"
92
+ end
93
+
94
+ if params.has_key?("inflated_object")
95
+ @role.description(params["inflated_object"].description)
96
+ @role.recipes(params["inflated_object"].recipes)
97
+ @role.default_attributes(params["inflated_object"].default_attributes)
98
+ @role.override_attributes(params["inflated_object"].override_attributes)
99
+ @role.save
100
+ self.status = 200
101
+ display(@role)
102
+ else
103
+ begin
104
+ @role.recipes(params[:for_role])
105
+ @role.description(params[:description]) if params[:description] != ''
106
+ @role.default_attributes(JSON.parse(params[:default_attributes])) if params[:default_attributes] != ''
107
+ @role.override_attributes(JSON.parse(params[:override_attributes])) if params[:override_attributes] != ''
108
+ @role.save
109
+ @_message = { :notice => "Updated Role" }
110
+ render :show
111
+ rescue ArgumentError
112
+ @available_recipes = get_available_recipes
113
+ @current_recipes = params[:for_role] ? params[:for_role] : []
114
+ @role.default_attributes(JSON.parse(params[:default_attributes])) if params[:default_attributes] != ''
115
+ @role.override_attributes(JSON.parse(params[:override_attributes])) if params[:override_attributes] != ''
116
+ render :edit
117
+ end
118
+
119
+ end
120
+ end
121
+
122
+ # DELETE /roles/:id
123
+ def destroy
124
+ begin
125
+ @role = Chef::Role.load(params[:id])
126
+ rescue Net::HTTPServerException => e
127
+ raise NotFound, "Cannot load role #{params[:id]}"
128
+ end
129
+ @role.destroy
130
+
131
+ if request.accept == "application/json"
132
+ display @role
133
+ else
134
+ redirect(absolute_slice_url(:roles), :message => { :notice => "Role #{@role.name} deleted successfully." }, :permanent => true)
135
+ end
136
+ end
137
+
138
+ end
@@ -0,0 +1,58 @@
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' / 'search'
21
+ require 'chef' / 'queue'
22
+
23
+ class ChefServerSlice::Search < ChefServerSlice::Application
24
+
25
+ provides :html, :json
26
+ before :login_required
27
+
28
+ def index
29
+ @s = Chef::Search.new
30
+ @search_indexes = @s.list_indexes
31
+ display @search_indexes
32
+ end
33
+
34
+ def show
35
+ @s = Chef::Search.new
36
+
37
+ query = params[:q].nil? ? "*" : (params[:q].empty? ? "*" : params[:q])
38
+ attributes = params[:a].nil? ? [] : params[:a].split(",").collect { |a| a.to_sym }
39
+ @results = @s.search(params[:id], query, attributes)
40
+
41
+ display @results
42
+ end
43
+
44
+ def destroy
45
+ @s = Chef::Search.new
46
+ @entries = @s.search(params[:id], "*")
47
+ @entries.each do |entry|
48
+ Chef::Queue.send_msg(:queue, :remove, entry)
49
+ end
50
+ @status = 202
51
+ if content_type == :html
52
+ redirect url(:search)
53
+ else
54
+ display @entries
55
+ end
56
+ end
57
+
58
+ end
@@ -0,0 +1,73 @@
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' / 'search'
21
+ require 'chef' / 'queue'
22
+
23
+ class ChefServerSlice::SearchEntries < ChefServerSlice::Application
24
+
25
+ provides :html, :json
26
+ before :login_required
27
+
28
+ def index
29
+ @s = Chef::Search.new
30
+ @entries = @s.search(params[:search_id])
31
+ display @entries
32
+ end
33
+
34
+ def show
35
+ @s = Chef::Search.new
36
+ @entry = @s.search(params[:search_id], "id:'#{params[:search_id]}_#{params[:id]}'").first
37
+ display @entry
38
+ end
39
+
40
+ def create
41
+ @to_index = params
42
+ @to_index.delete(:controller)
43
+ @to_index["index_name"] = params[:search_id]
44
+ @to_index["id"] = "#{params[:search_id]}_#{params[:id]}"
45
+ @to_index.delete(:search_id)
46
+ Chef::Queue.send_msg(:queue, :index, @to_index)
47
+ if content_type == :html
48
+ redirect url(:search)
49
+ else
50
+ @status = 202
51
+ display @to_index
52
+ end
53
+ end
54
+
55
+ def update
56
+ create
57
+ end
58
+
59
+ def destroy
60
+ @s = Chef::Search.new
61
+ @entries = @s.search(params[:id])
62
+ @entries.each do |entry|
63
+ Chef::Queue.send_msg(:queue, :remove, entry)
64
+ end
65
+ @status = 202
66
+ if content_type == :html
67
+ redirect url(:search)
68
+ else
69
+ display @entries
70
+ end
71
+ end
72
+
73
+ end
@@ -0,0 +1,34 @@
1
+ #
2
+ # Author:: Joe Williams (joe@joetify.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 'chef' / 'node'
20
+
21
+ class ChefServerSlice::Status < ChefServerSlice::Application
22
+
23
+ provides :html, :json
24
+ before :login_required
25
+
26
+ def index
27
+ @status = Chef::CouchDB.new.get_view("nodes", "status")["rows"].inject([]) do |result, item|
28
+ result << item["value"]
29
+ result
30
+ end
31
+ display @status
32
+ end
33
+
34
+ end
@@ -0,0 +1,144 @@
1
+ require 'chef/mixin/deep_merge'
2
+
3
+ module Merb
4
+ module ChefServerSlice
5
+ module ApplicationHelper
6
+
7
+ # @param *segments<Array[#to_s]> Path segments to append.
8
+ #
9
+ # @return <String>
10
+ # A path relative to the public directory, with added segments.
11
+ def image_path(*segments)
12
+ public_path_for(:image, *segments)
13
+ end
14
+
15
+ # @param *segments<Array[#to_s]> Path segments to append.
16
+ #
17
+ # @return <String>
18
+ # A path relative to the public directory, with added segments.
19
+ def javascript_path(*segments)
20
+ public_path_for(:javascript, *segments)
21
+ end
22
+
23
+ # @param *segments<Array[#to_s]> Path segments to append.
24
+ #
25
+ # @return <String>
26
+ # A path relative to the public directory, with added segments.
27
+ def stylesheet_path(*segments)
28
+ public_path_for(:stylesheet, *segments)
29
+ end
30
+
31
+ # Construct a path relative to the public directory
32
+ #
33
+ # @param <Symbol> The type of component.
34
+ # @param *segments<Array[#to_s]> Path segments to append.
35
+ #
36
+ # @return <String>
37
+ # A path relative to the public directory, with added segments.
38
+ def public_path_for(type, *segments)
39
+ ::ChefServerSlice.public_path_for(type, *segments)
40
+ end
41
+
42
+ # Construct an app-level path.
43
+ #
44
+ # @param <Symbol> The type of component.
45
+ # @param *segments<Array[#to_s]> Path segments to append.
46
+ #
47
+ # @return <String>
48
+ # A path within the host application, with added segments.
49
+ def app_path_for(type, *segments)
50
+ ::ChefServerSlice.app_path_for(type, *segments)
51
+ end
52
+
53
+ # Construct a slice-level path.
54
+ #
55
+ # @param <Symbol> The type of component.
56
+ # @param *segments<Array[#to_s]> Path segments to append.
57
+ #
58
+ # @return <String>
59
+ # A path within the slice source (Gem), with added segments.
60
+ def slice_path_for(type, *segments)
61
+ ::ChefServerSlice.slice_path_for(type, *segments)
62
+ end
63
+
64
+ def build_tree(name, node, default={}, override={})
65
+ node = Chef::Mixin::DeepMerge.merge(default, node)
66
+ node = Chef::Mixin::DeepMerge.merge(node, override)
67
+ html = "<table id='#{name}' class='tree table'>"
68
+ html << "<tr><th class='first'>Attribute</th><th class='last'>Value</th></tr>"
69
+ count = 0
70
+ parent = 0
71
+ append_tree(name, html, node, count, parent, override)
72
+ html << "</table>"
73
+ html
74
+ end
75
+
76
+ def append_tree(name, html, node, count, parent, override)
77
+ node.sort{ |a,b| a[0] <=> b[0] }.each do |key, value|
78
+ to_send = Array.new
79
+ count += 1
80
+ is_parent = false
81
+ local_html = ""
82
+ local_html << "<tr id='#{name}-#{count}' class='collapsed #{name}"
83
+ if parent != 0
84
+ local_html << " child-of-#{name}-#{parent}' style='display: none;'>"
85
+ else
86
+ local_html << "'>"
87
+ end
88
+ local_html << "<td class='table-key'><span toggle='#{name}-#{count}'/>#{key}</td>"
89
+ case value
90
+ when Hash
91
+ is_parent = true
92
+ local_html << "<td></td>"
93
+ p = count
94
+ to_send << Proc.new { append_tree(name, html, value, count, p, override) }
95
+ when Array
96
+ is_parent = true
97
+ local_html << "<td></td>"
98
+ as_hash = {}
99
+ value.each_index { |i| as_hash[i] = value[i] }
100
+ p = count
101
+ to_send << Proc.new { append_tree(name, html, as_hash, count, p, override) }
102
+ when String,Symbol
103
+ local_html << "<td><div class='json-attr'>#{value}</div></td>"
104
+ else
105
+ local_html << "<td>#{JSON.pretty_generate(value)}</td>"
106
+ end
107
+ local_html << "</tr>"
108
+ local_html.sub!(/class='collapsed/, 'class=\'collapsed parent') if is_parent
109
+ local_html.sub!(/<span/, "<span class='expander'") if is_parent
110
+ html << local_html
111
+ to_send.each { |s| count = s.call }
112
+ count += to_send.length
113
+ end
114
+ count
115
+ end
116
+
117
+ # Recursively build a tree of lists.
118
+ #def build_tree(node)
119
+ # list = "<dl>"
120
+ # list << "\n<!-- Beginning of Tree -->"
121
+ # walk = lambda do |key,value|
122
+ # case value
123
+ # when Hash, Array
124
+ # list << "\n<!-- Beginning of Enumerable obj -->"
125
+ # list << "\n<dt>#{key}</dt>"
126
+ # list << "<dd>"
127
+ # list << "\t<dl>\n"
128
+ # value.each(&walk)
129
+ # list << "\t</dl>\n"
130
+ # list << "</dd>"
131
+ # list << "\n<!-- End of Enumerable obj -->"
132
+ #
133
+ # else
134
+ # list << "\n<dt>#{key}</dt>"
135
+ # list << "<dd>#{value}</dd>"
136
+ # end
137
+ # end
138
+ # node.sort{ |a,b| a[0] <=> b[0] }.each(&walk)
139
+ # list << "</dl>"
140
+ #end
141
+
142
+ end
143
+ end
144
+ end