1
0
mirror of https://github.com/ansible/awx.git synced 2024-11-01 08:21:15 +03:00

updates to scheduler

- form and perspective next scheduler runs are in single list form view for projects and job templates
- submit/cancel/x at top of form project panel work
This commit is contained in:
John Mitchell 2016-02-02 10:56:10 -05:00
parent 1b357d5a3e
commit 068b32b1b4
11 changed files with 579 additions and 92 deletions

View File

@ -68,6 +68,7 @@ import './job-templates/main';
import './shared/features/main';
import './login/authenticationServices/pendo/ng-pendo';
import footer from './footer/main';
import scheduler from './scheduler/main';
/*#if DEBUG#*/
import {__deferLoadIfEnabled} from './debug';
@ -184,6 +185,7 @@ var tower = angular.module('Tower', [
'pendolytics',
'ui.router',
'ncy-angular-breadcrumb',
'scheduler'
])
.constant('AngularScheduler.partials', urlPrefix + 'lib/angular-scheduler/lib/')
@ -412,22 +414,6 @@ var tower = angular.module('Tower', [
}]
}
}).
state('jobTemplateSchedules', {
url: '/job_templates/:id/schedules',
templateUrl: urlPrefix + 'partials/schedule_detail.html',
controller: ScheduleEditController,
data: {
activityStream: true,
activityStreamTarget: 'schedule'
},
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}).
state('projects', {
url: '/projects',
templateUrl: urlPrefix + 'partials/projects.html',
@ -474,22 +460,6 @@ var tower = angular.module('Tower', [
}]
}
}).
state('projectSchedules', {
url: '/projects/:id/schedules',
templateUrl: urlPrefix + 'partials/schedule_detail.html',
controller: ScheduleEditController,
data: {
activityStream: true,
activityStreamTarget: 'schedule'
},
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
}).
state('projectOrganizations', {
url: '/projects/:project_id/organizations',
templateUrl: urlPrefix + 'partials/projects.html',

View File

@ -238,7 +238,7 @@ export function JobTemplatesList($scope, $rootScope, $location, $log,
};
$scope.scheduleJob = function (id) {
$state.transitionTo('jobTemplateSchedules', {id: id});
$state.go('jobTemplateSchedules', {id: id});
}
}

View File

@ -20,7 +20,7 @@ export default
angular.module('SchedulesHelper', [ 'Utilities', 'RestServices', 'SchedulesHelper', 'SearchHelper', 'PaginationHelpers', listGenerator.name, 'ModalDialog',
'GeneratorHelpers'])
.factory('ShowSchedulerModal', ['Wait', 'CreateDialog', function(Wait, CreateDialog) {
.factory('ShowSchedulerModal', ['$rootScope', 'Wait', 'CreateDialog', function($rootScope, Wait, CreateDialog) {
return function(params) {
// Set modal dimensions based on viewport width
@ -50,28 +50,7 @@ export default
"class": "btn btn-primary",
"id": "schedule-save-button"
}];
CreateDialog({
id: 'scheduler-modal-dialog',
scope: scope,
buttons: buttons,
title: title,
width: 700,
height: 725,
minWidth: 400,
onClose: function() {
$('#scheduler-modal-dialog #form-container').empty();
},
onOpen: function() {
Wait('stop');
$('#scheduler-tabs a:first').tab('show');
$('#schedulerName').focus();
$('#rrule_nlp_description').dblclick(function() {
setTimeout(function() { scope.$apply(function() { scope.showRRule = (scope.showRRule) ? false : true; }); }, 100);
});
},
callback: callback
});
$rootScope.$broadcast("ScheduleFormCreated", scope);
};
}])
@ -175,7 +154,11 @@ export default
}
schedule.rrule = schedule.rrule.replace(/ RRULE:/,';');
schedule.rrule = schedule.rrule.replace(/DTSTART:/,'DTSTART=');
ShowSchedulerModal({ scope: scope, callback: 'DialogReady', title: 'Edit Schedule' });
scope.$on("htmlDetailReady", function() {
scheduler.setRRule(schedule.rrule);
scheduler.setName(schedule.name);
ShowSchedulerModal({ scope: scope, callback: 'DialogReady', title: 'Edit Schedule' });
});
scope.showRRuleDetail = false;
});
@ -185,14 +168,12 @@ export default
}
scope.removeScheduleSaved = scope.$on('ScheduleSaved', function(e, data) {
Wait('stop');
$('#scheduler-modal-dialog').dialog('close');
if (callback) {
scope.$emit(callback, data);
}
});
scope.saveSchedule = function() {
$('#scheduler-tabs a:first').tab('show');
SchedulePost({
scope: scope,
url: url,
@ -203,16 +184,6 @@ export default
});
};
$('#scheduler-tabs li a').on('shown.bs.tab', function(e) {
if ($(e.target).text() === 'Details') {
if (!scheduler.isValid()) {
$('#scheduler-tabs a:first').tab('show');
}
}
});
Wait('start');
// Get the existing record
@ -290,21 +261,15 @@ export default
}
}
if (scope.removeDialogReady) {
scope.removeDialogReady();
}
scope.removeDialogReady = scope.$on('DialogReady', function() {
$('#scheduler-modal-dialog').dialog('open');
$('#schedulerName').focus();
});
Wait('start');
$('#form-container').empty();
scheduler = SchedulerInit({ scope: scope, requireFutureStartTime: false });
scheduler.inject('form-container', false);
scheduler.injectDetail('occurrences', false);
scheduler.clear();
ShowSchedulerModal({ scope: scope, callback: 'DialogReady', title: 'Add Schedule' });
scope.$on("htmlDetailReady", function() {
ShowSchedulerModal({ scope: scope, callback: 'DialogReady', title: 'Add Schedule' });
});
scope.showRRuleDetail = false;
if (scope.removeScheduleSaved) {
@ -312,14 +277,12 @@ export default
}
scope.removeScheduleSaved = scope.$on('ScheduleSaved', function(e, data) {
Wait('stop');
$('#scheduler-modal-dialog').dialog('close');
if (callback) {
scope.$emit(callback, data);
}
});
scope.saveSchedule = function() {
$('#scheduler-tabs a:first').tab('show');
SchedulePost({
scope: scope,
url: url,
@ -565,9 +528,9 @@ export default
}])
.factory('SchedulesControllerInit', ['$location', 'ToggleSchedule',
.factory('SchedulesControllerInit', ['$state', '$location', 'ToggleSchedule',
'DeleteSchedule', 'EditSchedule', 'AddSchedule',
function($location, ToggleSchedule, DeleteSchedule, EditSchedule,
function($state, $location, ToggleSchedule, DeleteSchedule, EditSchedule,
AddSchedule) {
return function(params) {
var scope = params.scope,
@ -598,18 +561,13 @@ export default
};
scope.editSchedule = function(id) {
EditSchedule({
scope: scope,
id: id,
callback: 'SchedulesRefresh'
});
var base = $state.current.name.split(".")[0];
$state.go(base + ".edit", {schedule_id: id});
};
scope.addSchedule = function() {
AddSchedule({
scope: scope,
callback: 'SchedulesRefresh'
});
var base = $state.current.name.split(".")[0];
$state.go(base + ".add", {passedScope: scope});
};
scope.refreshSchedules = function() {

View File

@ -50,6 +50,7 @@ export default
awToolTip: "Refresh the page",
ngClick: "refreshSchedules()",
actionClass: 'btn List-buttonDefault',
ngShow: "socketStatus == 'error'",
buttonContent: 'REFRESH'
},
add: {

View File

@ -0,0 +1,84 @@
/*************************************************
* Copyright (c) 2015 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
import controller from './scheduler.controller';
import addController from './schedulerAdd.controller';
import editController from './schedulerEdit.controller';
import {templateUrl} from '../shared/template-url/template-url.factory';
export default
angular.module('scheduler', [])
.controller('schedulerController', controller)
.controller('schedulerAddController', addController)
.controller('schedulerEditController', editController)
.run(['$stateExtender', function($stateExtender) {
$stateExtender.addState({
name: 'jobTemplateSchedules',
route: '/job_templates/:id/schedules',
templateUrl: templateUrl("scheduler/scheduler"),
controller: 'schedulerController',
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
});
$stateExtender.addState({
name: 'jobTemplateSchedules.add',
route: '/add',
templateUrl: templateUrl("scheduler/schedulerForm"),
controller: 'schedulerAddController',
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
});
$stateExtender.addState({
name: 'jobTemplateSchedules.edit',
route: '/:schedule_id',
templateUrl: templateUrl("scheduler/schedulerForm"),
controller: 'schedulerEditController',
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
});
$stateExtender.addState({
name: 'projectSchedules',
route: '/projects/:id/schedules',
templateUrl: templateUrl("scheduler/scheduler"),
controller: 'schedulerController',
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
});
$stateExtender.addState({
name: 'projectSchedules.add',
route: '/add',
templateUrl: templateUrl("scheduler/schedulerForm"),
controller: 'schedulerAddController',
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
});
$stateExtender.addState({
name: 'projectSchedules.edit',
route: '/:schedule_id',
templateUrl: templateUrl("scheduler/schedulerForm"),
controller: 'schedulerEditController',
resolve: {
features: ['FeaturesService', function(FeaturesService) {
return FeaturesService.get();
}]
}
});
}]);

View File

@ -0,0 +1,95 @@
/*************************************************
* Copyright (c) 2015 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
/**
* @ngdoc function
* @name controllers.function:Schedules
* @description This controller's for schedules
*/
export default [
'$scope', '$compile', '$location', '$stateParams', 'SchedulesList', 'Rest', 'ProcessErrors', 'ReturnToCaller', 'ClearScope',
'GetBasePath', 'Wait', 'Find', 'LoadDialogPartial', 'LoadSchedulesScope', 'GetChoices', 'Stream',
function ($scope, $compile, $location, $stateParams,
SchedulesList, Rest, ProcessErrors, ReturnToCaller, ClearScope,
GetBasePath, Wait, Find, LoadDialogPartial, LoadSchedulesScope, GetChoices,
Stream) {
ClearScope();
var base, e, id, url, parentObject;
base = $location.path().replace(/^\//, '').split('/')[0];
if ($scope.removePostRefresh) {
$scope.removePostRefresh();
}
$scope.removePostRefresh = $scope.$on('PostRefresh', function() {
var list = $scope.schedules;
list.forEach(function(element, idx) {
list[idx].play_tip = (element.enabled) ? 'Schedule is Active. Click to temporarily stop.' : 'Schedule is temporarily stopped. Click to activate.';
});
});
if ($scope.removeParentLoaded) {
$scope.removeParentLoaded();
}
$scope.removeParentLoaded = $scope.$on('ParentLoaded', function() {
url += "schedules/";
SchedulesList.well = true;
// include name of item in listTitle
SchedulesList.listTitle = parentObject.name + "<div class='List-titleLockup'></div>Schedules";
LoadSchedulesScope({
parent_scope: $scope,
scope: $scope,
list: SchedulesList,
id: 'schedule-list-target',
url: url,
pageSize: 20
});
});
if ($scope.removeChoicesReady) {
$scope.removeChocesReady();
}
$scope.removeChoicesReady = $scope.$on('choicesReady', function() {
// Load the parent object
id = $stateParams.id;
url = GetBasePath(base) + id + '/';
Rest.setUrl(url);
Rest.get()
.success(function(data) {
parentObject = data;
$scope.$emit('ParentLoaded');
})
.error(function(data, status) {
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. GET returned: ' + status });
});
});
$scope.refreshJobs = function() {
$scope.search(SchedulesList.iterator);
};
$scope.showActivity = function () {
Stream({ scope: $scope });
};
Wait('start');
GetChoices({
scope: $scope,
url: GetBasePath('unified_jobs'), //'/static/sample/data/types/data.json'
field: 'type',
variable: 'type_choices',
callback: 'choicesReady'
});
}];

View File

@ -0,0 +1,6 @@
<div ui-view></div>
<div class="Panel">
<div id="schedule-list-target"></div>
</div>
<div ng-include="'/static/partials/schedule_dialog.html'"></div>

View File

@ -0,0 +1,32 @@
export default ['$compile', '$state', '$stateParams', 'AddSchedule', 'Wait', '$scope', function($compile, $state, $stateParams, AddSchedule, Wait, $scope) {
$scope.$on("ScheduleFormCreated", function(e, scope) {
$scope.hideForm = false;
$scope = angular.extend($scope, scope);
$scope.$watchGroup(["schedulerStartDt",
"schedulerStartHour",
"schedulerStartMinute",
"schedulerStartSecond",
"schedulerTimeZone",
"schedulerFrequency",
"schedulerInterval"], function(val) {
if (!$scope.scheduler_form.$invalid) {
$scope.schedulerIsValid = true;
} else {
$scope.schedulerIsValid = false;
}
return val;
});
Wait('stop');
});
$scope.hideForm = true;
$scope.formCancel = function() {
$state.go("^");
}
AddSchedule({
scope: $scope,
callback: 'SchedulesRefresh'
});
}];

View File

@ -0,0 +1,33 @@
export default ['$compile', '$state', '$stateParams', 'EditSchedule', 'Wait', '$scope', function($compile, $state, $stateParams, EditSchedule, Wait, $scope) {
$scope.$on("ScheduleFormCreated", function(e, scope) {
$scope.hideForm = false;
$scope = angular.extend($scope, scope);
$scope.$watchGroup(["schedulerStartDt",
"schedulerStartHour",
"schedulerStartMinute",
"schedulerStartSecond",
"schedulerTimeZone",
"schedulerFrequency",
"schedulerInterval"], function(val) {
if (!$scope.scheduler_form.$invalid) {
$scope.schedulerIsValid = true;
} else {
$scope.schedulerIsValid = false;
}
return val;
});
Wait('stop');
});
$scope.hideForm = true;
$scope.formCancel = function() {
$state.go("^");
}
EditSchedule({
scope: $scope,
id: parseInt($stateParams.schedule_id),
callback: 'SchedulesRefresh'
});
}];

View File

@ -0,0 +1,307 @@
<div id="htmlTemplate" class=" SchedulerFormPanel Panel" ng-hide="hideForm">
<div class="Form-header">
<div class="Form-title">{{ schedulerName || "Add Schedule"}}</div>
<div class="Form-exitHolder">
<button class="Form-exit" ng-click="formCancel()">
<i class="fa fa-times-circle"></i>
</button>
</div>
</div>
<div id="SchedulerFormTarget">
<div class="row">
<div class="col-md-12">
<form class="form" role="form" name="scheduler_form" novalidate>
<div class="form-group">
<label><span class="red-text">*</span> Name</label>
<input type="text" class="form-control input-sm" name="schedulerName" id="schedulerName" ng-model="schedulerName" required placeholder="Schedule name">
<div class="error" ng-show="scheduler_form.schedulerName.$dirty && scheduler_form.schedulerName.$error.required">A schedule name is required.</div>
</div>
<div class="factDetailsNote" ng-if="isFactCleanup"><span class="factDetailsHeader">Note:</span> For facts collected older than the time period specified, save one fact scan (snapshot) per time window (frequency). For example, facts older than 30 days are purged, while one weekly fact scan is kept.
Caution: Setting both numerical variables to "0" will delete all facts.</div>
<div class="form-group" ng-if="cleanupJob && !isFactCleanup">
<label><span class="red-text">*</span> Days of data to keep</label>
<input type="number" class="form-control input-sm" name="schedulerPurgeDays" id="schedulerPurgeDays" min="1" ng-model="schedulerPurgeDays" required placeholder="Days of data to keep">
<div class="error" ng-show="scheduler_form.schedulerPurgeDays.$dirty && scheduler_form.schedulerPurgeDays.$error.required">A value is required.</div>
<div class="error" ng-show="scheduler_form.schedulerPurgeDays.$error.number">This is not a valid number.</div>
</div>
<div class="form-group cleanupStretcher factDaysToKeepCompacter" ng-if="isFactCleanup">
<div class="col-md-12">
<label><span class="red-text">*</span> Select a time period after which to remove old facts</label>
</div>
<div class="col-md-6 inputSpacer inputCompactMobile">
<input type="number" id="keep_amount" name="keep_amount" ng-model="keep_amount" ng-required="true" class="form-control input-sm" aw-min=0 aw-max=9999 integer></input>
<div class="error" ng-show="scheduler_form.keep_amount.$dirty && scheduler_form.keep_amount.$error.required">Please enter the number of days you would like to keep this data.</div>
<div class="error survey_error" ng-show="scheduler_form.keep_amount.$error.number || scheduler_form.keep_amount.$error.integer" >Please enter a valid number.</div>
<div class="error survey_error" ng-show="scheduler_form.keep_amount.$error.awMin">Please enter a non-negative number.</div>
<div class="error survey_error" ng-show="scheduler_form.keep_amount.$error.awMax">Please enter a number smaller than 9999.</div>
</div>
<div class="col-md-6 inputSpacer">
<select id="keep_unit" name="keep_unit" ng-model="keep_unit" ng-options="type.label for type in keep_unit_choices track by type.value" ng-required="true" class="form-control input-sm"></select>
</div>
</div>
<div class="form-group cleanupStretcher" ng-if="isFactCleanup">
<div class="col-md-12">
<label><span class="red-text">*</span> Select a frequency for snapshot retention</label>
</div>
<div class="col-md-6 inputSpacer inputCompactMobile">
<input type="number" class="form-control input-sm" id="granularity_keep_amount" name="granularity_keep_amount" ng-model="granularity_keep_amount" ng-required="true" aw-min=0 aw-max=9999 >
<div class="error" ng-show="scheduler_form.granularity_keep_amount.$dirty && scheduler_form.granularity_keep_amount.$error.required">Please enter the number of days you would like to keep this data.</div>
<div class="error survey_error" ng-show="scheduler_form.granularity_keep_amount.$error.number || scheduler_form.granularity_keep_amount.$error.integer" >Please enter a valid number.</div>
<div class="error survey_error" ng-show="scheduler_form.granularity_keep_amount.$error.awMin">Please enter a non-negative number.</div>
<div class="error survey_error" ng-show="scheduler_form.granularity_keep_amount.$error.awMax">Please enter a number smaller than 9999.</div>
</div>
<div class="col-md-6 inputSpacer">
<select id="granularity_keep_unit" name="granularity_keep_unit" ng-model="granularity_keep_unit" ng-options="type.label for type in granularity_keep_unit_choices track by type.value" ng-required="true" class="form-control input-sm"></select>
</div>
</div>
<div class="row">
<div class="col-md-5">
<div class="form-group">
<label><span class="red-text">*</span> Start Date <span class="fmt-help"> mm/dd/yyyy</span></label>
<div class="input-group">
<input type="text" class="form-control input-sm" name="schedulerStartDt" id="schedulerStartDt" ng-model="schedulerStartDt"
sch-date-picker placeholder="mm/dd/yyyy" required ng-change="scheduleTimeChange()" >
<span class="input-group-btn">
<button class="btn btn-default btn-sm" type="button" ng-click="showCalendar('schedulerStartDt')">
<i class="fa fa-calendar"></i></button>
</span>
</div>
</div>
</div>
<div class="col-md-7">
<div class="form-group">
<label><span class="red-text">*</span> Start Time <span class="fmt-help">HH24:MM:SS</span><span class="fmt-help" ng-show="!schedulerShowTimeZone">UTC</span></label>
<div class="input-group">
<input name="schedulerStartHour" id="schedulerStartHour" sch-spinner="scheduler_form" class="scheduler-time-spinner"
ng-model="schedulerStartHour" placeholder="HH24" aw-min="0" min="0" aw-max="23" max="23" data-zero-pad="2" required
ng-change="scheduleTimeChange()" >
<span>:</span><input name="schedulerStartMinute" id="schedulerStartMinute" sch-spinner="scheduler_form" class="scheduler-time-spinner" ng-model="schedulerStartMinute" placeholder="MM" min="0" max="59" data-zero-pad="2" required ng-change="scheduleTimeChange()" >
<span>:</span><input name="schedulerStartSecond" id="schedulerStartSecond" sch-spinner="scheduler_form" class="scheduler-time-spinner" ng-model="schedulerStartSecond" placeholder="SS" min="0" max="59" data-zero-pad="2" required ng-change="scheduleTimeChange()" >
</div>
<div class="error" ng-show="scheduler_startTime_error">The time must be in HH24:MM:SS format.</div>
</div>
</div>
</div>
<div class="row error-pull-up">
<div class="col-md-12">
<div class="error" ng-show="scheduler_form_schedulerStartDt_error" ng-bind="scheduler_form_schedulerStartDt_error"></div>
</div>
</div>
<div class="row">
<div class="col-md-4" ng-show="schedulerShowTimeZone">
<div class="form-group">
<label>Local Time Zone</label>
<select name="schedulerTimeZone" id="schedulerTimeZone" ng-model="schedulerTimeZone" ng-options="z.name for z in timeZones"
required class="form-control input-sm" ng-change="scheduleTimeChange()" ></select>
</div>
</div>
<div class="col-md-4" ng-show="schedulerShowUTCStartTime">
<div class="form-group">
<label>UTC Start Time</label>
<input type="text" name="schedulerUTCTime" ng-model="schedulerUTCTime" id="schedulerUTCTime" class="form-control input-sm" readonly>
</div>
</div>
</div>
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label>Repeat frequency</label>
<select name="schedulerFrequency" id="schedulerFrequency" ng-model="schedulerFrequency"
ng-options="f.name for f in frequencyOptions" required class="form-control input-sm"
ng-change="scheduleRepeatChange()"></select>
</div>
<div class="error" ng-show="sheduler_frequency_error"></div>
</div>
<div class="col-md-4">
<div class="form-group no-label" ng-show="schedulerShowInterval">
<label>Every</label>
<input name="schedulerInterval" id="schedulerInterval" sch-spinner="scheduler_form" class="scheduler-spinner"
ng-model="schedulerInterval" min="1" max="999" ng-change="resetError('scheduler_interval_error')">
<label class="inline-label" ng-bind="schedulerIntervalLabel"></label>
<div class="error" ng-show="scheduler_interval_error">Please provide a value between 1 and 999.</div>
</div>
</div>
</div>
<div class="row" ng-show="schedulerFrequency && schedulerFrequency.value == 'monthly'">
<div class="col-md-12">
<div class="form-group option-pad-left">
<div class="radio col-md-2">
<label><input type="radio" value="day" ng-model="monthlyRepeatOption" ng-change="monthlyRepeatChange()" name="monthlyRepeatOption"
id="monthlyRepeatOption"> on day</label>
</div>
<div class="col-md-3" style="padding-top:5px">
<input name="monthDay" id="monthDay" sch-spinner="scheduler_form" class="scheduler-spinner"
ng-model="monthDay" min="1" max="31" ng-change="resetError('scheduler_monthDay_error')" >
<div class="error" ng-show="scheduler_monthDay_error">The day must be between 1 and 31.</div>
</div>
</div>
</div>
</div>
<div class="row option-pad-bottom" ng-show="schedulerFrequency && schedulerFrequency.value == 'monthly'">
<div class="col-md-12">
<div class="form-group option-pad-left">
<div class="radio col-md-2">
<label><input type="radio" value="other" ng-model="monthlyRepeatOption" ng-change="monthlyRepeatChange()" name="monthlyRepeatOption" id="monthlyRepeatOption"> on the</label>
</div>
<div class="col-md-3">
<select name="monthlyOccurrence" id="monthlyOccurrence" ng-model="monthlyOccurrence" ng-options="o.name for o in occurrences"
ng-disabled="monthlyRepeatOption != 'other'" class="form-control input-sm" ></select>
</div>
<div class="col-md-3">
<select name="monthlyWeekDay" id="monthlyWeekDay" ng-model="monthlyWeekDay" ng-options="w.name for w in weekdays"
ng-disabled="monthlyRepeatOption != 'other'" class="form-control input-sm" ></select>
</div>
</div>
</div>
</div>
<div class="row" ng-show="schedulerFrequency && schedulerFrequency.value == 'yearly'">
<div class="col-md-12">
<div class="form-group option-pad-left">
<div class="radio col-md-2">
<label><input type="radio" value="month" ng-model="yearlyRepeatOption" ng-change="yearlyRepeatChange()" name="yearlyRepeatOption" id="yearlyRepeatOption"> on</label>
</div>
<div class="col-md-3 padding-top-slim">
<select name="yearlyMonth" id="yearlyMonth" ng-model="yearlyMonth" ng-options="m.name for m in months"
ng-disabled="yearlyRepeatOption != 'month'" class="form-control input-sm" ></select>
</div>
<div class="col-md-3 padding-top-slim">
<input name="yearlyMonthDay" id="yearlyMonthDay" sch-spinner="scheduler_form" class="scheduler-spinner"
ng-model="yearlyMonthDay" min="1" max="31" ng-change="resetError('scheduler_yearlyMonthDay_error')" >
<div class="error" ng-show="scheduler_yearlyMonthDay_error">The day must be between 1 and 31.</div>
</div>
</div>
</div>
</div>
<div class="row option-pad-bottom" ng-show="schedulerFrequency && schedulerFrequency.value == 'yearly'">
<div class="col-md-12">
<div class="form-group option-pad-left">
<div class="radio col-md-2">
<label><input type="radio" value="other" ng-model="yearlyRepeatOption" ng-change="yearlyRepeatChange()" name="yearlyRepeatOption"
id="yearlyRepeatOption"> on the</label>
</div>
<div class="col-md-2 padding-top-slim">
<select name="yearlyOccurrence" id="yearlyOccurrence" ng-model="yearlyOccurrence" ng-options="o.name for o in occurrences"
ng-disabled="yearlyRepeatOption != 'other'" class="form-control input-sm" ></select>
</div>
<div class="col-md-2 padding-top-slim">
<select name="yearlyWeekDay" id="yearlyWeekDay" ng-model="yearlyWeekDay" ng-options="w.name for w in weekdays"
ng-disabled="yearlyRepeatOption != 'other'" class="form-control input-sm" ></select>
</div>
<div class="col-md-2 padding-top-slim">
<select name="yearlyOtherMonth" id="yearlyOtherMonth" ng-model="yearlyOtherMonth" ng-options="m.name for m in months"
ng-disabled="yearlyRepeatOption != 'other'" class="form-control input-sm" ></select>
</div>
</div>
</div>
</div>
<div class="form-group option-pad-left option-pad-bottom" ng-show="schedulerFrequency && schedulerFrequency.value == 'weekly'">
<label><span class="red-text">*</span> On Days</label>
<div class="input-group">
<div class="btn-group" data-toggle="buttons-checkbox" id="weekdaySelect">
<button type="button" ng-class="weekDaySUClass" class="btn btn-default" data-value="SU" ng-click="setWeekday($event,'su')">Sun</button>
<button type="button" ng-class="weekDayMOClass" class="btn btn-default" data-value="MO" ng-click="setWeekday($event,'mo')">Mon</button>
<button type="button" ng-class="weekDayTUClass" class="btn btn-default" data-value="TU" ng-click="setWeekday($event,'tu')">Tue</button>
<button type="button" ng-class="weekDayWEClass" class="btn btn-default" data-value="WE" ng-click="setWeekday($event,'we')">Wed</button>
<button type="button" ng-class="weekDayTHClass" class="btn btn-default" data-value="TH" ng-click="setWeekday($event,'th')">Thu</button>
<button type="button" ng-class="weekDayFRClass" class="btn btn-default" data-value="FR" ng-click="setWeekday($event,'fr')">Fri</button>
<button type="button" ng-class="weekDaySAClass" class="btn btn-default" data-value="SA" ng-click="setWeekday($event,'sa')">Sat</button>
</div>
</div>
<div class="error" ng-show="scheduler_weekDays_error">Please select one or more days.</div>
</div>
<div class="row">
<div class="col-md-4">
<div class="form-group" ng-show="schedulerShowInterval">
<label>End</label>
<div>
<select id="schedulerEnd" name="schedulerEnd" ng-model="schedulerEnd" ng-options="e.name for e in endOptions" required class="form-control input-sm" ng-change="schedulerEndChange()"></select>
</div>
</div>
</div>
<div class="col-md-4" ng-show="schedulerEnd && schedulerEnd.value == 'after'">
<div class="form-group no-label">
<div class="input-group">
<input ng-name="schedulerOccurrenceCount" ng-id="schedulerOccurrenceCount" sch-spinner="scheduler_form" class="scheduler-spinner"
ng-model="schedulerOccurrenceCount" min="1" max="999" on-change="resetError('scheduler_occurrenceCount_error')" >
<label class="inline-label">Occurrence(s)</label>
</div>
<div class="error" ng-show="scheduler_occurrenceCount_error">Please provide a value between 1 and 999.</div>
</div>
</div>
<div class="col-md-4" ng-show="schedulerEnd && schedulerEnd.value == 'on'">
<div class="form-group no-label">
<div class="input-group">
<input type="text" name="schedulerEndDt" id="schedulerEndDt" class="form-control input-sm" ng-model="schedulerEndDt" sch-date-picker
data-min-today="true" placeholder="mm/dd/yyyy" ng-change="resetError('scheduler_endDt_error')">
<span class="input-group-btn">
<button class="btn btn-default btn-sm" type="button" ng-click="showCalendar('schedulerEndDt')">
<i class="fa fa-calendar"></i></button>
</span>
</div>
<div class="error" ng-show="scheduler_endDt_error">Please provide a valid date.</div>
</div>
</div>
</div>
</form>
<div id="scheduler-detail">
<div class="alert alert-danger" ng-show="!schedulerIsValid">
<p>The scheduler options are invalid or incomplete. Make the needed changes on the options tab, then come back here to see details.</p>
</div>
<div ng-show="schedulerIsValid">
<div class="form-group">
<label>Description</label>
<textarea ng-model="rrule_nlp_description" name="rrule_nlp_description" id="rrule_nlp_description" readonly class="form-control" rows="2"></textarea>
</div>
<div class="form-group" ng-show="showRRule">
<label>RRule</label>
<textarea ng-model="rrule" name="rrule" id="rrule" readonly class="form-control" rows="3"></textarea>
</div>
<div class="form-group">
<label id="occurrences-label">Occurrences <span class="sublabel">(limited to first 10)</label>
<div id="date-choice">
<label class="label-inline">Date format</label>
<label class="radio-inline"><input type="radio" ng-model="dateChoice" id="date-choice-local" value="local" >Local time</label>
<label class="radio-inline"><input type="radio" ng-model="dateChoice" id="date-choice-utc" value="utc" >UTC</label>
</div>
<ul class="occurrence-list mono-space" ng-show="dateChoice == 'utc'">
<li ng-repeat="occurrence in occurrence_list">{{ occurrence.utc }}</li>
</ul>
<ul class="occurrence-list mono-space" ng-show="dateChoice == 'local'">
<li ng-repeat="occurrence in occurrence_list">{{ occurrence.local }}</li>
</ul>
</div>
</div>
</div>
<div class="buttons Form-buttons">
<button type="button"
class="btn btn-sm Form-saveButton"
id="project_save_btn"
ng-click="saveSchedule()"
ng-disabled="scheduler_form.$invalid"> Save</button>
<button type="button"
class="btn btn-sm Form-cancelButton"
id="project_cancel_btn"
ng-click="formCancel()">Cancel</button>
</div>
</div><!-- col-md-12 -->
</div><!-- row -->
</div>
</div>

View File

@ -3,8 +3,9 @@ export default function($stateProvider){
this.$get = function(){
return {
addState: function(state) {
var route = state.route || state.url;
$stateProvider.state(state.name , {
url: state.route,
url: route,
controller: state.controller,
templateUrl: state.templateUrl,
resolve: state.resolve,