From 89bd66f1f6bd9f4366c3c9ffa9ff5b02927a2de5 Mon Sep 17 00:00:00 2001 From: Leigh Date: Fri, 13 May 2016 10:43:07 -0400 Subject: [PATCH] Schedules - audit, bugs, allow HH:MM:SS end time granularity (#1857) * cleanup unused code artifacts #1851 * fix bug found during audit where empty extra_data was being POSTd as null, #1593 * cleanup schedule helper #1851, update angular-scheduler dependency, automatically set end dt to start dt + 1 day in schedule > add, add hh:mm:ss end date grandularity, resolves #1758, resolves #1856' * clean up dead schedule dependencies #1851 * fix extra vars in schedule > edit view, fix munge of nested yaml, resolves #1547 squash * update angular-scheduler to v0.0.19 * re-add ng-toast dependency to bower manifest --- .../client/lib/angular-scheduler/.bower.json | 12 +- awx/ui/client/lib/angular-scheduler/LICENSE | 2 +- .../angular-scheduler/app/partials/main.html | 2 +- .../client/lib/angular-scheduler/bower.json | 4 +- .../lib/angular-scheduler-detail.html | 2 +- .../lib/angular-scheduler.css | 2 +- .../lib/angular-scheduler.html | 84 +++--------- .../lib/angular-scheduler.js | 122 +++++++----------- .../client/lib/angular-scheduler/package.json | 2 +- awx/ui/client/lib/angular/.bower.json | 4 +- awx/ui/client/lib/select2/.bower.json | 2 +- awx/ui/client/src/controllers/Schedules.js | 4 +- awx/ui/client/src/helpers/Schedules.js | 90 ++----------- .../src/job-detail/job-detail.partial.html | 2 - .../list/job-templates-list.partial.html | 1 - .../scheduler/schedulerForm.partial.html | 25 ++-- awx/ui/client/src/partials/home.html | 5 +- awx/ui/client/src/partials/jobs.html | 2 - awx/ui/client/src/partials/projects.html | 1 - .../client/src/partials/schedule_detail.html | 2 - .../client/src/partials/schedule_dialog.html | 13 -- .../src/scheduler/scheduler.controller.js | 8 +- .../src/scheduler/scheduler.partial.html | 2 - .../src/scheduler/schedulerAdd.controller.js | 38 +++--- .../src/scheduler/schedulerEdit.controller.js | 27 ---- .../src/scheduler/schedulerForm.partial.html | 98 ++++++++++---- 26 files changed, 212 insertions(+), 344 deletions(-) delete mode 100644 awx/ui/client/src/partials/schedule_dialog.html diff --git a/awx/ui/client/lib/angular-scheduler/.bower.json b/awx/ui/client/lib/angular-scheduler/.bower.json index d376fdee76..333c3dda7a 100644 --- a/awx/ui/client/lib/angular-scheduler/.bower.json +++ b/awx/ui/client/lib/angular-scheduler/.bower.json @@ -1,6 +1,6 @@ { "name": "angular-scheduler", - "version": "0.0.14", + "version": "0.0.19", "authors": [ "Chris Houseknecht " ], @@ -36,13 +36,13 @@ "rrule", "calendar" ], - "_release": "0.0.14", + "_release": "0.0.19", "_resolution": { "type": "version", - "tag": "v0.0.14", - "commit": "618c50fabaf774f91db3ed3fb086ac9f45c22136" + "tag": "v0.0.19", + "commit": "952fb090bae47fe748bbb502d7409915c68bb572" }, - "_source": "git://github.com/chouseknecht/angular-scheduler.git", - "_target": "~0.0.14", + "_source": "https://github.com/chouseknecht/angular-scheduler.git", + "_target": "~0.0.19", "_originalSource": "angular-scheduler" } \ No newline at end of file diff --git a/awx/ui/client/lib/angular-scheduler/LICENSE b/awx/ui/client/lib/angular-scheduler/LICENSE index a2cb8e33fc..8e6c0e1a34 100644 --- a/awx/ui/client/lib/angular-scheduler/LICENSE +++ b/awx/ui/client/lib/angular-scheduler/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015 Ansible, Inc. +Copyright (c) 2014 Ansible, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/awx/ui/client/lib/angular-scheduler/app/partials/main.html b/awx/ui/client/lib/angular-scheduler/app/partials/main.html index 578400203f..19b24a787a 100644 --- a/awx/ui/client/lib/angular-scheduler/app/partials/main.html +++ b/awx/ui/client/lib/angular-scheduler/app/partials/main.html @@ -1,7 +1,7 @@
- +
- +
@@ -131,7 +89,7 @@ Caution: Setting both numerical variables to "0" will delete all facts.
-
Please provide a value between 1 and 999.
+
Provide a value between 1 and 999
@@ -146,12 +104,12 @@ Caution: Setting both numerical variables to "0" will delete all facts.
-
The day must be between 1 and 31.
+
Must be between 1 and 31
- +
@@ -183,12 +141,12 @@ Caution: Setting both numerical variables to "0" will delete all facts.
-
The day must be between 1 and 31.
+
Must be between 1 and 31
- +
@@ -225,7 +183,7 @@ Caution: Setting both numerical variables to "0" will delete all facts.
-
Please select one or more days.
+
Select one or more days
@@ -242,9 +200,9 @@ Caution: Setting both numerical variables to "0" will delete all facts.
- +
-
Please provide a value between 1 and 999.
+
Provide a value between 1 and 999
@@ -257,7 +215,7 @@ Caution: Setting both numerical variables to "0" will delete all facts.
-
Please provide a valid date.
+
Provide a valid date
diff --git a/awx/ui/client/lib/angular-scheduler/lib/angular-scheduler.js b/awx/ui/client/lib/angular-scheduler/lib/angular-scheduler.js index cbf6ec80e0..8381bc7fff 100644 --- a/awx/ui/client/lib/angular-scheduler/lib/angular-scheduler.js +++ b/awx/ui/client/lib/angular-scheduler/lib/angular-scheduler.js @@ -1,13 +1,13 @@ /*************************************************************************** * angular-scheruler.js - * - * Copyright (c) 2015 Ansible, Inc. + * + * Copyright (c) 2014 Ansible, Inc. * * Maintainers: * * Chris Houseknecht * @chouseknecht - * chouse@ansible.com + * chouse@ansible.com * */ @@ -23,7 +23,7 @@ angular.module('underscore',[]) angular.module('AngularScheduler', ['underscore']) - + .constant('AngularScheduler.partials', '/lib/') .constant('AngularScheduler.useTimezone', false) .constant('AngularScheduler.showUTCField', false) @@ -59,7 +59,7 @@ angular.module('AngularScheduler', ['underscore']) scope.scheduleRepeatChange(); }; - scope.scheduleTimeChange = function() { + scope.scheduleTimeChange = function(callback) { if (scope.schedulerStartDt === "" || scope.schedulerStartDt === null || scope.schedulerStartDt === undefined) { scope.startDateError("Provide a valid start date and time"); scope.schedulerUTCTime = ''; @@ -91,6 +91,9 @@ angular.module('AngularScheduler', ['underscore']) ':' + scope.schedulerStartSecond + '.000Z'); } } + if (callback){ + callback(); + } }; scope.resetError = function(variable) { @@ -108,7 +111,6 @@ angular.module('AngularScheduler', ['underscore']) scope.schedulerEnd = scope.endOptions[0]; } scope.sheduler_frequency_error = false; - scope.$emit("updateSchedulerSelects"); }; @@ -169,12 +171,8 @@ angular.module('AngularScheduler', ['underscore']) } }; - scope.schedulerEndChange = function() { - var dt = new Date(), // date adjusted to local zone automatically - month = $filter('schZeroPad')(dt.getMonth() + 1, 2), - day = $filter('schZeroPad')(dt.getDate(), 2); - scope.schedulerEndDt = month + '/' + day + '/' + dt.getFullYear(); - scope.schedulerOccurrenceCount = 1; + scope.schedulerEndChange = function(key, value) { + scope[key] = $filter('schZeroPad')(parseInt(value), 2); }; // When timezones become available, use to set defaults @@ -195,24 +193,24 @@ angular.module('AngularScheduler', ['underscore']) } return CreateObject(scope, requireFutureStartTime); - + }; }]) - + /** Return an AngularScheduler object we can use to get the RRule result from user input, check if - user input is valid, reset the form, etc. All the things we need to access and manipulate the - scheduler widget + user input is valid, reset the form, etc. All the things we need to access and manipulate the + scheduler widget */ .factory('CreateObject', ['AngularScheduler.useTimezone', '$filter', 'GetRule', 'Inject', 'InjectDetail', 'SetDefaults', '$timezones', 'SetRule', 'InRange', function(useTimezone, $filter, GetRule, Inject, InjectDetail, SetDefaults, $timezones, SetRule, InRange) { return function(scope, requireFutureST) { var fn = function() { - + this.scope = scope; this.useTimezone = useTimezone; this.requireFutureStartTime = requireFutureST; - + // Evaluate user intput and build options for passing to rrule this.getOptions = function() { var options = {}; @@ -225,7 +223,10 @@ angular.module('AngularScheduler', ['underscore']) if (this.scope.schedulerEnd.value === 'on') { options.endDate = scope.schedulerEndDt.replace(/(\d{2})\/(\d{2})\/(\d{4})/, function(match, p1, p2, p3) { return p3 + '-' + p1 + '-' + p2; - }) + 'T' + this.scope.schedulerUTCTime.replace(/\d{2}\/\d{2}\/\d{4} /,'').replace(/ UTC/,'') + 'Z'; + }) + 'T' + + $filter('schZeroPad')(this.scope.schedulerEndHour,2) + ':' + + $filter('schZeroPad')(this.scope.schedulerEndMinute,2) + ':' + + $filter('schZeroPad')(this.scope.schedulerEndSecond,2)+ 'Z'; } if (this.scope.schedulerFrequency.value === 'weekly') { options.weekDays = this.scope.weekDays; @@ -263,7 +264,7 @@ angular.module('AngularScheduler', ['underscore']) this.scope.scheduler_occurrenceCount_error = false; this.scope.scheduler_monthDay_error = false; this.scope.scheduler_yearlyMonthDay_error = false; - + if (this.scope.scheduler_form && this.scope.scheduler_form.schedulerEndDt) { this.scope.scheduler_form.schedulerEndDt.$setValidity('custom-error', true); this.scope.scheduler_form.schedulerEndDt.$setPristine(); @@ -299,10 +300,7 @@ angular.module('AngularScheduler', ['underscore']) } return false; }); - scope.rrule_nlp_description = rrule.toText().replace(/^RRule error.*$/,'Minutely or hourly frequency selected'); - if(rrule === "none"){ - scope.rrule_nlp_description = 'Natural language description not available'; - } + scope.rrule_nlp_description = rrule.toText().replace(/^RRule error.*$/,'Natural language description not available'); scope.rrule = rrule.toString(); } }; @@ -321,7 +319,7 @@ angular.module('AngularScheduler', ['underscore']) this.scope.scheduler_occurrenceCount_error = true; validity = false; } - + if (this.scope.schedulerFrequency.value === 'weekly' && this.scope.weekDays.length === 0) { this.scope.scheduler_weekDays_error = true; validity = false; @@ -346,11 +344,6 @@ angular.module('AngularScheduler', ['underscore']) $('#schedulerName').addClass('ng-dirty'); validity = false; } - if(this.scope.cleanupJob===true && !this.scope.scheduler_form.schedulerPurgeDays.$valid){ - this.scope.scheduler_form.schedulerPurgeDays.$dirty = true; - $('#schedulerPurgeDays').addClass('ng-dirty'); - validity = false; - } if (this.scope.schedulerEnd.value === 'on') { if (!/^\d{2}\/\d{2}\/\d{4}$/.test(this.scope.schedulerEndDt)) { this.scope.scheduler_form.schedulerEndDt.$pristine = false; @@ -374,7 +367,7 @@ angular.module('AngularScheduler', ['underscore']) $filter('schZeroPad')(now.getHours(),2) + ':' + $filter('schZeroPad')(now.getMinutes(),2) + ':' + $filter('schZeroPad')(now.getSeconds(),2) + '.000Z'; - adjNow = $timezones.toUTC(dateStr, this.scope.schedulerTimeZone.name); //Adjust to the selected TZ + adjNow = $timezones.toUTC(dateStr, this.scope.schedulerTimeZone.name); //Adjust to the selected TZ timeNow = adjNow.getTime(); } else { @@ -408,7 +401,6 @@ angular.module('AngularScheduler', ['underscore']) return validity; }; - var that = this; that.scope.$on("loadSchedulerDetailPane", function() { @@ -442,7 +434,7 @@ angular.module('AngularScheduler', ['underscore']) this.scope.schedulerName = name; }; - // Read in the HTML partial, compile and inject it into the DOM. + // Read in the HTML partial, compile and inject it into the DOM. // Pass in the target element's id attribute value or an angular.element() // object. this.inject = function(element, showButtons) { @@ -499,7 +491,7 @@ angular.module('AngularScheduler', ['underscore']) .factory('Inject', ['AngularScheduler.partials', '$compile', '$http', '$log', function(scheduler_partial, $compile, $http) { return function(params) { - + var scope = params.scope, target = params.target, buttons = params.buttons; @@ -529,7 +521,7 @@ angular.module('AngularScheduler', ['underscore']) .factory('InjectDetail', ['AngularScheduler.partials', '$compile', '$http', '$log', function(scheduler_partial, $compile, $http) { return function(params) { - + var scope = params.scope, target = params.target, showRRule = params.showRRule; @@ -559,11 +551,11 @@ angular.module('AngularScheduler', ['underscore']) .factory('GetRule', ['$log', function($log) { return function(params) { // Convert user inputs to an rrule. Returns rrule object using https://github.com/jkbr/rrule - // **list of 'valid values' found below in LoadLookupValues - + // **list of 'valid values' found below in LoadLookupValues + var startDate = params.startDate, // date object or string in yyyy-MM-ddTHH:mm:ss.sssZ format frequency = params.frequency, // string, optional, valid value from frequencyOptions - interval = params.interval, // integer, optional + interval = params.interval, // integer, optional occurrenceCount = params.occurrenceCount, //integer, optional endDate = params.endDate, // date object or string in yyyy-MM-dd format, optional // ignored if occurrenceCount provided @@ -572,7 +564,7 @@ angular.module('AngularScheduler', ['underscore']) weekDays = params.weekDays, // integer, optional, valid value from weekdays setOccurrence = params.setOccurrence, // integer, optional, valid value from occurrences options = {}, i; - + if (angular.isDate(startDate)) { options.dtstart = startDate; } @@ -588,7 +580,7 @@ angular.module('AngularScheduler', ['underscore']) if (frequency && frequency !== 'none') { options.freq = RRule[frequency.toUpperCase()]; options.interval = interval; - + if (weekDays && typeof weekDays === 'string') { options.byweekday = RRule[weekDays.toUpperCase()]; } @@ -644,7 +636,7 @@ angular.module('AngularScheduler', ['underscore']) return function(rule, scope) { var set, result = '', i, setStartDate = false; - + // Search the set of RRule keys for a particular key, returning its value function getValue(set, key) { var pair = _.find(set, function(x) { @@ -806,17 +798,13 @@ angular.module('AngularScheduler', ['underscore']) }); } scope.schedulerEnd = scope.endOptions[2]; - if (useTimezone) { - dt = new Date(value); // date adjusted to local zone automatically - month = $filter('schZeroPad')(dt.getMonth() + 1, 2); - day = $filter('schZeroPad')(dt.getDate(), 2); - scope.schedulerEndDt = month + '/' + day + '/' + dt.getFullYear(); - } - else { scope.schedulerEndDt = value.replace(/T.*$/,'').replace(/(\d{4})-(\d{2})-(\d{2})/, function(match, p1, p2, p3) { return p2 + '/' + p3 + '/' + p1; }); - } + timeString = value.replace(/^.*T/,''); + scope.schedulerEndHour = $filter('schZeroPad')(timeString.substr(0,2),2); + scope.schedulerEndMinute = $filter('schZeroPad')(timeString.substr(3,2),2); + scope.schedulerEndSecond = $filter('schZeroPad')(timeString.substr(6,2),2); } if (key === 'BYMONTH') { @@ -849,7 +837,7 @@ angular.module('AngularScheduler', ['underscore']) } } } - + function isValid() { // Check what was put into scope vars, and see if anything is // missing or not quite right. @@ -896,7 +884,6 @@ angular.module('AngularScheduler', ['underscore']) defaultDay = $filter('schZeroPad')(defaultDate.getDate(), 2), defaultDateStr = defaultMonth + '/' + defaultDay + '/' + defaultDate.getFullYear(); scope.schedulerName = ''; - scope.schedulerPurgeDays = 30; scope.weekDays = []; scope.schedulerStartHour = '00'; scope.schedulerStartMinute = '00'; @@ -936,7 +923,7 @@ angular.module('AngularScheduler', ['underscore']) .factory('LoadLookupValues', [ function() { return function(scope) { - + scope.frequencyOptions = [ { name: 'None (run once)', value: 'none', intervalLabel: '' }, { name: 'Minute', value: 'minutely', intervalLabel: 'minutes' }, @@ -991,16 +978,12 @@ angular.module('AngularScheduler', ['underscore']) }; }]) - + // $filter('schZeroPad')(n, pad) -- or -- {{ n | afZeroPad:pad }} .filter('schZeroPad', [ function() { return function (n, pad) { var str = (Math.pow(10,pad) + '').replace(/^1/,'') + (n + '').trim(); - if (str.substr(str.length - pad) === 'll') { - return undefined; - } else { - return str.substr(str.length - pad); - } + return str.substr(str.length - pad); }; }]) @@ -1051,15 +1034,11 @@ angular.module('AngularScheduler', ['underscore']) }; }]) - // Custom directives + // Custom directives .directive('schSpinner', ['$filter', function($filter) { return { require: 'ngModel', link: function(scope, element, attr, ctrl) { - if (element.attr("ng-model").indexOf("$parent") > -1) { - scope = scope.$parent; - attr.ngModel = attr.ngModel.split("$parent.")[1]; - } // Add jquerui spinner to 'spinner' type input var form = attr.schSpinner, zeroPad = attr.zeroPad, @@ -1084,25 +1063,16 @@ angular.module('AngularScheduler', ['underscore']) }); }, 100); }, - icons: { - down: "Form-numberInputButton fa fa-angle-down", - up: "Form-numberInputButton fa fa-angle-up" - }, spin: function() { - if (scope[form][attr.ngModel]) { - scope[form][attr.ngModel].$setDirty(); - scope[form][attr.ngModel].$dirty = true; - scope[form][attr.ngModel].$pristine = false; - } + scope[form].$setDirty(); + ctrl.$dirty = true; + ctrl.$pristine = false; if (!scope.$$phase) { scope.$digest(); } } }); - - $('.ui-icon').text(''); - $(".ui-icon").removeClass('ui-icon ui-icon-triangle-1-n ui-icon-triangle-1-s'); - + $(element).on("click", function () { $(element).select(); }); diff --git a/awx/ui/client/lib/angular-scheduler/package.json b/awx/ui/client/lib/angular-scheduler/package.json index ed29e7c7f2..9e85396750 100644 --- a/awx/ui/client/lib/angular-scheduler/package.json +++ b/awx/ui/client/lib/angular-scheduler/package.json @@ -1,6 +1,6 @@ { "name": "angular-scheduler", - "version": "0.0.14", + "version": "0.0.19", "devDependencies": { "grunt": "~0.4.2", "grunt-contrib-jshint": "~0.6.3", diff --git a/awx/ui/client/lib/angular/.bower.json b/awx/ui/client/lib/angular/.bower.json index f8aad887e8..e15139ef5d 100644 --- a/awx/ui/client/lib/angular/.bower.json +++ b/awx/ui/client/lib/angular/.bower.json @@ -11,7 +11,7 @@ "tag": "v1.4.7", "commit": "6bdc6b4855b416bf029105324080ca7d6aca0e9f" }, - "_source": "git://github.com/angular/bower-angular.git", - "_target": "~1.4.0", + "_source": "https://github.com/angular/bower-angular.git", + "_target": "1.4.7", "_originalSource": "angular" } \ No newline at end of file diff --git a/awx/ui/client/lib/select2/.bower.json b/awx/ui/client/lib/select2/.bower.json index 16cde2eb15..9fb07f92b4 100644 --- a/awx/ui/client/lib/select2/.bower.json +++ b/awx/ui/client/lib/select2/.bower.json @@ -18,6 +18,6 @@ "commit": "622a619d25358b86a93c2335f88e1884acc9ccb8" }, "_source": "https://github.com/ivaynberg/select2.git", - "_target": "~4.0.2", + "_target": "~4.0.0", "_originalSource": "select2" } \ No newline at end of file diff --git a/awx/ui/client/src/controllers/Schedules.js b/awx/ui/client/src/controllers/Schedules.js index 79cf609d7c..88f4129122 100644 --- a/awx/ui/client/src/controllers/Schedules.js +++ b/awx/ui/client/src/controllers/Schedules.js @@ -12,7 +12,7 @@ export function ScheduleEditController($scope, $compile, $location, $stateParams, SchedulesList, Rest, ProcessErrors, ReturnToCaller, ClearScope, -GetBasePath, Wait, Find, LoadDialogPartial, LoadSchedulesScope, GetChoices) { +GetBasePath, Wait, Find, LoadSchedulesScope, GetChoices) { ClearScope(); @@ -82,4 +82,4 @@ GetBasePath, Wait, Find, LoadDialogPartial, LoadSchedulesScope, GetChoices) { } ScheduleEditController.$inject = [ '$scope', '$compile', '$location', '$stateParams', 'SchedulesList', 'Rest', 'ProcessErrors', 'ReturnToCaller', 'ClearScope', - 'GetBasePath', 'Wait', 'Find', 'LoadDialogPartial', 'LoadSchedulesScope', 'GetChoices']; + 'GetBasePath', 'Wait', 'Find', 'LoadSchedulesScope', 'GetChoices']; diff --git a/awx/ui/client/src/helpers/Schedules.js b/awx/ui/client/src/helpers/Schedules.js index 9db1420ef5..ae0c8649c0 100644 --- a/awx/ui/client/src/helpers/Schedules.js +++ b/awx/ui/client/src/helpers/Schedules.js @@ -20,41 +20,9 @@ export default angular.module('SchedulesHelper', [ 'Utilities', 'RestServices', 'SchedulesHelper', 'SearchHelper', 'PaginationHelpers', listGenerator.name, 'ModalDialog', 'GeneratorHelpers']) - .factory('ShowSchedulerModal', ['$rootScope', function($rootScope) { - return function(params) { - // Set modal dimensions based on viewport width - - var buttons, - scope = params.scope; - - buttons = [{ - "label": "Cancel", - "onClick": function() { - $(this).dialog('close'); - }, - "icon": "fa-times", - "class": "btn btn-default", - "id": "schedule-close-button" - },{ - "label": "Save", - "onClick": function() { - setTimeout(function(){ - scope.$apply(function(){ - scope.saveSchedule(); - }); - }); - }, - "icon": "fa-check", - "class": "btn btn-primary", - "id": "schedule-save-button" - }]; - $rootScope.$broadcast("ScheduleFormCreated", scope); - }; - }]) - - .factory('EditSchedule', ['SchedulerInit', 'ShowSchedulerModal', 'Wait', - 'Rest', 'ProcessErrors', 'GetBasePath', 'SchedulePost', '$state', - function(SchedulerInit, ShowSchedulerModal, Wait, Rest, ProcessErrors, + .factory('EditSchedule', ['SchedulerInit', '$rootScope', 'Wait', 'Rest', + 'ProcessErrors', 'GetBasePath', 'SchedulePost', '$state', + function(SchedulerInit, $rootScope, Wait, Rest, ProcessErrors, GetBasePath, SchedulePost, $state) { return function(params) { var scope = params.scope, @@ -155,7 +123,7 @@ export default scope.$on("htmlDetailReady", function() { scheduler.setRRule(schedule.rrule); scheduler.setName(schedule.name); - ShowSchedulerModal({ scope: scope, callback: 'DialogReady', title: 'Edit Schedule' }); + $rootScope.$broadcast("ScheduleFormCreated", scope); }); scope.showRRuleDetail = false; }); @@ -172,7 +140,7 @@ export default $state.go("^"); }); scope.saveSchedule = function() { - schedule.extra_data = scope.serializedExtraVars; + schedule.extra_data = scope.extraVars; SchedulePost({ scope: scope, url: url, @@ -190,7 +158,8 @@ export default Rest.get() .success(function(data) { schedule = data; - scope.serializedExtraVars = schedule.extra_data; + scope.extraVars = data.extra_data === '' ? '---' : '---\n' + jsyaml.safeDump(data.extra_data); + if(schedule.extra_data.hasOwnProperty('granularity')){ scope.isFactCleanup = true; } @@ -207,10 +176,9 @@ export default }; }]) - .factory('AddSchedule', ['$location', '$stateParams', 'SchedulerInit', - 'ShowSchedulerModal', 'Wait', 'GetBasePath', 'Empty', - 'SchedulePost', '$state', 'Rest', 'ProcessErrors', - function($location, $stateParams, SchedulerInit, ShowSchedulerModal, + .factory('AddSchedule', ['$location', '$rootScope', '$stateParams', + 'SchedulerInit', 'Wait', 'GetBasePath', 'Empty', 'SchedulePost', '$state', 'Rest', 'ProcessErrors', + function($location, $rootScope, $stateParams, SchedulerInit, Wait, GetBasePath, Empty, SchedulePost, $state, Rest, ProcessErrors) { return function(params) { @@ -286,11 +254,12 @@ export default Wait('start'); $('#form-container').empty(); scheduler = SchedulerInit({ scope: scope, requireFutureStartTime: false }); + scope.processSchedulerEndDt(); scheduler.inject('form-container', false); scheduler.injectDetail('occurrences', false); scheduler.clear(); scope.$on("htmlDetailReady", function() { - ShowSchedulerModal({ scope: scope, callback: 'DialogReady', title: 'Add Schedule' }); + $rootScope.$broadcast("ScheduleFormCreated", scope); }); scope.showRRuleDetail = false; @@ -356,12 +325,9 @@ export default }; schedule.extra_data = JSON.stringify(extra_vars); } - else if (scope.serializedExtraVars){ - schedule.extra_data = scope.serializedExtraVars; - } else if(scope.extraVars){ - schedule.extra_data = ToJSON(scope.parseType, - scope.extraVars, false); + schedule.extra_data = scope.parseType === 'yaml' ? + (scope.extraVars === '---' ? "" : jsyaml.safeLoad(scope.extraVars)) : scope.extraVars; } Rest.setUrl(url); if (mode === 'add') { @@ -401,34 +367,6 @@ export default }; }]) - /** - * Inject the scheduler_dialog.html wherever needed - */ - .factory('LoadDialogPartial', ['Rest', '$compile', 'ProcessErrors', function(Rest, $compile, ProcessErrors) { - return function(params) { - - var scope = params.scope, - element_id = params.element_id, - callback = params.callback, - url; - - // Add the schedule_dialog.html partial - url = '/static/partials/schedule_dialog.html'; - Rest.setUrl(url); - Rest.get() - .success(function(data) { - var e = angular.element(document.getElementById(element_id)); - e.append(data); - $compile(e)(scope); - scope.$emit(callback); - }) - .error(function(data, status) { - ProcessErrors(scope, data, status, null, { hdr: 'Error!', - msg: 'Call to ' + url + ' failed. GET returned: ' + status }); - }); - }; - }]) - /** * Flip a schedule's enable flag * diff --git a/awx/ui/client/src/job-detail/job-detail.partial.html b/awx/ui/client/src/job-detail/job-detail.partial.html index 311d484b0d..055496f07b 100644 --- a/awx/ui/client/src/job-detail/job-detail.partial.html +++ b/awx/ui/client/src/job-detail/job-detail.partial.html @@ -420,6 +420,4 @@ -
- 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 5b805e8690..5477993a8f 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 @@ -1,7 +1,6 @@
-
diff --git a/awx/ui/client/src/management-jobs/scheduler/schedulerForm.partial.html b/awx/ui/client/src/management-jobs/scheduler/schedulerForm.partial.html index 4031f1b6e4..1ec9de5056 100644 --- a/awx/ui/client/src/management-jobs/scheduler/schedulerForm.partial.html +++ b/awx/ui/client/src/management-jobs/scheduler/schedulerForm.partial.html @@ -13,7 +13,7 @@
@@ -25,13 +25,13 @@ type="text" class="form-control input-sm Form-textInput" - ng-class="{'RepeatFrequencyOptions-nameBorderErrorFix': scheduler_form_new.$dirty && scheduler_form_new.schedulerName.$error.required}" + ng-class="{'RepeatFrequencyOptions-nameBorderErrorFix': scheduler_form.$dirty && scheduler_form.schedulerName.$error.required}" name="schedulerName" id="schedulerName" ng-model="schedulerName" required placeholder="Schedule name">
+ ng-show="scheduler_form.$dirty && scheduler_form.schedulerName.$error.required"> A schedule name is required.
@@ -85,7 +85,7 @@
+ form-control input-sm">
@@ -475,7 +474,7 @@
+ ng-show="!schedulerIsValid && scheduler_form.$dirty">

The scheduler options are invalid or incomplete.

diff --git a/awx/ui/client/src/partials/home.html b/awx/ui/client/src/partials/home.html index 491a728e64..849917cac6 100644 --- a/awx/ui/client/src/partials/home.html +++ b/awx/ui/client/src/partials/home.html @@ -20,7 +20,6 @@
- - +--> diff --git a/awx/ui/client/src/partials/jobs.html b/awx/ui/client/src/partials/jobs.html index c37b3f8495..8b0b5afe89 100644 --- a/awx/ui/client/src/partials/jobs.html +++ b/awx/ui/client/src/partials/jobs.html @@ -43,7 +43,5 @@
-
-
diff --git a/awx/ui/client/src/partials/projects.html b/awx/ui/client/src/partials/projects.html index a841c78152..7c40a338ac 100644 --- a/awx/ui/client/src/partials/projects.html +++ b/awx/ui/client/src/partials/projects.html @@ -2,5 +2,4 @@
-
diff --git a/awx/ui/client/src/partials/schedule_detail.html b/awx/ui/client/src/partials/schedule_detail.html index f388303303..61f13b2c58 100644 --- a/awx/ui/client/src/partials/schedule_detail.html +++ b/awx/ui/client/src/partials/schedule_detail.html @@ -1,5 +1,3 @@
- -
diff --git a/awx/ui/client/src/partials/schedule_dialog.html b/awx/ui/client/src/partials/schedule_dialog.html deleted file mode 100644 index bdf72a5dd5..0000000000 --- a/awx/ui/client/src/partials/schedule_dialog.html +++ /dev/null @@ -1,13 +0,0 @@ -
- -
-
-
-
-
-
-
-
\ No newline at end of file diff --git a/awx/ui/client/src/scheduler/scheduler.controller.js b/awx/ui/client/src/scheduler/scheduler.controller.js index 8ba8122c14..f50376cef0 100644 --- a/awx/ui/client/src/scheduler/scheduler.controller.js +++ b/awx/ui/client/src/scheduler/scheduler.controller.js @@ -14,15 +14,19 @@ export default [ '$scope', '$compile', '$location', '$stateParams', 'SchedulesList', 'Rest', 'ProcessErrors', 'ReturnToCaller', 'ClearScope', 'GetBasePath', 'Wait', - 'Find', 'LoadDialogPartial', 'LoadSchedulesScope', 'GetChoices', '$q', + 'Find', 'LoadSchedulesScope', 'GetChoices', '$q', function ($scope, $compile, $location, $stateParams, SchedulesList, Rest, ProcessErrors, ReturnToCaller, ClearScope, - GetBasePath, Wait, Find, LoadDialogPartial, LoadSchedulesScope, GetChoices, + GetBasePath, Wait, Find, LoadSchedulesScope, GetChoices, $q) { ClearScope(); + $scope.schedulerStartDT = 'test'; + var base, id, url,parentObject, title; + $scope.schedulerStartDT = 'test'; + base = $location.path().replace(/^\//, '').split('/')[0]; if (base === 'management_jobs') { diff --git a/awx/ui/client/src/scheduler/scheduler.partial.html b/awx/ui/client/src/scheduler/scheduler.partial.html index b4b87d1f92..cf51d106ce 100644 --- a/awx/ui/client/src/scheduler/scheduler.partial.html +++ b/awx/ui/client/src/scheduler/scheduler.partial.html @@ -2,5 +2,3 @@
- -
diff --git a/awx/ui/client/src/scheduler/schedulerAdd.controller.js b/awx/ui/client/src/scheduler/schedulerAdd.controller.js index c88f7dbc5e..cc9485c0aa 100644 --- a/awx/ui/client/src/scheduler/schedulerAdd.controller.js +++ b/awx/ui/client/src/scheduler/schedulerAdd.controller.js @@ -4,12 +4,27 @@ * All Rights Reserved *************************************************/ -export default ['$compile', '$state', '$stateParams', 'AddSchedule', 'Wait', +export default ['$compile', '$filter', '$state', '$stateParams', 'AddSchedule', 'Wait', '$scope', '$rootScope', 'CreateSelect2', 'ParseTypeChange', 'GetBasePath', 'Rest', 'ParamPass', - function($compile, $state, $stateParams, AddSchedule, Wait, $scope, + function($compile, $filter, $state, $stateParams, AddSchedule, Wait, $scope, $rootScope, CreateSelect2, ParseTypeChange, GetBasePath, Rest, ParamPass) { + $scope.processSchedulerEndDt = function(){ + // set the schedulerEndDt to be equal to schedulerStartDt + 1 day @ midnight + var dt = new Date($scope.schedulerUTCTime); + // increment date by 1 day + dt.setDate(dt.getDate() + 1); + var month = $filter('schZeroPad')(dt.getMonth() + 1, 2), + day = $filter('schZeroPad')(dt.getDate(), 2); + $scope.$parent.schedulerEndDt = month + '/' + day + '/' + dt.getFullYear(); + }; + + // initial end @ midnight values + $scope.schedulerEndHour = "00"; + $scope.schedulerEndMinute = "00"; + $scope.schedulerEndSecond = "00"; + $scope.$on("ScheduleFormCreated", function(e, scope) { $scope.hideForm = false; $scope = angular.extend($scope, scope); @@ -37,7 +52,10 @@ export default ['$compile', '$state', '$stateParams', 'AddSchedule', 'Wait', "yearlyOtherMonth", "schedulerEnd", "schedulerOccurrenceCount", - "schedulerEndDt" + "schedulerEndDt", + "schedulerEndHour", + "schedulerEndMinute", + "schedularEndSecond" ], function() { $scope.$emit("formUpdated"); }, true); @@ -73,20 +91,6 @@ export default ['$compile', '$state', '$stateParams', 'AddSchedule', 'Wait', field_id: 'SchedulerForm-extraVars' }); }); - $scope.$watch('extraVars', function(){ - if ($scope.parseType === 'yaml'){ - try{ - $scope.serializedExtraVars = jsyaml.safeLoad($scope.extraVars); - } - catch(err){ return; } - } - else if ($scope.parseType === 'json'){ - try{ - $scope.serializedExtraVars = JSON.parse($scope.extraVars); - } - catch(err){ return; } - } - }); } else if ($state.current.name === 'projectSchedules.add'){ $scope.extraVars = '---'; diff --git a/awx/ui/client/src/scheduler/schedulerEdit.controller.js b/awx/ui/client/src/scheduler/schedulerEdit.controller.js index fae21615c5..4846465091 100644 --- a/awx/ui/client/src/scheduler/schedulerEdit.controller.js +++ b/awx/ui/client/src/scheduler/schedulerEdit.controller.js @@ -51,18 +51,6 @@ export default ['$compile', '$state', '$stateParams', 'EditSchedule', 'Wait', '$ // extra_data field is not manifested in the UI when scheduling a Management Job if ($state.current.name !== ('managementJobSchedules.add' || 'managementJobSchedules.edit')){ $scope.$on('ScheduleFound', function(){ - if ($scope.parseType === 'yaml'){ - try{ - $scope.extraVars = '---\n' + jsyaml.safeDump($scope.serializedExtraVars); - } - catch(err){ return; } - } - else if ($scope.parseType === 'json'){ - try{ - $scope.extraVars = JSON.stringify($scope.serializedExtraVars, null, ' '); - } - catch(err){ return; } - } ParseTypeChange({ scope: $scope, variable: 'extraVars', @@ -70,21 +58,6 @@ export default ['$compile', '$state', '$stateParams', 'EditSchedule', 'Wait', '$ field_id: 'SchedulerForm-extraVars' }); }); - - $scope.$watch('extraVars', function(){ - if ($scope.parseType === 'yaml'){ - try{ - $scope.serializedExtraVars = jsyaml.safeLoad($scope.extraVars); - } - catch(err){ return; } - } - else if ($scope.parseType === 'json'){ - try{ - $scope.serializedExtraVars = JSON.parse($scope.extraVars); - } - catch(err){ return; } - } - }); } EditSchedule({ diff --git a/awx/ui/client/src/scheduler/schedulerForm.partial.html b/awx/ui/client/src/scheduler/schedulerForm.partial.html index c991a3d28d..ca948a04da 100644 --- a/awx/ui/client/src/scheduler/schedulerForm.partial.html +++ b/awx/ui/client/src/scheduler/schedulerForm.partial.html @@ -12,7 +12,7 @@
@@ -24,13 +24,13 @@ type="text" class="form-control input-sm Form-textInput" - ng-class="{'RepeatFrequencyOptions-nameBorderErrorFix': scheduler_form_new.$dirty && scheduler_form_new.schedulerName.$error.required}" + ng-class="{'RepeatFrequencyOptions-nameBorderErrorFix': scheduler_form.$dirty && scheduler_form.schedulerName.$error.required}" name="schedulerName" id="schedulerName" ng-model="schedulerName" required placeholder="Schedule name">
+ ng-show="scheduler_form.$dirty && scheduler_form.schedulerName.$error.required"> A schedule name is required.
@@ -52,7 +52,7 @@ sch-date-picker placeholder="mm/dd/yyyy" required - ng-change="scheduleTimeChange()" > + ng-change="scheduleTimeChange(processSchedulerEndDt)" >
@@ -187,7 +175,7 @@ + form-control input-sm">
@@ -474,7 +461,7 @@ +
+ +
+ + + : + + + + : + + +
+
+ The time must be in HH24:MM:SS format. +
+
@@ -529,7 +575,7 @@
+ ng-show="!schedulerIsValid && scheduler_form.$dirty">

The scheduler options are invalid or incomplete.