diff --git a/awx/ui/client/src/app.js b/awx/ui/client/src/app.js index f5eaf2080b..0649023b54 100644 --- a/awx/ui/client/src/app.js +++ b/awx/ui/client/src/app.js @@ -40,7 +40,6 @@ if ($basePath) { import portalMode from './portal-mode/main'; import systemTracking from './system-tracking/main'; import inventories from './inventories/main'; -import inventorynew from './inventoriesnew/main'; import inventoryScripts from './inventory-scripts/main'; import credentialTypes from './credential-types/main'; import organizations from './organizations/main'; @@ -100,7 +99,6 @@ var tower = angular.module('Tower', [ configuration.name, systemTracking.name, inventories.name, - inventorynew.name, inventoryScripts.name, credentialTypes.name, organizations.name, diff --git a/awx/ui/client/src/inventories/add/inventory-add.controller.js b/awx/ui/client/src/inventories/add/inventory-add.controller.js index 4287cfb404..02e608af6c 100644 --- a/awx/ui/client/src/inventories/add/inventory-add.controller.js +++ b/awx/ui/client/src/inventories/add/inventory-add.controller.js @@ -77,7 +77,7 @@ function InventoriesAdd($scope, $location, .success(function(data) { var inventory_id = data.id; Wait('stop'); - $location.path('/inventories/' + inventory_id + '/manage'); + $location.path('/inventories/' + inventory_id); }) .error(function(data, status) { ProcessErrors($scope, data, status, form, { diff --git a/awx/ui/client/src/inventories/add/main.js b/awx/ui/client/src/inventories/add/main.js index fc9c82e6fd..2e477aa96c 100644 --- a/awx/ui/client/src/inventories/add/main.js +++ b/awx/ui/client/src/inventories/add/main.js @@ -7,5 +7,5 @@ import controller from './inventory-add.controller'; export default -angular.module('inventoryAdd', []) +angular.module('InventoryAdd', []) .controller('InventoryAddController', controller); diff --git a/awx/ui/client/src/inventories/edit/inventory-edit.controller.js b/awx/ui/client/src/inventories/edit/inventory-edit.controller.js index 78d35d311f..c08f101ce0 100644 --- a/awx/ui/client/src/inventories/edit/inventory-edit.controller.js +++ b/awx/ui/client/src/inventories/edit/inventory-edit.controller.js @@ -11,13 +11,13 @@ */ function InventoriesEdit($scope, $location, - $stateParams, InventoryForm, Rest, ProcessErrors, + $stateParams, InventoriesForm, Rest, ProcessErrors, ClearScope, GetBasePath, ParseTypeChange, Wait, ToJSON, ParseVariableString, $state, OrgAdminLookup) { // Inject dynamic view var defaultUrl = GetBasePath('inventory'), - form = InventoryForm, + form = InventoriesForm, inventory_id = $stateParams.inventory_id, master = {}, fld, json_data, data; @@ -122,10 +122,6 @@ function InventoriesEdit($scope, $location, }); }; - $scope.manageInventory = function() { - $location.path($location.path() + '/manage'); - }; - $scope.formCancel = function() { $state.go('inventories'); }; @@ -133,7 +129,7 @@ function InventoriesEdit($scope, $location, } export default ['$scope', '$location', - '$stateParams', 'InventoryForm', 'Rest', + '$stateParams', 'InventoriesForm', 'Rest', 'ProcessErrors', 'ClearScope', 'GetBasePath', 'ParseTypeChange', 'Wait', 'ToJSON', 'ParseVariableString', '$state', 'OrgAdminLookup', InventoriesEdit, diff --git a/awx/ui/client/src/inventories/edit/main.js b/awx/ui/client/src/inventories/edit/main.js index f8792fe442..130a5e8b4b 100644 --- a/awx/ui/client/src/inventories/edit/main.js +++ b/awx/ui/client/src/inventories/edit/main.js @@ -7,5 +7,5 @@ import controller from './inventory-edit.controller'; export default - angular.module('inventoryEdit', []) + angular.module('InventoryEdit', []) .controller('InventoryEditController', controller); diff --git a/awx/ui/client/src/inventories/groups/edit/build-groups-edit-state.factory.js b/awx/ui/client/src/inventories/groups/edit/build-groups-edit-state.factory.js new file mode 100644 index 0000000000..3687face76 --- /dev/null +++ b/awx/ui/client/src/inventories/groups/edit/build-groups-edit-state.factory.js @@ -0,0 +1,93 @@ +/************************************************* +* Copyright (c) 2017 Ansible, Inc. +* +* All Rights Reserved +*************************************************/ + +import GroupEditController from './groups-edit.controller'; + +export default ['$stateExtender', 'templateUrl', '$injector', + 'stateDefinitions','GroupForm','nestedGroupListState', + 'nestedHostsListState', 'buildHostAddState', 'buildHostEditState', + 'nestedGroupAddState', + function($stateExtender, templateUrl, $injector, stateDefinitions, GroupForm, + nestedGroupListState, nestedHostsListState, buildHostAddState, + buildHostEditState, nestedGroupAddState){ + var val = function(field, formStateDefinition, params) { + let state, states = [], + list = field.include ? $injector.get(field.include) : field, + breadcrumbLabel = (field.iterator.replace('_', ' ') + 's').toUpperCase(), + stateConfig = { + name: `${formStateDefinition.name}.${list.iterator}s.edit`, + url: `/edit/:group_id`, + ncyBreadcrumb: { + parent: `${formStateDefinition.name}`, + label: `${breadcrumbLabel}` + }, + views: { + 'groupForm@inventories': { + templateProvider: function(GenerateForm, GroupForm) { + let form = GroupForm; + return GenerateForm.buildHTML(form, { + mode: 'edit', + related: false + }); + }, + controller: GroupEditController + } + }, + resolve: { + 'FormDefinition': [params.form, function(definition) { + return definition; + }], + groupData: ['$stateParams', 'GroupManageService', function($stateParams, GroupManageService) { + return GroupManageService.get({ id: $stateParams.group_id }).then(res => res.data.results[0]); + }] + } + }; + state = $stateExtender.buildDefinition(stateConfig); + + let relatedGroupListState = nestedGroupListState(GroupForm.related.nested_groups, state, params); + let relatedGroupsAddState = nestedGroupAddState(GroupForm.related.nested_groups, state, params); + relatedGroupListState = $stateExtender.buildDefinition(relatedGroupListState); + relatedGroupsAddState = $stateExtender.buildDefinition(relatedGroupsAddState); + + let relatedHostsListState = nestedHostsListState(GroupForm.related.nested_hosts, state, params); + let relatedHostsAddState = buildHostAddState(GroupForm.related.nested_hosts, state, params); + let relatedHostsEditState = buildHostEditState(GroupForm.related.nested_hosts, state, params); + relatedHostsListState = $stateExtender.buildDefinition(relatedHostsListState); + relatedHostsAddState = $stateExtender.buildDefinition(relatedHostsAddState); + if(Array.isArray(relatedHostsEditState)) + { + relatedHostsEditState[0] = $stateExtender.buildDefinition(relatedHostsEditState[0]); + relatedHostsEditState[1] = $stateExtender.buildDefinition(relatedHostsEditState[1]); + states.push(state, + relatedGroupListState, + relatedGroupsAddState, + relatedHostsListState, + relatedHostsAddState, + relatedHostsEditState[0], + relatedHostsEditState[1]); + } + else { + relatedHostsEditState = $stateExtender.buildDefinition(relatedHostsEditState); + states.push(state, + relatedGroupListState, + relatedGroupsAddState, + relatedHostsListState, + relatedHostsAddState, + relatedHostsEditState); + } + + // states.push(state, + // relatedGroupListState, + // relatedGroupsAddState, + // relatedHostsListState, + // relatedHostsAddState, + // relatedHostsEditState[0], + // relatedHostsEditState[1]); + return states; + }; + return val; + } +]; diff --git a/awx/ui/client/src/inventories/groups/nested-groups/nested-groups-list-state.factory.js b/awx/ui/client/src/inventories/groups/nested-groups/nested-groups-list-state.factory.js new file mode 100644 index 0000000000..7efd37c391 --- /dev/null +++ b/awx/ui/client/src/inventories/groups/nested-groups/nested-groups-list-state.factory.js @@ -0,0 +1,85 @@ +/************************************************* +* Copyright (c) 2017 Ansible, Inc. +* +* All Rights Reserved +*************************************************/ +import NestedGroupsListController from './nested-groups-list.controller'; +export default ['$stateExtender', 'templateUrl', '$injector', + function($stateExtender, templateUrl, $injector){ + var val = function(field, formStateDefinition) { + let state, + list = field.include ? $injector.get(field.include) : field, + breadcrumbLabel = (field.iterator.replace('_', ' ') + 's').toUpperCase(), + stateConfig = { + searchPrefix: `${list.iterator}`, + squash: '', + name: `${formStateDefinition.name}.nested_groups`, + url: `/${list.iterator}s`, + ncyBreadcrumb: { + parent: `${formStateDefinition.name}`, + label: `${breadcrumbLabel}` + }, + params: { + [list.iterator + '_search']: { + value: { order_by: field.order_by ? field.order_by : 'name' } + }, + }, + views: { + // 'related@inventories.edit.groups.edit': { + 'related': { + templateProvider: function(NestedGroupListDefinition, generateList) { + let list = _.cloneDeep(NestedGroupListDefinition); + + let html = generateList.build({ + list: list, + mode: 'edit' + }); + // Include the custom group delete modal template + // return $templateRequest(templateUrl('inventories/groups/list/groups-list')).then((template) => { + // return html.concat(template); + // }); + return html; + }, + controller: NestedGroupsListController + } + }, + resolve: { + ListDefinition: () => { + return list; + }, + Dataset: ['ListDefinition', 'QuerySet', '$stateParams', 'GetBasePath', '$interpolate', '$rootScope', + (list, qs, $stateParams, GetBasePath, $interpolate, $rootScope) => { + // allow related list definitions to use interpolated $rootScope / $stateParams in basePath field + let path, interpolator; + if (GetBasePath(list.basePath)) { + path = GetBasePath(list.basePath); + } else { + interpolator = $interpolate(list.basePath); + path = interpolator({ $rootScope: $rootScope, $stateParams: $stateParams }); + } + if($stateParams.group_id){ + path = `api/v2/groups/${$stateParams.group_id}/children`; + } + else if($stateParams.host_id){ + path = GetBasePath('hosts') + $stateParams.host_id + '/all_groups'; + } + return qs.search(path, $stateParams[`${list.iterator}_search`]); + } + ], + inventoryData: ['InventoryManageService', '$stateParams', 'host', function(InventoryManageService, $stateParams, host) { + var id = ($stateParams.inventory_id) ? $stateParams.inventory_id : host.data.summary_fields.inventory.id; + return InventoryManageService.getInventory(id).then(res => res.data); + }] + } + }; + + state = $stateExtender.buildDefinition(stateConfig); + // appy any default search parameters in form definition + if (field.search) { + state.params[`${field.iterator}_search`].value = _.merge(state.params[`${field.iterator}_search`].value, field.search); + } + return state; + }; + return val; + } +]; diff --git a/awx/ui/client/src/inventories/groups/nested-hosts/nested-hosts-list.controller.js b/awx/ui/client/src/inventories/groups/nested-hosts/nested-hosts-list.controller.js new file mode 100644 index 0000000000..20196b1647 --- /dev/null +++ b/awx/ui/client/src/inventories/groups/nested-hosts/nested-hosts-list.controller.js @@ -0,0 +1,162 @@ +/************************************************* + * Copyright (c) 2017 Ansible, Inc. + * + * All Rights Reserved + *************************************************/ + +export default ['$scope', 'NestedHostsListDefinition', '$rootScope', 'GetBasePath', + 'rbacUiControlService', 'Dataset', '$state', '$filter', 'Prompt', 'Wait', + 'HostManageService', 'SetStatus', + function($scope, NestedHostsListDefinition, $rootScope, GetBasePath, + rbacUiControlService, Dataset, $state, $filter, Prompt, Wait, + HostManageService, SetStatus) { + + let list = NestedHostsListDefinition; + + init(); + + function init(){ + $scope.canAdd = false; + $scope.enableSmartInventoryButton = false; + + rbacUiControlService.canAdd('hosts') + .then(function(canAdd) { + $scope.canAdd = canAdd; + }); + + // Search init + $scope.list = list; + $scope[`${list.iterator}_dataset`] = Dataset.data; + $scope[list.name] = $scope[`${list.iterator}_dataset`].results; + + $rootScope.flashMessage = null; + + $scope.$watchCollection(list.name, function() { + $scope[list.name] = _.map($scope.nested_hosts, function(value) { + value.inventory_name = value.summary_fields.inventory.name; + value.inventory_id = value.summary_fields.inventory.id; + return value; + }); + setJobStatus(); + }); + + $rootScope.$on('$stateChangeSuccess', function(event, toState, toParams) { + if(toState.name === 'hosts.addSmartInventory') { + $scope.enableSmartInventoryButton = false; + } + else { + if(toParams && toParams.host_search) { + let hasMoreThanDefaultKeys = false; + angular.forEach(toParams.host_search, function(value, key) { + if(key !== 'order_by' && key !== 'page_size') { + hasMoreThanDefaultKeys = true; + } + }); + $scope.enableSmartInventoryButton = hasMoreThanDefaultKeys ? true : false; + } + else { + $scope.enableSmartInventoryButton = false; + } + } + }); + + $scope.$on('selectedOrDeselected', function(e, value) { + let item = value.value; + + if (value.isSelected) { + if(!$scope.hostsSelected) { + $scope.hostsSelected = []; + } + $scope.hostsSelected.push(item); + } else { + _.remove($scope.hostsSelected, { id: item.id }); + if($scope.hostsSelected.length === 0) { + $scope.hostsSelected = null; + } + } + + $scope.systemTrackingDisabled = ($scope.hostsSelected && $scope.hostsSelected.length > 2) ? true : false; + }); + + } + + function setJobStatus(){ + _.forEach($scope.hosts, function(value) { + SetStatus({ + scope: $scope, + host: value + }); + }); + } + + $scope.createHost = function(){ + $state.go('inventories.edit.groups.edit.nested_hosts.add'); + }; + $scope.editHost = function(id){ + $state.go('inventories.edit.groups.edit.nested_hosts.edit', {host_id: id}); + }; + $scope.deleteHost = function(id, name){ + var body = '
These arguments are used with the ' + - 'specified module. You can find information about the ' + - val.value + ' module here.
'; - } else { - // no module selected - $scope.argsPopOver = "These arguments are used with the" + - " specified module.
"; - } - }, true); - - // initially set to the same as no module selected - $scope.argsPopOver = "These arguments are used with the " + - "specified module.
"; - }; - - // pre-populate host patterns from the inventory page and - // delete the value off of rootScope - privateFn.instantiateHostPatterns = function(hostPattern) { - $scope.limit = hostPattern; - $scope.providedHostPatterns = $scope.limit; - }; - - // call helpers to initialize lookup and select fields through get - // requests - privateFn.initializeFields = function(machineCredentialUrl, adhocUrl) { - - // setup module name select - GetChoices({ - scope: $scope, - url: adhocUrl, - field: 'module_name', - variable: 'adhoc_module_options', - callback: 'adhocFormReady' - }); - - // setup verbosity options select - GetChoices({ - scope: $scope, - url: adhocUrl, - field: 'verbosity', - variable: 'adhoc_verbosity_options', - callback: 'adhocFormReady' - }); - }; - - // instantiate all variables on scope for display in the partial - privateFn.initializeForm = function(id, urls, hostPattern) { - // inject the adhoc command form - GenerateForm.inject(adhocForm, - { mode: 'add', related: true, scope: $scope }); - - // set when "working" starts and stops - privateFn.setLoadingStartStop(); - - // put the inventory id on scope for the partial to use - $scope.inv_id = id; - - // set the arguments help to watch on change of the module - privateFn.instantiateArgumentHelp(); - - // pre-populate host patterns from the inventory page and - // delete the value off of rootScope - privateFn.instantiateHostPatterns(hostPattern); - - privateFn.initializeFields(urls.machineCredentialUrl, urls.adhocUrl); - }; - - privateFn.initializeForm(id, urls, hostPattern); - - // init codemirror - $scope.extra_vars = '---'; - $scope.parseType = 'yaml'; - $scope.envParseType = 'yaml'; - ParseTypeChange({ scope: $scope, field_id: 'adhoc_extra_vars' , variable: "extra_vars"}); - - $scope.formCancel = function(){ - $state.go('inventoryManage'); - }; - - // remove all data input into the form and reset the form back to defaults - $scope.formReset = function () { - GenerateForm.reset(); - - // pre-populate host patterns from the inventory page and - // delete the value off of rootScope - privateFn.instantiateHostPatterns($scope.providedHostPatterns); - - KindChange({ scope: $scope, form: adhocForm, reset: false }); - - // set the default options for the selects of the adhoc form - privateFn.setFieldDefaults($scope.adhoc_verbosity_options, - $scope.forks_default); - }; - - // launch the job with the provided form data - $scope.launchJob = function () { - var adhocUrl = GetBasePath('inventory') + $stateParams.inventory_id + - '/ad_hoc_commands/', fld, data={}, html; - - html = '