1
0
mirror of https://github.com/ansible/awx.git synced 2024-10-31 23:51:09 +03:00

Merge pull request #1404 from kensible/1049-copyMove

1049 inventory copy move modalectomy
This commit is contained in:
kensible 2016-04-07 12:59:15 -04:00
commit 72cd60462b
15 changed files with 755 additions and 23 deletions

View File

@ -437,10 +437,10 @@ angular.module('HostsHelper', [ 'RestServices', 'Utilities', listGenerator.name,
.factory('HostsEdit', ['$rootScope', '$location', '$log', '$stateParams', 'Rest', 'Alert', 'HostForm', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'HostsReload', 'ParseTypeChange', 'Wait', 'Find', 'SetStatus', 'ApplyEllipsis',
'ToJSON', 'ParseVariableString', 'CreateDialog', 'TextareaResize', 'ParamPass',
'ToJSON', 'ParseVariableString', 'CreateDialog', 'TextareaResize',
function($rootScope, $location, $log, $stateParams, Rest, Alert, HostForm, GenerateForm, Prompt, ProcessErrors,
GetBasePath, HostsReload, ParseTypeChange, Wait, Find, SetStatus, ApplyEllipsis, ToJSON,
ParseVariableString, CreateDialog, TextareaResize, ParamPass) {
ParseVariableString, CreateDialog, TextareaResize) {
return function(params) {
var parent_scope = params.host_scope,

View File

@ -0,0 +1,303 @@
function CopyGroupsCtrl($compile, $state, $scope, $location, Rest, ProcessErrors, CreateDialog,
GetBasePath, Wait, GenerateList, GroupList, SearchInit, PaginateInit, GetRootGroups, ParamPass, Store) {
var vm = this;
var name;
var params = ParamPass.get();
if (params !== undefined) {
var group_id = $state.params.group_id,
parent_scope = params.scope,
scope = parent_scope.$new(),
parent_group = parent_scope.selected_group_id,
url, group;
} else {
var group_id = $state.params.group_id;
var parent_scope = $scope.$new();
var scope = parent_scope.$new();
}
var inventory_id = $state.params.inventory_id;
var PreviousSearchParams = Store('group_current_search_params');
if (scope.removeGroupsCopyPostRefresh) {
scope.removeGroupsCopyPostRefresh();
}
scope.removeGroupCopyPostRefresh = scope.$on('PostRefresh', function() {
scope.copy_groups.forEach(function(row, i) {
scope.copy_groups[i].checked = '0';
});
Wait('stop');
// prevent backspace from navigation when not in input or textarea field
$(document).on('keydown', function(e) {
if (e.which === 8 && !$(e.target).is('input[type="text"], textarea')) {
e.preventDefault();
}
});
});
if (scope.removeCopyDialogReady) {
scope.removeCopyDialogReady();
}
scope.removeCopyDialogReady = scope.$on('CopyDialogReady', function() {
var url = GetBasePath('inventory') + inventory_id + '/groups/';
url += (parent_group) ? '?not__id__in=' + group_id + ',' + parent_group : '?not__id=' + group_id;
GenerateList.inject(GroupList, {
mode: 'lookup',
id: 'copyMove-directive--copyGroupSelect',
scope: scope
});
SearchInit({
scope: scope,
set: GroupList.name,
list: GroupList,
url: url
});
PaginateInit({
scope: scope,
list: GroupList,
url: url,
mode: 'lookup'
});
scope.search(GroupList.iterator);
});
if (scope.removeShowDialog) {
scope.removeShowDialog();
}
scope.removeShowDialog = scope.$on('ShowDialog', function() {
var d;
scope.name = group.name;
scope.copy_choice = "copy";
d = angular.element(document.getElementById('copyMove-directive--copyGroupSelect'));
$compile(d)(scope);
scope.$emit('CopyDialogReady');
});
if (scope.removeRootGroupsReady) {
scope.removeRootGroupsReady();
}
scope.removeRootGroupsReady = scope.$on('RootGroupsReady', function(e, root_groups) {
scope.offer_root_group = true;
scope.use_root_group = false;
root_groups.every(function(row) {
if (row.id === group_id) {
scope.offer_root_group = false;
return false;
}
return true;
});
url = GetBasePath('groups') + group_id + '/';
Rest.setUrl(url);
Rest.get()
.success(function(data) {
group = data;
vm.name = group.name;
scope.$emit('ShowDialog');
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, {
hdr: 'Error!',
msg: 'Call to ' + url + ' failed. GET returned: ' + status
});
});
});
Wait('start');
GetRootGroups({
scope: scope,
group_id: group_id,
inventory_id: $state.params.inventory_id,
callback: 'RootGroupsReady'
});
var restoreSearch = function() {
// Restore search params and related stuff, plus refresh
// groups and hosts lists
SearchInit({
scope: $scope,
set: PreviousSearchParams.set,
list: PreviousSearchParams.list,
url: PreviousSearchParams.defaultUrl,
iterator: PreviousSearchParams.iterator,
sort_order: PreviousSearchParams.sort_order,
setWidgets: false
});
$scope.refreshHostsOnGroupRefresh = true;
//$scope.search(InventoryGroups.iterator, null, true, false, true);
}
var cancel = function() {
restoreSearch(); // Restore all parent search stuff and refresh hosts and groups lists
scope.$destroy();
$state.go('inventoryManage', {}, {
reload: true
});
};
var allowSave = false;
scope['toggle_' + GroupList.iterator] = function(id) {
var count = 0,
list = GroupList;
scope[list.name].forEach(function(row, i) {
if (row.id === id) {
if (row.checked) {
scope[list.name][i].success_class = 'success';
} else {
scope[list.name][i].success_class = '';
}
} else {
scope[list.name][i].checked = 0;
scope[list.name][i].success_class = '';
}
});
// Check if any rows are checked
scope[list.name].forEach(function(row) {
if (row.checked) {
count++;
}
});
if (count === 0) {
vm.allowSave = false;
} else {
vm.allowSave = true;
}
};
scope.toggleUseRootGroup = function() {
var list = GroupList;
if (scope.use_root_group) {
$('#group-copy-ok-button').removeAttr('disabled');
} else {
// check for group selection
$('#group-copy-ok-button').attr('disabled', 'disabled');
scope[list.name].every(function(row) {
if (row.checked === 1) {
$('#group-copy-ok-button').removeAttr('disabled');
return false;
}
return true;
});
}
};
var performCopy = function() {
var list = GroupList,
target,
url;
Wait('start');
if (scope.use_root_group) {
target = null;
} else {
scope[list.name].every(function(row) {
if (row.checked === 1) {
target = row;
return false;
}
return true;
});
}
if (vm.copy_choice === 'move') {
// Respond to move
// disassociate the group from the original parent
if (scope.removeGroupRemove) {
scope.removeGroupRemove();
}
scope.removeGroupRemove = scope.$on('RemoveGroup', function() {
if (parent_group > 0) {
// Only remove a group from a parent when the parent is a group and not the inventory root
url = GetBasePath('groups') + parent_group + '/children/';
Rest.setUrl(url);
Rest.post({
id: group.id,
disassociate: 1
})
.success(function() {
vm.cancel();
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, {
hdr: 'Error!',
msg: 'Failed to remove ' + group.name + ' from group ' + parent_group + '. POST returned: ' + status
});
});
} else {
vm.cancel();
}
});
// add the new group to the target
url = (target) ?
GetBasePath('groups') + target.id + '/children/' :
GetBasePath('inventory') + inventory_id + '/groups/';
group = {
id: group.id,
name: group.name,
description: group.description,
inventory: inventory_id
};
Rest.setUrl(url);
Rest.post(group)
.success(function() {
scope.$emit('RemoveGroup');
})
.error(function(data, status) {
var target_name = (target) ? target.name : 'inventory';
ProcessErrors(scope, data, status, null, {
hdr: 'Error!',
msg: 'Failed to add ' + group.name + ' to ' + target_name + '. POST returned: ' + status
});
});
} else {
// Respond to copy by adding the new group to the target
url = (target) ?
GetBasePath('groups') + target.id + '/children/' :
GetBasePath('inventory') + inventory_id + '/groups/';
group = {
id: group.id,
name: group.name,
description: group.description,
inventory: inventory_id
};
Rest.setUrl(url);
Rest.post(group)
.success(function() {
vm.cancel();
})
.error(function(data, status) {
var target_name = (target) ? target.name : 'inventory';
ProcessErrors(scope, data, status, null, {
hdr: 'Error!',
msg: 'Failed to add ' + group.name + ' to ' + target_name + '. POST returned: ' + status
});
});
}
};
var copy_choice = 'copy';
angular.extend(vm, {
cancel: cancel,
performCopy: performCopy,
copy_choice: copy_choice,
name: name,
allowSave: allowSave
});
};
export default ['$compile', '$state', '$scope', '$location', 'Rest', 'ProcessErrors', 'CreateDialog', 'GetBasePath', 'Wait', 'generateList', 'GroupList', 'SearchInit',
'PaginateInit', 'GetRootGroups', 'ParamPass', 'Store', CopyGroupsCtrl
];

View File

@ -0,0 +1,22 @@
<div>
<div class="Form-header">
<div class="Form-title ng-binding">{{vm.name}}</div>
</div>
<div class="form-group copyMove-directive--copyMoveChoices">
<label class="radio-inline">
<input type="radio" ng-model="vm.copy_choice" value="copy" class="ng-pristine ng-valid ng-touched" name="199"> Copy
</label>
<label class="radio-inline">
<input type="radio" ng-model="vm.copy_choice" value="move" class="ng-pristine ng-untouched ng-valid" name="200"> Move
</label>
</div>
<div id="copyMove-directive--copyGroupSelect"></div>
<div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix">
<div class="ui-dialog-buttonset">
<button type="button" class="btn btn-primary Form-saveButton" id="Inventory-copyGroup--saveButton" ng-disabled="!vm.allowSave" ng-click="vm.performCopy()">
Save</button>
<button type="button" class="btn btn-default Form-cancelButton" id="Inventory-copyGroup--cancelButton" ng-click="vm.cancel()">
Cancel</button>
</div>
</div>
</div>

View File

@ -0,0 +1,239 @@
function CopyHostsCtrl($compile, $state, $scope, Rest, ProcessErrors, CreateDialog, GetBasePath, Wait, GenerateList, GroupList, SearchInit, PaginateInit, ParamPass, Store) {
var vm = this;
var name;
var host_id = $state.params.host_id;
var inventory_id = $state.params.inventory_id;
var url, host;
var params = ParamPass.get();
if (params !== undefined) {
var group_scope = params.group_scope,
parent_scope = params.host_scope,
parent_group = group_scope.selected_group_id,
scope = parent_scope.$new();
} else {
var group_scope = $scope.$new();
var parent_scope = $scope.$new();
var scope = parent_scope.$new();
}
var PreviousSearchParams = Store('group_current_search_params');
if (scope.removeHostCopyPostRefresh) {
scope.removeHostCopyPostRefresh();
}
scope.removeHostCopyPostRefresh = scope.$on('PostRefresh', function() {
scope.copy_groups.forEach(function(row, i) {
scope.copy_groups[i].checked = '0';
});
Wait('stop');
// prevent backspace from navigation when not in input or textarea field
$(document).on("keydown", function(e) {
if (e.which === 8 && !$(e.target).is('input[type="text"], textarea')) {
e.preventDefault();
}
});
});
if (scope.removeHostCopyDialogReady) {
scope.removeHostCopyDialogReady();
}
scope.removeCopyDialogReady = scope.$on('HostCopyDialogReady', function() {
var url = GetBasePath('inventory') + inventory_id + '/groups/';
GenerateList.inject(GroupList, {
mode: 'lookup',
id: 'copyMove-directive--copyHostSelect',
scope: scope
//,
//instructions: instructions
});
SearchInit({
scope: scope,
set: GroupList.name,
list: GroupList,
url: url
});
PaginateInit({
scope: scope,
list: GroupList,
url: url,
mode: 'lookup'
});
scope.search(GroupList.iterator, null, true, false);
});
if (scope.removeShowDialog) {
scope.removeShowDialog();
}
scope.removeShowDialog = scope.$on('ShowDialog', function() {
var d;
scope.name = host.name;
d = angular.element(document.getElementById('copyMove-directive--copyHostPanel'));
$compile(d)(scope);
scope.$emit('HostCopyDialogReady');
});
Wait('start');
url = GetBasePath('hosts') + host_id + '/';
Rest.setUrl(url);
Rest.get()
.success(function(data) {
host = data;
vm.name = host.name;
scope.$emit('ShowDialog');
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, {
hdr: 'Error!',
msg: 'Call to ' + url + ' failed. GET returned: ' + status
});
});
var cancel = function() {
$(document).off("keydown");
restoreSearch(); // Restore all parent search stuff and refresh hosts and groups lists
scope.$destroy();
$state.go('inventoryManage', {}, {
reload: true
});
};
var allowSave = false;
scope['toggle_' + GroupList.iterator] = function(id) {
var count = 0,
list = GroupList;
scope[list.name].forEach(function(row, i) {
if (row.id === id) {
if (row.checked) {
scope[list.name][i].success_class = 'success';
} else {
scope[list.name][i].success_class = '';
}
} else {
scope[list.name][i].checked = 0;
scope[list.name][i].success_class = '';
}
});
// Check if any rows are checked
scope[list.name].forEach(function(row) {
if (row.checked) {
count++;
}
});
if (count === 0) {
vm.allowSave = false;
} else {
vm.allowSave = true;
}
};
var restoreSearch = function() {
// Restore search params and related stuff, plus refresh
// groups and hosts lists
SearchInit({
scope: $scope,
set: PreviousSearchParams.set,
list: PreviousSearchParams.list,
url: PreviousSearchParams.defaultUrl,
iterator: PreviousSearchParams.iterator,
sort_order: PreviousSearchParams.sort_order,
setWidgets: false
});
$scope.refreshHostsOnGroupRefresh = true;
};
var performCopy = function() {
var list = GroupList,
target,
url;
Wait('start');
if (scope.use_root_group) {
target = null;
} else {
scope[list.name].every(function(row) {
if (row.checked === 1) {
target = row;
return false;
}
return true;
});
}
if (vm.copy_choice === 'move') {
// Respond to move
// disassociate the host from the original parent
if (scope.removeHostRemove) {
scope.removeHostRemove();
}
scope.removeHostRemove = scope.$on('RemoveHost', function() {
if (parent_group > 0) {
// Only remove a host from a parent when the parent is a group and not the inventory root
url = GetBasePath('groups') + parent_group + '/hosts/';
Rest.setUrl(url);
Rest.post({
id: host.id,
disassociate: 1
})
.success(function() {
vm.cancel();
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, {
hdr: 'Error!',
msg: 'Failed to remove ' + host.name + ' from group ' + parent_group + '. POST returned: ' + status
});
});
} else {
vm.cancel();
}
});
// add the new host to the target
url = GetBasePath('groups') + target.id + '/hosts/';
Rest.setUrl(url);
Rest.post(host)
.success(function() {
scope.$emit('RemoveHost');
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, {
hdr: 'Error!',
msg: 'Failed to add ' + host.name + ' to ' + target.name + '. POST returned: ' + status
});
});
} else {
// Respond to copy by adding the new host to the target
url = GetBasePath('groups') + target.id + '/hosts/';
Rest.setUrl(url);
Rest.post(host)
.success(function() {
vm.cancel();
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, {
hdr: 'Error!',
msg: 'Failed to add ' + host.name + ' to ' + target.name + '. POST returned: ' + status
});
});
}
};
var copy_choice = 'copy';
angular.extend(vm, {
copy_choice: copy_choice,
name: name,
cancel: cancel,
allowSave: allowSave,
performCopy: performCopy
});
}
export default ['$compile', '$state', '$scope', 'Rest', 'ProcessErrors', 'CreateDialog', 'GetBasePath', 'Wait', 'generateList', 'GroupList', 'SearchInit',
'PaginateInit', 'ParamPass', 'Store', CopyHostsCtrl
];

View File

@ -0,0 +1,23 @@
<div>
<div class="Form-header">
<div class="Form-title ng-binding">{{vm.name}}</div>
</div>
<div class="form-group copyMove-directive--copyMoveChoices">
<label class="radio-inline">
<input type="radio" ng-model="vm.copy_choice" value="copy" class="ng-pristine ng-valid ng-touched" name="199"> Copy
</label>
<label class="radio-inline">
<input type="radio" ng-model="vm.copy_choice" value="move" class="ng-pristine ng-untouched ng-valid" name="200"> Move
</label>
</div>
<div id="copyMove-directive--copyHostSelect"></div>
<div id="copyMove-directive--copyHostPanel"></div>
<div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix">
<div class="ui-dialog-buttonset">
<button type="button" class="btn btn-primary Form-saveButton" id="Inventory-copyGroup--saveButton" ng-disabled="!vm.allowSave" ng-click="vm.performCopy()">
Save</button>
<button type="button" class="btn btn-default Form-cancelButton" id="Inventory-copyGroup--cancelButton" ng-click="vm.cancel()">
Cancel</button>
</div>
</div>
</div>

View File

@ -0,0 +1,30 @@
@import "awx/ui/client/src/shared/branding/colors.default.less";
#Inventory-copyMovePanel {
.List-searchRow {
width: 50%;
}
.ui-dialog-buttonpane.ui-widget-content {
border: none;
text-align: right;
margin-top: 15px;
}
.Form-header {
width: 50%;
margin-top: -20px;
}
.Form-saveButton {
&:disabled {
border-color: @default-icon-hov;
}
}
}
.copyMove-directive--copyMoveChoices {
float: right;
width: 25%;
text-align: right;
}

View File

@ -0,0 +1,16 @@
function inventoryManageCopyCtrl($state) {
var vm = this;
var cancelPanel = function() {
$state.go('inventoryManage', {}, {
reload: true
})
};
angular.extend(vm, {
cancelPanel: cancelPanel
});
};
export default ['$state', inventoryManageCopyCtrl
];

View File

@ -0,0 +1,10 @@
<div class="tab-pane" id="Inventory-copyMovePanel">
<div ng-cloak id="Inventory-groupCopy--panel" class="Panel">
<div class="Form-exitHolder">
<button class="Form-exit" ng-click="vm.cancelPanel()">
<i class="fa fa-times-circle"></i>
</button>
</div>
<ui-view></ui-view>
</div>
</div>

View File

@ -0,0 +1,59 @@
/*************************************************
* Copyright (c) 2016 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
import {
templateUrl
} from '../../../shared/template-url/template-url.factory';
import inventoryManageCopyCtrl from './copy.controller';
import CopyGroupsCtrl from './copy-groups.controller';
import CopyHostsCtrl from './copy-hosts.controller';
export default {
copy: {
name: 'inventoryManage.copy',
route: '/copy',
templateUrl: templateUrl('inventories/manage/copy/copy'),
ncyBreadcrumb: {
label: "COPY"
},
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}],
},
controller: inventoryManageCopyCtrl,
controllerAs: 'vm',
bindToController: true,
},
copyGroup: {
name: 'inventoryManage.copy.group',
route: '/group/:group_id?groups',
templateUrl: templateUrl('inventories/manage/copy/copy-groups'),
data: {
group_id: 'group_id',
},
ncyBreadcrumb: {
label: "GROUP"
},
controller: CopyGroupsCtrl,
controllerAs: 'vm',
bindToController: true
},
copyHost: {
name: 'inventoryManage.copy.host',
route: '/host/:host_id?groups',
templateUrl: templateUrl('inventories/manage/copy/copy-hosts'),
data: {
host_id: 'host_id',
},
ncyBreadcrumb: {
label: "HOST"
},
controller: CopyHostsCtrl,
controllerAs: 'vm',
bindToController: true
}
};

View File

@ -0,0 +1,15 @@
/*************************************************
* Copyright (c) 2015 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
import route from './copy.route';
export default
angular.module('inventory-copy', [])
.run(['$stateExtender', function($stateExtender) {
$stateExtender.addState(route.copy);
$stateExtender.addState(route.copyGroup);
$stateExtender.addState(route.copyHost);
}]);

View File

@ -400,10 +400,12 @@ function InventoriesManage($log, $scope, $rootScope, $location,
$scope.copyGroup = function(id) {
PreviousSearchParams = Store('group_current_search_params');
GroupsCopy({
scope: $scope,
group_id: id
});
var params = {
scope: $scope
};
ParamPass.set(params);
$location.search('groups', null);
$state.go('inventoryManage.copy.group', {group_id: id});
};
$scope.deleteGroup = function (id) {
@ -427,7 +429,7 @@ function InventoriesManage($log, $scope, $rootScope, $location,
host_id: null,
selected_group_id: $scope.selected_group_id,
inventory_id: $scope.inventory.id
}
};
ParamPass.set(params);
$state.go('inventoryManage.addHost');
};
@ -439,7 +441,7 @@ function InventoriesManage($log, $scope, $rootScope, $location,
mode: 'edit',
host_id: host_id,
inventory_id: $scope.inventory.id
}
};
ParamPass.set(params);
$state.go('inventoryManage.editHost', {host_id: host_id});
};
@ -455,11 +457,15 @@ function InventoriesManage($log, $scope, $rootScope, $location,
hostScope.copyHost = function(id) {
PreviousSearchParams = Store('group_current_search_params');
HostsCopy({
group_scope: $scope,
host_scope: hostScope,
host_id: id
});
var params = {
group_scope: $scope,
host_scope: hostScope,
host_id: id
};
ParamPass.set(params);
$state.go('inventoryManage.copy.host', {host_id: id});
};
hostScope.toggleHostEnabled = function (host_id, external_source) {

View File

@ -8,11 +8,13 @@ import route from './inventory-manage.route';
import manageHosts from './manage-hosts/main';
import manageGroups from './manage-groups/main';
import copy from './copy/main';
export default
angular.module('inventoryManage', [
manageHosts.name,
manageGroups.name
manageGroups.name,
copy.name,
])
.run(['$stateExtender', function($stateExtender) {
$stateExtender.addState(route);

View File

@ -11,7 +11,7 @@ function manageHostsDirectiveController($rootScope, $location, $log, $stateParam
var vm = this;
var params = ParamPass.get();
if(params === undefined) {
if (params === undefined) {
params = {};
params.host_scope = $scope.$new();
params.group_scope = $scope.$new();
@ -29,7 +29,7 @@ function manageHostsDirectiveController($rootScope, $location, $log, $stateParam
relatedSets = {},
url, form_scope;
var host_id = $stateParams.host_id || undefined;
var host_id = $stateParams.host_id || undefined;
form_scope =
generator.inject(HostForm, {
@ -94,7 +94,11 @@ function manageHostsDirectiveController($rootScope, $location, $log, $stateParam
scope.enabled = true;
scope.variables = '---';
defaultUrl = data.related.hosts;
//scope.$emit('hostVariablesLoaded');
scope.parseType = 'yaml';
ParseTypeChange({
scope: scope,
field_id: 'host_variables',
});
scope.parseType = 'yaml';
ParseTypeChange({
scope: scope,
@ -183,7 +187,7 @@ function manageHostsDirectiveController($rootScope, $location, $log, $stateParam
angular.extend(vm, {
cancelPanel: cancelPanel,
saveHost: saveHost,
mode: mode
mode: mode
});
}

View File

@ -882,7 +882,9 @@ angular.module('Utilities', ['RestServices', 'Utilities', 'sanitizeFilter'])
}
function get() {
return savedData;
var returnData = savedData;
savedData = undefined;
return returnData;
}
return {

View File

@ -1,10 +1,9 @@
export default function($stateProvider){
this.$get = function(){
export default function($stateProvider) {
this.$get = function() {
return {
addState: function(state) {
var route = state.route || state.url;
$stateProvider.state(state.name , {
$stateProvider.state(state.name, {
url: route,
controller: state.controller,
templateUrl: state.templateUrl,
@ -14,6 +13,8 @@ export default function($stateProvider){
ncyBreadcrumb: state.ncyBreadcrumb,
onEnter: state.onEnter,
onExit: state.onExit,
template: state.template,
controllerAs: state.controllerAs,
views: state.views
});
}