chef-server-webui 0.9.18 → 0.10.0.beta.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/README.rdoc +0 -4
  2. data/Rakefile +10 -0
  3. data/app/controllers/application.rb +34 -6
  4. data/app/controllers/cookbooks.rb +125 -35
  5. data/app/controllers/environments.rb +235 -0
  6. data/app/controllers/nodes.rb +26 -19
  7. data/app/controllers/roles.rb +37 -44
  8. data/app/controllers/search.rb +13 -13
  9. data/app/helpers/application_helper.rb +34 -0
  10. data/app/views/cookbooks/_cookbook_content.html.haml +7 -0
  11. data/app/views/cookbooks/index.html.haml +22 -7
  12. data/app/views/cookbooks/show.html.haml +8 -50
  13. data/app/views/environments/_form.html.erb +91 -0
  14. data/app/views/environments/_navigation.html.haml +9 -0
  15. data/app/views/environments/_version_selector.html.erb +8 -0
  16. data/app/views/environments/edit.html.erb +17 -0
  17. data/app/views/environments/index.html.haml +26 -0
  18. data/app/views/environments/new.html.erb +17 -0
  19. data/app/views/environments/show.html.haml +31 -0
  20. data/app/views/layout/application.html.haml +22 -13
  21. data/app/views/layout/login.html.haml +2 -2
  22. data/app/views/nodes/_form.html.erb +69 -0
  23. data/app/views/nodes/index.html.haml +6 -2
  24. data/app/views/nodes/show.html.haml +4 -1
  25. data/app/views/roles/_form.html.erb +92 -0
  26. data/app/views/roles/_run_lists.html.erb +26 -0
  27. data/app/views/roles/edit.html.haml +1 -1
  28. data/app/views/roles/new.html.haml +1 -1
  29. data/app/views/roles/show.html.haml +10 -7
  30. data/app/views/status/index.html.haml +2 -1
  31. data/bin/chef-server-webui +1 -0
  32. data/config/router.rb +14 -8
  33. data/lib/chef-server-webui/version.rb +1 -1
  34. data/public/javascripts/chef.js +206 -49
  35. data/public/javascripts/cookbook_constraint_ctrl.js +191 -0
  36. data/public/javascripts/cookbook_versions.js +75 -0
  37. data/public/javascripts/jquery-1.4.4.min.js +167 -0
  38. data/public/javascripts/jquery.suggest.js +250 -0
  39. data/public/stylesheets/base.css +30 -24
  40. data/public/stylesheets/chef.css +212 -45
  41. data/public/stylesheets/jquery.suggest.css +28 -0
  42. data/public/stylesheets/jsonedit_main.css +26 -10
  43. data/public/stylesheets/themes/djime-cerulean/style.css +31 -18
  44. metadata +22 -29
  45. data/app/controllers/cookbook_attributes.rb +0 -41
  46. data/app/controllers/cookbook_definitions.rb +0 -41
  47. data/app/controllers/cookbook_files.rb +0 -39
  48. data/app/controllers/cookbook_libraries.rb +0 -41
  49. data/app/controllers/cookbook_recipes.rb +0 -40
  50. data/app/controllers/cookbook_templates.rb +0 -57
  51. data/app/helpers/cookbook_attributes_helper.rb +0 -7
  52. data/app/helpers/cookbook_definitions_helper.rb +0 -8
  53. data/app/helpers/cookbook_files_helper.rb +0 -8
  54. data/app/helpers/cookbook_libraries_helper.rb +0 -7
  55. data/app/helpers/cookbook_recipes_helper.rb +0 -8
  56. data/app/helpers/cookbook_templates_helper.rb +0 -8
  57. data/app/helpers/exceptions_helper.rb +0 -6
  58. data/app/helpers/global_helpers.rb +0 -39
  59. data/app/helpers/nodes_helper.rb +0 -43
  60. data/app/helpers/openid_consumer_helper.rb +0 -8
  61. data/app/helpers/openid_register_helper.rb +0 -8
  62. data/app/helpers/openid_server_helper.rb +0 -6
  63. data/app/helpers/openid_server_helpers.rb +0 -32
  64. data/app/helpers/roles_helper.rb +0 -5
  65. data/app/helpers/search_entries_helper.rb +0 -8
  66. data/app/helpers/search_helper.rb +0 -44
  67. data/app/views/nodes/_form.html.haml +0 -52
  68. data/app/views/roles/_form.html.haml +0 -52
@@ -0,0 +1,26 @@
1
+ <div class="runListWithControlsContainer <%= environment == @current_env ? 'active' : 'inactive' -%>" id="<%= environment %>">
2
+ <div class="sortable runListContainer">
3
+
4
+ <% run_list_class, empty_controls_class = run_list ? %w{active inactive} : %w{inactive active} -%>
5
+
6
+ <ul class="ui-sortable connectedSortable runListItemList <%= run_list_class -%>" id="<%= environment %>">
7
+ <% Array(run_list).each do |item| %>
8
+ <li id="<%=h(item)%>" class="<%= class_for_run_list_item(item) -%> runListItem"><%=h display_run_list_item(item)-%></li>
9
+ <% end %>
10
+ </ul>
11
+ <div class="emptyRunListControlsContainer <%= empty_controls_class -%>" id="<%=environment -%>">
12
+ <div class="cloneRunListTitle">This role has no environment specific run list for the (<%= environment -%>) environment.</div>
13
+ <div class="cloneRunListOption">
14
+ <a href="javascript:void(0)" class="createEmptyRunListControl" id="<%= environment -%>">Create a new empty run list</a>
15
+ </div>
16
+ <div class="cloneRunListOption">
17
+ Or, clone an existing run list: <%= select :environment_to_clone, :collection => @existing_run_list_environments, :id => environment, :class => 'environmentToClone' %>
18
+ </div>
19
+ </div>
20
+ </div>
21
+ <div class="runListAdditionalControls" id="<%= environment -%>">
22
+ <% if run_list && (environment != '_default')%>
23
+ <a href="javascript:void(0);" class="deleteEnvRunList" id="<%= environment -%>">Remove environment specific run list for <%= environment %></a>
24
+ <% end %>
25
+ </div>
26
+ </div>
@@ -3,4 +3,4 @@
3
3
  %h2.title= "Role #{h @role.name}"
4
4
  .inner
5
5
  = partial('navigation', :active => 'edit')
6
- = partial('form', :header => "Edit Role #{@role.name}", :form_id => 'edit_role', :submit_name => "Save Role", :submit_id => "edit_role_button", :form_for => 'edit', :form_url => url(:role, @role.name) )
6
+ = partial('form', :header => "Edit Role #{@role.name}", :form_id => 'edit_role', :submit_name => "Save Role", :submit_id => "edit_role_button", :form_for => 'edit', :form_url => url(:role, @role.name), :method => :put)
@@ -3,4 +3,4 @@
3
3
  %h2.title= "Role"
4
4
  .inner
5
5
  = partial('navigation', :active => 'create')
6
- = partial('form', :header => "Create new Role", :form_id => 'create_role', :submit_name => "Create Role", :submit_id => "create_role_button", :form_for => 'create', :form_url => url(:roles))
6
+ = partial('form', :header => "Create new Role", :form_id => 'create_role', :submit_name => "Create Role", :submit_id => "create_role_button", :method => :post, :form_for => 'create', :form_url => url(:roles))
@@ -10,24 +10,27 @@
10
10
  = @role.description
11
11
 
12
12
  .left
13
- %h3 Run List
13
+ %h3
14
+ = "Run List for Environment \"#{@current_env}\""
15
+ = @env_run_list_exists ? "" : "(_default)"
14
16
  %table.table
15
17
  %tr
16
18
  %th.first Position
17
19
  %th Name
20
+ %th Version
18
21
  %th.last Type
19
- - if @role.run_list.empty?
22
+ - if @run_list.empty?
20
23
  %tr
21
24
  %td{:colspan => 2} This role does not include any roles or recipes.
22
25
  - else
23
- -@role.run_list.each_with_index do |run_list_item, i|
26
+ -@run_list.each_with_index do |run_list_item, i|
24
27
  %tr
25
28
  %td.position= i
26
29
  %td= run_list_item.name
30
+ %td= run_list_item.version
27
31
  %td= run_list_item.type
28
32
  .left.accordion
29
33
  %h3.head= link_to("Recipes", "#")
30
- - recipes = @role.run_list.expand('server').recipes
31
34
  %div
32
35
  %span.description.form.help
33
36
  This is the list of recipes, fully expanded, as they will be applied to the node in question.
@@ -35,14 +38,14 @@
35
38
  %tr
36
39
  %th.first Position
37
40
  %th.last Name
38
- - if @role.run_list.empty?
41
+ - if @run_list.empty?
39
42
  %tr
40
43
  %td{:colspan => 2} This node has no recipes applied.
41
44
  - else
42
- - recipes.each_with_index do |recipe, i|
45
+ - @recipes.each_with_index do |recipe, i|
43
46
  %tr
44
47
  %td.position= i
45
- %td= recipes
48
+ %td= recipe
46
49
  .left
47
50
  %h3 Default Attributes
48
51
  = build_tree('defattrs', @role.default_attributes)
@@ -79,6 +79,7 @@
79
79
  %tr
80
80
  %th.first Position
81
81
  %th Name
82
+ %th Version
82
83
  %th.last Type
83
84
  %tbody
84
85
  - if node[1].run_list.empty?
@@ -89,5 +90,5 @@
89
90
  %tr
90
91
  %td.position= i
91
92
  %td= run_list_item.name
93
+ %td= run_list_item.version
92
94
  %td= run_list_item.type
93
-
@@ -28,6 +28,7 @@ require "merb-core"
28
28
 
29
29
  # Load chef and chef-server-api from source rather than gem, if present
30
30
  $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../../chef/lib'))
31
+ $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../../chef-solr/lib/'))
31
32
  $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib'))
32
33
 
33
34
  # Print the version if we have -v or --version
data/config/router.rb CHANGED
@@ -19,9 +19,20 @@
19
19
 
20
20
  Merb::Router.prepare do
21
21
  resources :nodes, :id => /[^\/]+/
22
+ match("/nodes/_environments/:environment_id").to(:controller => "nodes", :action => "index").name(:nodes_by_environment)
23
+
22
24
  resources :clients, :id => /[^\/]+/
23
25
  resources :roles
24
26
 
27
+ resources :environments do |e|
28
+ e.match("/recipes", :method => "get").to(:controller=>"environments", :action=>"list_recipes")
29
+ e.match("/cookbooks").to(:contoller => "environments", :action => "list_cookbooks").name(:cookbooks)
30
+ e.match("/nodes").to(:controller => "environments", :action => "list_nodes").name(:nodes)
31
+ e.match("/select").to(:controller => "environments", :action => "select_environment").name(:select)
32
+ end
33
+
34
+ #match('/environments/create').to(:controller => "environments", :action => "create").name(:environments_create)
35
+
25
36
  match("/status").to(:controller => "status", :action => "index").name(:status)
26
37
 
27
38
  resources :searches, :path => "search", :controller => "search"
@@ -36,17 +47,12 @@ Merb::Router.prepare do
36
47
  match("/cookbooks/_recipe_files").to(:controller => "cookbooks", :action => "recipe_files")
37
48
  match("/cookbooks/_definition_files").to(:controller => "cookbooks", :action => "definition_files")
38
49
  match("/cookbooks/_library_files").to(:controller => "cookbooks", :action => "library_files")
50
+ match("/cookbooks/_environments/:environment_id").to(:controller => "cookbooks", :action => "index").name(:cookbooks_by_environment)
39
51
 
40
- match("/cookbooks/:cookbook_id/templates", :cookbook_id => /[\w\.]+/).to(:controller => "cookbook_templates", :action => "index")
41
- match("/cookbooks/:cookbook_id/libraries", :cookbook_id => /[\w\.]+/).to(:controller => "cookbook_libraries", :action => "index")
42
- match("/cookbooks/:cookbook_id/definitions", :cookbook_id => /[\w\.]+/).to(:controller => "cookbook_definitions", :action => "index")
43
- match("/cookbooks/:cookbook_id/recipes", :cookbook_id => /[\w\.]+/).to(:controller => "cookbook_recipes", :action => "index")
44
- match("/cookbooks/:cookbook_id/attributes", :cookbook_id => /[\w\.]+/).to(:controller => "cookbook_attributes", :action => "index")
45
- match("/cookbooks/:cookbook_id/files", :cookbook_id => /[\w\.]+/).to(:controller => "cookbook_files", :action => "index")
46
-
52
+ match("/cookbooks/:cookbook_id", :cookbook_id => /[\w\.]+/, :method => 'get').to(:controller => "cookbooks", :action => "cb_versions")
47
53
  match("/cookbooks/:cookbook_id/:cb_version", :cb_version => /[\w\.]+/, :method => 'get').to(:controller => "cookbooks", :action => "show").name(:show_specific_version_cookbook)
48
54
  resources :cookbooks
49
-
55
+
50
56
  resources :clients
51
57
 
52
58
  match("/databags/:databag_id/databag_items", :method => 'get').to(:controller => "databags", :action => "show", :id=>":databag_id")
@@ -1,3 +1,3 @@
1
1
  module ChefServerWebui
2
- VERSION = '0.9.18'
2
+ VERSION = '0.10.0.beta.0'
3
3
  end
@@ -7,9 +7,9 @@
7
7
  // Licensed under the Apache License, Version 2.0 (the "License");
8
8
  // you may not use this file except in compliance with the License.
9
9
  // You may obtain a copy of the License at
10
- //
10
+ //
11
11
  // http://www.apache.org/licenses/LICENSE-2.0
12
- //
12
+ //
13
13
  // Unless required by applicable law or agreed to in writing, software
14
14
  // distributed under the License is distributed on an "AS IS" BASIS,
15
15
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -17,23 +17,45 @@
17
17
  // limitations under the License.
18
18
  //
19
19
 
20
+
20
21
  $(document).ready(function(){
21
22
 
22
- $('form#edit_role, form#create_role').submit(function(event) {
23
- var form = $(this);
24
- var to_role = $('ul#for_role').sortable('toArray');
25
- if (form.attr('id') == 'edit_role') {
26
- form.append('<input type="hidden" name="_method" value="put">');
27
- }
28
- form.append($('input#role_name')).css('display', 'none');
29
- form.append($('textarea#role_description')).css('display', 'none');
23
+ var buildHiddenFormFromDragDrop = function(form, runListSet) {
24
+ runListSet.each(function(i, envRunListUl) {
25
+ runListItemList = $(envRunListUl).find('li.runListItem')
26
+ if(runListItemList.length == 0){
27
+ activeRunListUl = envRunListUl.getAttribute("class").split(" ").indexOf('active')
28
+ if(activeRunListUl >= 0){
29
+ form.append('<input type="hidden" name="env_run_lists[' + envRunListUl.id + ']"/>');
30
+ }
31
+ }
32
+ else{
33
+ runListItemList.each(function(i, field) {
34
+ form.append('<input type="hidden" name="env_run_lists[' + envRunListUl.id + '][]" value="' + field.id + '"/>');
35
+ });
36
+ }
37
+ });
38
+ };
39
+
40
+ var buildHiddenFormFromJSONEditor = function(form) {
30
41
  form.append('<input type="hidden" id="default_attributes" name="default_attributes"/>');
31
- $('input#default_attributes').attr('value', BCJTEP.save('json["defaults"]'))
42
+ $('input#default_attributes').attr('value', BCJTEP.save('json["defaults"]'));
32
43
  form.append('<input type="hidden" id="override_attributes" name="override_attributes"/>');
33
44
  $('input#override_attributes').attr('value', BCJTEP.save('json["overrides"]'));
34
- jQuery.each(to_role, function(i, field) {
35
- form.append('<input type="hidden" name="for_role[]" value="' + field + '"/>');
36
- });
45
+ };
46
+
47
+ $('a#debugFormBuild').click(function(event) {buildHiddenFormFromDragDrop(event)});
48
+
49
+
50
+ $('form.roleForm').submit(function(event) {
51
+ buildHiddenFormFromDragDrop($(this), $('ul.runListItemList'));
52
+ buildHiddenFormFromJSONEditor($(this));
53
+ });
54
+
55
+ $('form#edit_environment, form#create_environment').submit(function(event) {
56
+ var form = $(this);
57
+ form.append('<input type="hidden" id="attributes" name="attributes"/>');
58
+ $('input#attributes').attr('value', BCJTEP.save('json'))
37
59
  });
38
60
 
39
61
  $('form#edit_node, form#create_node').submit(function(event) {
@@ -59,7 +81,7 @@ $(document).ready(function(){
59
81
  form.append($('input#json_data').attr('value', BCJTEP.save()));
60
82
  });
61
83
 
62
- $('form#edit_databag, form#create_databag').submit(function(event) {
84
+ $('form#edit_databag, form#create_databag').submit(function(event) {
63
85
  var form = $(this);
64
86
  if (form.attr('id') == 'edit_databag') {
65
87
  form.append('<input type="hidden" name="_method" value="put">');
@@ -84,77 +106,212 @@ $(document).ready(function(){
84
106
  var form = $(this);
85
107
  if (form.attr('id') == 'edit_user') {
86
108
  form.append('<input type="hidden" name="_method" value="put">');
87
- form.append($('input#user_new_password')).css('display', 'none');
88
- form.append($('input#user_admin')).css('display', 'none');
89
- form.append($('input#user_confirm_new_password')).css('display', 'none');
90
- form.append($('input#openid')).css('display', 'none');
91
- }
92
- if (form.attr('id') == 'login') {
93
- form.append($('input#user_name')).css('display', 'none');
94
- form.append($('input#password')).css('display', 'none');
95
- }
109
+ form.append($('input#user_new_password')).css('display', 'none');
110
+ form.append($('input#user_admin')).css('display', 'none');
111
+ form.append($('input#user_confirm_new_password')).css('display', 'none');
112
+ form.append($('input#openid')).css('display', 'none');
113
+ }
114
+ if (form.attr('id') == 'login') {
115
+ form.append($('input#user_name')).css('display', 'none');
116
+ form.append($('input#password')).css('display', 'none');
117
+ }
96
118
  });
97
119
 
98
120
  // livequery hidden form for link_to ajax magic
99
121
  $('a[method]').livequery(function(){
100
122
  var message = $(this).attr('confirm');
101
123
  var method = $(this).attr('method');
102
-
124
+
103
125
  if (!method && !message) return;
104
-
126
+
105
127
  $(this).click(function(event){
106
128
  if (message && !confirm(message)) {
107
129
  event.preventDefault();
108
130
  return;
109
131
  }
110
-
111
- if (method == 'post' || method == 'put' || method == 'delete') {
132
+
133
+ if (method === 'post' || method === 'put' || method === 'delete') {
112
134
  event.preventDefault();
113
135
  var form = $("<form/>").attr('method', 'post').attr('action', this.href).attr('style', 'display: none');
114
- if (method != "post") {
136
+ if (method !== "post") {
115
137
  form.append($('<input type="hidden" name="_method"/>').attr('value', method));
116
138
  }
117
139
  form.insertAfter(this).submit();
118
140
  }
119
141
  });
120
142
  });
121
-
143
+
122
144
  // accordion for the cookbooks show view
123
- $('.accordion .head').click(function() {
124
- $(this).next().toggle('slow');
125
- return false;
126
- }).next().hide();
127
-
128
- // global facebox callback
129
- $('a[rel*=facebox]').facebox();
130
-
131
-
132
- $('.connectedSortable').sortable({
133
- placeholder: 'ui-state-highlight',
134
- connectWith: $('.connectedSortable')
135
- }).disableSelection();
145
+ $('.accordion .head').click(function() {
146
+ $(this).next().toggle('slow');
147
+ return false;
148
+ }).next().hide();
149
+
150
+ // global facebox callback
151
+ $('a[rel*=facebox]').facebox();
152
+
153
+
154
+ var enableDragDropBehavior = function() {
155
+ $('.connectedSortable').sortable({
156
+ placeholder: 'ui-state-highlight',
157
+ connectWith: $('.connectedSortable')
158
+ }).disableSelection();
159
+ };
160
+
161
+ var disableDragDropBehavior = function() {
162
+ $('.connectedSortable').sortable("destroy");
163
+ };
164
+
165
+ enableDragDropBehavior();
136
166
 
137
167
  // The table tree!
138
168
  $('table.tree').treeTable({ expandable: true });
139
169
  $('span.expander').click(function() { $('tr#' + $(this).attr('toggle')).toggleBranch(); });
140
-
170
+
141
171
  // Tooltips
142
- $("div.tooltip").tooltip({
172
+ $("div.tooltip").tooltip({
143
173
  position: ['center', 'right'],
144
174
  offset: [-5, 10],
145
175
  effect: 'toggle',
146
- opacity: 0.7
176
+ opacity: 0.7
147
177
  });
148
-
178
+
149
179
  // Show the sidebars if they have text in them!
150
180
  var sidebar_block_notice_children = $("#sidebar_block_notice").children().length;
151
181
  var sidebar_block_children = $("#sidebar_block").children().length;
152
-
182
+
153
183
  if (sidebar_block_notice_children > 0) {
154
184
  $("#sidebar_block_notice").fadeIn();
155
185
  }
156
-
186
+
157
187
  if (sidebar_block_children > 0) {
158
188
  $("#sidebar_block").fadeIn();
159
189
  }
190
+
191
+ // Run list editor with per-env run lists for roles
192
+
193
+ var populateAvailableRecipesForEnv = function(currentEnvironment, callback) {
194
+ $.getJSON('/environments/' + currentEnvironment + '/recipes', function(data) {
195
+ $('div#available_recipes_container .spinner').hide();
196
+ for (var i=0; i < data['recipes'].length; i++) {
197
+ var recipe = data['recipes'][i];
198
+ $('ul.availableRecipes').append('<li id="recipe[' + recipe + ']" class="ui-state-default runListItem">' + recipe + '</li>');
199
+ }
200
+ });
201
+ if (callback) { callback(); }
202
+ };
203
+
204
+ var depopulateAvailableRecipesForEnv = function() {
205
+ $('ul.availableRecipes li').remove();
206
+ $('div#available_recipes_container .spinner').show();
207
+ };
208
+
209
+ // If the attribute 'data-initial-env' exists on this element, use it to load
210
+ // the recipes for that environment via ajax.
211
+ var initialEnvironment = $('div#environmentRunListSelector').data('initial-env');
212
+ if (initialEnvironment) {
213
+ populateAvailableRecipesForEnv(initialEnvironment);
214
+ }
215
+
216
+ var resetAvailableRoleList = function() {
217
+ $('ul#availableRoles li').remove();
218
+ var allRoles = $('ul#availableRoles').data('role-list');
219
+ for (var i=0; i < allRoles.length; i++) {
220
+ var role = allRoles[i];
221
+ $('ul#availableRoles').append('<li id="role[' + role + ']" class="ui-state-highlight runListItem">' + role + '</li>');
222
+ }
223
+
224
+ };
225
+
226
+ var clearRunListFor = function(environment) {
227
+ $('ul.runListItemList#' + environment).children().remove();
228
+ };
229
+
230
+ var removeEnvironmentFromCloneControls = function(environment) {
231
+ $('select.environmentToClone option[value="' + environment + '"]').remove();
232
+ };
233
+
234
+ var addEnvironmentToCloneControls = function(environment) {
235
+ $('select.environmentToClone').append('<option value="' + environment + '">' + environment + '</option>');
236
+ };
237
+
238
+ var deleteEnvRunList = function(environment) {
239
+ clearRunListFor(environment);
240
+ $('ul.runListItemList#' + environment).removeClass('active').addClass('inactive');
241
+ $('div.emptyRunListControlsContainer#' + environment).removeClass('inactive').addClass('active');
242
+ $('div.runListAdditionalControls#' + environment + " a").remove();
243
+ removeEnvironmentFromCloneControls(environment);
244
+ };
245
+
246
+ var createRunListDeleteLinkFor = function(environment) {
247
+ // remove any existing link
248
+ $('a.deleteEnvRunList#' + environment).remove();
249
+ var containerDiv = $('div.runListAdditionalControls#' + environment);
250
+ var link = '<a href="javascript:void(0);" class="deleteEnvRunList" id="' + environment + '">Remove environment specific run list for ' + environment + '</a>';
251
+ containerDiv.append(link);
252
+ containerDiv.find('a').click(function(j) {deleteEnvRunList(environment);});
253
+ };
254
+
255
+ $('a.createEmptyRunListControl').each(function(i) {
256
+ var environment = $(this).attr('id');
257
+ $(this).click(function(event) {
258
+ $('div.emptyRunListControlsContainer#' + environment).removeClass('active').addClass('inactive');
259
+ var runListContainerForEnv = $('div.runListContainer#' + environment + 'RunListContainer');
260
+ $('ul.runListItemList#' + environment).removeClass('inactive').addClass('active');
261
+ // remove all previous drag/drop events/behavior/whatever, then re-add it for the new run list container
262
+ disableDragDropBehavior();
263
+ enableDragDropBehavior();
264
+ createRunListDeleteLinkFor(environment);
265
+ addEnvironmentToCloneControls(environment);
266
+ });
267
+ });
268
+
269
+ var setActiveRunListLabelFor = function(environment) {
270
+ var labelElement = $('span#selectedRunListEditorLabel');
271
+ if (environment === '_default') {
272
+ labelElement.html('Default Run List');
273
+ }
274
+ else {
275
+ labelElement.html('Run List for ' + environment);
276
+ }
277
+ };
278
+
279
+ $('a.deleteEnvRunList').each(function(i) {
280
+ var environment = $(this).attr('id');
281
+ $(this).click(function(j) {deleteEnvRunList(environment);});
282
+ });
283
+
284
+ $('select#activeEnvironment').change(function() {
285
+ // set the active run list editor
286
+ var newActiveEnvironment = $(this).val();
287
+ if (newActiveEnvironment !== 'noop') {
288
+ $('div.runListWithControlsContainer.active').removeClass('active').addClass('inactive');
289
+ $('div.runListWithControlsContainer#' + newActiveEnvironment).addClass('active', 10000).removeClass('inactive');
290
+ setActiveRunListLabelFor(newActiveEnvironment);
291
+ depopulateAvailableRecipesForEnv();
292
+ var selector = $(this);
293
+ populateAvailableRecipesForEnv(newActiveEnvironment, function() { selector.val('noop');});
294
+ resetAvailableRoleList();
295
+ }
296
+ });
297
+
298
+ $('select.environmentToClone').change(function() {
299
+ var environmentToClone = $(this).val();
300
+ var targetEnvironment = $(this).attr('id');
301
+ var targetRunList = $('ul.runListItemList#' + targetEnvironment);
302
+ clearRunListFor(targetEnvironment); // be sure we start with a clean slate
303
+ $('ul.runListItemList#' + environmentToClone).children().clone().appendTo(targetRunList);
304
+ $('ul.runListItemList#' + targetEnvironment).removeClass('inactive').addClass('active');
305
+ $('div.emptyRunListControlsContainer#' + targetEnvironment).removeClass('active').addClass('inactive');
306
+ createRunListDeleteLinkFor(targetEnvironment);
307
+ addEnvironmentToCloneControls(targetEnvironment);
308
+ });
309
+
310
+ $('select#nodeEnvironment').change(function() {
311
+ // set the active run list editor
312
+ var newNodeEnvironment = $(this).val();
313
+ depopulateAvailableRecipesForEnv();
314
+ populateAvailableRecipesForEnv(newNodeEnvironment);
315
+ });
316
+
160
317
  });