From e34aebcd931e773996c949dbf2fe1d8692f4e012 Mon Sep 17 00:00:00 2001 From: Leigh Johnson Date: Fri, 11 Mar 2016 14:41:05 -0500 Subject: [PATCH] refactor delete-job-template.service-test, integrate jobTemplate.copy, resolves #1105 & #1047, tracking #1176 --- .../add/job-templates-add.controller.js | 12 +- .../copy/job-templates-copy.controller.js | 32 ++++ .../copy/job-templates-copy.route.js | 13 ++ .../copy/job-templates-copy.service.js | 38 +++++ awx/ui/client/src/job-templates/copy/main.js | 17 +++ .../delete-job-template.service.js | 28 ++-- .../edit/job-templates-edit.controller.js | 29 ++-- .../edit/job-templates-edit.route.js | 3 + .../list/job-templates-list.controller.js | 140 +----------------- .../list/job-templates-list.partial.html | 7 - awx/ui/client/src/job-templates/main.js | 5 +- awx/ui/client/src/lists/JobTemplates.js | 2 +- awx/ui/client/src/lists/ScanJobs.js | 3 +- .../delete-job-template.service-test.js | 46 ++++-- config/awx-munin.conf | 11 +- 15 files changed, 174 insertions(+), 212 deletions(-) create mode 100644 awx/ui/client/src/job-templates/copy/job-templates-copy.controller.js create mode 100644 awx/ui/client/src/job-templates/copy/job-templates-copy.route.js create mode 100644 awx/ui/client/src/job-templates/copy/job-templates-copy.service.js create mode 100644 awx/ui/client/src/job-templates/copy/main.js diff --git a/awx/ui/client/src/job-templates/add/job-templates-add.controller.js b/awx/ui/client/src/job-templates/add/job-templates-add.controller.js index 1c7000d399..3c0a1c2812 100644 --- a/awx/ui/client/src/job-templates/add/job-templates-add.controller.js +++ b/awx/ui/client/src/job-templates/add/job-templates-add.controller.js @@ -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) { diff --git a/awx/ui/client/src/job-templates/copy/job-templates-copy.controller.js b/awx/ui/client/src/job-templates/copy/job-templates-copy.controller.js new file mode 100644 index 0000000000..808e5df8e1 --- /dev/null +++ b/awx/ui/client/src/job-templates/copy/job-templates-copy.controller.js @@ -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(); + } + ]; \ No newline at end of file diff --git a/awx/ui/client/src/job-templates/copy/job-templates-copy.route.js b/awx/ui/client/src/job-templates/copy/job-templates-copy.route.js new file mode 100644 index 0000000000..dd9d5ac5af --- /dev/null +++ b/awx/ui/client/src/job-templates/copy/job-templates-copy.route.js @@ -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' +} \ No newline at end of file diff --git a/awx/ui/client/src/job-templates/copy/job-templates-copy.service.js b/awx/ui/client/src/job-templates/copy/job-templates-copy.service.js new file mode 100644 index 0000000000..d43fbff3b0 --- /dev/null +++ b/awx/ui/client/src/job-templates/copy/job-templates-copy.service.js @@ -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}); + }); + } + } + } + ]; \ No newline at end of file diff --git a/awx/ui/client/src/job-templates/copy/main.js b/awx/ui/client/src/job-templates/copy/main.js new file mode 100644 index 0000000000..e0c8dc1c33 --- /dev/null +++ b/awx/ui/client/src/job-templates/copy/main.js @@ -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) + }]); diff --git a/awx/ui/client/src/job-templates/delete-job-template.service.js b/awx/ui/client/src/job-templates/delete-job-template.service.js index 64a6da8dac..b8e275e62a 100644 --- a/awx/ui/client/src/job-templates/delete-job-template.service.js +++ b/awx/ui/client/src/job-templates/delete-job-template.service.js @@ -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(); -} + } +}] \ No newline at end of file diff --git a/awx/ui/client/src/job-templates/edit/job-templates-edit.controller.js b/awx/ui/client/src/job-templates/edit/job-templates-edit.controller.js index 786358d52d..2996a7ef5c 100644 --- a/awx/ui/client/src/job-templates/edit/job-templates-edit.controller.js +++ b/awx/ui/client/src/job-templates/edit/job-templates-edit.controller.js @@ -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 diff --git a/awx/ui/client/src/job-templates/edit/job-templates-edit.route.js b/awx/ui/client/src/job-templates/edit/job-templates-edit.route.js index 2a4ab960e4..bff528f567 100644 --- a/awx/ui/client/src/job-templates/edit/job-templates-edit.route.js +++ b/awx/ui/client/src/job-templates/edit/job-templates-edit.route.js @@ -18,5 +18,8 @@ export default { features: ['FeaturesService', function(FeaturesService) { return FeaturesService.get(); }] + }, + params: { + copied: null } }; diff --git a/awx/ui/client/src/job-templates/list/job-templates-list.controller.js b/awx/ui/client/src/job-templates/list/job-templates-list.controller.js index c23258017f..3fe1fe3337 100644 --- a/awx/ui/client/src/job-templates/list/job-templates-list.controller.js +++ b/awx/ui/client/src/job-templates/list/job-templates-list.controller.js @@ -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 }); }; diff --git a/awx/ui/client/src/job-templates/list/job-templates-list.partial.html b/awx/ui/client/src/job-templates/list/job-templates-list.partial.html index 4fcfdeb6e9..5b805e8690 100644 --- a/awx/ui/client/src/job-templates/list/job-templates-list.partial.html +++ b/awx/ui/client/src/job-templates/list/job-templates-list.partial.html @@ -4,11 +4,4 @@
- diff --git a/awx/ui/client/src/job-templates/main.js b/awx/ui/client/src/job-templates/main.js index bba8038410..4bbf4c1125 100644 --- a/awx/ui/client/src/job-templates/main.js +++ b/awx/ui/client/src/job-templates/main.js @@ -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); diff --git a/awx/ui/client/src/lists/JobTemplates.js b/awx/ui/client/src/lists/JobTemplates.js index 55ed708df2..d7331d62d5 100644 --- a/awx/ui/client/src/lists/JobTemplates.js +++ b/awx/ui/client/src/lists/JobTemplates.js @@ -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', diff --git a/awx/ui/client/src/lists/ScanJobs.js b/awx/ui/client/src/lists/ScanJobs.js index 457a7d2d1e..93eaa9486c 100644 --- a/awx/ui/client/src/lists/ScanJobs.js +++ b/awx/ui/client/src/lists/ScanJobs.js @@ -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' diff --git a/awx/ui/client/tests/job-templates/delete-job-template.service-test.js b/awx/ui/client/tests/job-templates/delete-job-template.service-test.js index f301995c57..014d46651f 100644 --- a/awx/ui/client/tests/job-templates/delete-job-template.service-test.js +++ b/awx/ui/client/tests/job-templates/delete-job-template.service-test.js @@ -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); }); }); +}); diff --git a/config/awx-munin.conf b/config/awx-munin.conf index 90c479f77a..833a6f36bf 100644 --- a/config/awx-munin.conf +++ b/config/awx-munin.conf @@ -1,17 +1,12 @@ - -Alias /munin /var/cache/munin/www - +Alias /munin /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 - - ExpiresActive On - ExpiresDefault M310 - +ScriptAlias /munin-cgi/munin-cgi-graph /var/www/cgi-bin/munin-cgi-graph \ No newline at end of file