diff --git a/awx/ui/static/js/controllers/Groups.js b/awx/ui/static/js/controllers/Groups.js index 41383b06a5..cc0c774c1c 100644 --- a/awx/ui/static/js/controllers/Groups.js +++ b/awx/ui/static/js/controllers/Groups.js @@ -10,241 +10,155 @@ function InventoryGroups ($scope, $rootScope, $compile, $location, $log, $routeParams, InventoryGroupsForm, GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, Prompt, BuildTree, GetBasePath, GroupsList, GroupsAdd, GroupsEdit, LoadInventory, - GroupsDelete, RefreshGroupName, EditInventory, InventoryStatus) + GroupsDelete, RefreshGroupName, EditInventory, InventoryStatus) { - ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior + + ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior //scope. - var generator = GenerateForm; - var form = InventoryGroupsForm; - var defaultUrl=GetBasePath('inventory'); - - $('#tree-view').empty(); - var scope = generator.inject(form, { mode: 'edit', related: true, buildTree: true }); - var base = $location.path().replace(/^\//,'').split('/')[0]; - var id = $routeParams.inventory_id; - - scope.grpBtnDisable = false; - scope['inventory_id'] = id; - - // Retrieve each related sets and any lookups - if (scope.inventoryLoadedRemove) { - scope.inventoryLoadedRemove(); - } - scope.inventoryLoadedRemove = scope.$on('inventoryLoaded', function() { - LoadBreadCrumbs({ path: '/inventories/' + id, title: scope.inventory_name }); - BuildTree({ - scope: scope, - inventory_id: id, - emit_on_select: 'NodeSelect', - target_id: 'search-tree-container', - moveable: true - }); - if (!scope.$$phase) { - scope.$digest(); - } - }); + var generator = GenerateForm; + var form = InventoryGroupsForm; + var defaultUrl=GetBasePath('inventory'); - LoadInventory({ scope: scope, doPostSteps: false }); + $('#tree-view').empty(); + var scope = generator.inject(form, { mode: 'edit', related: true, buildTree: true }); + var base = $location.path().replace(/^\//,'').split('/')[0]; + var id = $routeParams.inventory_id; - scope.treeController = function($node) { + scope.grpBtnDisable = false; + scope['inventory_id'] = id; - var nodeType = $($node).attr('type'); - if (nodeType == 'inventory') { - return { - editInventory: { - label: 'Inventory Properties', - action: function(obj) { - scope.group_id = null; - if (!scope.$$phase) { - scope.$digest(); - } - EditInventory({ scope: scope, "inventory_id": id }); - }, - separator_after: true - }, - addGroup: { - label: 'Create New Group', - action: function(obj) { - scope.group_id = null; - if (!scope.$$phase) { - scope.$digest(); - } - GroupsAdd({ "inventory_id": id, group_id: null }); - } - } - } - } - else { - return { - edit: { - label: 'Group Properties', - action: function(obj) { - scope.group_id = $(obj).attr('group_id'); - if (!scope.$$phase) { - scope.$digest(); - } - GroupsEdit({ "inventory_id": id, group_id: $(obj).attr('group_id') }); - }, - separator_after: true - }, + // Retrieve each related sets and any lookups + if (scope.inventoryLoadedRemove) { + scope.inventoryLoadedRemove(); + } + scope.inventoryLoadedRemove = scope.$on('inventoryLoaded', function() { + LoadBreadCrumbs({ path: '/inventories/' + id, title: scope.inventory_name }); + BuildTree({ + scope: scope, + inventory_id: id, + emit_on_select: 'NodeSelect', + target_id: 'search-tree-container', + refresh: false, + moveable: true + }); + }); - addGroup: { - label: 'Add Existing Group', - action: function(obj) { - scope.group_id = $(obj).attr('group_id'); - if (!scope.$$phase) { - scope.$digest(); - } - GroupsList({ "inventory_id": id, group_id: $(obj).attr('group_id') }); - } - }, + LoadInventory({ scope: scope, doPostSteps: false }); - createGroup: { - label: 'Create New Group', - action: function(obj) { - scope.group_id = $(obj).attr('group_id'); - if (!scope.$$phase) { - scope.$digest(); - } - GroupsAdd({ "inventory_id": id, group_id: $(obj).attr('group_id') }); - } - }, - - "delete": { - label: 'Delete Group', - action: function(obj) { - scope.group_id = $(obj).attr('group_id'); - if (!scope.$$phase) { - scope.$digest(); - } - GroupsDelete({ scope: scope, "inventory_id": id, group_id: $(obj).attr('group_id') }); - } - } - } - } - } - - scope.$on('NodeSelect', function(e, id, group_id, name) { + scope.$on('NodeSelect', function(e, id, group_id, name) { - // Respond to user clicking on a tree node + // Respond to user clicking a tree node - var node = $('#' + id); - var parent = node.parent().parent(); - var type = (group_id == null) ? 'inventory' : 'group'; - var url; + var node = $('#' + id); + var parent = node.parent().parent(); + var type = (group_id == null) ? 'inventory' : 'group'; + var url; + + scope['selectedNode'] = node; + scope['selectedNodeName'] = name + scope['grpBtnDisable'] = false; + scope['flashMessage'] = null; + scope['groupUpdateHide'] = true; + + if (type == 'group') { + //url = node.attr('all'); + scope.groupAddHide = false; + scope.groupCreateHide = false; + scope.groupEditHide = false; + scope.inventoryEditHide = true; + scope.groupDeleteHide = false; + scope.createButtonShow = true; + scope.group_id = group_id; + scope.addGroupHelp = "Copy an existing group into " + name; + scope.createGroupHelp = "Create a new group, adding it to " + name; + scope.updateGroupHelp = "Start the inventory update process, refreshing " + name; + if (parent.attr('id') == 'inventory-root-node') { + scope.deleteGroupHelp = "Remove " + name + " from " + parent.attr('data-name') + + " Inventory. Any hosts will still be available in All Hosts."; + } + else { + scope.deleteGroupHelp = "Remove " + name + " from " + parent.attr('data-name') + + ". Any hosts will still be available in " + parent.attr('data-name') + "."; + } + + // Load the form + GroupsEdit({ "inventory_id": scope['inventory_id'], group_id: scope['group_id'] }); + + // Slide in the group properties form + $('#tree-form').show(); + $('input:first').focus(); + } + else if (type == 'inventory') { + //url = node.attr('hosts'); + scope.groupAddHide = true; + scope.groupCreateHide = false; + scope.groupEditHide =true; + scope.inventoryEditHide=false; + scope.groupDeleteHide = true; + scope.createButtonShow = false; + scope.group_id = null; + scope.inventory_name = name; + InventoryStatus({ scope: scope }); + $('#tree-form').show(); + } + + if (!scope.$$phase) { + scope.$digest(); + } + }); + + scope.addGroup = function() { + GroupsList({ "inventory_id": id, group_id: scope.group_id }); + } + + scope.createGroup = function() { + GroupsAdd({ "inventory_id": id, group_id: scope.group_id }); + } + + scope.editGroup = function() { + // Slide in the group properties form + $('#tree-form').show('slide', {direction: 'up'}, 500, + function() { + // Remove any tooltips that might be lingering + $('.tooltip').each( function(index) { + $(this).remove(); + }); + $('.popover').each(function(index) { + // remove lingering popover
. Seems to be a bug in TB3 RC1 + $(this).remove(); + }); + // Set the focust to the first form field + $('input:first').focus(); + }); - /*if ($rootScope.timer) { - // Kill any lingering timers from the inventory summary page - clearInterval($rootScope.timer); - $rootScope.timer = null; - }*/ + // Disable all the group related buttons + scope.grpBtnDisable = false; + } - scope['selectedNode'] = node; - scope['selectedNodeName'] = name - scope['grpBtnDisable'] = false; - scope['flashMessage'] = null; - scope['groupUpdateHide'] = true; + scope.closeForm = function() { + // Slide in the group properties form + $('#tree-form').hide('slide',{ direction: 'right' }, 500, function() { $('#tree-form').empty(); }); + scope.grpBtnDisable = false; + } - //$('#tree-view').jstree('open_node',node); - - if (type == 'group') { - //url = node.attr('all'); - scope.groupAddHide = false; - scope.groupCreateHide = false; - scope.groupEditHide = false; - scope.inventoryEditHide = true; - scope.groupDeleteHide = false; - scope.createButtonShow = true; - scope.group_id = group_id; - scope.addGroupHelp = "Copy an existing group into " + name; - scope.createGroupHelp = "Create a new group, adding it to " + name; - scope.updateGroupHelp = "Start the inventory update process, refreshing " + name; - if (parent.attr('id') == 'inventory-root-node') { - scope.deleteGroupHelp = "Remove " + name + " from " + parent.attr('data-name') + - " Inventory. Any hosts will still be available in All Hosts."; - } - else { - scope.deleteGroupHelp = "Remove " + name + " from " + parent.attr('data-name') + - ". Any hosts will still be available in " + parent.attr('name') + " and All Hosts."; - } - - // Load the form - GroupsEdit({ "inventory_id": scope['inventory_id'], group_id: scope['group_id'] }); + scope.editInventory = function() { + EditInventory({ scope: scope, inventory_id: id }); + } - // Slide in the group properties form - $('#tree-form').show(); - $('input:first').focus(); - } - else if (type == 'inventory') { - //url = node.attr('hosts'); - scope.groupAddHide = true; - scope.groupCreateHide = false; - scope.groupEditHide =true; - scope.inventoryEditHide=false; - scope.groupDeleteHide = true; - scope.createButtonShow = false; - scope.group_id = null; - scope.inventory_name = name; - InventoryStatus({ scope: scope }); - $('#tree-form').show(); - } + scope.deleteGroup = function() { + GroupsDelete({ scope: scope, "inventory_id": id, group_id: scope.group_id }); + } - if (!scope.$$phase) { - scope.$digest(); - } - }); - - scope.addGroup = function() { - GroupsList({ "inventory_id": id, group_id: scope.group_id }); - } - - scope.createGroup = function() { - GroupsAdd({ "inventory_id": id, group_id: scope.group_id }); - } - - scope.editGroup = function() { - // Slide in the group properties form - $('#tree-form').show('slide', {direction: 'up'}, 500, function() { - // Remove any tooltips that might be lingering - $('.tooltip').each( function(index) { - $(this).remove(); - }); - $('.popover').each(function(index) { - // remove lingering popover
. Seems to be a bug in TB3 RC1 - $(this).remove(); - }); - // Set the focust to the first form field - $('input:first').focus(); - }); - - // Disable all the group related buttons - scope.grpBtnDisable = false; - - } - - scope.closeForm = function() { - // Slide in the group properties form - $('#tree-form').hide('slide',{ direction: 'right' }, 500, function() { $('#tree-form').empty(); }); - scope.grpBtnDisable = false; - } - - scope.editInventory = function() { - EditInventory({ scope: scope, inventory_id: id }); - } - - scope.deleteGroup = function() { - GroupsDelete({ scope: scope, "inventory_id": id, group_id: scope.group_id }); - } - - scope.editHosts = function() { - $location.path('/inventories/' + scope.inventory_id + '/hosts'); - } + scope.editHosts = function() { + $location.path('/inventories/' + scope.inventory_id + '/hosts'); + } } -InventoryGroups.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'InventoryGroupsForm', - 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'Prompt', - 'BuildTree', 'GetBasePath', 'GroupsList', 'GroupsAdd', 'GroupsEdit', 'LoadInventory', - 'GroupsDelete', 'RefreshGroupName', 'EditInventory', 'InventoryStatus' - ]; +InventoryGroups.$inject = [ + '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'InventoryGroupsForm', + 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope', 'Prompt', + 'BuildTree', 'GetBasePath', 'GroupsList', 'GroupsAdd', 'GroupsEdit', 'LoadInventory', + 'GroupsDelete', 'RefreshGroupName', 'EditInventory', 'InventoryStatus' + ]; \ No newline at end of file diff --git a/awx/ui/static/js/forms/Groups.js b/awx/ui/static/js/forms/Groups.js index ebf7ee1148..c15e700a0c 100644 --- a/awx/ui/static/js/forms/Groups.js +++ b/awx/ui/static/js/forms/Groups.js @@ -103,7 +103,7 @@ angular.module('GroupFormDefinition', []) ngChange: 'sourceChange()', addRequired: false, editRequired: false, - 'default': { label: 'Manual', value: null } + 'default': { label: 'Manual', value: '' } }, source_path: { label: 'Script Path', @@ -177,8 +177,7 @@ angular.module('GroupFormDefinition', []) "
---
somevar: somevalue
password: magic
\n" + '

View JSON examples at www.json.org

' + '

View YAML examples at ansibleworks.com

', - dataContainer: 'body', - awPopOverRight: true + dataContainer: 'body' }, update_interval: { label: 'Update Interval', diff --git a/awx/ui/static/js/helpers/Groups.js b/awx/ui/static/js/helpers/Groups.js index a7fbb5e5be..e76ef4cd58 100644 --- a/awx/ui/static/js/helpers/Groups.js +++ b/awx/ui/static/js/helpers/Groups.js @@ -13,13 +13,26 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' 'PromptDialog', 'InventorySummaryHelpDefinition', 'TreeSelector' ]) - .factory('GetSourceTypeOptions', [ function() { - return function() { - return [ - { label: 'none', value: null }, - { label: 'ec2', value: 'ec2' }, - { label: 'rackspace', value: 'rackspace' } - ]; + .factory('GetSourceTypeOptions', [ 'Rest', 'ProcessErrors', 'GetBasePath', function(Rest, ProcessErrors, GetBasePath) { + return function(params) { + // Lookup options for source and build an array of drop-down choices + var scope = params.scope; + var variable = params.variable; + if (scope[variable] == undefined) { + scope[variable] = []; + Rest.setUrl(GetBasePath('inventory_sources')); + Rest.options() + .success( function(data, status, headers, config) { + var choices = data.actions.GET.source.choices + for (var i=0; i < choices.length; i++) { + scope[variable].push({ label: [ (choices[i][0] == "") ? 'Manual' : choices[i][1] ], value: choices[i][0] }); + } + }) + .error( function(data, status, headers, config) { + ProcessErrors(scope, data, status, null, + { hdr: 'Error!', msg: 'Failed to retrieve options for inventory_sources.source. OPTIONS status: ' + status }); + }); + } } }]) @@ -175,9 +188,9 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' .factory('InventoryStatus', [ '$rootScope', '$routeParams', 'Rest', 'Alert', 'ProcessErrors', 'GetBasePath', 'FormatDate', 'InventorySummary', 'GenerateList', 'ClearScope', 'SearchInit', 'PaginateInit', 'Refresh', 'InventoryUpdate', 'GroupsEdit', 'ShowUpdateStatus', 'HelpDialog', - 'ShowGroupHelp', 'InventorySummaryHelp', 'BuildTree', + 'ShowGroupHelp', 'InventorySummaryHelp', 'BuildTree', 'ClickNode', function($rootScope, $routeParams, Rest, Alert, ProcessErrors, GetBasePath, FormatDate, InventorySummary, GenerateList, ClearScope, SearchInit, - PaginateInit, Refresh, InventoryUpdate, GroupsEdit, ShowUpdateStatus, HelpDialog, ShowGroupHelp, InventorySummaryHelp, BuildTree) { + PaginateInit, Refresh, InventoryUpdate, GroupsEdit, ShowUpdateStatus, HelpDialog, ShowGroupHelp, InventorySummaryHelp, BuildTree, ClickNode) { return function(params) { //Build a summary of a given inventory @@ -361,12 +374,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' // Click on group name scope.GroupsEdit = function(group_id) { // On the tree, select the first occurrance of the requested group - var node = $('#tree-view').find("li[group_id='" + group_id + "']").first(); - var selected = $('#tree-view').jstree('get_selected'); - selected.each(function(idx) { - $('#tree-view').jstree('deselect_node', $(this)); - }); - $('#tree-view').jstree('select_node', node); + ClickNode({ selector: '#inventory-tree li[data-group-id="' + group_id + '"]' }); } if (scope.removeCancelUpdate) { @@ -515,9 +523,9 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' .factory('GroupsAdd', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm', - 'Prompt', 'ProcessErrors', 'GetBasePath', 'ParseTypeChange', 'GroupsEdit', 'BuildTree', + 'Prompt', 'ProcessErrors', 'GetBasePath', 'ParseTypeChange', 'GroupsEdit', 'BuildTree', 'ClickNode', function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors, - GetBasePath, ParseTypeChange, GroupsEdit, BuildTree) { + GetBasePath, ParseTypeChange, GroupsEdit, BuildTree, ClickNode) { return function(params) { var inventory_id = params.inventory_id; @@ -529,20 +537,22 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' var form = GroupForm; var generator = GenerateForm; var scope = generator.inject(form, {mode: 'add', modal: true, related: false}); + var groupCreated = false; scope.formModalActionLabel = 'Save'; scope.formModalHeader = 'Create New Group'; scope.formModalCancelShow = true; scope.parseType = 'yaml'; - scope.source = { label: 'Manual', value: null }; + scope.source = null; ParseTypeChange(scope); $('#form-modal .btn-none').removeClass('btn-none').addClass('btn-success'); - $('#form-modal').off('hide.bs.modal').on('hide.bs.modal', function() { - //GroupsEdit({ "inventory_id": scope['inventory_id'], group_id: scope['group_id'] }); - scope.$emit('NodeSelect', scope['nodeSelectValue']); + $('#form-modal').on('hidden.bs.modal', function () { + if (!groupCreated) { + ClickNode({ selector: '#' + scope['selectedNode'].attr('id') }); + } }); - + generator.reset(); var master={}; @@ -551,9 +561,8 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' } // Save - scope.formModalAction = function() { + scope.formModalAction = function() { try { - scope.formModalActionDisabled = true; // Make sure we have valid variable data @@ -579,14 +588,17 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' if (inventory_id) { data['inventory'] = inventory_id; } - - data.variables = json_data; + + if (json_data) { + data['variables'] = JSON.stringify(json_data, undefined, '\t'); + } Rest.setUrl(defaultUrl); Rest.post(data) .success( function(data, status, headers, config) { - var id = data.id; - scope.showGroupHelp = false; // get rid of the Hint + groupCreated = true; + scope.formModalActionDisabled = false; + scope.showGroupHelp = false; //get rid of the Hint $('#form-modal').modal('hide'); BuildTree({ scope: scope, @@ -595,7 +607,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' target_id: 'search-tree-container', refresh: true, moveable: true, - group_id: id + group_id: data.id }); }) .error( function(data, status, headers, config) { @@ -638,9 +650,10 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' generator.reset(); var master = {}; var relatedSets = {}; - - scope.source_type_options = GetSourceTypeOptions(); + + GetSourceTypeOptions({ scope: scope, variable: 'source_type_options' }); scope.update_interval_options = GetUpdateIntervalOptions(); + scope.source = null; scope.parseType = 'yaml'; scope[form.fields['source_vars'].parseTypeName] = 'yaml'; scope.sourcePasswordRequired = false; @@ -652,9 +665,6 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' ParseTypeChange(scope); ParseTypeChange(scope, 'source_vars', form.fields['source_vars'].parseTypeName); - - //$('#form-modal .btn-none').removeClass('btn-none').addClass('btn-success'); - // After the group record is loaded, retrieve related data if (scope.groupLoadedRemove) { @@ -704,16 +714,13 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' } if (fld == 'source') { var found = false; - if (data['source'] == '') { - data['source'] = null; - } for (var i=0; i < scope.source_type_options.length; i++) { if (scope.source_type_options[i].value == data['source']) { scope['source'] = scope.source_type_options[i]; found = true; } } - if (!found || scope['source'].value == null) { + if (!found || scope['source'].value == "") { scope['groupUpdateHide'] = true; } else { @@ -749,10 +756,11 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' master[fld] = scope[fld]; } } - scope['group_update_url'] = data.related['update']; + scope['group_update_url'] = data.related['update']; + scope.sourceChange(); }) .error( function(data, status, headers, config) { - scope.source = null; + scope.source = ""; ProcessErrors(scope, data, status, form, { hdr: 'Error!', msg: 'Failed to retrieve inventory source. GET status: ' + status }); }); @@ -1027,20 +1035,21 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' .factory('GroupsDelete', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm', - 'Prompt', 'ProcessErrors', 'GetBasePath', 'RefreshTree', 'Wait', + 'Prompt', 'ProcessErrors', 'GetBasePath', 'BuildTree', 'Wait', 'ClickNode', function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors, - GetBasePath, RefreshTree, Wait) { + GetBasePath, BuildTree, Wait, ClickNode) { return function(params) { // Delete the selected group node. Disassociates it from its parent. var scope = params.scope; var group_id = params.group_id; var inventory_id = params.inventory_id; - var obj = $('#tree-view li[group_id="' + group_id + '"]'); - var parent = (obj.parent().last().prop('tagName') == 'LI') ? obj.parent().last() : obj.parent().parent().last(); + var obj = scope['selectedNode']; + var parent = obj.parent().parent(); + //var parent = (obj.parent().last().prop('tagName') == 'LI') ? obj.parent().last() : obj.parent().parent().last(); var url; - if (parent.attr('type') == 'group') { - url = GetBasePath('base') + 'groups/' + parent.attr('group_id') + '/children/'; + if (parent.attr('data-group-id')) { + url = GetBasePath('base') + 'groups/' + parent.attr('data-group-id') + '/children/'; } else { url = GetBasePath('inventory') + inventory_id + '/groups/'; @@ -1051,20 +1060,28 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' Rest.setUrl(url); Rest.post({ id: group_id, disassociate: 1 }) .success( function(data, status, headers, config) { - scope.selectedNode = scope.selectedNode.parent().parent(); - RefreshTree({ scope: scope }); + //DeleteNode({ selector: '#' + obj.attr('id') }); + BuildTree({ + scope: scope, + inventory_id: scope['inventory_id'], + emit_on_select: 'NodeSelect', + target_id: 'search-tree-container', + refresh: true, + id: parent.attr('id'), + moveable: true + }); + Wait('stop'); }) .error( function(data, status, headers, config) { - //$('#prompt-modal').modal('hide'); - RefreshTree({ scope: scope }); + Wait('stop'); ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status }); }); }; //Force binds to work. Not working usual way. $('#prompt-header').text('Delete Group'); - $('#prompt-body').html('

Are you sure you want to remove group ' + $(obj).attr('name') + ' from group ' + - parent.attr('name') + '?

'); + $('#prompt-body').html('

Are you sure you want to remove group ' + $(obj).attr('data-name') + ' from group ' + + parent.attr('data-name') + '?

'); $('#prompt-action-btn').addClass('btn-danger'); scope.promptAction = action_to_take; // for some reason this binds? $('#prompt-modal').modal({ diff --git a/awx/ui/static/js/helpers/JobSubmission.js b/awx/ui/static/js/helpers/JobSubmission.js index 234914e56d..4fcc8e3fc0 100644 --- a/awx/ui/static/js/helpers/JobSubmission.js +++ b/awx/ui/static/js/helpers/JobSubmission.js @@ -385,8 +385,8 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential // Sumbit Inventory Update request .factory('InventoryUpdate',['PromptPasswords', '$compile', 'Rest', '$location', 'GetBasePath', 'ProcessErrors', 'Alert', - 'GroupForm', 'InventorySummary', - function(PromptPasswords, $compile, Rest, $location, GetBasePath, ProcessErrors, Alert, GroupForm, InventorySummary) { + 'GroupForm', 'BuildTree', + function(PromptPasswords, $compile, Rest, $location, GetBasePath, ProcessErrors, Alert, GroupForm, BuildTree) { return function(params) { var scope = params.scope; @@ -404,13 +404,21 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential // Refresh the project list after update request submitted Alert('Update Started', 'The request to start the inventory update process was submitted. Monitor progress from the inventory summary screen. ' + 'The screen will refresh every 10 seconds, or refresh manually by clicking the Refresh button.', 'alert-info'); - var node = $('#inventory-node') - var selected = $('#tree-view').jstree('get_selected'); - scope['inventorySummaryGroup'] = null; - selected.each(function(idx) { - $('#tree-view').jstree('deselect_node', $(this)); + //var node = $('#inventory-node') + //var selected = $('#tree-view').jstree('get_selected'); + //scope['inventorySummaryGroup'] = null; + //selected.each(function(idx) { + // $('#tree-view').jstree('deselect_node', $(this)); + // }); + //$('#tree-view').jstree('select_node', node); + BuildTree({ + scope: scope, + inventory_id: scope['inventory_id'], + emit_on_select: 'NodeSelect', + target_id: 'search-tree-container', + refresh: false, + moveable: true }); - $('#tree-view').jstree('select_node', node); } }); diff --git a/awx/ui/static/less/ansible-ui.less b/awx/ui/static/less/ansible-ui.less index 56e1c1f9ef..f11e5e8507 100644 --- a/awx/ui/static/less/ansible-ui.less +++ b/awx/ui/static/less/ansible-ui.less @@ -997,18 +997,13 @@ select.field-mini-height { list-style-type: none; padding-left: 16px; } - - li { - padding-top: 3px; - } - + .tree-root { padding-left: 0; } .activate { - padding-left: 3px; - padding-right: 3px; + padding: 3px; } .activate:hover { @@ -1027,11 +1022,7 @@ select.field-mini-height { .badge-container, .title-container { display: inline-block; - vertical-align: top; - } - - .badge-container, - .title-container { + vertical-align: middle; border-bottom: 2px solid @well; } @@ -1040,6 +1031,12 @@ select.field-mini-height { text-align: center; } + .badge-container { + vertical-align: none; + margin-bottom: 3px; + padding-bottom: 2px; + } + #root-expand-container { width: 20px; text-align: left; @@ -1053,6 +1050,10 @@ select.field-mini-height { word-break: break-all; } + #root-title-container { + margin-left: 5px; + } + .expand-container:hover { background-color: #ddd; } @@ -1060,7 +1061,7 @@ select.field-mini-height { .field-badge { font-size: 10px; line-height: normal; - vertical-align: baseline; + /*vertical-align: baseline;*/ } } diff --git a/awx/ui/static/lib/ansible/TreeSelector.js b/awx/ui/static/lib/ansible/TreeSelector.js index 4a7cf9fe8c..0adabc0e8c 100644 --- a/awx/ui/static/lib/ansible/TreeSelector.js +++ b/awx/ui/static/lib/ansible/TreeSelector.js @@ -19,6 +19,7 @@ angular.module('TreeSelector', ['Utilities', 'RestServices']) var refresh_tree = (params.refresh == undefined || params.refresh == false) ? false : true; var moveable = (params.moveable == undefined || params.moveable == false) ? false : true; var group_id = params.group_id; + var id = params.id; var html = ''; var toolTip = 'Hosts have failed jobs?'; @@ -110,6 +111,7 @@ angular.module('TreeSelector', ['Utilities', 'RestServices']) var variables; function cleanUp(state) { + /* if (state !== 'fail') { // Visually move the element. Elment will be appended to the // end of target element list @@ -150,6 +152,11 @@ angular.module('TreeSelector', ['Utilities', 'RestServices']) setExpander(parent); } Wait('stop'); + */ + // Reload the tree + html = ''; + idx = 0; + loadTreeData(); } // disassociate the group from the original parent @@ -238,7 +245,15 @@ angular.module('TreeSelector', ['Utilities', 'RestServices']) } if (refresh_tree && group_id !== undefined) { - $('li[data-group-id="' + group_id + '"]').first().click(); + // pick a specific node on the tree + $('li[data-group-id="' + group_id + '"] .activate').first().click(); + } + else if (refresh_tree && id !== undefined) { + $('#' + id + ' .activate').first().click(); + } + else if (!refresh_tree) { + // default to the root node + $('#inventory-root-node .activate').first().click(); } // Attempt to stop the title from dropping to the next @@ -259,7 +274,7 @@ angular.module('TreeSelector', ['Utilities', 'RestServices']) helper: 'clone', start: function (e, ui) { var txt = '[ ' + ui.helper.text() + ' ]'; - ui.helper.css({ 'font-weight': 'normal', 'color': '#A9A9A9', 'background-color': '#f5f5f5' }).text(txt); + ui.helper.css({ 'font-weight': 'normal', 'color': '#171717', 'background-color': '#f5f5f5' }).text(txt); } }) .droppable({ @@ -269,11 +284,11 @@ angular.module('TreeSelector', ['Utilities', 'RestServices']) var p = $(this).parent().parent(); p.find('div').each(function(idx) { if (idx > 0 && idx < 3) { - $(this).css({ 'border-bottom': '2px solid #A9A9A9' }); + $(this).css({ 'border-bottom': '2px solid #171717' }); } }); var c = p.find('.expand-container').first(); - c.empty().html(''); + c.empty().html(''); }, out: function (e, ui) { var p = $(this).parent().parent(); @@ -388,39 +403,39 @@ angular.module('TreeSelector', ['Utilities', 'RestServices']) }); }); - Wait('start'); + + function loadTreeData() { + // Load the inventory root node + Wait('start'); + Rest.setUrl (GetBasePath('inventory') + inventory_id + '/'); + Rest.get() + .success( function(data, status, headers, config) { + html += "
Group Selector:
\n" + + "
\n" + + "
    \n" + + "
  • " + + "
    " + + "
    " + + ""; + + scope.$emit('buildAllGroups', data.name, data.related.tree, data.related.groups); + + }) + .error( function(data, status, headers, config) { + ProcessErrors(scope, data, status, null, + { hdr: 'Error!', msg: 'Failed to get inventory: ' + inventory_id + '. GET returned: ' + status }); + }); + } - // Load the inventory root node - Rest.setUrl (GetBasePath('inventory') + inventory_id + '/'); - Rest.get() - .success( function(data, status, headers, config) { - html += "
    Group Selector:
    \n" + - "
    \n" + - "
      \n" + - "
    • "+ - "
      " + - "
      " + - ""; - - scope.$emit('buildAllGroups', data.name, data.related.tree, data.related.groups); - - if (!refresh_tree) { - // if caller requests with refresh true, let caller handle next steps / node selection - // otherwise, we're refreshing to summary page - scope.$emit(emit_on_select, 'inventory-root-node', null, 'All Hosts'); - } + loadTreeData(); - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Failed to get inventory: ' + inventory_id + '. GET returned: ' + status }); - }); } }]) @@ -452,8 +467,14 @@ angular.module('TreeSelector', ['Utilities', 'RestServices']) var selector = params.selector; //jquery selector string to find the correct
    • $(selector + ' .activate').first().click(); } + }]) + + .factory('DeleteNode', [ function() { + return function(params) { + var selector = params.selector; //jquery selector string to find the correct
    • + $(selector).first().detach(); + } }]); - diff --git a/awx/ui/static/lib/ansible/form-generator.js b/awx/ui/static/lib/ansible/form-generator.js index 31ae213ea1..0cc946c556 100644 --- a/awx/ui/static/lib/ansible/form-generator.js +++ b/awx/ui/static/lib/ansible/form-generator.js @@ -973,7 +973,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies']) } // Start the well - if ( this.has('well') ) { + if ( !this.modal && this.has('well') ) { html += "
      \n"; } @@ -1118,7 +1118,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies']) } html += "\n"; - if ( this.has('well') ) { + if ( !this.modal && this.has('well') ) { html += "
      \n"; } @@ -1190,49 +1190,12 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies']) icon: 'icon-sitemap' } }; - if (form.type == 'groupsview') { - navigation.inventory.active = false; navigation.hosts.active = false; navigation.groups.active = true; - html += this.breadCrumbs(options, navigation); - - // build the groups page - //html += "
      \n"; - //html += "\n"; - //html += "

      Hint: Get started building your inventory by adding a group. After creating a group " + - // "go to the Hosts page to " + - // "add hosts to the group.

      "; - //html += "
      \n"; - - /* - html += "
      \n"; - html += "
      \n"; - html += "
      \n"; - html += "
      \n"; - html += "
      \n"; - html += "
      \n"; - html += "
      \n"; - html += "
      \n"; - html += "
      \n"; - html += "\n"; - html += "\n"; - html += "\n"; - html += "\n"; - html += "
      \n"; - html += "
      \n"; - html += "
      \n"; - html += "
      \n"; - */ html += "
      \n"; html += "
      \n" + "
      \n" + @@ -1242,35 +1205,14 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies']) html += "
      \n"; html += "
      \n
      \n"; html += "
      \n"; - //html += "
      \n"; - //html += "
      \n"; html += "
      \n"; - } else { // build the hosts page - navigation.inventory.active = false; navigation.hosts.active = true; navigation.groups.active = false; - html += this.breadCrumbs(options, navigation); - - // Hint text - /* - html += "
      \n"; - html += "\n"; - html += "

      Hint: Get started building your inventory by adding a group on the " + - "Inventories->Groups page. After creating a group, " + - "return here and add hosts to the group.

      "; - html += "
      \n"; - - html += "
      \n"; - html += "\n"; - html += "

      Hint: To add hosts to the inventory, select a group using the Group Selector.

      "; - html += "
      \n"; - */ - html += "
      \n"; html += "
      \n"; html += "
      \n"; @@ -1278,38 +1220,18 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies']) html += "
      \n"; html += "
      \n"; html += "
      \n"; - html += "
      \n"; - html += SearchWidget({ iterator: form.iterator, template: form, mini: true, size: 'col-md-5 col-lg-5'}); - html += "
      \n" html += "
      \n"; + // Add actions(s) for (var action in form.actions) { - /*html += "\n";*/ html += this.button(form.actions[action], action); } html += "
      \n"; html += "
      \n"; html += "
      \n"; - html += "
      \n"; // Start the list