refactor delete-job-template.service-test, integrate jobTemplate.copy, resolves #1105 & #1047, tracking #1176

This commit is contained in:
Leigh Johnson 2016-03-11 14:41:05 -05:00
parent 92f8885946
commit e34aebcd93
15 changed files with 174 additions and 212 deletions

View File

@ -308,17 +308,7 @@
function saveCompleted() {
setTimeout(function() {
$scope.$apply(function() {
var base = $location.path().replace(/^\//, '').split('/')[0];
if (base === 'job_templates') {
ReturnToCaller();
}
else {
ReturnToCaller(1);
}
});
}, 500);
$state.go('jobTemplates', null, {reload: true});
}
if ($scope.removeTemplateSaveSuccess) {

View File

@ -0,0 +1,32 @@
/*************************************************
* Copyright (c) 2016 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
export default
[ 'Wait', '$state', '$scope', 'jobTemplateCopyService',
'ProcessErrors', 'GetBasePath',
function(Wait, $state, $scope, jobTemplateCopyService,
ProcessErrors, GetBasePath){
// GETs the job_template to copy
// POSTs a new job_template
// routes to JobTemplates.edit when finished
var init = function(){
Wait('start');
jobTemplateCopyService.get($state.params.id)
.success(function(res){
jobTemplateCopyService.set(res)
.success(function(res){
Wait('stop');
$state.go('jobTemplates.edit', {template_id: res.id, copied: true}, {reload: true});
});
})
.error(function(res, status){
ProcessErrors($rootScope, res, status, null, {hdr: 'Error!',
msg: 'Call to '+ defaultUrl + ' failed. Return status: '+ status});
});
};
init();
}
];

View File

@ -0,0 +1,13 @@
/*************************************************
* Copyright (c) 2016 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
import {templateUrl} from '../../shared/template-url/template-url.factory';
export default {
name: 'jobTemplates.copy',
route: '/:id/copy',
controller: 'jobTemplateCopyController'
}

View File

@ -0,0 +1,38 @@
/*************************************************
* Copyright (c) 2016 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
export default
['$rootScope', 'Rest', 'ProcessErrors', 'GetBasePath', 'moment',
function($rootScope, Rest, ProcessErrors, GetBasePath, moment){
return {
get: function(id){
var defaultUrl = GetBasePath('job_templates') + '?id=' + id;
Rest.setUrl(defaultUrl);
return Rest.get()
.success(function(res){
return res
})
.error(function(res, status){
ProcessErrors($rootScope, res, status, null, {hdr: 'Error!',
msg: 'Call to '+ defaultUrl + ' failed. Return status: '+ status});
});
},
set: function(data){
var defaultUrl = GetBasePath('job_templates');
Rest.setUrl(defaultUrl);
data.results[0].name = data.results[0].name + ' ' + moment().format('h:mm:ss a'); // 2:49:11 pm
return Rest.post(data.results[0])
.success(function(res){
return res
})
.error(function(res, status){
ProcessErrors($rootScope, res, status, null, {hdr: 'Error!',
msg: 'Call to '+ defaultUrl + ' failed. Return status: '+ status});
});
}
}
}
];

View File

@ -0,0 +1,17 @@
/*************************************************
* Copyright (c) 2016 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
import controller from './job-templates-copy.controller';
import route from './job-templates-copy.route';
import service from './job-templates-copy.service';
export default
angular.module('jobTemplates.copy', [])
.service('jobTemplateCopyService', service)
.controller('jobTemplateCopyController', controller)
.run(['$stateExtender', function($stateExtender) {
$stateExtender.addState(route)
}]);

View File

@ -4,23 +4,15 @@
* All Rights Reserved
*************************************************/
var rest, getBasePath;
export default ['Rest', 'GetBasePath', function(Rest, GetBasePath){
return {
deleteJobTemplate: function(id){
var url = GetBasePath('job_templates');
export default
[ 'Rest',
'GetBasePath',
function(_rest, _getBasePath) {
rest = _rest;
getBasePath = _getBasePath;
return deleteJobTemplate;
url = url + id;
Rest.setUrl(url);
return Rest.destroy();
}
];
function deleteJobTemplate(id) {
var url = getBasePath('job_templates');
url = url + id;
rest.setUrl(url);
return rest.destroy();
}
}
}]

View File

@ -402,17 +402,7 @@ export default
});
function saveCompleted() {
setTimeout(function() {
$scope.$apply(function() {
var base = $location.path().replace(/^\//, '').split('/')[0];
if (base === 'job_templates') {
ReturnToCaller();
}
else {
ReturnToCaller(1);
}
});
}, 500);
$state.go('jobTemplates', null, {reload: true});
}
if ($scope.removeTemplateSaveSuccess) {
@ -518,7 +508,22 @@ export default
};
$scope.formCancel = function () {
$state.transitionTo('jobTemplates');
// the form was just copied in the previous state, it's safe to destroy on cancel
if ($state.params.copied){
var defaultUrl = GetBasePath('job_templates') + $state.params.template_id;
Rest.setUrl(defaultUrl);
Rest.destroy()
.success(function(res){
$state.go('jobTemplates', null, {reload: true, notify:true});
})
.error(function(res, status){
ProcessErrors($rootScope, res, status, null, {hdr: 'Error!',
msg: 'Call to '+ defaultUrl + ' failed. Return status: '+ status});
});
}
else {
$state.go('jobTemplates');
}
};
// Related set: Add button

View File

@ -18,5 +18,8 @@ export default {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
},
params: {
copied: null
}
};

View File

@ -9,7 +9,7 @@ export default
'$stateParams', 'Rest', 'Alert', 'JobTemplateList', 'generateList',
'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope',
'ProcessErrors', 'GetBasePath', 'JobTemplateForm', 'CredentialList',
'LookUpInit', 'PlaybookRun', 'Wait', 'CreateDialog' , '$compile',
'LookUpInit', 'PlaybookRun', 'Wait', '$compile',
'$state',
function(
@ -17,7 +17,7 @@ export default
$stateParams, Rest, Alert, JobTemplateList, GenerateList, Prompt,
SearchInit, PaginateInit, ReturnToCaller, ClearScope, ProcessErrors,
GetBasePath, JobTemplateForm, CredentialList, LookUpInit, PlaybookRun,
Wait, CreateDialog, $compile, $state
Wait, $compile, $state
) {
ClearScope();
@ -94,142 +94,6 @@ export default
});
};
$scope.copyJobTemplate = function(id, name){
var element,
buttons = [{
"label": "Cancel",
"onClick": function() {
$(this).dialog('close');
},
"icon": "fa-times",
"class": "btn btn-default",
"id": "copy-close-button"
},{
"label": "Copy",
"onClick": function() {
copyAction();
// setTimeout(function(){
// scope.$apply(function(){
// if(mode==='survey-taker'){
// scope.$emit('SurveyTakerCompleted');
// } else{
// scope.saveSurvey();
// }
// });
// });
},
"icon": "fa-copy",
"class": "btn btn-primary",
"id": "job-copy-button"
}],
copyAction = function () {
// retrieve the copy of the job template object from the api, then overwrite the name and throw away the id
Wait('start');
var url = defaultUrl + id + '/';
Rest.setUrl(url);
Rest.get()
.success(function (data) {
data.name = $scope.new_copy_name;
delete data.id;
$scope.$emit('GoToCopy', data);
})
.error(function (data) {
Wait('stop');
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
});
};
CreateDialog({
id: 'copy-job-modal',
title: "Copy",
scope: $scope,
buttons: buttons,
width: 500,
height: 300,
minWidth: 200,
callback: 'CopyDialogReady'
});
$('#job_name').text(name);
$('#copy-job-modal').show();
if ($scope.removeCopyDialogReady) {
$scope.removeCopyDialogReady();
}
$scope.removeCopyDialogReady = $scope.$on('CopyDialogReady', function() {
//clear any old remaining text
$scope.new_copy_name = "" ;
$scope.copy_form.$setPristine();
$('#copy-job-modal').dialog('open');
$('#job-copy-button').attr('ng-disabled', "!copy_form.$valid");
element = angular.element(document.getElementById('job-copy-button'));
$compile(element)($scope);
});
if ($scope.removeGoToCopy) {
$scope.removeGoToCopy();
}
$scope.removeGoToCopy = $scope.$on('GoToCopy', function(e, data) {
var url = defaultUrl,
old_survey_url = (data.related.survey_spec) ? data.related.survey_spec : "" ;
Rest.setUrl(url);
Rest.post(data)
.success(function (data) {
if(data.survey_enabled===true){
$scope.$emit("CopySurvey", data, old_survey_url);
}
else {
$('#copy-job-modal').dialog('close');
Wait('stop');
$location.path($location.path() + '/' + data.id);
}
})
.error(function (data) {
Wait('stop');
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. DELETE returned status: ' + status });
});
});
if ($scope.removeCopySurvey) {
$scope.removeCopySurvey();
}
$scope.removeCopySurvey = $scope.$on('CopySurvey', function(e, new_data, old_url) {
// var url = data.related.survey_spec;
Rest.setUrl(old_url);
Rest.get()
.success(function (survey_data) {
Rest.setUrl(new_data.related.survey_spec);
Rest.post(survey_data)
.success(function () {
$('#copy-job-modal').dialog('close');
Wait('stop');
$location.path($location.path() + '/' + new_data.id);
})
.error(function (data) {
Wait('stop');
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + new_data.related.survey_spec + ' failed. DELETE returned status: ' + status });
});
})
.error(function (data) {
Wait('stop');
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + old_url + ' failed. DELETE returned status: ' + status });
});
});
};
$scope.submitJob = function (id) {
PlaybookRun({ scope: $scope, id: id });
};

View File

@ -4,11 +4,4 @@
<div ng-include="'/static/partials/schedule_dialog.html'"></div>
<div ng-include="'/static/partials/logviewer.html'"></div>
<div id="copy-job-modal" style="display:none">
<form name="copy_form" id="copy_form">
What would you like to name the copy of job template <b><span id=job_name></span></b>?<br>
<input id="new_copy_name" name="new_copy_name" ng-model ="new_copy_name" ng-required="true" class="form-control ng-pristine ng-invalid-required ng-invalid" style="margin-top:10px;">
<div class="error survey_error ng-hide" ng-show="copy_form.new_copy_name.$dirty && copy_form.new_copy_name.$error.required">Please enter a name for this job template copy.</div></input>
</form>
</div>
</div>

View File

@ -10,7 +10,10 @@ import surveyMaker from './survey-maker/main';
import jobTemplatesList from './list/main';
import jobTemplatesAdd from './add/main';
import jobTemplatesEdit from './edit/main';
import jobTemplatesCopy from './copy/main';
export default
angular.module('jobTemplates', [surveyMaker.name, jobTemplatesList.name, jobTemplatesAdd.name, jobTemplatesEdit.name])
angular.module('jobTemplates',
[surveyMaker.name, jobTemplatesList.name, jobTemplatesAdd.name,
jobTemplatesEdit.name, jobTemplatesCopy.name])
.service('deleteJobTemplate', deleteJobTemplate);

View File

@ -71,7 +71,7 @@ export default
},
copy: {
label: 'Copy',
ngClick: "copyJobTemplate(job_template.id, job_template.name)",
'ui-sref': 'jobTemplates.copy({id: job_template.id})',
"class": 'btn-danger btn-xs',
awToolTip: 'Copy template',
dataPlacement: 'top',

View File

@ -58,8 +58,7 @@ export default
},
copy: {
label: 'Copy',
ngClick: "copyJobTemplate(job_template.id, job_template.name)",
"class": 'btn-danger btn-xs',
'ui-sref': 'jobTemplates.copy({id: job_template.id})', "class": 'btn-danger btn-xs',
awToolTip: 'Copy template',
dataPlacement: 'top',
ngHide: 'job_template.summary_fields.can_copy===false'

View File

@ -1,26 +1,44 @@
import '../support/node';
import jobTemplates from 'job-templates/main';
import {describeModule} from '../support/describe-module';
import jobTemplatesModule from 'job-templates/main';
import RestStub from '../support/rest-stub';
describeModule(jobTemplates.name)
.testService('deleteJobTemplate', function(test, restStub) {
//import RestStub from '../support/rest-stub';
var service;
describe('jobTemplates.service', function(){
var $httpBackend, jobTemplates, service, Rest, $q, $stateExtender;
test.withService(function(_service) {
service = _service;
});
before('instantiate RestStub', function(){
Rest = new RestStub();
});
it('deletes the job template', function() {
var result = {};
beforeEach('instantiate the jobTemplates module', function(){
angular.mock.module(jobTemplatesModule.name);
});
var actual = service();
beforeEach('mock dependencies', angular.mock.module(['$provide', function(_$provide_){
var $provide = _$provide_;
$provide.value('GetBasePath', angular.noop);
$provide.value('$stateExtender', {addState: angular.noop});
$provide.value('Rest', Rest);
}]));
restStub.succeedOn('destroy', result);
restStub.flush();
beforeEach('put $q into the scope', window.inject(['$q', function($q){
Rest.$q = $q;
}]))
expect(actual).to.eventually.equal(result);
beforeEach('inject real dependencies', inject(function($injector){
$httpBackend = $injector.get('$httpBackend');
service = $injector.get('deleteJobTemplate');
}));
describe('deleteJobTemplate', function(){
it('deletes a job template', function() {
var result = {};
var actual = service.deleteJobTemplate(1);
$httpBackend.when('DELETE', 'url').respond(200)
expect(actual).to.eventually.equal(result);
});
});
});

View File

@ -1,17 +1,12 @@
Alias /munin /var/cache/munin/www
<Directory /var/cache/munin/www>
Alias /munin /var/www/html/munin/
<Directory /var/www/html/munin/>
Order Allow,Deny
Allow from all
Options FollowSymLinks
AuthUserFile /var/lib/awx/.munin_htpasswd
AuthName "Munin"
AuthType Basic
require valid-user
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault M310
</IfModule>
</Directory>
ScriptAlias /munin-cgi/munin-cgi-graph /var/www/cgi-bin/munin-cgi-graph