1
0
Fork 0
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:
Mumshad Mannambeth 2017-06-07 13:36:44 -04:00
commit c92f737237
273 changed files with 16964 additions and 0 deletions

View file

@ -0,0 +1,134 @@
'use strict';
const angular = require('angular');
/*@ngInject*/
export function newPlayController($scope, $uibModalInstance, ansible, plays, selectedPlayIndex) {
$scope.loading_msg = '';
$scope.title = "Create Play";
$scope.editMode = false;
$scope.editHostMode = false;
var selectedPlay;
if(selectedPlayIndex > -1){
selectedPlay = plays[selectedPlayIndex];
$scope.title = "Edit Play";
$scope.editMode = true;
if(selectedPlay && selectedPlay.tags)$scope.tags = selectedPlay.tags.join(',');
}
$scope.newPlay = selectedPlay || {};
$scope.newPlay_roles = $scope.newPlay.roles;
$scope.createPlayLoading = false;
$scope.createPlay = function () {
$scope.ok($scope.newPlay)
};
$scope.ok = function (newPlay) {
if($scope.tags)
newPlay.tags = $scope.tags.split(',');
if($scope.newPlay_roles && $scope.newPlay_roles.length){
var roles = [];
angular.forEach($scope.newPlay_roles,function(role){
roles.push(role.text)
});
newPlay.roles = roles;
}else if(newPlay.roles){
delete newPlay.roles;
}
$uibModalInstance.close(newPlay);
};
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
$scope.getHostsFromInventory = function(){
var hosts = [];
angular.forEach($scope.inventory_data_json.hosts, function(host){
hosts.push({name:host})
});
angular.forEach($scope.inventory_data_json.groups, function(group){
if(group.name !== 'Un grouped')
hosts.push({name:group.name})
});
return hosts;
};
$scope.listOfInventoryFiles = function(){
$scope.loading_msg = 'Loading Inventory Files';
ansible.getInventoryList(function(response){
$scope.loading_msg = '';
$scope.inventoryFiles = response.data;
},
function(response){
$scope.loading_msg = '';
$scope.err_msg = response.data
})
};
$scope.listOfRoles = function(){
$scope.loading_msg = 'Loading Roles';
ansible.getRoleList(function(response){
$scope.loading_msg = '';
$scope.roleList = response.data;
},
function(response){
$scope.loading_msg = '';
$scope.err_msg = response.data
})
};
$scope.inventorySelected = function(selectedInventoryFile){
$scope.loading_msg = 'Loading Hosts';
ansible.readInventory(selectedInventoryFile,
function(response){
$scope.loading_msg = '';
$scope.inventory_data_json = ansible.parseINIString(response.data);
$scope.hosts = $scope.getHostsFromInventory();
},function(response){
$scope.loading_msg = '';
$scope.err_msg = response.data
})
};
$scope.getHostObject = function(hostname){
var result = $scope.hosts.filter(function(host){
return host.name == hostname
});
if(result.length){
return result[0]
}
};
$scope.listOfInventoryFiles();
$scope.listOfRoles();
$scope.loadTags = function(query){
if($scope.roleList){
var tempList = $scope.roleList.filter(function(role){
return role.indexOf(query) > -1
});
return tempList
}
}
}
export default angular.module('webAppApp.new_play', [])
.controller('NewPlayController', newPlayController)
.name;

View file

@ -0,0 +1,17 @@
'use strict';
describe('Controller: NewPlayCtrl', function() {
// load the controller's module
beforeEach(module('webAppApp.new_play'));
var NewPlayCtrl;
// Initialize the controller and a mock scope
beforeEach(inject(function($controller) {
NewPlayCtrl = $controller('NewPlayCtrl', {});
}));
it('should ...', function() {
expect(1).to.equal(1);
});
});

View file

@ -0,0 +1,96 @@
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">{{title}}</h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-6">
<p class="form-group">
<label>Name</label>
<input ng-model="newPlay.name" type="text" class="form-control" placeholder="Play Name">
</p>
<p class="form-group">
<label>Tags</label>
<input ng-model="tags" type="text" class="form-control" placeholder="Tags separated by comma">
</p>
<p class="form-group" ng-show="!editMode || editHostMode">
<label>Inventory Files</label>
<select class="form-control" ng-disabled="loading_msg" ng-change="inventorySelected(selectedInventoryFile);" ng-model="selectedInventoryFile" ng-options="inventoryFile as inventoryFile for inventoryFile in inventoryFiles">
</select>
</p>
<p class="form-group" ng-show="!editMode || editHostMode">
<label>Hosts</label>
<select class="form-control" ng-disabled="loading_msg" ng-model="newPlay.hosts" ng-options="host.name as host.name for host in hosts">
</select>
</p>
<p class="form-group" ng-show="editMode && !editHostMode">
<label>Hosts </label>
<input ng-model="newPlay.hosts" ng-disabled="true" type="text" class="form-control" placeholder="Host Name">
</p>
<div class="input-group-btn" ng-show="editMode && !editHostMode">
<button class="btn btn-default" ng-click="editHostMode = true"> <span class="fa fa-edit"></span> Edit Hosts </button>
</div>
<label>Roles</label>
<tags-input ng-model="newPlay_roles" add-from-autocomplete-only="true" placeholder="Add roles to play">
<auto-complete source="loadTags($query)" min-length="0" load-on-empty="true" load-on-focus="true" load-on-down-arrow="true" ></auto-complete>
</tags-input>
</div>
<div class="col-md-6">
<h4 ng-if="selectedHostInfo.ip">IP - {{selectedHostInfo.ip}}</h4>
<h4 ng-if="selectedHostInfo.members">Members:</h4>
<ul class="list-group" ng-if="selectedHostInfo.members">
<li class="list-group-item" ng-repeat="member in selectedHostInfo.members.split(',')">{{member}}</li>
</ul>
<div ng-if="hostGroups">
<h4 >Member Of:</h4>
<ul class="list-group">
<li class="list-group-item" ng-repeat="group in hostGroups">{{group.name}}</li>
</ul>
</div>
<!--<div ui-ace="{theme:'twilight',document:'INI',mode:'ini',showGutter:false}" ng-model="hostInfo">
</div>-->
</div>
</div>
<div class="row" ng-if="selectedHostInfo">
<h4>Variables</h4>
<div class="input-group">
<span class="input-group-addon" >Groups</span>
<select class="form-control" ng-change="variableGroupSelected(selectedVariableGroup.value)" ng-model="selectedVariableGroup.value" ng-options="group.name as group.name for group in [selectedHostInfo].concat(hostGroups)">
</select>
</div>
<div ui-ace="{theme:'twilight',document:'INI',mode:'ini'}" ng-model="variableInfo">
</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">
<span ng-show="loading_msg" class="fa fa-spin fa-spinner"></span> {{loading_msg}}
</div>
<div class="col-md-9" style="text-align: right">
<button class="btn btn-primary" ng-click="createPlay()">Save <span ng-if="createPlayLoading" class="fa fa-spinner fa-spin"></span> </button>
<button class="btn btn-default" type="button" ng-click="cancel()">Close</button>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,35 @@
'use strict';
const angular = require('angular');
/*@ngInject*/
export function newPlaybookController($scope,$uibModalInstance,ansible) {
$scope.newPlaybook = {name:null};
$scope.createPlaybookLoading = false;
$scope.createPlaybook = function(){
$scope.createPlaybookLoading = true;
ansible.createPlaybook($scope.newPlaybook.name + '.yml',"",
function(response){
$scope.createPlaybookLoading = false;
$scope.ok();
},
function(response){
$scope.createPlaybookLoading = false;
$scope.err_msg = response.data;
})
};
$scope.ok = function () {
$uibModalInstance.close(null);
};
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
}
export default angular.module('webAppApp.new_playbook', [])
.controller('NewPlaybookController', newPlaybookController)
.name;

View file

@ -0,0 +1,17 @@
'use strict';
describe('Controller: NewPlaybookCtrl', function() {
// load the controller's module
beforeEach(module('webAppApp.new_playbook'));
var NewPlaybookCtrl;
// Initialize the controller and a mock scope
beforeEach(inject(function($controller) {
NewPlaybookCtrl = $controller('NewPlaybookCtrl', {});
}));
it('should ...', function() {
expect(1).to.equal(1);
});
});

View file

@ -0,0 +1,19 @@
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">New Playbook</h4>
</div>
<div class="modal-body">
<p class="form-group">
<label>Playbook Name</label>
<input type="text" ng-model="newPlaybook.name" class="form-control">
</p>
</div>
<div class="alert alert-danger" ng-if="err_msg">{{err_msg}}</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-disabled="!newPlaybook.name" ng-click="createPlaybook()">Create <span ng-if="createPlaybookLoading" class="fa fa-spinner fa-spin"></span></button>
<button class="btn btn-default" type="button" ng-click="cancel()">Close</button>
</div>
</div>

View file

@ -0,0 +1,328 @@
'use strict';
const angular = require('angular');
const uiRouter = require('angular-ui-router');
import routes from './playbook.routes';
export class PlaybookComponent {
/*@ngInject*/
constructor($scope,$uibModal,YAML,ansible,yamlFile) {
'ngInject';
$scope.isopen = {playbooks:true,plays:false,tasks:false};
$scope.selectedPlaybook = {playbook: "",content: ""};
$scope.selectedPlay = {play: ""};
$scope.showSaveButton = {};
$scope.loadingButtons = {};
$scope.editPlaybook = {value:false};
$scope.loadingModuleCode = false;
$scope.$on('projectLoaded',function(){
$scope.getPlaybooks()
});
//To fix a warning message in console
$scope.aceLoaded = function(_editor){
_editor.$blockScrolling = Infinity;
};
// --------------------------------------- PLAYBOOKS ----------------
$scope.getPlaybooks = function(){
ansible.getPlaybookList(
function(response){
$scope.playbooks = response.data;
},
function(response){
console.log(response.data)
}
)
};
if($scope.$parent.selectedProject && $scope.$parent.selectedProject.ansibleEngine){
$scope.getPlaybooks()
}
$scope.showPlaybookCode = function(playbook_name){
$scope.loadingModuleCode = true;
if(!playbook_name){
$scope.selectedPlaybook.content = "Select a module";
return;
}
ansible.readPlaybook(playbook_name,function(response) {
$scope.isopen.playbooks = true;
$scope.isopen.plays = true
$scope.loadingModuleCode = false;
$scope.selectedPlaybook.content = response.data.split("Stream :: close")[0];
$scope.getPlaysFromPlayBook($scope.selectedPlaybook.content);
});
};
$scope.$watch('selectedPlaybook.playbook',function(newValue,oldValue){
if(newValue && newValue !== oldValue){
$scope.selectedPlaybook.content = "Loading Code...";
$scope.showPlaybookCode(newValue);
}
});
$scope.$watch('selectedPlay.play',function(newValue,oldValue){
if(newValue && newValue !== oldValue){
$scope.selectedPlay.play.tasks = $scope.selectedPlay.play.tasks || [];
$scope.isopen.playbooks = false;
$scope.isopen.plays = false;
$scope.isopen.tasks = true;
$scope.isopen.roles = true;
}
});
$scope.showCreatePlaybookModal = function(){
var modalInstance = $uibModal.open({
animation: true,
/*templateUrl: 'createTaskContent.html',*/
templateUrl: 'app/designer/playbook/new_playbook/new_playbook.html',
controller: 'NewPlaybookController',
size: 'md',
backdrop : 'static',
keyboard : false,
closeByEscape : false,
closeByDocument : false,
resolve: {
selectedProject: function(){
return $scope.$parent.selectedProject
}
}
});
modalInstance.result.then(function () {
$scope.getPlaybooks();
}, function () {
});
};
$scope.editPlaybookMethod = function(){
$scope.editPlaybook.value = true;
$scope.uneditedPlaybokContents = $scope.selectedPlaybook.content
};
$scope.cancelPlaybookChanges = function(){
$scope.editPlaybook.value = false;
$scope.selectedPlaybook.content = $scope.uneditedPlaybokContents
};
$scope.savePlaybook = function(buttonVariable){
console.log("Saving Playbook")
$scope.loadingButtons[buttonVariable] = true;
ansible.createPlaybook($scope.selectedPlaybook.playbook,$scope.selectedPlaybook.content,
function(response){
$scope.loadingButtons[buttonVariable] = false;
$scope.showSaveButton[buttonVariable] = false;
$scope.editPlaybook.value = false;
},
function(response){
$scope.loadingButtons[buttonVariable] = false;
$scope.showSaveButton[buttonVariable] = false;
$scope.err_msg = response.data;
})
};
$scope.deletePlaybook = function(){
$scope.deletePlaybookLoading = true;
ansible.deletePlaybook($scope.selectedPlaybook.playbook,
function(response){
$scope.deletePlaybookLoading = false;
$scope.selectedPlaybook.playbook = "";
$scope.getPlaybooks();
},
function(response){
$scope.deletePlaybookLoading = false;
$scope.err_msg = response.data;
})
};
//--------------- PLAY --------------
$scope.showCreatePlayModal = function(selectedPlayIndex){
var modalInstance = $uibModal.open({
animation: true,
/*templateUrl: 'createPlayContent.html',*/
templateUrl: 'app/designer/playbook/new_play/new_play.html',
controller: 'NewPlayController',
size: 'lg',
backdrop : 'static',
keyboard : false,
closeByEscape : false,
closeByDocument : false,
resolve: {
selectedProject: function () {
return $scope.$parent.selectedProject;
},
plays: function () {
return $scope.plays;
},
selectedPlayIndex: function () {
return selectedPlayIndex;
}
}
});
modalInstance.result.then(
function (newPlay) {
if(selectedPlayIndex == null)
$scope.plays.push(newPlay);
$scope.clearEmptyTasks($scope.plays);
$scope.selectedPlaybook.content = yamlFile.jsonToYamlFile($scope.plays, 'Playbook file: ' + $scope.selectedPlaybook.playbook)
$scope.savePlaybook();
}, function () {
});
};
// FUNCTION - GET PLAYS FROM PLAYBOOK
$scope.getPlaysFromPlayBook = function(playbookYamlData){
$scope.plays = YAML.parse(playbookYamlData) || []
};
// FUNCTION - DELETE PLAY
$scope.deletePlay = function(index){
$scope.plays.splice(index,1);
$scope.selectedPlaybook.content = yamlFile.jsonToYamlFile($scope.plays, 'Playbook file: ' + $scope.selectedPlaybook.playbook)
$scope.savePlaybook();
$scope.selectedPlay = {play: ""};
};
// ------------------- EXECUTE PLAYBOOK MODAL -------------
$scope.executeAnsiblePlayBook = function(tags,executionType,executionName,selectedPlay){
console.log("Tags type" + typeof tags)
var modalInstance = $uibModal.open({
animation: true,
/*templateUrl: 'createTaskContent.html',*/
templateUrl: 'app/designer/execution/executeModal.html',
controller: 'ExecutionController',
size: 'lg',
backdrop : 'static',
keyboard : false,
closeByEscape : false,
closeByDocument : false,
resolve: {
tags: function(){
return tags
},
selectedProject: function(){
return $scope.$parent.selectedProject
},
selectedPlaybook: function(){
return $scope.selectedPlaybook
},
selectedPlay: function(){
return selectedPlay
},
executionType: function(){
return executionType
},
executionName: function(){
return executionName
},
readOnly: function(){
return false
},
runData: function(){
return null
},
projectFolder: function(){
return null
},
roleName: function(){
return null
}
}
});
};
$scope.clearEmptyTasks = function(plays){
//Check for empty tasks list
angular.forEach(plays,function(play){
if((play.tasks && !play.tasks.length) || !play.tasks){
delete play.tasks
}
});
};
// ---------------------- TASKS -------------------
$scope.updatePlaybookFileContent = function(save,buttonVariable){
var playsCopy = angular.copy($scope.plays);
$scope.clearEmptyTasks(playsCopy);
$scope.selectedPlaybook.content = yamlFile.jsonToYamlFile(playsCopy, 'Playbook file: ' + $scope.selectedPlaybook.playbook)
if(save)
$scope.savePlaybook(buttonVariable);
};
$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.showSaveButton[buttonVariable] = true
};
$scope.cancelChange = function(buttonVariable){
if($scope.preChangeData){
$scope.plays = angular.copy($scope.preChangeData);
$scope.preChangeData = null
}
$scope.updatePlaybookFileContent(false);
$scope.showSaveButton[buttonVariable] = 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.showSaveButton[buttonVariable] = true
};
}
}
export default angular.module('webAppApp.playbook', [uiRouter])
.config(routes)
.component('playbook', {
template: require('./playbook.html'),
controller: PlaybookComponent,
controllerAs: 'playbookCtrl'
})
.name;

View file

@ -0,0 +1,17 @@
'use strict';
describe('Component: PlaybookComponent', function() {
// load the controller's module
beforeEach(module('webAppApp.playbook'));
var PlaybookComponent;
// Initialize the controller and a mock scope
beforeEach(inject(function($componentController) {
PlaybookComponent = $componentController('playbook', {});
}));
it('should ...', function() {
expect(1).to.equal(1);
});
});

View file

@ -0,0 +1,166 @@
<div class="col-md-6">
<uib-accordion close-others="false">
<div uib-accordion-group class="panel-default" is-open="isopen.playbooks">
<uib-accordion-heading>
Playbooks <i class="pull-right glyphicon"
ng-class="{'glyphicon-chevron-down': isopen.playbooks, 'glyphicon-chevron-right': !isopen.playbooks}"></i>
</uib-accordion-heading>
<button class="btn btn-default" ng-click="showCreatePlaybookModal()">Create Playbook <span
class="fa fa-plus"></span></button>
<button class="btn btn-default" ng-if="!editPlaybook.value" ng-click="editPlaybookMethod()">Edit <span
ng-if="!showSaveButton.savePlaybookLoading" class="fa fa-edit"></span></button>
<button class="btn btn-primary" ng-if="editPlaybook.value" ng-disabled="!selectedPlaybook.playbook"
ng-click="savePlaybook('savePlaybookLoading')">Save <span ng-if="!showSaveButton.savePlaybookLoading"
class="fa fa-save"></span><span
ng-if="showSaveButton.savePlaybookLoading" class="fa fa-spinner fa-spin"></span></button>
<button class="btn btn-warning" ng-if="editPlaybook.value" confirm="Are you sure you want to discard the changes?"
ng-click="cancelPlaybookChanges()">Cancel <span class="fa fa-times-circle"></span></button>
<button class="btn btn-danger" confirm="Are you sure you want to delete playbook? "
ng-disabled="!selectedPlaybook.playbook" ng-click="deletePlaybook()">Delete <span
ng-show="!deletePlaybookLoading" class="fa fa-save"></span><span ng-show="deletePlaybookLoading"
class="fa fa-spinner fa-spin"></span></button>
<button class="btn btn-success" ng-disabled="!selectedPlaybook.playbook"
ng-click="executeAnsiblePlayBook(null,'Playbook')">Play <span class="fa fa-play"></span></button>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>Select</th>
<th>Name</th>
<!--<th>Actions</th>-->
</tr>
</thead>
<tbody>
<tr ng-repeat="playbook in playbooks">
<td><input name="playbookGroup" type="radio" ng-model="selectedPlaybook.playbook" ng-value="playbook">
</td>
<td>{{playbook}}</td>
<!--<td><div class="btn-group">
<label class="btn btn-default btn-sm" ng-click="showCreatePlayModal($index)" ><span class="fa fa-edit"></span></label>
<label class="btn btn-danger btn-sm" confirm="Are you sure you want to delete?" ng-click="deletePlay($index)" ><span class="fa fa-trash-o"></span></label>
<div style="display: inline-block" tooltip-enable="!play.tags" uib-tooltip="Tag must be assigned to play individually"><label class="btn btn-success btn-sm" ng-disabled="!play.tags" ng-click="executeAnsiblePlayBook(play.tags,'Play',play.name,play)" ><span class="fa fa-play"></span></label></div>
</div></td>-->
</tr>
</tbody>
</table>
</div>
</div>
<div uib-accordion-group class="panel-default" is-open="isopen.plays" ng-show="plays">
<uib-accordion-heading>
Plays <i class="pull-right glyphicon"
ng-class="{'glyphicon-chevron-down': isopen.plays, 'glyphicon-chevron-right': !isopen.plays}"></i>
</uib-accordion-heading>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<tr>
<th>Select</th>
<th>Name</th>
<!--<th>Tags</th>-->
<th>Hosts</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="play in plays">
<td><input name="playGroup" type="radio" ng-model="selectedPlay.play" ng-value="play">
</td>
<td>{{play.name}}</td>
<!--<td>{{play.tags.join(', ')}}</td>-->
<td>{{play.hosts}}</td>
<td>
<div class="btn-group">
<label class="btn btn-default btn-sm" ng-click="showCreatePlayModal($index)"><span
class="fa fa-edit"></span></label>
<label class="btn btn-danger btn-sm" confirm="Are you sure you want to delete?"
ng-click="deletePlay($index)"><span class="fa fa-trash-o"></span></label>
<div style="display: inline-block" tooltip-enable="!play.tags"
uib-tooltip="Tag must be assigned to play individually"><label class="btn btn-success btn-sm"
ng-disabled="!play.tags"
ng-click="executeAnsiblePlayBook(play.tags,'Play',play.name,play)"><span
class="fa fa-play"></span></label></div>
<label class="btn btn-primary btn-sm" ng-disabled="$first"
ng-click="moveUp(plays,$index,'savePlayLoading')"><span class="fa fa-arrow-up"></span></label>
<label class="btn btn-primary btn-sm" ng-disabled="$last"
ng-click="moveDown(plays,$index,'savePlayLoading')"><span
class="fa fa-arrow-down"></span></label>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<button class="btn btn-default" ng-click="showCreatePlayModal()">Create <span class="fa fa-plus"></span></button>
<button class="btn btn-primary" ng-if="showSaveButton.savePlayLoading" ng-click="savePlaybook('savePlayLoading')">
Save <span ng-if="loadingButtons.savePlayLoading" class="fa fa-spinner fa-spin"></span></button>
<button class="btn btn-warning" ng-if="showSaveButton.savePlayLoading" ng-click="cancelChange('savePlayLoading')">
Cancel <span class="fa fa-times"></span></button>
</div>
<div uib-accordion-group class="panel-default" is-open="isopen.tasks" ng-show="selectedPlay.play">
<uib-accordion-heading>
Tasks <i class="pull-right glyphicon"
ng-class="{'glyphicon-chevron-down': isopen.tasks, 'glyphicon-chevron-right': !isopen.tasks}"></i>
</uib-accordion-heading>
<tasks tasks-list="selectedPlay.play.tasks" update-playbook-file-content="updatePlaybookFileContent" selected-play="selectedPlay" save-playbook="savePlaybook" execute-ansible-play-book="executeAnsiblePlayBook"></tasks>
</div>
<div uib-accordion-group class="panel-default" is-open="isopen.roles" ng-show="selectedPlay.play.roles">
<uib-accordion-heading>
Roles <i class="pull-right glyphicon"
ng-class="{'glyphicon-chevron-down': isopen.tasks, 'glyphicon-chevron-right': !isopen.tasks}"></i>
</uib-accordion-heading>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>Select</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="role in selectedPlay.play.roles">
<td><input name="playGroup" type="radio" ng-model="selectedRole.role" ng-value="role">
</td>
<td>{{role}}</td>
</tr>
</tbody>
</table>
</div>
<div class="panel">
<div class="panel panel-default">
<div class="panel-heading">File Browser</div>
<div class="panel-body">
<treecontrol ng-if="roleData.children" class="tree-classic"
tree-model="roleData.children"
options="treeOptions"
on-selection="showSelected(node)"
selected-node="node1"
filter-expression="{name: '!.git'}">
{{node.name}}
</treecontrol>
</div>
</div>
</div>
</div>
</uib-accordion>
</div>
<div class="col-md-6">
<div ng-readonly="!editPlaybook.value" ui-ace="{theme:'twilight',document:'YAML',mode:'yaml',onChange:codeChanged,onLoad:aceLoaded}"
ng-model="selectedPlaybook.content">
</div>
</div>

View file

@ -0,0 +1,10 @@
'use strict';
export default function($stateProvider) {
'ngInject';
$stateProvider
.state('designer.playbook', {
url: '/playbook',
template: '<playbook></playbook>'
});
}