diff --git a/awx/ui/static/js/controllers/Inventories.js b/awx/ui/static/js/controllers/Inventories.js index cee1fd14d9..1427b60bd0 100644 --- a/awx/ui/static/js/controllers/Inventories.js +++ b/awx/ui/static/js/controllers/Inventories.js @@ -318,7 +318,8 @@ InventoriesAdd.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$lo function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateList, ClearScope, InventoryGroups, InventoryHosts, BuildTree, Wait, GetSyncStatusMsg, InjectHosts, HostsReload, GroupsAdd, GroupsEdit, GroupsDelete, Breadcrumbs, LoadBreadCrumbs, Empty, - Rest, ProcessErrors, InventoryUpdate, Alert, ToggleChildren, ViewUpdateStatus, GroupsCancelUpdate) + Rest, ProcessErrors, InventoryUpdate, Alert, ToggleChildren, ViewUpdateStatus, GroupsCancelUpdate, Find, + HostsCreate, EditInventoryProperties) { ClearScope('htmlTemplate'); //Garbage collection. Don't leave behind any listeners/watchers from the prior //scope. @@ -329,12 +330,12 @@ function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateLis $scope.inventory_id = $routeParams.inventory_id; - LoadBreadCrumbs(); + LoadBreadCrumbs({ path: $location.path(), title: '{{ inventory_name }}' }); if ($scope.removeGroupTreeLoaded) { $scope.removeGroupTreeLoaded(); } - $scope.removeGroupTreeLoaded = $scope.$on('groupTreeLoaded', function(e, inventory_name, groups) { + $scope.removeGroupTreeLoaded = $scope.$on('GroupTreeLoaded', function(e, inventory_name, groups) { // After the tree data loads, generate the groups list // Add breadcrumbs var e = angular.element(document.getElementById('breadcrumbs')); @@ -367,21 +368,23 @@ function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateLis if ($scope.removeGroupTreeRefreshed) { $scope.removeGroupTreeRefreshed(); } - $scope.removeGroupTreeRefreshed = $scope.$on('groupTreeRefreshed', function(e, inventory_name, groups, emit) { + $scope.removeGroupTreeRefreshed = $scope.$on('GroupTreeRefreshed', function(e, inventory_name, groups) { // Called after tree data is reloaded on refresh button click. // Reselect the preveiously selected group node, causing host view to refresh. - $scope.showHosts($scope.selected_tree_id, $scope.selected_group_id, false, emit); + $scope.showHosts($scope.selected_tree_id, $scope.selected_group_id, false); }); if ($scope.removeGroupDeleteCompleted) { $scope.removeGroupDeleteCompleted(); } - $scope.removeGroupDeleteCompleted = $scope.$on('groupDeleteCompleted', function(e) { + $scope.removeGroupDeleteCompleted = $scope.$on('GroupDeleteCompleted', function(e) { // Group was deleted. Now we need to refresh the group view. + $scope.selected_tree_id = 1; + $scope.selected_group_id = null; BuildTree({ scope: $scope, inventory_id: $scope.inventory_id, refresh: true }); }); - $scope.showHosts = function(tree_id, group_id, show_failures, emit) { + $scope.showHosts = function(tree_id, group_id, show_failures) { // Clicked on group if (tree_id !== null) { Wait('start'); @@ -400,7 +403,10 @@ function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateLis $scope.groups[i].active_class = ''; } } - HostsReload({ scope: $scope, group_id: group_id, tree_id: tree_id, inventory_id: $scope.inventory_id, emit: emit }); + HostsReload({ scope: $scope, group_id: group_id, tree_id: tree_id, inventory_id: $scope.inventory_id }); + } + else { + Wait('stop'); } } @@ -408,47 +414,47 @@ function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateLis GroupsAdd({ scope: $scope, inventory_id: $scope.inventory_id, group_id: $scope.selected_group_id }); } - $scope.editGroup = function(group_id) { - GroupsEdit({ scope: $scope, inventory_id: $scope.inventory_id, group_id: group_id }); + $scope.editGroup = function(group_id, tree_id) { + GroupsEdit({ scope: $scope, inventory_id: $scope.inventory_id, group_id: group_id, tree_id: tree_id }); } // Launch inventory sync $scope.updateGroup = function(id) { - for (var i=0; i < $scope.groups.length; i++) { - if ($scope.groups[i].id == id) { - if (Empty($scope.groups[i].source)) { - // if no source, do nothing. - } - else if ($scope.groups[i].status == 'updating') { - Alert('Update in Progress', 'The inventory update process is currently running for group ' + - $scope.groups[i].name + '. Use the Refresh button to monitor the status.', 'alert-info'); - } - else { - Wait('start'); - Rest.setUrl($scope.groups[i].related.inventory_source); - Rest.get() - .success( function(data, status, headers, config) { - InventoryUpdate({ - scope: $scope, - url: data.related.update, - group_name: data.summary_fields.group.name, - group_source: data.source - }); - }) - .error( function(data, status, headers, config) { - Wait('stop'); - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to retrieve inventory source: ' + $scope.groups[i].related.inventory_source + - ' POST returned status: ' + status }); + var group = Find({ list: $scope.groups, key: 'id', val: id}); + if (group) { + if (Empty(group.source)) { + // if no source, do nothing. + } + else if (group.status == 'updating') { + Alert('Update in Progress', 'The inventory update process is currently running for group ' + + $scope.groups[i].name + '. Use the Refresh button to monitor the status.', 'alert-info'); + } + else { + Wait('start'); + Rest.setUrl(group.related.inventory_source); + Rest.get() + .success( function(data, status, headers, config) { + InventoryUpdate({ + scope: $scope, + url: data.related.update, + group_name: data.summary_fields.group.name, + group_source: data.source, + tree_id: group.id, + group_id: group.group_id }); - } - break; + }) + .error( function(data, status, headers, config) { + Wait('stop'); + ProcessErrors(scope, data, status, form, + { hdr: 'Error!', msg: 'Failed to retrieve inventory source: ' + group.related.inventory_source + + ' POST returned status: ' + status }); + }); } } } $scope.cancelUpdate = function(id) { - GroupsCancelUpdate({ scope: $scope, id: id }); + GroupsCancelUpdate({ scope: $scope, tree_id: id }); } $scope.toggle = function(id) { @@ -456,20 +462,31 @@ function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateLis ToggleChildren({ scope: $scope, list: list, id: id }); } - $scope.refreshGroups = function(emit) { + $scope.refreshGroups = function(tree_id, group_id) { // Refresh the tree data when refresh button cicked - // Pass a string label value, if you want to attach scope.$on() to the completion of the refresh - BuildTree({ scope: $scope, inventory_id: $scope.inventory_id, refresh: true, emit: emit }); + if (tree_id) { + $scope.selected_tree_id = tree_id; + $scope.selected_group_id = group_id; + } + BuildTree({ scope: $scope, inventory_id: $scope.inventory_id, refresh: true }); } - $scope.viewUpdateStatus = function(id) { - ViewUpdateStatus({ scope: $scope, tree_id: id }); + $scope.viewUpdateStatus = function(tree_id, group_id) { + ViewUpdateStatus({ scope: $scope, tree_id: tree_id, group_id: group_id }); } - $scope.deleteGroup = function(id) { - GroupsDelete({ scope: $scope, tree_id: id, inventory_id: $scope.inventory_id }); + $scope.deleteGroup = function(tree_id, group_id) { + GroupsDelete({ scope: $scope, tree_id: tree_id, group_id: group_id, inventory_id: $scope.inventory_id }); + } + + $scope.createHost = function() { + HostsCreate({ scope: $scope }); } + $scope.editInventoryProperties = function() { + EditInventoryProperties({ scope: $scope, inventory_id: $scope.inventory_id }); + } + //Load tree data for the first time BuildTree({ scope: $scope, inventory_id: $scope.inventory_id, refresh: false }); @@ -478,6 +495,6 @@ function InventoriesEdit ($scope, $location, $routeParams, $compile, GenerateLis InventoriesEdit.$inject = [ '$scope', '$location', '$routeParams', '$compile', 'GenerateList', 'ClearScope', 'InventoryGroups', 'InventoryHosts', 'BuildTree', 'Wait', 'GetSyncStatusMsg', 'InjectHosts', 'HostsReload', 'GroupsAdd', 'GroupsEdit', 'GroupsDelete', 'Breadcrumbs', 'LoadBreadCrumbs', 'Empty', 'Rest', 'ProcessErrors', 'InventoryUpdate', 'Alert', 'ToggleChildren', - 'ViewUpdateStatus', 'GroupsCancelUpdate' + 'ViewUpdateStatus', 'GroupsCancelUpdate', 'Find', 'HostsCreate', 'EditInventoryProperties' ]; diff --git a/awx/ui/static/js/forms/Inventories.js b/awx/ui/static/js/forms/Inventories.js index 1a6b5ce938..120a39695c 100644 --- a/awx/ui/static/js/forms/Inventories.js +++ b/awx/ui/static/js/forms/Inventories.js @@ -79,7 +79,7 @@ angular.module('InventoryFormDefinition', []) addRequired: false, editRequird: false, parseTypeName: 'inventoryParseType', - rows: 10, + rows: 6, "default": "---", awPopOver: "

Enter inventory variables using either JSON or YAML syntax. Use the radio button to toggle between the two.

" + "JSON:
\n" + @@ -89,7 +89,7 @@ angular.module('InventoryFormDefinition', []) '

View JSON examples at www.json.org

' + '

View YAML examples at ansibleworks.com

', dataTitle: 'Inventory Variables', - dataPlacement: 'left', + dataPlacement: 'right', dataContainer: 'body' } }, diff --git a/awx/ui/static/js/helpers/Groups.js b/awx/ui/static/js/helpers/Groups.js index 87fb816939..2fd023f451 100644 --- a/awx/ui/static/js/helpers/Groups.js +++ b/awx/ui/static/js/helpers/Groups.js @@ -82,21 +82,19 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' } }]) - .factory('ViewUpdateStatus', [ 'Rest', 'ProcessErrors', 'GetBasePath', 'ShowUpdateStatus', 'Alert', 'Wait', 'Empty', - function(Rest, ProcessErrors, GetBasePath, ShowUpdateStatus, Alert, Wait, Empty) { + .factory('ViewUpdateStatus', [ 'Rest', 'ProcessErrors', 'GetBasePath', 'ShowUpdateStatus', 'Alert', 'Wait', 'Empty', 'Find', + function(Rest, ProcessErrors, GetBasePath, ShowUpdateStatus, Alert, Wait, Empty, Find) { return function(params) { var scope = params.scope; - var id = params.tree_id; + var tree_id = params.tree_id; + var group_id = params.group_id; var found = false; - var group; - for (var i=0; i < scope.groups.length; i++) { - if (scope.groups[i].id == id) { - found = true; - group = scope.groups[i]; - } - } - if (found) { + var group = Find({ list: scope.group, key: 'id', val: tree_id }); + + scope.showHosts(tree_id, group_id, false); + + if (group) { if (Empty(group.source)) { Alert('Missing Configuration', 'The selected group is not configured for inventory sync. ' + 'You must first edit the group, provide Source settings, and then run the sync process.', 'alert-info'); @@ -323,196 +321,6 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' } }]) - .factory('InventoryStatus', [ '$rootScope', '$routeParams', 'Rest', 'Alert', 'ProcessErrors', 'GetBasePath', 'FormatDate', 'InventorySummary', - 'GenerateList', 'ClearScope', 'SearchInit', 'PaginateInit', 'Refresh', 'InventoryUpdate', 'GroupsEdit', 'HelpDialog', - 'InventorySummaryHelp', 'ClickNode', 'GetHostsStatusMsg', 'GetSyncStatusMsg', 'ViewUpdateStatus', 'Wait', - function($rootScope, $routeParams, Rest, Alert, ProcessErrors, GetBasePath, FormatDate, InventorySummary, GenerateList, ClearScope, - SearchInit, PaginateInit, Refresh, InventoryUpdate, GroupsEdit, HelpDialog, InventorySummaryHelp, ClickNode, - GetHostsStatusMsg, GetSyncStatusMsg, ViewUpdateStatus, Wait) { - return function(params) { - //Build a summary of a given inventory - - ClearScope('tree-form'); - - $('#tree-form').hide().empty(); - var view = GenerateList; - var list = InventorySummary; - var scope = view.inject(InventorySummary, { mode: 'summary', id: 'tree-form', breadCrumbs: false }); - var defaultUrl = GetBasePath('inventory') + scope['inventory_id'] + '/groups/'; - //?group__isnull=false'; - var msg, update_status; - - if (scope.PostRefreshRemove) { - scope.PostRefreshRemove(); - } - scope.PostRefreshRemove = scope.$on('PostRefresh', function() { - for (var i=0; i < scope.groups.length; i++) { - var last_update = (scope.groups[i].summary_fields.inventory_source.last_updated == null) ? null : - FormatDate(new Date(scope.groups[i].summary_fields.inventory_source.last_updated)); - - // Set values for Failed Hosts column - scope.groups[i].failed_hosts = scope.groups[i].hosts_with_active_failures + ' / ' + scope.groups[i].total_hosts; - - msg = GetHostsStatusMsg({ - active_failures: scope.groups[i].hosts_with_active_failures, - total_hosts: scope.groups[i].total_hosts, - inventory_id: scope['inventory_id'], - group_id: scope['groups'][i]['id'] - }); - - update_status = GetSyncStatusMsg({ status: scope.groups[i].summary_fields.inventory_source.status }); - - scope.groups[i].failed_hosts_tip = msg['tooltip']; - scope.groups[i].failed_hosts_link = msg['url']; - scope.groups[i].failed_hosts_class = msg['class']; - scope.groups[i].status = update_status['status']; - scope.groups[i].source = scope.groups[i].summary_fields.inventory_source.source; - scope.groups[i].last_updated = last_update; - scope.groups[i].status_badge_class = update_status['class']; - scope.groups[i].status_badge_tooltip = update_status['tooltip']; - - // Set cancel button attributes - if (scope.groups[i].summary_fields.inventory_source.status == 'updating' || - scope.groups[i].summary_fields.inventory_source.status == 'updating') { - scope.groups[i].cancel_tooltip = "Cancel the update process"; - scope.groups[i].cancel_class = ""; - } - else { - scope.groups[i].cancel_tooltip = "Update process is not running"; - scope.groups[i].cancel_class = "btn-disabled"; - } - - // Set update button attributes - if (scope.groups[i].summary_fields.inventory_source.source == "" || - scope.groups[i].summary_fields.inventory_source.source == null) { - scope.groups[i].update_tooltip = "No external source. Does not require an update."; - scope.groups[i].update_class = "btn-disabled"; - } - else { - scope.groups[i].update_tooltip = "Start the inventory update process"; - scope.groups[i].update_class = ""; - } - } - - if (scope.groups.length == 0) { - // Force display for help tooltip when no groups exist - $('#inventory-summary-help').focus(); - } - - }); - - SearchInit({ scope: scope, set: 'groups', list: list, url: defaultUrl }); - PaginateInit({ scope: scope, list: list, url: defaultUrl }); - - if (scope['inventorySummaryGroup'] || $routeParams['name']) { - scope[list.iterator + 'SearchField'] = 'name'; - scope[list.iterator + 'SearchType'] = 'iexact'; - scope[list.iterator + 'SearchValue'] = (scope['inventorySummaryGroup']) ? - scope['inventorySummaryGroup'] : $routeParams['name']; - scope[list.iterator + 'SearchFieldLabel'] = list.fields['name'].label; - } - else if ($routeParams['has_external_source']) { - scope[list.iterator + 'SearchField'] = 'has_external_source'; - scope[list.iterator + 'SearchValue'] = list.fields['has_external_source'].searchValue; - scope[list.iterator + 'InputDisable'] = true; - scope[list.iterator + 'SearchType'] = 'in'; - scope[list.iterator + 'SearchFieldLabel'] = list.fields['has_external_source'].label; - } - else if ($routeParams['status']) { - // with status param, called post update-submit - scope[list.iterator + 'SearchField'] = 'status'; - scope[list.iterator + 'SelectShow'] = true; - scope[list.iterator + 'SearchSelectOpts'] = list.fields['status'].searchOptions; - scope[list.iterator + 'SearchFieldLabel'] = list.fields['status'].label.replace(/\/g,' '); - for (var opt in list.fields['status'].searchOptions) { - if (list.fields['status'].searchOptions[opt].value == $routeParams['status']) { - scope[list.iterator + 'SearchSelectValue'] = list.fields['status'].searchOptions[opt]; - break; - } - } - } - - scope.search(list.iterator, false, true); - - scope.showHelp = function() { - // Display help dialog - $('.btn').blur(); //remove focus from the help button and all buttons - //this stops the tooltip from continually displaying - HelpDialog({ defn: InventorySummaryHelp }); - } - - scope.viewUpdateStatus = function(group_id) { ViewUpdateStatus({ scope: scope, group_id: group_id }) }; - - // Click on group name - scope.GroupsEdit = function(group_id) { - // On the tree, select the first occurrance of the requested group - ClickNode({ selector: '#inventory-tree li[data-group-id="' + group_id + '"]' }); - } - - - // Respond to refresh button - scope.refresh = function() { - /*scope.search(list.iterator, false, true); - BuildTree({ - scope: scope, - inventory_id: scope['inventory_id'], - emit_on_select: 'NodeSelect', - target_id: 'search-tree-container', - refresh: true, - moveable: true - });*/ - } - - // Start the update process - scope.updateGroup = function(id) { - for (var i=0; i < scope.groups.length; i++) { - if (scope.groups[i].id == id) { - if (scope.groups[i].summary_fields.inventory_source.source == "" || scope.groups[i].summary_fields.inventory_source.source == null) { - //Alert('Missing Configuration', 'The selected group is not configured for updates. You must first edit the group and provide ' + - // 'external Source settings before attempting an update.', 'alert-info'); - // Do nothing. Act as though button is disabled. - } - else if (scope.groups[i].summary_fields.inventory_source.status == 'updating') { - Alert('Update in Progress', 'The inventory update process is currently running for group ' + - scope.groups[i].name + '. Use the Refresh button to monitor the status.', 'alert-info'); - } - else { - /*if (scope.groups[i].summary_fields.inventory_source.source == 'ec2') { - scope.sourceUsernameLabel = 'Access Key ID'; - scope.sourcePasswordLabel = 'Secret Access Key'; - scope.sourcePasswordConfirmLabel = 'Confirm Secret Access Key'; - } - else { - scope.sourceUsernameLabel = 'Username'; - scope.sourcePasswordLabel = 'Password'; - scope.sourcePasswordConfirmLabel = 'Confirm Password'; - }*/ - Wait('start'); - Rest.setUrl(scope.groups[i].related.inventory_source); - Rest.get() - .success( function(data, status, headers, config) { - InventoryUpdate({ - scope: scope, - group_id: id, - url: data.related.update, - group_name: data.summary_fields.group.name, - group_source: data.source - }); - }) - .error( function(data, status, headers, config) { - Wait('stop'); - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to retrieve inventory source: ' + scope.groups[i].related.inventory_source + - ' POST returned status: ' + status }); - }); - } - break; - } - } - } - } - }]) - .factory('SourceChange', [ 'GetBasePath', 'CredentialList', 'LookUpInit', function(GetBasePath, CredentialList, LookUpInit){ return function(params) { @@ -607,6 +415,9 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' // Cancel the update process var group = Find({ list: scope.groups, key: 'id', val: id }); + scope.selected_tree_id = group.id; + scope.selected_group_id = group.group_id; + if (group && (group.status == 'updating' || group.status == 'pending')) { // We found the group, and there is a running update Wait('start'); @@ -630,10 +441,10 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' }]) .factory('GroupsAdd', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm', - 'Prompt', 'ProcessErrors', 'GetBasePath', 'ParseTypeChange', 'GroupsEdit', 'ClickNode', 'Wait', 'GetChoices', + 'Prompt', 'ProcessErrors', 'GetBasePath', 'ParseTypeChange', 'GroupsEdit', 'Wait', 'GetChoices', 'GetSourceTypeOptions', 'LookUpInit', 'BuildTree', 'SourceChange', function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors, - GetBasePath, ParseTypeChange, GroupsEdit, ClickNode, Wait, GetChoices, GetSourceTypeOptions, LookUpInit, BuildTree, + GetBasePath, ParseTypeChange, GroupsEdit, Wait, GetChoices, GetSourceTypeOptions, LookUpInit, BuildTree, SourceChange) { return function(params) { @@ -646,7 +457,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' GetBasePath('inventory') + inventory_id + '/groups/'; var form = GroupForm; var generator = GenerateForm; - var scope = generator.inject(form, {mode: 'add', modal: true, related: false}); + var scope = generator.inject(form, { mode: 'add', modal: true, related: false, show_modal: false }); var groupCreated = false; scope.formModalActionLabel = 'Save'; @@ -656,11 +467,6 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' ParseTypeChange(scope); $('#form-modal .btn-none').removeClass('btn-none').addClass('btn-success'); - $('#form-modal').on('hidden.bs.modal', function () { - //if (!groupCreated) { - // ClickNode({ selector: '#' + scope['selectedNode'].attr('id') }); - //} - }); generator.reset(); var master={}; @@ -668,7 +474,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' if (scope.removeAddTreeRefreshed) { scope.removeAddTreeRefreshed(); } - scope.removeAddTreeRefreshed = scope.$on('groupTreeRefreshed', function(e) { + scope.removeAddTreeRefreshed = scope.$on('GroupTreeRefreshed', function(e) { Wait('stop'); $('#form-modal').modal('hide'); scope.removeAddTreeRefreshed(); @@ -677,11 +483,11 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' if (scope.removeSaveComplete) { scope.removeSaveComplete(); } - scope.removeSaveComplete = scope.$on('SaveComplete', function(e, error) { + scope.removeSaveComplete = scope.$on('SaveComplete', function(e, group_id, error) { if (!error) { scope.formModalActionDisabled = false; scope.showGroupHelp = false; //get rid of the Hint - BuildTree({ scope: inventory_scope, inventory_id: inventory_id, refresh: true }); + BuildTree({ scope: inventory_scope, inventory_id: inventory_id, refresh: true, new_group_id: group_id }); } }); @@ -754,10 +560,10 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' Rest.setUrl(url) Rest.put(data) .success( function(data, status, headers, config) { - scope.$emit('SaveComplete', false); + scope.$emit('SaveComplete', group_id, false); }) .error( function(data, status, headers, config) { - scope.$emit('SaveComplete', true); + scope.$emit('SaveComplete', group_id, true); ProcessErrors(scope, data, status, form, { hdr: 'Error!', msg: 'Failed to update group inventory source. PUT status: ' + status }); }); @@ -765,7 +571,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' } else { // No source value - scope.$emit('SaveComplete', false); + scope.$emit('SaveComplete', group_id, false); } }); @@ -845,6 +651,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' scope.removeChoicesReady = scope.$on('choicesReadyGroup', function() { choicesReady++; if (choicesReady == 2) { + $('#form-modal').modal('show'); Wait('stop'); } }); @@ -877,42 +684,46 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' .factory('GroupsEdit', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm', 'Prompt', 'ProcessErrors', 'GetBasePath', 'SetNodeName', 'ParseTypeChange', 'GetSourceTypeOptions', 'InventoryUpdate', - 'GetUpdateIntervalOptions', 'ClickNode', 'LookUpInit', 'Empty', 'Wait', 'GetChoices', 'UpdateGroup', 'SourceChange', + 'GetUpdateIntervalOptions', 'LookUpInit', 'Empty', 'Wait', 'GetChoices', 'UpdateGroup', 'SourceChange', function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors, - GetBasePath, SetNodeName, ParseTypeChange, GetSourceTypeOptions, InventoryUpdate, GetUpdateIntervalOptions, ClickNode, + GetBasePath, SetNodeName, ParseTypeChange, GetSourceTypeOptions, InventoryUpdate, GetUpdateIntervalOptions, LookUpInit, Empty, Wait, GetChoices, UpdateGroup, SourceChange) { return function(params) { + var parent_scope = params.scope; var group_id = params.group_id; + var tree_id = params.tree_id; var inventory_id = params.inventory_id; + var generator = GenerateForm; var form = GroupForm; var defaultUrl = GetBasePath('groups') + group_id + '/'; - var groups_scope = params.scope; - - //var scope = - var scope = generator.inject(form, { mode: 'edit', modal: true, related: false }); - generator.reset(); - var master = {}; var relatedSets = {}; + + // Load the modal form + var scope = generator.inject(form, { mode: 'edit', modal: true, related: false, show_modal: false }); + generator.reset(); + + // Change the selected group + parent_scope.showHosts(tree_id, group_id, false); GetSourceTypeOptions({ scope: scope, variable: 'source_type_options' }); - - //scope.update_interval_options = GetUpdateIntervalOptions(); + scope.formModalActionLabel = 'Save'; + scope.formModalHeader = 'Group'; scope.formModalCancelShow = true; scope.source = form.fields.source['default']; scope.parseType = 'yaml'; scope[form.fields['source_vars'].parseTypeName] = 'yaml'; scope.sourcePathRequired = false; - + ParseTypeChange(scope); ParseTypeChange(scope, 'source_vars', form.fields['source_vars'].parseTypeName); - + // After the group record is loaded, retrieve related data if (scope.groupLoadedRemove) { - scope.groupLoadedRemove(); + scope.groupLoadedRemove(); } scope.groupLoadedRemove = scope.$on('groupLoaded', function() { for (var set in relatedSets) { @@ -1046,11 +857,10 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' } }); - if (scope.removeChoicesComplete) { scope.removeChoicesComplete(); } - scope.removeChoicesComplete = scope.$on('choicesCompleteGroup', function() { + scope.removeChoicesComplete = scope.$on('choicesCompleteGroup', function() { // Retrieve detail record and prepopulate the form Rest.setUrl(defaultUrl); Rest.get() @@ -1069,6 +879,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' } scope.variable_url = data.related.variable_data; scope.source_url = data.related.inventory_source; + $('#form-modal').modal('show'); scope.$emit('groupLoaded'); }) .error( function(data, status, headers, config) { @@ -1110,17 +921,13 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' Wait('start'); - //if (!scope.$$phase) { - // scope.$digest(); - //} - if (scope.removeSaveComplete) { - scope.removeSaveComplete(); + scope.removeSaveComplete(); } scope.removeSaveComplete = scope.$on('SaveComplete', function(e, error) { if (!error) { UpdateGroup({ - scope: groups_scope, + scope: parent_scope, group_id: group_id, properties: { name: scope.name, @@ -1136,7 +943,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' }); if (scope.removeFormSaveSuccess) { - scope.removeFormSaveSuccess(); + scope.removeFormSaveSuccess(); } scope.removeFormSaveSuccess = scope.$on('formSaveSuccess', function(e, group_id) { @@ -1152,14 +959,14 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' if (scope.source.value !== null && scope.source.value !== '') { var data = { group: group_id, - source: scope['source'].value, - source_path: scope['source_path'], - credential: scope['credential'], - overwrite: scope['overwrite'], - overwrite_vars: scope['overwrite_vars'], - update_on_launch: scope['update_on_launch'] - //update_interval: scope['update_interval'].value - }; + source: scope['source'].value, + source_path: scope['source_path'], + credential: scope['credential'], + overwrite: scope['overwrite'], + overwrite_vars: scope['overwrite_vars'], + update_on_launch: scope['update_on_launch'] + //update_interval: scope['update_interval'].value + }; // Create a string out of selected list of regions var regions = $('#s2id_group_source_regions').select2("data"); @@ -1248,15 +1055,20 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' Rest.put(data) .success( function(data, status, headers, config) { if (scope.variables) { - //update group variables - Rest.setUrl(scope.variable_url); - Rest.put(json_data) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to update group variables. PUT status: ' + status }); - }); + //update group variables + Rest.setUrl(scope.variable_url); + Rest.put(json_data) + .success( function(data, status, headers, config) { + scope.$emit('formSaveSuccess', data.id); + }) + .error( function(data, status, headers, config) { + ProcessErrors(scope, data, status, form, + { hdr: 'Error!', msg: 'Failed to update group variables. PUT status: ' + status }); + }); + } + else { + scope.$emit('formSaveSuccess', data.id); } - scope.$emit('formSaveSuccess', data.id); }) .error( function(data, status, headers, config) { Wait('stop'); @@ -1324,41 +1136,22 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' .factory('GroupsDelete', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm', - 'Prompt', 'ProcessErrors', 'GetBasePath', 'Wait', 'ClickNode', 'BuildTree', + 'Prompt', 'ProcessErrors', 'GetBasePath', 'Wait', 'BuildTree', 'Find', function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors, - GetBasePath, Wait, ClickNode, BuildTree) { + GetBasePath, Wait, BuildTree, Find) { return function(params) { // Delete the selected group node. Disassociates it from its parent. var scope = params.scope; var tree_id = params.tree_id; + var group_id = params.group_id; var inventory_id = params.inventory_id; - var node, parent, url, parent_name; - - for (var i=0; i < scope.groups.length; i++) { - if (scope.groups[i].id == tree_id) { - node = scope.groups[i]; - } - } - //if (node.parent != 0) { - // for (var i=0; i < scope.groups.length; i++) { - // if (scope.groups[i].id == node.parent) { - // parent = scope.groups[i]; - // parent_name = scope.groups[i].name; - // } - // } - // } - // else { - // parent_name = scope.inventory_name; - // } + var node = Find({ list: scope.groups, key: 'id', val: tree_id }); + var url = GetBasePath('inventory') + inventory_id + '/groups/'; - //if (parent) { - // url = GetBasePath('base') + 'groups/' + parent.group_id + '/children/'; - //} - //else { - url = GetBasePath('inventory') + inventory_id + '/groups/'; - //} + scope.showHosts(tree_id, group_id, false); + var action_to_take = function() { $('#prompt-modal').on('hidden.bs.modal', function(){ Wait('start'); }); $('#prompt-modal').modal('hide'); @@ -1366,7 +1159,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' Rest.post({ id: node.group_id, disassociate: 1 }) .success( function(data, status, headers, config) { $('#prompt-modal').off(); - scope.$emit('groupDeleteCompleted'); // Signal a group refresh to start + scope.$emit('GroupDeleteCompleted'); // Signal a group refresh to start }) .error( function(data, status, headers, config) { Wait('stop'); @@ -1377,19 +1170,6 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', ' Prompt({ hdr: 'Delete Group', body: '

Are you sure you want to delete group ' + node.name + '?

', action: action_to_take, 'class': 'btn-danger' }); - - //' from ' + parent_name + ' - //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('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({ - // backdrop: 'static', - // keyboard: true, - // show: true - // }); } }]) diff --git a/awx/ui/static/js/helpers/Hosts.js b/awx/ui/static/js/helpers/Hosts.js index 21276e3462..c0611d4507 100644 --- a/awx/ui/static/js/helpers/Hosts.js +++ b/awx/ui/static/js/helpers/Hosts.js @@ -22,8 +22,7 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H var group_id = params.group_id; var tree_id = params.tree_id var inventory_id = params.inventory_id; - var emit = params.emit; - + var url = ( !Empty(group_id) ) ? GetBasePath('groups') + group_id + '/all_hosts/' : GetBasePath('inventory') + inventory_id + '/hosts/'; @@ -34,9 +33,7 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H } scope.removePostRefresh = scope.$on('PostRefresh', function(e) { Wait('stop'); - if (emit) { - scope.$emit(emit); - } + scope.$emit('HostReloadComplete'); }); SearchInit({ scope: scope, set: 'hosts', list: InventoryHosts, url: url }); @@ -53,14 +50,13 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H var inventory_id = params.inventory_id; var group_id = params.group_id; var tree_id = params.tree_id; - var emit = params.emit; - + // Inject the list html var generator = GenerateList; generator.inject(InventoryHosts, { scope: scope, mode: 'edit', id: 'hosts-container', breadCrumbs: false, searchSize: 'col-lg-6 col-md-6 col-sm-6' }); // Load data - HostsReload({ scope: scope, group_id: group_id, tree_id: tree_id, inventory_id: inventory_id, emit: emit }); + HostsReload({ scope: scope, group_id: group_id, tree_id: tree_id, inventory_id: inventory_id }); } }]) @@ -214,9 +210,10 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, GenerateForm, Prompt, ProcessErrors, GetBasePath, HostsReload, ParseTypeChange, Wait) { return function(params) { - - var inventory_id = params.inventory_id; - var group_id = (params.group_id !== undefined) ? params.group_id : null; + + var parent_scope = params.scope; + var inventory_id = parent_scope.inventory_id; + var group_id = parent_scope.selected_group_id; // Inject dynamic view var defaultUrl = GetBasePath('groups') + group_id + '/hosts/'; @@ -247,19 +244,26 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H if (!scope.$$phase) { scope.$digest(); } + + if (scope.removeHostSaveComplete) { + scope.removeHostSaveComplete(); + } + scope.removeHostSaveComplete = scope.$on('HostSaveComplete', function() { + Wait('stop'); + $('#form-modal').modal('hide'); + HostsReload({ + scope: parent_scope, + group_id: parent_scope.selected_group_id, + tree_id: parent_scope.selected_tree_id, + inventory_id: parent_scope.inventory_id }); + }); // Save scope.formModalAction = function() { Wait('start'); - function finished() { - $('#form-modal').modal('hide'); - scope.$emit('hostsReload'); - } - - try { - + try { scope.formModalActionDisabled = true; // Make sure we have valid variable data @@ -294,8 +298,7 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'H Rest.setUrl(defaultUrl); Rest.post(data) .success( function(data, status, headers, config) { - Wait('stop'); - finished(); + scope.$emit('HostSaveComplete'); }) .error( function(data, status, headers, config) { Wait('stop'); diff --git a/awx/ui/static/js/helpers/JobSubmission.js b/awx/ui/static/js/helpers/JobSubmission.js index 6cca02c1f7..b9fb511de9 100644 --- a/awx/ui/static/js/helpers/JobSubmission.js +++ b/awx/ui/static/js/helpers/JobSubmission.js @@ -413,14 +413,17 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential var url = params.url; var group_name = params.group_name; var group_source = params.group_source; + var group_id = params.group_id; + var tree_id = params.tree_id; - if (scope.removeSubmitRefreshCompleted) { - scope.removeSubmitRefreshCompleted(); + if (scope.removeHostReloadComplete) { + scope.removeHostReloadComplete(); } - scope.removeSubmitRefreshCompleted = scope.$on('SubmitRefreshCompleted', function(e) { + scope.removeHostReloadComplete = scope.$on('HostReloadComplete', function(e) { Wait('stop'); Alert('Update Started', 'The request to start the inventory update process was submitted. Monitor progress of the update process ' + 'by clicking the button.', 'alert-info'); + scope.removeHostReloadComplete(); }); if (scope.removeUpdateSubmitted) { @@ -428,7 +431,10 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential } scope.removeUpdateSubmitted = scope.$on('UpdateSubmitted', function(e, action) { if (action == 'started') { - scope.refreshGroups('SubmitRefreshComplete'); + // Cancel the update process + scope.selected_tree_id = tree_id; + scope.selected_group_id = group_id; + scope.refreshGroups(); } }); diff --git a/awx/ui/static/js/helpers/inventory.js b/awx/ui/static/js/helpers/inventory.js index 6e415d1a25..32fd9d0340 100644 --- a/awx/ui/static/js/helpers/inventory.js +++ b/awx/ui/static/js/helpers/inventory.js @@ -14,101 +14,9 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi 'InventoryFormDefinition', 'ParseHelper' ]) - .factory('LoadRootGroups', ['Rest', 'ProcessErrors', function(Rest, ProcessErrors) { - return function(params) { - - // Build an array of root group IDs. We'll need this when copying IDs. - - var scope = params.scope; - Rest.setUrl(scope.inventoryRootGroupsUrl); - Rest.get() - .success( function(data, status, headers, config) { - scope.inventoryRootGroups = []; - for (var i=0; i < data.results.length; i++){ - scope.inventoryRootGroups.push(data.results[i].id); - } - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Failed to retrieve root groups for inventory: ' + - scope.inventory_id + '. GET status: ' + status }); - }); - } - }]) - - .factory('LoadInventory', ['$routeParams', 'Alert', 'Rest', 'Authorization', '$http', 'ProcessErrors', - 'RelatedSearchInit', 'RelatedPaginateInit', 'GetBasePath', 'LoadBreadCrumbs', 'InventoryForm', 'LoadRootGroups', - function($routeParams, Alert, Rest, Authorization, $http, ProcessErrors, RelatedSearchInit, RelatedPaginateInit, - GetBasePath, LoadBreadCrumbs, InventoryForm, LoadRootGroups) { - return function(params) { - - // Load inventory detail record - - var scope = params.scope; - var form = InventoryForm; - scope.relatedSets = []; - scope.master = {}; - - if (scope.removeLevelOneGroups) { - scope.removeLevelOneGroups(); - } - scope.removeLevelOneGroups = scope.$on('inventoryLoaded', function() { - LoadRootGroups({ scope: scope }); - }); - - Rest.setUrl(GetBasePath('inventory') + scope['inventory_id'] + '/'); - Rest.get() - .success( function(data, status, headers, config) { - - LoadBreadCrumbs({ path: '/inventories/' + $routeParams.id, title: data.name }); - - for (var fld in form.fields) { - if (form.fields[fld].realName) { - if (data[form.fields[fld].realName]) { - scope[fld] = data[form.fields[fld].realName]; - scope.master[fld] = scope[fld]; - } - } - else { - if (data[fld]) { - scope[fld] = data[fld]; - scope.master[fld] = scope[fld]; - } - } - if (form.fields[fld].type == 'lookup' && data.summary_fields[form.fields[fld].sourceModel]) { - scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] = - data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField]; - scope.master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] = - scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField]; - } - } - - scope.inventoryGroupsUrl = data.related.groups; - scope.inventoryRootGroupsUrl = data.related.root_groups; - scope.TreeParams = { scope: scope, inventory: data }; - scope.variable_url = data.related.variable_data; - scope.relatedSets['hosts'] = { url: data.related.hosts, iterator: 'host' }; - scope.treeData = data.related.tree; - - // Load the tree view - if (params.doPostSteps) { - RelatedSearchInit({ scope: scope, form: form, relatedSets: scope.relatedSets }); - RelatedPaginateInit({ scope: scope, relatedSets: scope.relatedSets }); - } - scope.$emit('inventoryLoaded'); - }) - .error( function(data, status, headers, config) { - ProcessErrors(scope, data, status, null, - { hdr: 'Error!', msg: 'Failed to retrieve inventory: ' + $routeParams.id + '. GET status: ' + status }); - }); - - } - }]) - .factory('SaveInventory', ['InventoryForm', 'Rest', 'Alert', 'ProcessErrors', 'LookUpInit', 'OrganizationList', - 'GetBasePath', 'ParseTypeChange', 'LoadInventory', 'Wait', - function(InventoryForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath, ParseTypeChange, - LoadInventory, Wait) { + 'GetBasePath', 'ParseTypeChange', 'Wait', + function(InventoryForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath, ParseTypeChange, Wait) { return function(params) { // Save inventory property modifications @@ -153,7 +61,7 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi Rest.put(json_data) .success( function(data, status, headers, config) { Wait('stop'); - scope.$emit('inventorySaved'); + scope.$emit('InventorySaved'); }) .error( function(data, status, headers, config) { ProcessErrors(scope, data, status, form, @@ -161,7 +69,7 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi }); } else { - scope.$emit('inventorySaved'); + scope.$emit('InventorySaved'); } }) .error( function(data, status, headers, config) { @@ -177,104 +85,111 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi } }]) - .factory('PostLoadInventory', ['InventoryForm', 'Rest', 'Alert', 'ProcessErrors', 'LookUpInit', 'OrganizationList', 'GetBasePath', - function(InventoryForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath) { - return function(params) { - - var scope = params.scope; - - LookUpInit({ - scope: scope, - form: InventoryForm, - current_item: (scope.organization !== undefined) ? scope.organization : null, - list: OrganizationList, - field: 'organization' - }); - if (scope.variable_url) { - Rest.setUrl(scope.variable_url); - Rest.get() - .success( function(data, status, headers, config) { - if ($.isEmptyObject(data)) { - scope.inventory_variables = "---"; - } - else { - scope.inventory_variables = jsyaml.safeDump(data); - } - scope.master.inventory_variables = scope.inventory_variables; - }) - .error( function(data, status, headers, config) { - scope.inventory_variables = null; - ProcessErrors(scope, data, status, form, - { hdr: 'Error!', msg: 'Failed to retrieve inventory variables. GET returned status: ' + status }); - }); - } - else { - scope.inventory_variables = "---"; - } - if (!scope.$$phase) { - scope.$digest(); - } - - } - }]) - - .factory('EditInventory', ['InventoryForm', 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LookUpInit', 'OrganizationList', - 'GetBasePath', 'ParseTypeChange', 'LoadInventory', 'SaveInventory', 'PostLoadInventory', - function(InventoryForm, GenerateForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath, ParseTypeChange, - LoadInventory, SaveInventory, PostLoadInventory) { + .factory('EditInventoryProperties', ['InventoryForm', 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LookUpInit', 'OrganizationList', + 'GetBasePath', 'ParseTypeChange', 'SaveInventory', 'Wait', + function(InventoryForm, GenerateForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath, ParseTypeChange, SaveInventory, + Wait) { return function(params) { + var parent_scope = params.scope + var inventory_id = params.inventory_id; + var generator = GenerateForm; var form = InventoryForm; var defaultUrl=GetBasePath('inventory'); - var scope = params.scope - + var master = {}; + form.well = false; - form.formLabelSize = 'col-lg-3'; - form.formFieldSize = 'col-lg-9'; + //form.formLabelSize = 'col-lg-3'; + //form.formFieldSize = 'col-lg-9'; - generator.inject(form, {mode: 'edit', modal: true, related: false}); + var scope = generator.inject(form, {mode: 'edit', modal: true, related: false, modal_show: false }); /* Reset form properties. Otherwise it screws up future requests of the Inventories detail page */ form.well = true; - delete form.formLabelSize; - delete form.formFieldSize; + //delete form.formLabelSize; + //delete form.formFieldSize; ParseTypeChange(scope,'inventory_variables', 'inventoryParseType'); - scope.inventoryParseType = 'yaml'; - scope['inventory_id'] = params['inventory_id']; scope.formModalActionLabel = 'Save'; scope.formModalCancelShow = true; scope.formModalInfo = false; - $('#form-modal .btn-success').removeClass('btn-none').addClass('btn-success'); scope.formModalHeader = 'Inventory Properties'; - // Retrieve each related set and any lookups - if (scope.inventoryLoadedRemove) { - scope.inventoryLoadedRemove(); - } - scope.inventoryLoadedRemove = scope.$on('inventoryLoaded', function() { - PostLoadInventory({ scope: scope }); - }); - - LoadInventory({ scope: scope, doPostSteps: false }); + $('#form-modal .btn-success').removeClass('btn-none').addClass('btn-success'); - if (!scope.$$phase) { - scope.$digest(); - } + Wait('start'); + Rest.setUrl(GetBasePath('inventory') + inventory_id + '/'); + Rest.get() + .success( function(data, status, headers, config) { + for (var fld in form.fields) { + if (fld == 'inventory_variables') { + // Parse variables, converting to YAML. + if ($.isEmptyObject(data.variables) || data.variables == "\{\}" || + data.variables == "null" || data.data_variables == "") { + scope.inventory_variables = "---"; + } + else { + var json_obj = JSON.parse(data.variables); + scope.inventory_variables = jsyaml.safeDump(json_obj); + } + master.inventory_variables = scope.variables; + } + else if (fld == 'inventory_name') { + scope[fld] = data.name; + master[fld] = scope[fld]; + } + else if (fld == 'inventory_description') { + scope[fld] = data.description; + master[fld] = scope[fld]; + } + else if (data[fld]) { + scope[fld] = data[fld]; + master[fld] = scope[fld]; + } + if (form.fields[fld].sourceModel && data.summary_fields && + data.summary_fields[form.fields[fld].sourceModel]) { + scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] = + data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField]; + master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] = + data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField]; + } + } + + LookUpInit({ + scope: scope, + form: form, + current_item: scope.organization, + list: OrganizationList, + field: 'organization' + }); + + Wait('stop'); + $('#form-modal').modal('show'); + + }) + .error( function(data, status, headers, config) { + Wait('stop'); + ProcessErrors(scope, data, status, null, + { hdr: 'Error!', msg: 'Failed to get inventory: ' + inventory_id + '. GET returned: ' + status }); + }); + if (scope.removeInventorySaved) { scope.removeInventorySaved(); } - scope.removeInventorySaved = scope.$on('inventorySaved', function() { + scope.removeInventorySaved = scope.$on('InventorySaved', function() { $('#form-modal').modal('hide'); }); scope.formModalAction = function() { + scope.inventory_id = inventory_id; + parent_scope.inventory_name = scope.inventory_name; + console.log('set inventory_name to: ' + parent_scope.inventory_name); SaveInventory({ scope: scope }); - } + } } }]); diff --git a/awx/ui/static/js/lists/InventoryGroups.js b/awx/ui/static/js/lists/InventoryGroups.js index 2b06eb7c42..6d527fd2d6 100644 --- a/awx/ui/static/js/lists/InventoryGroups.js +++ b/awx/ui/static/js/lists/InventoryGroups.js @@ -75,12 +75,12 @@ angular.module('InventoryGroupsDefinition', []) create: { mode: 'all', ngClick: "createGroup()", - ngHide: 'selected_tree_id == 1', //disable when 'All Hosts' selected awToolTip: "Create a new group" }, properties: { mode: 'all', - awToolTip: "Edit inventory properties" + awToolTip: "Edit inventory properties", + ngClick: 'editInventoryProperties()' }, refresh: { mode: 'all', @@ -107,7 +107,7 @@ angular.module('InventoryGroupsDefinition', []) fieldActions: { sync_status: { mode: 'all', - ngClick: "viewUpdateStatus(\{\{ group.id \}\})", + ngClick: "viewUpdateStatus(\{\{ group.id + ',' + group.group_id \}\})", ngShow: "group.id > 1", // hide for all hosts awToolTip: "\{\{ group.status_tooltip \}\}", ngClass: "group.status_class", @@ -142,7 +142,7 @@ angular.module('InventoryGroupsDefinition', []) edit: { //label: 'Edit', mode: 'all', - ngClick: "editGroup(\{\{ group.group_id \}\})", + ngClick: "editGroup(\{\{ group.group_id + ',' + group.id \}\})", awToolTip: 'Edit group', ngShow: "group.id > 1", // hide for all hosts dataPlacement: "top" @@ -150,7 +150,7 @@ angular.module('InventoryGroupsDefinition', []) "delete": { //label: 'Delete', mode: 'all', - ngClick: "deleteGroup(\{\{ group.id \}\})", + ngClick: "deleteGroup(\{\{ group.id + ',' + group.group_id \}\})", awToolTip: 'Delete group', ngShow: "group.id != 1", // hide for all hosts dataPlacement: "top" diff --git a/awx/ui/static/js/lists/InventoryHosts.js b/awx/ui/static/js/lists/InventoryHosts.js index d53fbb6295..07f4b386fd 100644 --- a/awx/ui/static/js/lists/InventoryHosts.js +++ b/awx/ui/static/js/lists/InventoryHosts.js @@ -27,19 +27,6 @@ angular.module('InventoryHostsDefinition', []) ngClick: "editHost(\{\{ host.id \}\}, '\{\{ host.name \}\}')", searchPlaceholder: "search_place_holder" }, - active_failures: { - label: 'Job Status', - ngHref: "\{\{ host.activeFailuresLink \}\}", - awToolTip: "\{\{ host.badgeToolTip \}\}", - dataPlacement: 'top', - badgeNgHref: '\{\{ host.activeFailuresLink \}\}', - badgeIcon: "\{\{ 'fa icon-failures-' + host.has_active_failures \}\}", - badgePlacement: 'left', - badgeToolTip: "\{\{ host.badgeToolTip \}\}", - badgeTipPlacement: 'top', - searchable: false, - nosort: true - }, enabled_flag: { label: 'Enabled', badgeIcon: "\{\{ 'fa icon-enabled-' + host.enabled \}\}", @@ -84,6 +71,20 @@ angular.module('InventoryHostsDefinition', []) }, fieldActions: { + active_failures: { + //label: 'Job Status', + + awToolTip: "\{\{ host.badgeToolTip \}\}", + dataPlacement: 'top', + badgeNgHref: '\{\{ host.activeFailuresLink \}\}', + + iconClass: "\{\{ 'fa icon-failures-' + host.has_active_failures \}\}", + + + badgePlacement: 'left', + badgeToolTip: "\{\{ host.badgeToolTip \}\}", + badgeTipPlacement: 'top' + }, edit: { //label: 'Edit', ngClick: "editGroup(\{\{ host.id \}\})", @@ -104,7 +105,7 @@ angular.module('InventoryHostsDefinition', []) create: { mode: 'all', ngClick: "createHost()", - ngHide: "!selected_tree_id", + ngHide: 'selected_tree_id == 1', //disable when 'All Hosts' selected awToolTip: "Create a new host" }, stream: { diff --git a/awx/ui/static/lib/ansible/InventoryTree.js b/awx/ui/static/lib/ansible/InventoryTree.js index 9a07418779..fca72fb889 100644 --- a/awx/ui/static/lib/ansible/InventoryTree.js +++ b/awx/ui/static/lib/ansible/InventoryTree.js @@ -178,7 +178,8 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper']) var inventory_id = params.inventory_id; var scope = params.scope; var refresh = params.refresh; - var emit = params.emit; + var emit = params.emit; + var new_group_id = params.new_group_id; //var selected_id = params. @@ -235,6 +236,11 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper']) show: true } groups.push(group); + if (new_group_id && group.group_id == new_group_id) { + // For new group + scope.selected_tree_id = id; + scope.selected_group_id = group.group_id; + } if (sorted[i].children.length > 0) { buildGroups(sorted[i].children, id, level + 1); } @@ -243,7 +249,7 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper']) // Build the HTML for our tree if (scope.buildAllGroupsRemove) { - scope.buildAllGroupsRemove(); + scope.buildAllGroupsRemove(); } scope.buildAllGroupsRemove = scope.$on('buildAllGroups', function(e, inventory_name, inventory_tree) { Rest.setUrl(inventory_tree); @@ -253,10 +259,10 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper']) //console.log(groups); if (refresh) { scope.groups = groups; - scope.$emit('groupTreeRefreshed', inventory_name, groups, emit); + scope.$emit('GroupTreeRefreshed', inventory_name, groups, emit); } else { - scope.$emit('groupTreeLoaded', inventory_name, groups, emit); + scope.$emit('GroupTreeLoaded', inventory_name, groups, emit); } }) .error( function(data, status, headers, config) { @@ -333,18 +339,4 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper']) $('#inventory-root-node').attr('data-name', name).attr('data-description', descr).find('.activate').first().text(name); } } - }]) - - .factory('ClickNode', [ function() { - return function(params) { - 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(); - } }]); \ No newline at end of file diff --git a/awx/ui/static/lib/ansible/Utilities.js b/awx/ui/static/lib/ansible/Utilities.js index 0a8c8d91b7..ff132db28e 100644 --- a/awx/ui/static/lib/ansible/Utilities.js +++ b/awx/ui/static/lib/ansible/Utilities.js @@ -181,7 +181,6 @@ angular.module('Utilities',['RestServices', 'Utilities']) $rootScope.crumbCache.push(crumb); } } - var paths = $location.path().replace(/^\//,'').split('/'); var ppath = ''; $rootScope.breadcrumbs = []; @@ -191,41 +190,41 @@ angular.module('Utilities',['RestServices', 'Utilities']) if (i > 0 && paths[i].match(/\d+/)) { parent = paths[i-1]; if (parent == 'inventories') { - child = 'inventory'; + child = 'inventory'; } else { - child = parent.substring(0,parent.length - 1); //assumes parent ends with 's' + child = parent.substring(0,parent.length - 1); //assumes parent ends with 's' } // find the correct title for (var j=0; j < $rootScope.crumbCache.length; j++) { if ($rootScope.crumbCache[j].path == '/' + parent + '/' + paths[i]) { - child = $rootScope.crumbCache[j].title; - break; + child = $rootScope.crumbCache[j].title; + break; } } if ($rootScope.crumbCache[j] && $rootScope.crumbCache[j]['altPath'] !== undefined) { - // Use altPath to override default path construction - $rootScope.breadcrumbs.push({ title: child, path: $rootScope.crumbCache[j].altPath }); + // Use altPath to override default path construction + $rootScope.breadcrumbs.push({ title: child, path: $rootScope.crumbCache[j].altPath }); } else { - if (paths[i - 1] == 'hosts') { - // For hosts, there is no /hosts, so we need to link back to the inventory - // We end up here when user has clicked refresh and the crumbcache is missing - $rootScope.breadcrumbs.push({ title: child, - path: '/inventories/' + $routeParams.inventory + '/hosts' }); - } - else { - $rootScope.breadcrumbs.push({ title: child, path: ppath + '/' + paths[i] }); - } + if (paths[i - 1] == 'hosts') { + // For hosts, there is no /hosts, so we need to link back to the inventory + // We end up here when user has clicked refresh and the crumbcache is missing + $rootScope.breadcrumbs.push({ title: child, + path: '/inventories/' + $routeParams.inventory + '/hosts' }); + } + else { + $rootScope.breadcrumbs.push({ title: child, path: ppath + '/' + paths[i] }); + } } } else { if (paths[i] == 'hosts') { - $rootScope.breadcrumbs.push({ title: paths[i], path: '/inventories/' + $routeParams.inventory + - '/hosts' }); + $rootScope.breadcrumbs.push({ title: paths[i], path: '/inventories/' + $routeParams.inventory + + '/hosts' }); } else { - $rootScope.breadcrumbs.push({ title: paths[i], path: ppath + '/' + paths[i] }); + $rootScope.breadcrumbs.push({ title: paths[i], path: ppath + '/' + paths[i] }); } } ppath += '/' + paths[i]; diff --git a/awx/ui/static/lib/ansible/form-generator.js b/awx/ui/static/lib/ansible/form-generator.js index e44f5aa837..b391cb7833 100644 --- a/awx/ui/static/lib/ansible/form-generator.js +++ b/awx/ui/static/lib/ansible/form-generator.js @@ -149,11 +149,12 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities']) $(options.modal_selector).unbind('hidden.bs.modal'); } else { - $('#form-modal').modal({ show: true, backdrop: 'static', keyboard: true }); + var show = (options.show_modal == false) ? false : true; + $('#form-modal').modal({ show: show, backdrop: 'static', keyboard: true }); $('#form-modal').on('shown.bs.modal', function() { $('#form-modal input:first').focus(); }); - $('#form-modal').on('hidden.bs.modal'); + $('#form-modal').off('hidden.bs.modal'); } $(document).bind('keydown', function(e) { if (e.keyCode === 27) {