mirror of
https://github.com/ansible/awx.git
synced 2026-01-13 19:10:07 -03:30
Adding the ability to add/edit hosts to a group
includes adding the ansible facts to that host form
This commit is contained in:
parent
0bec96ff28
commit
fe63303816
@ -75,9 +75,6 @@ export default [
|
||||
if(key === "AD_HOC_COMMANDS"){
|
||||
$scope[key] = data[key].toString();
|
||||
}
|
||||
else if(key === "AUTH_LDAP_USER_SEARCH" || key === "AUTH_LDAP_GROUP_SEARCH"){
|
||||
$scope[key] = JSON.stringify(data[key]);
|
||||
}
|
||||
else {
|
||||
$scope[key] = ConfigurationUtils.arrayToList(data[key], key);
|
||||
}
|
||||
@ -356,38 +353,27 @@ export default [
|
||||
clearApiErrors();
|
||||
_.each(keys, function(key) {
|
||||
if($scope.configDataResolve[key].type === 'choice' || multiselectDropdowns.indexOf(key) !== -1) {
|
||||
|
||||
// Handle AD_HOC_COMMANDS
|
||||
if(multiselectDropdowns.indexOf(key) !== -1) {
|
||||
let newModules = $("#configuration_jobs_template_AD_HOC_COMMANDS > option")
|
||||
.filter("[data-select2-tag=true]")
|
||||
.map((i, val) => ({value: $(val).text()}));
|
||||
newModules.each(function(i, val) {
|
||||
$scope[key].push(val);
|
||||
});
|
||||
|
||||
payload[key] = ConfigurationUtils.listToArray(_.map($scope[key], 'value').join(','));
|
||||
}
|
||||
|
||||
//Parse dropdowns and dropdowns labeled as lists
|
||||
else if($scope[key] === null) {
|
||||
if($scope[key] === null) {
|
||||
payload[key] = null;
|
||||
} else if($scope[key][0] && $scope[key][0].value !== undefined) {
|
||||
payload[key] = _.map($scope[key], 'value').join(',');
|
||||
if(multiselectDropdowns.indexOf(key) !== -1) {
|
||||
// Handle AD_HOC_COMMANDS
|
||||
payload[key] = ConfigurationUtils.listToArray(_.map($scope[key], 'value').join(','));
|
||||
} else {
|
||||
payload[key] = _.map($scope[key], 'value').join(',');
|
||||
}
|
||||
} else {
|
||||
payload[key] = $scope[key].value;
|
||||
if(multiselectDropdowns.indexOf(key) !== -1) {
|
||||
// Default AD_HOC_COMMANDS to an empty list
|
||||
payload[key] = $scope[key].value || [];
|
||||
} else {
|
||||
payload[key] = $scope[key].value;
|
||||
}
|
||||
}
|
||||
} else if($scope.configDataResolve[key].type === 'list' && $scope[key] !== null) {
|
||||
|
||||
if(key === "AUTH_LDAP_USER_SEARCH" || key === "AUTH_LDAP_GROUP_SEARCH"){
|
||||
payload[key] = $scope[key] === "{}" ? [] : ToJSON($scope.parseType,
|
||||
$scope[key]);
|
||||
}
|
||||
else {
|
||||
// Parse lists
|
||||
payload[key] = ConfigurationUtils.listToArray($scope[key], key);
|
||||
}
|
||||
|
||||
// Parse lists
|
||||
payload[key] = ConfigurationUtils.listToArray($scope[key], key);
|
||||
}
|
||||
else if($scope.configDataResolve[key].type === 'nested object') {
|
||||
if($scope[key] === '') {
|
||||
|
||||
@ -10,8 +10,9 @@
|
||||
* @description This form is for adding/editing a Group on the inventory page
|
||||
*/
|
||||
|
||||
export default ['i18n', 'nestedGroupListState',
|
||||
function(i18n, nestedGroupListState){
|
||||
export default ['i18n', 'nestedGroupListState', 'nestedHostsListState',
|
||||
'buildHostAddState',
|
||||
function(i18n, nestedGroupListState, nestedHostsListState, buildHostAddState){
|
||||
return {
|
||||
addTitle: 'CREATE GROUP',
|
||||
editTitle: '{{ name }}',
|
||||
@ -91,6 +92,16 @@ function(i18n, nestedGroupListState){
|
||||
// addState: buildGroupsAddState,
|
||||
// editState: buildGroupsEditState
|
||||
},
|
||||
nested_hosts: {
|
||||
name: 'nested_hosts',
|
||||
ngClick: "$state.go('inventories.edit.groups.edit.nested_hosts')",
|
||||
include: "NestedHostsListDefinition",
|
||||
title: i18n._('Hosts'),
|
||||
iterator: 'nested_hosts',
|
||||
listState: nestedHostsListState,
|
||||
addState: buildHostAddState,
|
||||
// editState: buildGroupsEditState
|
||||
},
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@ -8,6 +8,7 @@ import groupList from './list/main';
|
||||
import groupAdd from './add/main';
|
||||
import groupEdit from './edit/main';
|
||||
import nestedGroups from './nested-groups/main';
|
||||
import nestedHosts from './nested-hosts/main';
|
||||
import groupFormDefinition from './groups.form';
|
||||
import groupListDefinition from './groups.list';
|
||||
import service from './groups.service';
|
||||
@ -22,7 +23,8 @@ export default
|
||||
groupList.name,
|
||||
groupAdd.name,
|
||||
groupEdit.name,
|
||||
nestedGroups.name
|
||||
nestedGroups.name,
|
||||
nestedHosts.name
|
||||
])
|
||||
.factory('GroupForm', groupFormDefinition)
|
||||
.value('GroupList', groupListDefinition)
|
||||
|
||||
17
awx/ui/client/src/inventories/groups/nested-hosts/main.js
Normal file
17
awx/ui/client/src/inventories/groups/nested-hosts/main.js
Normal file
@ -0,0 +1,17 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2017 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
import nestedHostsListState from './nested-hosts-list-state.factory';
|
||||
import nestedHostsListDefinition from './nested-hosts.list';
|
||||
import nestedHostsFormDefinition from './nested-hosts.form';
|
||||
import controller from './nested-hosts-list.controller';
|
||||
|
||||
export default
|
||||
angular.module('nestedHosts', [])
|
||||
.factory('nestedHostsListState', nestedHostsListState)
|
||||
.value('NestedHostsListDefinition', nestedHostsListDefinition)
|
||||
.factory('NestedHostsFormDefinition', nestedHostsFormDefinition)
|
||||
.controller('NestedHostsListController', controller);
|
||||
@ -0,0 +1,79 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2017 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
import NestedHostsListController from './nested-hosts-list.controller';
|
||||
export default ['NestedHostsListDefinition', '$stateExtender', 'templateUrl', '$injector',
|
||||
function(NestedHostsListDefinition, $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_hosts`,
|
||||
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(NestedHostsListDefinition, generateList) {
|
||||
let list = _.cloneDeep(NestedHostsListDefinition);
|
||||
|
||||
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: NestedHostsListController
|
||||
}
|
||||
},
|
||||
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 });
|
||||
}
|
||||
path = `api/v2/groups/${$stateParams.group_id}/all_hosts`;
|
||||
return qs.search(path, $stateParams[`${list.iterator}_search`]);
|
||||
}
|
||||
],
|
||||
inventoryData: ['InventoryManageService', '$stateParams', function(InventoryManageService, $stateParams) {
|
||||
return InventoryManageService.getInventory($stateParams.inventory_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;
|
||||
}
|
||||
];
|
||||
@ -0,0 +1,131 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2017 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
export default {
|
||||
name: 'nested_hosts',
|
||||
iterator: 'nested_host',
|
||||
editTitle: '{{ nested_host.name }}', // i don't think this is correct
|
||||
// showTitle: false,
|
||||
well: true,
|
||||
wellOverride: true,
|
||||
index: false,
|
||||
hover: true,
|
||||
// hasChildren: true,
|
||||
multiSelect: true,
|
||||
trackBy: 'nested_host.id',
|
||||
basePath: 'api/v2/groups/{{$stateParams.group_id}}/all_hosts/',
|
||||
|
||||
fields: {
|
||||
active_failures: {
|
||||
label: '',
|
||||
iconOnly: true,
|
||||
nosort: true,
|
||||
// do not remove this ng-click directive
|
||||
// the list generator case to handle fields without ng-click
|
||||
// cannot handle the aw-* directives
|
||||
ngClick: 'noop()',
|
||||
awPopOver: "{{ nested_host.job_status_html }}",
|
||||
dataTitle: "{{ nested_host.job_status_title }}",
|
||||
awToolTip: "{{ nested_host.badgeToolTip }}",
|
||||
dataPlacement: 'top',
|
||||
icon: "{{ 'fa icon-job-' + nested_host.active_failures }}",
|
||||
id: 'active-failures-action',
|
||||
columnClass: 'status-column List-staticColumn--smallStatus'
|
||||
},
|
||||
name: {
|
||||
key: true,
|
||||
label: 'Hosts',
|
||||
ngClick: "editHost(nested_host.id)",
|
||||
ngClass: "{ 'host-disabled-label': !nested_host.enabled }",
|
||||
columnClass: 'col-lg-6 col-md-8 col-sm-8 col-xs-7',
|
||||
dataHostId: "{{ nested_host.id }}",
|
||||
dataType: "nested_host",
|
||||
class: 'InventoryManage-breakWord'
|
||||
}
|
||||
},
|
||||
|
||||
fieldActions: {
|
||||
|
||||
columnClass: 'col-lg-6 col-md-4 col-sm-4 col-xs-5 text-right',
|
||||
copy: {
|
||||
mode: 'all',
|
||||
ngClick: "copyMoveHost(nested_host.id)",
|
||||
awToolTip: 'Copy or move host to another group',
|
||||
dataPlacement: "top",
|
||||
ngShow: 'nested_host.summary_fields.user_capabilities.edit'
|
||||
},
|
||||
edit: {
|
||||
//label: 'Edit',
|
||||
ngClick: "editHost(nested_host.id)",
|
||||
icon: 'icon-edit',
|
||||
awToolTip: 'Edit host',
|
||||
dataPlacement: 'top',
|
||||
ngShow: 'nested_host.summary_fields.user_capabilities.edit'
|
||||
},
|
||||
view: {
|
||||
//label: 'Edit',
|
||||
ngClick: "editHost(nested_host.id)",
|
||||
awToolTip: 'View host',
|
||||
dataPlacement: 'top',
|
||||
ngShow: '!nested_host.summary_fields.user_capabilities.edit'
|
||||
},
|
||||
"delete": {
|
||||
//label: 'Delete',
|
||||
ngClick: "deleteHost(nested_host.id, nested_host.name)",
|
||||
icon: 'icon-trash',
|
||||
awToolTip: 'Delete host',
|
||||
dataPlacement: 'top',
|
||||
ngShow: 'nested_host.summary_fields.user_capabilities.delete'
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
launch: {
|
||||
mode: 'all',
|
||||
ngDisabled: '!hostsSelected',
|
||||
ngClick: 'setAdhocPattern()',
|
||||
awToolTip: "Select an inventory source by clicking the check box beside it. The inventory source can be a single group or host, a selection of multiple hosts, or a selection of multiple groups.",
|
||||
dataTipWatch: "adhocCommandTooltip",
|
||||
actionClass: 'btn List-buttonDefault',
|
||||
buttonContent: 'RUN COMMANDS',
|
||||
showTipWhenDisabled: true,
|
||||
tooltipInnerClass: "Tooltip-wide",
|
||||
// TODO: we don't always want to show this
|
||||
ngShow: true
|
||||
},
|
||||
system_tracking: {
|
||||
buttonContent: 'System Tracking',
|
||||
ngClick: 'systemTracking()',
|
||||
awToolTip: "Select one or two hosts by clicking the checkbox beside the host. System tracking offers the ability to compare the results of two scan runs from different dates on one host or the same date on two hosts.",
|
||||
dataTipWatch: "systemTrackingTooltip",
|
||||
dataPlacement: 'top',
|
||||
awFeature: 'system_tracking',
|
||||
actionClass: 'btn List-buttonDefault system-tracking',
|
||||
ngDisabled: 'systemTrackingDisabled || !hostsSelected',
|
||||
showTipWhenDisabled: true,
|
||||
tooltipInnerClass: "Tooltip-wide",
|
||||
ngShow: true
|
||||
},
|
||||
refresh: {
|
||||
mode: 'all',
|
||||
awToolTip: "Refresh the page",
|
||||
ngClick: "refreshGroups()",
|
||||
ngShow: "socketStatus == 'error'",
|
||||
actionClass: 'btn List-buttonDefault',
|
||||
buttonContent: 'REFRESH'
|
||||
},
|
||||
create: {
|
||||
mode: 'all',
|
||||
ngClick: "createHost()",
|
||||
awToolTip: "Create a new host",
|
||||
actionClass: 'btn List-buttonSubmit',
|
||||
buttonContent: '+ ADD HOST',
|
||||
ngShow: 'canAdd',
|
||||
dataPlacement: "top",
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
@ -1,8 +1,8 @@
|
||||
<div class="tab-pane" id="inventories-panel">
|
||||
<div ui-view="copyMove"></div>
|
||||
<div ui-view="adhocForm"></div>
|
||||
<div ui-view="groupForm"></div>
|
||||
<div ui-view="hostForm"></div>
|
||||
<div ui-view="groupForm"></div>
|
||||
<div ui-view="sourcesForm"></div>
|
||||
<div ui-view="form"></div>
|
||||
<div ng-cloak id="htmlTemplate" class="Panel">
|
||||
|
||||
@ -256,6 +256,7 @@ angular.module('inventory', [
|
||||
};
|
||||
|
||||
let relatedHostsAnsibleFacts = factsConfig('inventories.edit.hosts.edit.ansible_facts');
|
||||
let nestedHostsAnsibleFacts = factsConfig('inventories.edit.groups.edit.nested_hosts.edit.ansible_facts');
|
||||
|
||||
return Promise.all([
|
||||
basicInventoryAdd,
|
||||
@ -304,6 +305,7 @@ angular.module('inventory', [
|
||||
stateExtender.buildDefinition(addSchedule),
|
||||
stateExtender.buildDefinition(editSchedule),
|
||||
stateExtender.buildDefinition(relatedHostsAnsibleFacts),
|
||||
stateExtender.buildDefinition(nestedHostsAnsibleFacts),
|
||||
stateExtender.buildDefinition(copyMoveGroupRoute),
|
||||
stateExtender.buildDefinition(copyMoveHostRoute)
|
||||
])
|
||||
|
||||
@ -50,9 +50,9 @@ export default ['$state', '$stateParams', '$scope', 'RelatedHostsFormDefinition'
|
||||
};
|
||||
HostManageService.post(params).then(function(res) {
|
||||
// assign the host to current group if not at the root level
|
||||
if ($stateParams.group) {
|
||||
HostManageService.associateGroup(res.data, _.last($stateParams.group)).then(function() {
|
||||
$state.go('^.edit', { host_id: res.data.id }, { reload: true });
|
||||
if ($stateParams.group_id) {
|
||||
HostManageService.associateGroup(res.data, $stateParams.group_id).then(function() {
|
||||
$state.go('inventories.edit.groups.edit.nested_hosts', { group_id: $stateParams.group_id }, { reload: true });
|
||||
});
|
||||
} else {
|
||||
$state.go('^.edit', { host_id: res.data.id }, { reload: true });
|
||||
|
||||
@ -21,7 +21,8 @@ export default ['i18n', function(i18n) {
|
||||
formLabelSize: 'col-lg-3',
|
||||
formFieldSize: 'col-lg-9',
|
||||
iterator: 'host',
|
||||
activeEditState: 'inventories.edit.hosts.edit',
|
||||
// activeEditState: 'inventories.edit.hosts.edit',
|
||||
// activeEditState: 'inventories.edit.groups.edit.nested_hosts.edit',
|
||||
stateTree: 'inventories.edit.hosts',
|
||||
headerFields:{
|
||||
enabled: {
|
||||
|
||||
@ -563,7 +563,7 @@ function($injector, $stateExtender, $log, i18n) {
|
||||
if(field && field.addState){
|
||||
let formState = field.addState(field, formStateDefinition, params);
|
||||
states.push(formState);
|
||||
// intent here is to add lookup states for any add-forms
|
||||
// intent below is to add lookup states for any add-forms
|
||||
if(field.includeForm){
|
||||
let form = field.includeForm ? $injector.get(field.includeForm) : field;
|
||||
states.push(that.generateLookupNodes(form, formState));
|
||||
@ -573,7 +573,7 @@ function($injector, $stateExtender, $log, i18n) {
|
||||
if(field && field.editState){
|
||||
let formState = field.editState(field, formStateDefinition, params);
|
||||
states.push(formState);
|
||||
// intent here is to add lookup states for any edit-forms
|
||||
// intent below is to add lookup states for any edit-forms
|
||||
if(field.includeForm){
|
||||
let form = field.includeForm ? $injector.get(field.includeForm) : field;
|
||||
states.push(that.generateLookupNodes(form, formState));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user