mirror of
https://github.com/mmumshad/ansible-playable.git
synced 2025-03-09 23:38:54 +00:00
Initial Commit
This commit is contained in:
commit
c92f737237
273 changed files with 16964 additions and 0 deletions
446
client/app/designer/tasks/new_task/new_task.controller.js
Normal file
446
client/app/designer/tasks/new_task/new_task.controller.js
Normal file
|
@ -0,0 +1,446 @@
|
|||
'use strict';
|
||||
const angular = require('angular');
|
||||
|
||||
|
||||
|
||||
/*@ngInject*/
|
||||
export function newTaskController($window, $scope, $sce, $uibModal, ansi2html, ansible, $uibModalInstance, tasksList, selectedTaskIndex, copyTask, files, selectedPlay, selectedRole, $filter, Projects) {
|
||||
var selectedTask;
|
||||
|
||||
/**
|
||||
* Edit task - in case of edit task , selectedTaskIndex is not null.
|
||||
* Set selectedTask to a copy of selected task to edit.
|
||||
*/
|
||||
if(selectedTaskIndex > -1 && tasksList){
|
||||
if(copyTask){
|
||||
selectedTask = angular.copy(tasksList[selectedTaskIndex]);
|
||||
selectedTask.name = "Copy of " + selectedTask.name;
|
||||
selectedTaskIndex = null;
|
||||
}else{
|
||||
selectedTask = tasksList[selectedTaskIndex]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* List of files for include purpose
|
||||
*/
|
||||
if(files){
|
||||
$scope.files = files;
|
||||
}
|
||||
|
||||
$scope.getModuleDescriptionLoading = false;
|
||||
$scope.modulesLoading = false;
|
||||
|
||||
$scope.modules = null;
|
||||
$scope.singeLineModules = ["shell"];
|
||||
$scope.showHelp = false;
|
||||
|
||||
$scope.newTask = {};
|
||||
$scope.title = "New Task";
|
||||
$scope.createTaskLoading = false;
|
||||
|
||||
/**
|
||||
* Get Ansible Modules
|
||||
* If Edit Task, get module description for selected task
|
||||
*/
|
||||
$scope.getAnsibleModules = function(){
|
||||
$scope.modulesLoading = true;
|
||||
ansible.getAnsibleModules(function(response){
|
||||
$scope.modules = response;
|
||||
$scope.modulesLoading = false;
|
||||
|
||||
if(selectedTask){
|
||||
$scope.title = "Edit Task";
|
||||
selectedTask = angular.copy(selectedTask);
|
||||
$scope.newTask = selectedTask;
|
||||
if(selectedTask.tags)$scope.newTask.tags = $scope.newTask.tags.join(',');
|
||||
var module = $scope.getModuleFromTask(selectedTask);
|
||||
$scope.getModuleDescription(module,true)
|
||||
}
|
||||
|
||||
}, function(response){
|
||||
$scope.result = $sce.trustAsHtml(ansi2html.toHtml(response.data).replace(/\n/g, "<br>").replace(/ /g," "));
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get Module Description whenever a module is selected by the user
|
||||
* @param module - Module Object
|
||||
* @param override - Override variables in case of edit task
|
||||
* @param refresh - Refresh module description from server. Don't display from cache
|
||||
*/
|
||||
$scope.getModuleDescription = function(module,override,refresh){
|
||||
|
||||
if(!module)return;
|
||||
|
||||
var module_copy = angular.copy(module);
|
||||
|
||||
$scope.getModuleDescriptionLoading = true;
|
||||
var moduleName = module.name;
|
||||
|
||||
if($scope.singeLineModules.indexOf(moduleName) > -1){
|
||||
module.singleLine = true;
|
||||
}
|
||||
|
||||
$scope.detailHelp = "";
|
||||
$scope.examples = "";
|
||||
module.variables = [];
|
||||
|
||||
ansible.getAnsibleModuleDescription(moduleName,
|
||||
function(response){
|
||||
$scope.showHelp = true;
|
||||
$scope.result = $sce.trustAsHtml(ansi2html.toHtml(response).replace(/\n/g, "<br>").replace(/ /g," "));
|
||||
|
||||
$scope.detailHelp = response;
|
||||
$scope.examples = response.substr(response.indexOf("#"));
|
||||
//var re = /(^[-=] .*)/gm;
|
||||
//var re = /(^[-=] .*)[^]*?(?:(\(Choices[^]+?\))?\s*(\[.*\])|(?=^[-=]|^EXAMPLES))/gm;
|
||||
var re = /(^[-=] .*)([^]*?)(?:(\(Choices[^]+?\))?\s*(\[.*\])|(?=^[-=]|^EXAMPLES))/gm;
|
||||
var m;
|
||||
|
||||
while ((m = re.exec($scope.detailHelp.split("EXAMPLES")[0]+"EXAMPLES")) !== null) {
|
||||
//while ((m = re.exec($scope.detailHelp.split("#")[0])) !== null) {
|
||||
//while ((m = re.exec($scope.detailHelp)) !== null) {
|
||||
if (m.index === re.lastIndex) {
|
||||
re.lastIndex++;
|
||||
}
|
||||
// View your result using the m-variable.
|
||||
// eg m[0] etc.
|
||||
|
||||
var option_name = m[1];
|
||||
var description = m[2];
|
||||
var choices = m[3];
|
||||
var default_value = m[4];
|
||||
|
||||
|
||||
var breakup = option_name.split(" ");
|
||||
var variable_name = breakup[1];
|
||||
var mandatory = breakup[0] == "=";
|
||||
|
||||
var complex_value = {};
|
||||
|
||||
if(default_value)
|
||||
default_value = default_value.replace(/\[Default: (.*)\]/,"$1");
|
||||
|
||||
if(default_value == 'None')
|
||||
default_value = null
|
||||
|
||||
var variable_value = default_value || '';
|
||||
|
||||
if(choices)
|
||||
choices = choices.replace(/\s+/g,"").replace(/\n\s+/g,"").replace(/\(Choices:(.*)\)/,"$1").split(",");
|
||||
|
||||
if(override && module_copy.variables){
|
||||
var matching_variable = module_copy.variables.filter(function(item){
|
||||
if(item.name == variable_name){
|
||||
return true
|
||||
}
|
||||
});
|
||||
if(matching_variable.length){
|
||||
variable_value = matching_variable[0].value;
|
||||
if(typeof variable_value=='object'){
|
||||
complex_value = angular.copy(variable_value)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.variables.push({name:variable_name,description:description,mandatory:mandatory,value:variable_value,complexValue:complex_value,choices:choices,default_value:default_value});
|
||||
$scope.getModuleDescriptionLoading = false;
|
||||
}
|
||||
}, function(response){
|
||||
$scope.result = $sce.trustAsHtml(ansi2html.toHtml(response.data).replace(/\n/g, "<br>"));
|
||||
console.log(ansi2html.toHtml(response.data));
|
||||
$scope.detailHelp = response.data;
|
||||
$scope.getModuleDescriptionLoading = false;
|
||||
},refresh)
|
||||
};
|
||||
|
||||
/**
|
||||
* Reload Module Description and variables. Ignore displaying from cache.
|
||||
* Used when a custom module is updated and description and variables info need to be updated.
|
||||
* @param module - module object
|
||||
*/
|
||||
$scope.reloadModuleDetails = function(module){
|
||||
|
||||
if(selectedTask){
|
||||
$scope.getModuleDescription(module,true,true)
|
||||
}else{
|
||||
$scope.getModuleDescription(module,false,true)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Identify module from a given task object.
|
||||
* @param task - Single task object containing task properties
|
||||
* @returns {{}}
|
||||
*/
|
||||
$scope.getModuleFromTask = function(task){
|
||||
var moduleObject = {};
|
||||
$scope.local_action = false;
|
||||
var task_properties = null;
|
||||
|
||||
var module = ansible.getModuleFromTask(task);
|
||||
|
||||
if(module === 'include'){
|
||||
module = null;
|
||||
task.tags = task.include.replace(/.*tags=(.*)/,"$1")
|
||||
return;
|
||||
}else if(module === 'local_action'){
|
||||
$scope.local_action = true;
|
||||
module = task.local_action.module;
|
||||
task_properties = task.local_action;
|
||||
delete task_properties.module;
|
||||
}else{
|
||||
task_properties = task[module];
|
||||
}
|
||||
|
||||
angular.forEach($scope.modules, function(item,index) {
|
||||
if(item.name == module){
|
||||
moduleObject = item;
|
||||
$scope.newTask.module = item;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if(!(moduleObject && moduleObject.name)){
|
||||
$scope.err_msg = "Unable to find module " + module + " in Ansible controller";
|
||||
return
|
||||
}
|
||||
|
||||
//moduleObject.name = module;
|
||||
moduleObject.variables = [];
|
||||
if(typeof task_properties == "string"){
|
||||
moduleObject.variables.push({'name':'free_form','value':task_properties});
|
||||
|
||||
var re = /\b(\w+)=\s*([^=]*\S)\b\s*(?=\w+=|$)/g;
|
||||
var m;
|
||||
|
||||
while ((m = re.exec(task_properties)) !== null) {
|
||||
if (m.index === re.lastIndex) {
|
||||
re.lastIndex++;
|
||||
}
|
||||
// View your result using the m-variable.
|
||||
// eg m[0] etc.
|
||||
var k=m[1];
|
||||
var v=m[2];
|
||||
moduleObject.variables.push({'name':k,'value':v})
|
||||
}
|
||||
|
||||
}else if(typeof task_properties == "object"){
|
||||
|
||||
angular.forEach(task_properties,function(value,key){
|
||||
this.push({'name':key,'value':value,'complexValue':value})
|
||||
},moduleObject.variables)
|
||||
|
||||
}
|
||||
return moduleObject
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Create Task - Creates new task object and set task variables.
|
||||
* Push new task object to tasksList
|
||||
* Close new task modal
|
||||
*/
|
||||
$scope.createTask = function(){
|
||||
|
||||
if(!$scope.newTask.module && !$scope.newTask.include){
|
||||
$scope.err_msg = "Must select atleast one module or include statement";
|
||||
return
|
||||
}
|
||||
|
||||
$scope.createTaskLoading = true;
|
||||
|
||||
if(!tasksList){
|
||||
tasksList = []
|
||||
}
|
||||
|
||||
var taskObject = {name:$scope.newTask.name};
|
||||
|
||||
if($scope.newTask.include)
|
||||
taskObject['include'] = $scope.newTask.include;
|
||||
|
||||
if($scope.newTask.tags)
|
||||
taskObject['tags'] = $scope.newTask.tags.split(',');
|
||||
|
||||
if($scope.newTask.register)
|
||||
taskObject['register'] = $scope.newTask.register;
|
||||
|
||||
if($scope.newTask.async){
|
||||
taskObject['async'] = $scope.newTask.async;
|
||||
if(!$scope.newTask.poll)
|
||||
$scope.newTask.poll = 10;
|
||||
taskObject['poll'] = $scope.newTask.poll;
|
||||
}
|
||||
|
||||
var variablesObject = null;
|
||||
if($scope.newTask.module){
|
||||
if($scope.newTask.module.singleLine){
|
||||
variablesObject = "";
|
||||
//Add all mandatory variables first
|
||||
angular.forEach($scope.newTask.module.variables.filter(function(item){
|
||||
return item.mandatory
|
||||
}),function(item){
|
||||
if(item.name == 'free_form'){
|
||||
variablesObject += item.value;
|
||||
}else if(item.value){
|
||||
variablesObject += " " + item.name + "=" + item.value;
|
||||
}
|
||||
});
|
||||
|
||||
//Add optional variables
|
||||
angular.forEach($scope.newTask.module.variables.filter(function(item){
|
||||
return !item.mandatory
|
||||
}),function(item){
|
||||
if(item.value != item.default_value){
|
||||
if(item.name == 'free_form'){
|
||||
variablesObject += item.value;
|
||||
}else if(item.value){
|
||||
variablesObject += " " + item.name + "=" + item.value;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}else{
|
||||
variablesObject = {};
|
||||
angular.forEach($scope.newTask.module.variables,function(item){
|
||||
if((item.value || (item.isComplexVariable && item.complexValue)) && item.value != item.default_value){
|
||||
if(item.isComplexVariable){
|
||||
variablesObject[item.name] = item.complexValue;
|
||||
}else{
|
||||
variablesObject[item.name] = item.value;
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
taskObject[$scope.newTask.module.name] = variablesObject;
|
||||
|
||||
if($scope.local_action){
|
||||
variablesObject.module = $scope.newTask.module.name;
|
||||
taskObject['local_action'] = variablesObject;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(selectedTaskIndex != null){
|
||||
// If Edit Task
|
||||
|
||||
tasksList[selectedTaskIndex] = taskObject
|
||||
|
||||
}else{
|
||||
// If New Task
|
||||
|
||||
tasksList.push(taskObject);
|
||||
}
|
||||
|
||||
$uibModalInstance.close(taskObject);
|
||||
};
|
||||
|
||||
/**
|
||||
* Close modal
|
||||
*/
|
||||
$scope.ok = function () {
|
||||
$uibModalInstance.close($scope.newTask);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cancel modal
|
||||
*/
|
||||
$scope.cancel = function () {
|
||||
$uibModalInstance.dismiss('cancel');
|
||||
};
|
||||
|
||||
/**
|
||||
* Get host variables using Ansible Python API in the backend
|
||||
*/
|
||||
$scope.getHostVars = function(){
|
||||
|
||||
if(!(selectedPlay && selectedPlay.play && selectedPlay.play.hosts))return;
|
||||
|
||||
ansible.getVars(Projects.selectedInventoryFileName,selectedPlay.play.hosts,function(response){
|
||||
console.log(response.data);
|
||||
if(response.data.length)
|
||||
$scope.hostvars = $filter('dictToKeyValueArray')(response.data[0]);
|
||||
else $scope.err_msg = "Getting host variables - No variables returned" ;
|
||||
|
||||
},function(error){
|
||||
console.log(error.data);
|
||||
$scope.err_msg = "Getting host variables - " + error.data;
|
||||
})
|
||||
};
|
||||
|
||||
if(selectedPlay)
|
||||
$scope.getHostVars();
|
||||
|
||||
|
||||
$scope.getRoleVars = function(){
|
||||
|
||||
if(!(selectedRole && selectedRole.role))return;
|
||||
|
||||
ansible.getRoleVars(selectedRole.role,function(response){
|
||||
console.log(response.data);
|
||||
if(response.data)
|
||||
$scope.hostvars = $filter('dictToKeyValueArray')(response.data);
|
||||
else $scope.err_msg = "Getting host variables - No variables returned" ;
|
||||
|
||||
},function(error){
|
||||
console.log(error.data);
|
||||
$scope.err_msg = "Getting host variables - " + error.data;
|
||||
})
|
||||
};
|
||||
|
||||
if(selectedRole)
|
||||
$scope.getRoleVars();
|
||||
|
||||
|
||||
if(!$scope.modules){
|
||||
$scope.getAnsibleModules();
|
||||
}
|
||||
|
||||
$scope.showComplexVariable = function(variable){
|
||||
variable.isComplexVariable = true;
|
||||
var modalInstance = $uibModal.open({
|
||||
animation: true,
|
||||
/*templateUrl: 'createTaskContent.html',*/
|
||||
templateUrl: 'app/modals/complex_var_modal/complexVariable.html',
|
||||
controller: 'ComplexVarModalController',
|
||||
size: 'sm',
|
||||
backdrop: 'static',
|
||||
keyboard: false,
|
||||
closeByEscape: false,
|
||||
closeByDocument: false,
|
||||
resolve: {
|
||||
path: function () {
|
||||
return variable.name
|
||||
},
|
||||
hostvars: function(){
|
||||
return $scope.hostvars
|
||||
},
|
||||
members: function(){
|
||||
return variable.complexValue
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
modalInstance.result.then(function (selectedItem) {
|
||||
variable.complexValue = selectedItem
|
||||
}, function () {
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default angular.module('webAppApp.new_task', [])
|
||||
.controller('NewTaskController', newTaskController)
|
||||
.name;
|
|
@ -0,0 +1,17 @@
|
|||
'use strict';
|
||||
|
||||
describe('Controller: NewTaskCtrl', function() {
|
||||
// load the controller's module
|
||||
beforeEach(module('webAppApp.new_task'));
|
||||
|
||||
var NewTaskCtrl;
|
||||
|
||||
// Initialize the controller and a mock scope
|
||||
beforeEach(inject(function($controller) {
|
||||
NewTaskCtrl = $controller('NewTaskCtrl', {});
|
||||
}));
|
||||
|
||||
it('should ...', function() {
|
||||
expect(1).to.equal(1);
|
||||
});
|
||||
});
|
134
client/app/designer/tasks/new_task/new_task.html
Normal file
134
client/app/designer/tasks/new_task/new_task.html
Normal file
|
@ -0,0 +1,134 @@
|
|||
<!--<script type="text/ng-template" id="createTaskContent.html">-->
|
||||
<!-- Modal content-->
|
||||
<div class="modal-content" >
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" ng-click="cancel()" data-dismiss="modal">×</button>
|
||||
<h4 class="modal-title">{{title}}</h4>
|
||||
</div>
|
||||
<div class="modal-body" id="TaskCreationModal">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon" >Name</span>
|
||||
<input ng-model="newTask.name" type="text" class="form-control" placeholder="Task Name">
|
||||
</div>
|
||||
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon" >Include</span>
|
||||
<input type="text" ng-model="newTask.include" uib-typeahead="file.name as file.name for file in files | filter: $viewValue" class="form-control">
|
||||
</div>
|
||||
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon" >Module</span>
|
||||
<input type="text" ng-disabled="!modules || newTask.include" ng-model="newTask.module" typeahead-on-select="getModuleDescription(newTask.module)" uib-typeahead="module as module.name for module in modules | filter: $viewValue" class="form-control">
|
||||
</div>
|
||||
|
||||
<i ng-if="modulesLoading" class="fa fa-spinner fa-spin"></i>
|
||||
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon" >Tags</span>
|
||||
<input ng-model="newTask.tags" type="text" class="form-control" placeholder="Tags separated by comma">
|
||||
</div>
|
||||
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon" >Async (s)</span>
|
||||
<input ng-model="newTask.async" type="text" class="form-control" placeholder="Max run time in seconds">
|
||||
</div>
|
||||
|
||||
<div ng-if="newTask.async">
|
||||
<div class="hint">{{newTask.async / 60 | number}} minutes</div>
|
||||
<div class="input-group" >
|
||||
<span class="input-group-addon" >Poll (s)</span>
|
||||
<input ng-model="newTask.poll" type="text" class="form-control" placeholder="10" ng-value="10">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon" >Register Result</span>
|
||||
<input ng-model="newTask.register" type="text" class="form-control" placeholder="Variable Name">
|
||||
</div>
|
||||
<div class="hint">Register results of to a variable</div>
|
||||
|
||||
<label class="checkbox-inline"><input type="checkbox" ng-model="newTask.module.singleLine">Single Line</label>
|
||||
<span ng-if="getModuleDescriptionLoading" class="fa fa-spinner fa-spin"></span>
|
||||
|
||||
<div ng-if="newTask.module.variables">
|
||||
<h4>Arguments</h4>
|
||||
<div ng-repeat="variable in newTask.module.variables | orderBy : '-mandatory'">
|
||||
<!--<div class="input-group" ng-show="!variable.isVariable && !variable.choices.length">
|
||||
<span class="input-group-addon" >{{ variable.mandatory ? "*" : "" }} {{variable.name}}</span>
|
||||
<input ng-model="variable.value" type="text" class="form-control" required="{{variable.mandatory}}">
|
||||
</div>-->
|
||||
|
||||
<!--Input Type - Default Typeahead - variable or string-->
|
||||
<div class="input-group" ng-show="!variable.choices.length">
|
||||
<span class="input-group-addon" uib-tooltip="{{variable.description}}">{{ variable.mandatory ? "*" : "" }} {{variable.name}}</span>
|
||||
<!--<select class="form-control" ng-model="variable.value" ng-options="('"\{\{' + var.name + '\}\}"') as (var.name + '-' + var.value) disable when var.disabled for var in hostvars">
|
||||
</select>-->
|
||||
|
||||
<input type="text" ng-model="variable.value" uib-typeahead="('\{\{' + var.key + '\}\}') as (var.key + ' = ' + var.value) for var in hostvars | filter: $viewValue" class="form-control" placeholder="{{variable.description}}">
|
||||
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-secondary" ng-click="showComplexVariable(variable)" uib-tooltip="Click to configure Complex Variable">{ }</button>
|
||||
</span>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<!--Input Type - Choice-->
|
||||
<div class="input-group" ng-show="variable.choices.length">
|
||||
<span class="input-group-addon" uib-tooltip="{{variable.description}}">{{ variable.mandatory ? "*" : "" }} {{variable.name}}</span>
|
||||
<select class="form-control" ng-model="variable.value" ng-options="choice for choice in variable.choices">
|
||||
</select>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!--<div class="input-group" ng-show="variable.isComplexVariable">
|
||||
<span class="input-group-addon" >{{ variable.mandatory ? "*" : "" }} {{variable.name}}</span>
|
||||
<!–<json-tree json="variable.complexValue"></json-tree>–>
|
||||
<button class="btn btn-default" ng-click="showComplexVariable(variable)">Configure</button>
|
||||
</div>-->
|
||||
|
||||
<!--<label class="checkbox-inline"><input type="checkbox" ng-model="variable.isVariable">Variable</label>-->
|
||||
<label class="checkbox-inline" ng-show="variable.isVariable"><input type="checkbox" ng-model="variable.isComplexVariable">Complex Variable</label>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div ng-if="showHelp">
|
||||
<h4>Help</h4>
|
||||
<textarea rows="20" cols="60" ng-model="detailHelp" style="font-size: 13px"></textarea>
|
||||
|
||||
<h4>Examples</h4>
|
||||
<textarea rows="20" cols="60" ng-model="examples" style="font-size: 13px"></textarea>
|
||||
|
||||
</div>
|
||||
<!--{{newTask.module.variables}}-->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="alert alert-danger" ng-if="err_msg">{{err_msg}}</div>
|
||||
<div class="modal-footer">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-3" style="text-align: left">
|
||||
<button class="btn btn-default" type="button" ng-click="reloadModuleDetails(newTask.module)">Reload Module <span class="fa fa-refresh"></span></button>
|
||||
</div>
|
||||
<div class="col-md-9" style="text-align: right">
|
||||
<button class="btn btn-primary" ng-click="createTask()">Save <span ng-if="createTaskLoading" class="fa fa-spinner fa-spin"></span></button>
|
||||
<button class="btn btn-default" type="button" ng-click="cancel()">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!--
|
||||
</script>
|
||||
-->
|
0
client/app/designer/tasks/tasks.css
Normal file
0
client/app/designer/tasks/tasks.css
Normal file
229
client/app/designer/tasks/tasks.directive.js
Normal file
229
client/app/designer/tasks/tasks.directive.js
Normal file
|
@ -0,0 +1,229 @@
|
|||
'use strict';
|
||||
const angular = require('angular');
|
||||
|
||||
export default angular.module('webAppApp.tasks', [])
|
||||
.directive('tasks', function(ansible, $uibModal) {
|
||||
return {
|
||||
templateUrl: 'app/designer/tasks/tasks.html',
|
||||
restrict: 'EA',
|
||||
scope: {
|
||||
tasksList: '=',
|
||||
selectedPlay: '=',
|
||||
savePlaybook: '&',
|
||||
selectedRole: '=',
|
||||
updatePlaybookFileContent: '&',
|
||||
executeAnsiblePlayBook: '&',
|
||||
files: '=' //List of files for include purpose
|
||||
},
|
||||
link: function (scope, element, attrs) {
|
||||
scope.getModuleFromTask = ansible.getModuleFromTask;
|
||||
|
||||
scope.buttonStates = {loading:false,save:false,err_msg:false};
|
||||
|
||||
scope.tasksMetaData = [];
|
||||
|
||||
scope.$watch('tasksList',function(){
|
||||
console.log('tasks list changed');
|
||||
scope.tasksMetaData = [];
|
||||
|
||||
angular.forEach(scope.tasksList,function(task){
|
||||
var taskModule = ansible.getModuleFromTask(task);
|
||||
var taskName = task.name;
|
||||
|
||||
if(taskModule === 'include'){
|
||||
taskName = task[taskModule].replace(/(.*yml) .*/,"$1")
|
||||
}
|
||||
|
||||
scope.tasksMetaData.push({taskModule:taskModule,taskName:taskName,selected:false})
|
||||
})
|
||||
|
||||
},true);
|
||||
|
||||
|
||||
/**
|
||||
* Detect when the user selects tasks.
|
||||
* Enable play button if tasks are selected and has tags assigned
|
||||
* Enable delete button if tasks are selected
|
||||
*/
|
||||
scope.$watch('tasksMetaData',function(newValue,oldValue){
|
||||
scope.selectedTasksPlayButton = false;
|
||||
scope.selectedTasksDeleteButton = false
|
||||
|
||||
if(!(scope.tasksMetaData))return;
|
||||
|
||||
var selectedTasks = scope.tasksMetaData.filter(item => item.selected);
|
||||
var includeTasks = scope.tasksMetaData.filter(item => item.taskModule === 'include');
|
||||
var selectedTasksWithoutTags = [];
|
||||
|
||||
/**
|
||||
* Find selected tasks without any tags.
|
||||
* If there are any play button will not be enabled
|
||||
*/
|
||||
angular.forEach(scope.tasksMetaData,function(item,index){
|
||||
scope.tasksListItem = scope.tasksList[index];
|
||||
if(!scope.tasksListItem.tags && item.selected){
|
||||
selectedTasksWithoutTags.push(scope.tasksListItem)
|
||||
}
|
||||
});
|
||||
|
||||
console.log("selectedTasksWithoutTags=")
|
||||
console.log(selectedTasksWithoutTags)
|
||||
|
||||
if(selectedTasks.length){
|
||||
//if(!includeTasks.length && !selectedTasksWithoutTags.length){
|
||||
if(!selectedTasksWithoutTags.length){
|
||||
scope.selectedTasksPlayButton = true
|
||||
}
|
||||
scope.selectedTasksDeleteButton = true
|
||||
|
||||
}else{
|
||||
scope.selectedTasksPlayButton = false;
|
||||
scope.selectedTasksDeleteButton = false
|
||||
}
|
||||
|
||||
},true);
|
||||
|
||||
|
||||
//scope.moveUp = scope.moveUp();
|
||||
//scope.moveDown = scope.moveDown();
|
||||
scope.savePlaybook = scope.savePlaybook();
|
||||
scope.updatePlaybookFileContent = scope.updatePlaybookFileContent();
|
||||
scope.executeAnsiblePlayBook = scope.executeAnsiblePlayBook();
|
||||
|
||||
scope.showTaskModal = function(selectedTaskIndex, copyTask){
|
||||
var modalInstance = $uibModal.open({
|
||||
animation: true,
|
||||
/*templateUrl: 'createTaskContent.html',*/
|
||||
templateUrl: 'app/designer/tasks/new_task/new_task.html',
|
||||
controller: 'NewTaskController',
|
||||
size: 'lg',
|
||||
backdrop : 'static',
|
||||
keyboard : false,
|
||||
closeByEscape : false,
|
||||
closeByDocument : false,
|
||||
resolve: {
|
||||
selectedProject: function () {
|
||||
return scope.$parent.selectedProject;
|
||||
},
|
||||
selectedPlay: function(){
|
||||
return scope.selectedPlay
|
||||
},
|
||||
selectedRole: function(){
|
||||
return scope.selectedRole
|
||||
},
|
||||
tasksList: function () {
|
||||
return scope.tasksList;
|
||||
},
|
||||
selectedTaskIndex: function(){
|
||||
return selectedTaskIndex
|
||||
},
|
||||
copyTask : function(){
|
||||
return copyTask
|
||||
},
|
||||
//List of files for include purpose
|
||||
files: function(){
|
||||
return scope.files
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
modalInstance.result.then(
|
||||
function (newTask) {
|
||||
// if(!selectedTaskIndex)
|
||||
// scope.tasksList.push(newTask);
|
||||
scope.updatePlaybookFileContent(true);
|
||||
//$scope.selectedPlay = {play: ""};
|
||||
}, function () {
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
|
||||
scope.deleteTask = function(index){
|
||||
scope.tasksList.splice(index,1);
|
||||
scope.updatePlaybookFileContent(true);
|
||||
};
|
||||
|
||||
scope.deleteTasks = function(){
|
||||
|
||||
scope.tasksMetaData.filter(function(item, index){
|
||||
if(item.selected){
|
||||
scope.tasksList.splice(index,1);
|
||||
}
|
||||
});
|
||||
scope.updatePlaybookFileContent(true);
|
||||
};
|
||||
|
||||
|
||||
scope.moveUp = function(list,index,buttonVariable){
|
||||
if(!scope.preChangeData) scope.preChangeData = angular.copy(list);
|
||||
var temp = angular.copy(list[index]);
|
||||
list[index] = list[index-1];
|
||||
list[index-1] = temp;
|
||||
|
||||
scope.updatePlaybookFileContent(false);
|
||||
|
||||
scope.buttonStates.save = true
|
||||
|
||||
};
|
||||
|
||||
scope.cancelChange = function(buttonVariable){
|
||||
if(scope.preChangeData){
|
||||
//scope.tasksList = angular.copy(scope.preChangeData);
|
||||
scope.selectedPlay.play.tasks = angular.copy(scope.preChangeData);
|
||||
scope.preChangeData = null
|
||||
|
||||
}
|
||||
scope.updatePlaybookFileContent(false,null,scope.tasksList);
|
||||
|
||||
scope.buttonStates.save = false;
|
||||
};
|
||||
|
||||
scope.moveDown = function(list,index,buttonVariable){
|
||||
if(!scope.preChangeData) scope.preChangeData = angular.copy(list);
|
||||
var temp = angular.copy(list[index]);
|
||||
list[index] = list[index+1];
|
||||
list[index+1] = temp;
|
||||
|
||||
scope.updatePlaybookFileContent(false);
|
||||
scope.buttonStates.save = true;
|
||||
|
||||
};
|
||||
|
||||
|
||||
scope.executeSelectedTasks = function(){
|
||||
|
||||
/*var selectedTasks = scope.tasksMetaData.map(function(item){return item.selected});*/
|
||||
var selectedTags = [];
|
||||
var selectedTaskNames = [];
|
||||
/*if(selectedTasks.length){
|
||||
selectedTags = selectedTasks.map(function(item){return item.tags});
|
||||
selectedTaskNames = selectedTasks.map(function(item){return item.name})
|
||||
}*/
|
||||
|
||||
angular.forEach(scope.tasksMetaData, function(item,index){
|
||||
if(item.selected){
|
||||
if(scope.tasksList[index].tags){
|
||||
// As tags is an array and each task can have multiple tags
|
||||
var task_tags = scope.tasksList[index].tags
|
||||
if(typeof task_tags == 'object')
|
||||
task_tags = task_tags[0] //task_tags.join(',')
|
||||
selectedTags.push(task_tags);
|
||||
selectedTaskNames.push(scope.tasksList[index].name)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if(selectedTags.length){
|
||||
var play = scope.selectedPlay && scope.selectedPlay.play;
|
||||
scope.executeAnsiblePlayBook(selectedTags,'Tasks',selectedTaskNames.join(","),play)
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
};
|
||||
})
|
||||
.name;
|
20
client/app/designer/tasks/tasks.directive.spec.js
Normal file
20
client/app/designer/tasks/tasks.directive.spec.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
'use strict';
|
||||
|
||||
describe('Directive: tasks', function() {
|
||||
// load the directive's module and view
|
||||
beforeEach(module('webAppApp.tasks'));
|
||||
beforeEach(module('app/designer/tasks/tasks.html'));
|
||||
|
||||
var element, scope;
|
||||
|
||||
beforeEach(inject(function($rootScope) {
|
||||
scope = $rootScope.$new();
|
||||
}));
|
||||
|
||||
it('should make hidden element visible', inject(function($compile) {
|
||||
element = angular.element('<tasks></tasks>');
|
||||
element = $compile(element)(scope);
|
||||
scope.$apply();
|
||||
expect(element.text()).to.equal('this is the tasks directive');
|
||||
}));
|
||||
});
|
53
client/app/designer/tasks/tasks.html
Normal file
53
client/app/designer/tasks/tasks.html
Normal file
|
@ -0,0 +1,53 @@
|
|||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Select</th>
|
||||
<th>Name</th>
|
||||
<th>Module</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="task in tasksList">
|
||||
<td><input type="checkbox" ng-model="tasksMetaData[$index].selected">
|
||||
</td>
|
||||
<td>{{tasksMetaData[$index].taskName}}</td>
|
||||
<td>{{tasksMetaData[$index].taskModule}}</td>
|
||||
<td>
|
||||
<div class="btn-group">
|
||||
<label class="btn btn-default btn-sm" ng-click="showTaskModal($index)"><span
|
||||
class="fa fa-edit"></span></label>
|
||||
<!--<label class="btn btn-default btn-sm" ng-click="showTaskModal($index,true)"><span
|
||||
class="fa fa-copy"></span></label>-->
|
||||
<!--<label class="btn btn-danger btn-sm" ng-click="deleteTask($index)"
|
||||
confirm="Are you sure you want to delete?"><span class="fa fa-trash"></span></label>-->
|
||||
<!--<div style="display: inline-block" tooltip-enable="!task.tags"
|
||||
uib-tooltip="Tag must be assigned to play individually"><label class="btn btn-success btn-sm"
|
||||
ng-disabled="!task.tags"
|
||||
ng-click="executeAnsiblePlayBook(task.tags,'Task',task.name, selectedPlay)"><span
|
||||
class="fa fa-play"></span></label></div>-->
|
||||
<label class="btn btn-primary btn-sm" ng-disabled="$first"
|
||||
ng-click="moveUp(tasksList,$index,'saveTaskListLoading')"><span
|
||||
class="fa fa-arrow-up"></span></label>
|
||||
<label class="btn btn-primary btn-sm" ng-disabled="$last"
|
||||
ng-click="moveDown(tasksList,$index,'saveTaskListLoading')"><span
|
||||
class="fa fa-arrow-down"></span></label>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-default" data-toggle="modal" data-target="#createTaskModal" ng-click="showTaskModal()">
|
||||
Create Task <span class="fa fa-plus"></span></button>
|
||||
<button class="btn btn-success" data-toggle="modal" ng-disabled="!selectedTasksPlayButton" ng-if="!buttonStates.save"
|
||||
ng-click="executeSelectedTasks()"> Play <span class="fa fa-play"></span></button>
|
||||
<button class="btn btn-danger" data-toggle="modal" ng-disabled="!selectedTasksDeleteButton" ng-if="!buttonStates.save" confirm="Are you sure you want to delete the selected tasks?"
|
||||
ng-click="deleteTasks()"> Delete <span class="fa fa-trash-o"></span></button>
|
||||
<button class="btn btn-primary" ng-if="buttonStates.save"
|
||||
ng-click="savePlaybook(buttonStates)">Save <span ng-if="buttonStates.loading"
|
||||
class="fa fa-spinner fa-spin"></span></button>
|
||||
<button class="btn btn-warning" ng-if="buttonStates.save"
|
||||
ng-click="cancelChange(buttonStates)">Cancel <span class="fa fa-times"></span></button>
|
Loading…
Add table
Add a link
Reference in a new issue