From 3d5a09e39e296ab81ab194e335dae4aed9b6a6f1 Mon Sep 17 00:00:00 2001 From: Chris Houseknecht Date: Fri, 10 Jan 2014 20:32:52 +0000 Subject: [PATCH] Inventory refactor: Add host works. Click on a row level action on the groups list now shows the row as selected and refreshes the host list. Edit inventory properties now works. Add and Edit dialog boxes are now displayed at the last minute after all data is loaded- accomplished with new list-generator show_modal parameter. --- awx/ui/static/js/controllers/Inventories.js | 111 +++--- awx/ui/static/js/forms/Inventories.js | 4 +- awx/ui/static/js/helpers/Groups.js | 366 ++++---------------- awx/ui/static/js/helpers/Hosts.js | 43 +-- awx/ui/static/js/helpers/JobSubmission.js | 14 +- awx/ui/static/js/helpers/inventory.js | 245 +++++-------- awx/ui/static/js/lists/InventoryGroups.js | 10 +- awx/ui/static/js/lists/InventoryHosts.js | 29 +- awx/ui/static/lib/ansible/InventoryTree.js | 28 +- awx/ui/static/lib/ansible/Utilities.js | 37 +- awx/ui/static/lib/ansible/form-generator.js | 5 +- 11 files changed, 303 insertions(+), 589 deletions(-) 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) {