cron-editor
Version:
A cron expression generator to be used in Angular applications
748 lines (745 loc) • 115 kB
JavaScript
import { __read, __spread } from 'tslib';
import { Component, Input, Output, EventEmitter, NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @type {?} */
var Days = {
'SUN': 'Sunday',
'MON': 'Monday',
'TUE': 'Tuesday',
'WED': 'Wednesday',
'THU': 'Thursday',
'FRI': 'Friday',
'SAT': 'Saturday'
};
/** @type {?} */
var MonthWeeks = {
'#1': 'First',
'#2': 'Second',
'#3': 'Third',
'#4': 'Fourth',
'#5': 'Fifth',
'L': 'Last'
};
/** @enum {number} */
var Months = {
January: 1,
February: 2,
March: 3,
April: 4,
May: 5,
June: 6,
July: 7,
August: 8,
September: 9,
October: 10,
November: 11,
December: 12,
};
Months[Months.January] = 'January';
Months[Months.February] = 'February';
Months[Months.March] = 'March';
Months[Months.April] = 'April';
Months[Months.May] = 'May';
Months[Months.June] = 'June';
Months[Months.July] = 'July';
Months[Months.August] = 'August';
Months[Months.September] = 'September';
Months[Months.October] = 'October';
Months[Months.November] = 'November';
Months[Months.December] = 'December';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
// @dynamic
var
// @dynamic
Utils = /** @class */ (function () {
function Utils() {
}
/** This returns a range of numbers. Starts from 0 if 'startFrom' is not set */
/**
* This returns a range of numbers. Starts from 0 if 'startFrom' is not set
* @param {?} startFrom
* @param {?} until
* @return {?}
*/
Utils.getRange = /**
* This returns a range of numbers. Starts from 0 if 'startFrom' is not set
* @param {?} startFrom
* @param {?} until
* @return {?}
*/
function (startFrom, until) {
return Array.from({ length: (until + 1 - startFrom) }, function (_, k) { return k + startFrom; });
};
return Utils;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
var CronEditorComponent = /** @class */ (function () {
function CronEditorComponent() {
// the name is an Angular convention, @Input variable name + "Change" suffix
this.cronChange = new EventEmitter();
this.selectOptions = this.getSelectOptions();
}
Object.defineProperty(CronEditorComponent.prototype, "cron", {
get: /**
* @return {?}
*/
function () { return this.localCron; },
set: /**
* @param {?} value
* @return {?}
*/
function (value) {
this.localCron = value;
this.cronChange.emit(this.localCron);
},
enumerable: true,
configurable: true
});
/**
* @return {?}
*/
CronEditorComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () {
if (this.options.removeSeconds) {
this.options.hideSeconds = true;
}
this.state = this.getDefaultState();
this.handleModelChange(this.cron);
};
/**
* @param {?} changes
* @return {?}
*/
CronEditorComponent.prototype.ngOnChanges = /**
* @param {?} changes
* @return {?}
*/
function (changes) {
/** @type {?} */
var newCron = changes['cron'];
if (newCron && !newCron.firstChange) {
this.handleModelChange(this.cron);
}
};
/**
* @param {?} tab
* @return {?}
*/
CronEditorComponent.prototype.setActiveTab = /**
* @param {?} tab
* @return {?}
*/
function (tab) {
if (!this.disabled) {
this.activeTab = tab;
this.regenerateCron();
}
};
/**
* @param {?} day
* @return {?}
*/
CronEditorComponent.prototype.dayDisplay = /**
* @param {?} day
* @return {?}
*/
function (day) {
return Days[day];
};
/**
* @param {?} monthWeekNumber
* @return {?}
*/
CronEditorComponent.prototype.monthWeekDisplay = /**
* @param {?} monthWeekNumber
* @return {?}
*/
function (monthWeekNumber) {
return MonthWeeks[monthWeekNumber];
};
/**
* @param {?} month
* @return {?}
*/
CronEditorComponent.prototype.monthDisplay = /**
* @param {?} month
* @return {?}
*/
function (month) {
return Months[month];
};
/**
* @param {?} month
* @return {?}
*/
CronEditorComponent.prototype.monthDayDisplay = /**
* @param {?} month
* @return {?}
*/
function (month) {
if (month === 'L') {
return 'Last Day';
}
else if (month === 'LW') {
return 'Last Weekday';
}
else if (month === '1W') {
return 'First Weekday';
}
else {
return "" + month + this.getOrdinalSuffix(month) + " day";
}
};
/**
* @return {?}
*/
CronEditorComponent.prototype.regenerateCron = /**
* @return {?}
*/
function () {
var _this = this;
this.isDirty = true;
switch (this.activeTab) {
case 'minutes':
this.cron = "0/" + this.state.minutes.minutes + " * 1/1 * ?";
if (!this.options.removeSeconds) {
this.cron = this.state.minutes.seconds + " " + this.cron;
}
if (!this.options.removeYears) {
this.cron = this.cron + " *";
}
break;
case 'hourly':
this.cron = this.state.hourly.minutes + " 0/" + this.state.hourly.hours + " 1/1 * ?";
if (!this.options.removeSeconds) {
this.cron = this.state.hourly.seconds + " " + this.cron;
}
if (!this.options.removeYears) {
this.cron = this.cron + " *";
}
break;
case 'daily':
switch (this.state.daily.subTab) {
case 'everyDays':
// tslint:disable-next-line:max-line-length
this.cron = this.state.daily.everyDays.minutes + " " + this.hourToCron(this.state.daily.everyDays.hours, this.state.daily.everyDays.hourType) + " 1/" + this.state.daily.everyDays.days + " * ?";
if (!this.options.removeSeconds) {
this.cron = this.state.daily.everyDays.seconds + " " + this.cron;
}
if (!this.options.removeYears) {
this.cron = this.cron + " *";
}
break;
case 'everyWeekDay':
// tslint:disable-next-line:max-line-length
this.cron = this.state.daily.everyWeekDay.minutes + " " + this.hourToCron(this.state.daily.everyWeekDay.hours, this.state.daily.everyWeekDay.hourType) + " ? * MON-FRI";
if (!this.options.removeSeconds) {
this.cron = this.state.daily.everyWeekDay.seconds + " " + this.cron;
}
if (!this.options.removeYears) {
this.cron = this.cron + " *";
}
break;
default:
throw new Error('Invalid cron daily subtab selection');
}
break;
case 'weekly':
/** @type {?} */
var days = this.selectOptions.days
.reduce(function (acc, day) { return _this.state.weekly[day] ? acc.concat([day]) : acc; }, [])
.join(',');
this.cron = this.state.weekly.minutes + " " + this.hourToCron(this.state.weekly.hours, this.state.weekly.hourType) + " ? * " + days;
if (!this.options.removeSeconds) {
this.cron = this.state.weekly.seconds + " " + this.cron;
}
if (!this.options.removeYears) {
this.cron = this.cron + " *";
}
break;
case 'monthly':
switch (this.state.monthly.subTab) {
case 'specificDay':
/** @type {?} */
var day = this.state.monthly.runOnWeekday ? this.state.monthly.specificDay.day + "W" : this.state.monthly.specificDay.day;
// tslint:disable-next-line:max-line-length
this.cron = this.state.monthly.specificDay.minutes + " " + this.hourToCron(this.state.monthly.specificDay.hours, this.state.monthly.specificDay.hourType) + " " + day + " 1/" + this.state.monthly.specificDay.months + " ?";
if (!this.options.removeSeconds) {
this.cron = this.state.monthly.specificDay.seconds + " " + this.cron;
}
if (!this.options.removeYears) {
this.cron = this.cron + " *";
}
break;
case 'specificWeekDay':
// tslint:disable-next-line:max-line-length
this.cron = this.state.monthly.specificWeekDay.minutes + " " + this.hourToCron(this.state.monthly.specificWeekDay.hours, this.state.monthly.specificWeekDay.hourType) + " ? " + this.state.monthly.specificWeekDay.startMonth + "/" + this.state.monthly.specificWeekDay.months + " " + this.state.monthly.specificWeekDay.day + this.state.monthly.specificWeekDay.monthWeek;
if (!this.options.removeSeconds) {
this.cron = this.state.monthly.specificWeekDay.seconds + " " + this.cron;
}
if (!this.options.removeYears) {
this.cron = this.cron + " *";
}
break;
default:
throw new Error('Invalid cron monthly subtab selection');
}
break;
case 'yearly':
switch (this.state.yearly.subTab) {
case 'specificMonthDay':
// tslint:disable-next-line:max-line-length
/** @type {?} */
var day = this.state.yearly.runOnWeekday ? this.state.yearly.specificMonthDay.day + "W" : this.state.yearly.specificMonthDay.day;
// tslint:disable-next-line:max-line-length
this.cron = this.state.yearly.specificMonthDay.minutes + " " + this.hourToCron(this.state.yearly.specificMonthDay.hours, this.state.yearly.specificMonthDay.hourType) + " " + day + " " + this.state.yearly.specificMonthDay.month + " ?";
if (!this.options.removeSeconds) {
this.cron = this.state.yearly.specificMonthDay.seconds + " " + this.cron;
}
if (!this.options.removeYears) {
this.cron = this.cron + " *";
}
break;
case 'specificMonthWeek':
// tslint:disable-next-line:max-line-length
this.cron = this.state.yearly.specificMonthWeek.minutes + " " + this.hourToCron(this.state.yearly.specificMonthWeek.hours, this.state.yearly.specificMonthWeek.hourType) + " ? " + this.state.yearly.specificMonthWeek.month + " " + this.state.yearly.specificMonthWeek.day + this.state.yearly.specificMonthWeek.monthWeek;
if (!this.options.removeSeconds) {
this.cron = this.state.yearly.specificMonthWeek.seconds + " " + this.cron;
}
if (!this.options.removeYears) {
this.cron = this.cron + " *";
}
break;
default:
throw new Error('Invalid cron yearly subtab selection');
}
break;
case 'advanced':
this.cron = this.state.advanced.expression;
break;
default:
throw new Error('Invalid cron active tab selection');
}
};
/**
* @private
* @param {?} hour
* @return {?}
*/
CronEditorComponent.prototype.getAmPmHour = /**
* @private
* @param {?} hour
* @return {?}
*/
function (hour) {
return this.options.use24HourTime ? hour : (hour + 11) % 12 + 1;
};
/**
* @private
* @param {?} hour
* @return {?}
*/
CronEditorComponent.prototype.getHourType = /**
* @private
* @param {?} hour
* @return {?}
*/
function (hour) {
return this.options.use24HourTime ? undefined : (hour >= 12 ? 'PM' : 'AM');
};
/**
* @private
* @param {?} hour
* @param {?} hourType
* @return {?}
*/
CronEditorComponent.prototype.hourToCron = /**
* @private
* @param {?} hour
* @param {?} hourType
* @return {?}
*/
function (hour, hourType) {
if (this.options.use24HourTime) {
return hour;
}
else {
return hourType === 'AM' ? (hour === 12 ? 0 : hour) : (hour === 12 ? 12 : hour + 12);
}
};
/**
* @private
* @param {?} cron
* @return {?}
*/
CronEditorComponent.prototype.handleModelChange = /**
* @private
* @param {?} cron
* @return {?}
*/
function (cron) {
var _this = this;
if (this.isDirty) {
this.isDirty = false;
return;
}
else {
this.isDirty = false;
}
this.validate(cron);
/** @type {?} */
var cronSeven = cron;
if (this.options.removeSeconds) {
cronSeven = "0 " + cron;
}
if (this.options.removeYears) {
cronSeven = cronSeven + " *";
}
var _a = __read(cronSeven.split(' '), 6), seconds = _a[0], minutes = _a[1], hours = _a[2], dayOfMonth = _a[3], month = _a[4], dayOfWeek = _a[5];
if (cronSeven.match(/\d+ 0\/\d+ \* 1\/1 \* \? \*/)) {
this.activeTab = 'minutes';
this.state.minutes.minutes = Number(minutes.substring(2));
this.state.minutes.seconds = Number(seconds);
}
else if (cronSeven.match(/\d+ \d+ 0\/\d+ 1\/1 \* \? \*/)) {
this.activeTab = 'hourly';
this.state.hourly.hours = Number(hours.substring(2));
this.state.hourly.minutes = Number(minutes);
this.state.hourly.seconds = Number(seconds);
}
else if (cronSeven.match(/\d+ \d+ \d+ 1\/\d+ \* \? \*/)) {
this.activeTab = 'daily';
this.state.daily.subTab = 'everyDays';
this.state.daily.everyDays.days = Number(dayOfMonth.substring(2));
/** @type {?} */
var parsedHours = Number(hours);
this.state.daily.everyDays.hours = this.getAmPmHour(parsedHours);
this.state.daily.everyDays.hourType = this.getHourType(parsedHours);
this.state.daily.everyDays.minutes = Number(minutes);
this.state.daily.everyDays.seconds = Number(seconds);
}
else if (cronSeven.match(/\d+ \d+ \d+ \? \* MON-FRI \*/)) {
this.activeTab = 'daily';
this.state.daily.subTab = 'everyWeekDay';
/** @type {?} */
var parsedHours = Number(hours);
this.state.daily.everyWeekDay.hours = this.getAmPmHour(parsedHours);
this.state.daily.everyWeekDay.hourType = this.getHourType(parsedHours);
this.state.daily.everyWeekDay.minutes = Number(minutes);
this.state.daily.everyWeekDay.seconds = Number(seconds);
}
else if (cronSeven.match(/\d+ \d+ \d+ \? \* (MON|TUE|WED|THU|FRI|SAT|SUN)(,(MON|TUE|WED|THU|FRI|SAT|SUN))* \*/)) {
this.activeTab = 'weekly';
this.selectOptions.days.forEach(function (weekDay) { return _this.state.weekly[weekDay] = false; });
dayOfWeek.split(',').forEach(function (weekDay) { return _this.state.weekly[weekDay] = true; });
/** @type {?} */
var parsedHours = Number(hours);
this.state.weekly.hours = this.getAmPmHour(parsedHours);
this.state.weekly.hourType = this.getHourType(parsedHours);
this.state.weekly.minutes = Number(minutes);
this.state.weekly.seconds = Number(seconds);
}
else if (cronSeven.match(/\d+ \d+ \d+ (\d+|L|LW|1W) 1\/\d+ \? \*/)) {
this.activeTab = 'monthly';
this.state.monthly.subTab = 'specificDay';
if (dayOfMonth.indexOf('W') !== -1) {
this.state.monthly.specificDay.day = dayOfMonth.charAt(0);
this.state.monthly.runOnWeekday = true;
}
else {
this.state.monthly.specificDay.day = dayOfMonth;
}
this.state.monthly.specificDay.months = Number(month.substring(2));
/** @type {?} */
var parsedHours = Number(hours);
this.state.monthly.specificDay.hours = this.getAmPmHour(parsedHours);
this.state.monthly.specificDay.hourType = this.getHourType(parsedHours);
this.state.monthly.specificDay.minutes = Number(minutes);
this.state.monthly.specificDay.seconds = Number(seconds);
}
else if (cronSeven.match(/\d+ \d+ \d+ \? \d+\/\d+ (MON|TUE|WED|THU|FRI|SAT|SUN)((#[1-5])|L) \*/)) {
/** @type {?} */
var day = dayOfWeek.substr(0, 3);
/** @type {?} */
var monthWeek = dayOfWeek.substr(3);
this.activeTab = 'monthly';
this.state.monthly.subTab = 'specificWeekDay';
this.state.monthly.specificWeekDay.monthWeek = monthWeek;
this.state.monthly.specificWeekDay.day = day;
if (month.indexOf('/') !== -1) {
var _b = __read(month.split('/').map(Number), 2), startMonth = _b[0], months = _b[1];
this.state.monthly.specificWeekDay.months = months;
this.state.monthly.specificWeekDay.startMonth = startMonth;
}
/** @type {?} */
var parsedHours = Number(hours);
this.state.monthly.specificWeekDay.hours = this.getAmPmHour(parsedHours);
this.state.monthly.specificWeekDay.hourType = this.getHourType(parsedHours);
this.state.monthly.specificWeekDay.minutes = Number(minutes);
this.state.monthly.specificWeekDay.seconds = Number(seconds);
}
else if (cronSeven.match(/\d+ \d+ \d+ (\d+|L|LW|1W) \d+ \? \*/)) {
this.activeTab = 'yearly';
this.state.yearly.subTab = 'specificMonthDay';
this.state.yearly.specificMonthDay.month = Number(month);
if (dayOfMonth.indexOf('W') !== -1) {
this.state.yearly.specificMonthDay.day = dayOfMonth.charAt(0);
this.state.yearly.runOnWeekday = true;
}
else {
this.state.yearly.specificMonthDay.day = dayOfMonth;
}
/** @type {?} */
var parsedHours = Number(hours);
this.state.yearly.specificMonthDay.hours = this.getAmPmHour(parsedHours);
this.state.yearly.specificMonthDay.hourType = this.getHourType(parsedHours);
this.state.yearly.specificMonthDay.minutes = Number(minutes);
this.state.yearly.specificMonthDay.seconds = Number(seconds);
}
else if (cronSeven.match(/\d+ \d+ \d+ \? \d+ (MON|TUE|WED|THU|FRI|SAT|SUN)((#[1-5])|L) \*/)) {
/** @type {?} */
var day = dayOfWeek.substr(0, 3);
/** @type {?} */
var monthWeek = dayOfWeek.substr(3);
this.activeTab = 'yearly';
this.state.yearly.subTab = 'specificMonthWeek';
this.state.yearly.specificMonthWeek.monthWeek = monthWeek;
this.state.yearly.specificMonthWeek.day = day;
this.state.yearly.specificMonthWeek.month = Number(month);
/** @type {?} */
var parsedHours = Number(hours);
this.state.yearly.specificMonthWeek.hours = this.getAmPmHour(parsedHours);
this.state.yearly.specificMonthWeek.hourType = this.getHourType(parsedHours);
this.state.yearly.specificMonthWeek.minutes = Number(minutes);
this.state.yearly.specificMonthWeek.seconds = Number(seconds);
}
else {
this.activeTab = 'advanced';
this.state.advanced.expression = cron;
}
};
/**
* @private
* @param {?} cron
* @return {?}
*/
CronEditorComponent.prototype.validate = /**
* @private
* @param {?} cron
* @return {?}
*/
function (cron) {
this.state.validation.isValid = false;
this.state.validation.errorMessage = '';
if (!cron) {
this.state.validation.errorMessage = 'Cron expression cannot be null';
return;
}
/** @type {?} */
var cronParts = cron.split(' ');
/** @type {?} */
var expected = 5;
if (!this.options.removeSeconds) {
expected++;
}
if (!this.options.removeYears) {
expected++;
}
if (cronParts.length !== expected) {
this.state.validation.errorMessage = "Invalid cron expression, there must be " + expected + " segments";
return;
}
this.state.validation.isValid = true;
return;
};
/**
* @private
* @return {?}
*/
CronEditorComponent.prototype.getDefaultAdvancedCronExpression = /**
* @private
* @return {?}
*/
function () {
if (this.options.removeSeconds && !this.options.removeYears) {
return '15 10 L-2 * ? 2019';
}
if (!this.options.removeSeconds && this.options.removeYears) {
return '0 15 10 L-2 * ?';
}
if (this.options.removeSeconds && this.options.removeYears) {
return '15 10 L-2 * ?';
}
return '0 15 10 L-2 * ? 2019';
};
/**
* @private
* @return {?}
*/
CronEditorComponent.prototype.getDefaultState = /**
* @private
* @return {?}
*/
function () {
var _a = __read(this.options.defaultTime.split(':').map(Number), 3), defaultHours = _a[0], defaultMinutes = _a[1], defaultSeconds = _a[2];
return {
minutes: {
minutes: 1,
seconds: 0
},
hourly: {
hours: 1,
minutes: 0,
seconds: 0
},
daily: {
subTab: 'everyDays',
everyDays: {
days: 1,
hours: this.getAmPmHour(defaultHours),
minutes: defaultMinutes,
seconds: defaultSeconds,
hourType: this.getHourType(defaultHours)
},
everyWeekDay: {
hours: this.getAmPmHour(defaultHours),
minutes: defaultMinutes,
seconds: defaultSeconds,
hourType: this.getHourType(defaultHours)
}
},
weekly: {
MON: true,
TUE: false,
WED: false,
THU: false,
FRI: false,
SAT: false,
SUN: false,
hours: this.getAmPmHour(defaultHours),
minutes: defaultMinutes,
seconds: defaultSeconds,
hourType: this.getHourType(defaultHours)
},
monthly: {
subTab: 'specificDay',
runOnWeekday: false,
specificDay: {
day: '1',
months: 1,
hours: this.getAmPmHour(defaultHours),
minutes: defaultMinutes,
seconds: defaultSeconds,
hourType: this.getHourType(defaultHours)
},
specificWeekDay: {
monthWeek: '#1',
day: 'MON',
startMonth: 1,
months: 1,
hours: this.getAmPmHour(defaultHours),
minutes: defaultMinutes,
seconds: defaultSeconds,
hourType: this.getHourType(defaultHours)
}
},
yearly: {
subTab: 'specificMonthDay',
runOnWeekday: false,
specificMonthDay: {
month: 1,
day: '1',
hours: this.getAmPmHour(defaultHours),
minutes: defaultMinutes,
seconds: defaultSeconds,
hourType: this.getHourType(defaultHours)
},
specificMonthWeek: {
monthWeek: '#1',
day: 'MON',
month: 1,
hours: this.getAmPmHour(defaultHours),
minutes: defaultMinutes,
seconds: defaultSeconds,
hourType: this.getHourType(defaultHours)
}
},
advanced: {
expression: this.getDefaultAdvancedCronExpression()
},
validation: {
isValid: true,
errorMessage: ''
}
};
};
/**
* @private
* @param {?} value
* @return {?}
*/
CronEditorComponent.prototype.getOrdinalSuffix = /**
* @private
* @param {?} value
* @return {?}
*/
function (value) {
if (value.length > 1) {
/** @type {?} */
var secondToLastDigit = value.charAt(value.length - 2);
if (secondToLastDigit === '1') {
return 'th';
}
}
/** @type {?} */
var lastDigit = value.charAt(value.length - 1);
switch (lastDigit) {
case '1':
return 'st';
case '2':
return 'nd';
case '3':
return 'rd';
default:
return 'th';
}
};
/**
* @private
* @return {?}
*/
CronEditorComponent.prototype.getSelectOptions = /**
* @private
* @return {?}
*/
function () {
return {
months: Utils.getRange(1, 12),
monthWeeks: ['#1', '#2', '#3', '#4', '#5', 'L'],
days: ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'],
minutes: Utils.getRange(0, 59),
fullMinutes: Utils.getRange(0, 59),
seconds: Utils.getRange(0, 59),
hours: Utils.getRange(1, 23),
monthDays: Utils.getRange(1, 31),
monthDaysWithLasts: __spread(Utils.getRange(1, 31).map(String), ['L']),
hourTypes: ['AM', 'PM']
};
};
CronEditorComponent.decorators = [
{ type: Component, args: [{
selector: 'cron-editor',
template: "<!-- Tabs -->\r\n<ul class=\"nav nav-tabs tab-nav\" role=\"tablist\">\r\n <li [ngClass]=\"{'active': activeTab === 'minutes'}\" *ngIf=\"!options.hideMinutesTab\">\r\n <a aria-controls=\"minutes\" role=\"tab\" data-toggle=\"tab\" (click)=\"setActiveTab('minutes')\">\r\n Minutes\r\n </a>\r\n </li>\r\n\r\n <li role=\"presentation\" *ngIf=\"!options.hideHourlyTab\" [ngClass]=\"{'active': activeTab === 'hourly'}\">\r\n <a aria-controls=\"hourly\" role=\"tab\" data-toggle=\"tab\" (click)=\"setActiveTab('hourly')\">\r\n Hourly\r\n </a>\r\n </li>\r\n\r\n <li role=\"presentation\" *ngIf=\"!options.hideDailyTab\" [ngClass]=\"{'active': activeTab === 'daily'}\">\r\n <a aria-controls=\"daily\" role=\"tab\" data-toggle=\"tab\" (click)=\"setActiveTab('daily')\">\r\n Daily\r\n </a>\r\n </li>\r\n\r\n <li role=\"presentation\" *ngIf=\"!options.hideWeeklyTab\" [ngClass]=\"{'active': activeTab === 'weekly'}\">\r\n <a aria-controls=\"weekly\" role=\"tab\" data-toggle=\"tab\" (click)=\"setActiveTab('weekly')\">\r\n Weekly\r\n </a>\r\n </li>\r\n\r\n <li role=\"presentation\" *ngIf=\"!options.hideMonthlyTab\" [ngClass]=\"{'active': activeTab === 'monthly'}\">\r\n <a aria-controls=\"monthly\" role=\"tab\" data-toggle=\"tab\" (click)=\"setActiveTab('monthly')\">\r\n Monthly\r\n </a>\r\n </li>\r\n\r\n <li role=\"presentation\" *ngIf=\"!options.hideYearlyTab\" [ngClass]=\"{'active': activeTab === 'yearly'}\">\r\n <a aria-controls=\"yearly\" role=\"tab\" data-toggle=\"tab\" (click)=\"setActiveTab('yearly')\">\r\n Yearly\r\n </a>\r\n </li>\r\n\r\n <li role=\"presentation\" *ngIf=\"!options.hideAdvancedTab\" [ngClass]=\"{'active': activeTab === 'advanced'}\">\r\n <a aria-controls=\"advanced\" role=\"tab\" data-toggle=\"tab\" (click)=\"setActiveTab('advanced')\">\r\n Advanced\r\n </a>\r\n </li>\r\n</ul>\r\n\r\n<!-- Tab content -->\r\n<div class=\"cron-editor-container\">\r\n <div class=\"row\">\r\n <div class=\"col-xs-12\">\r\n <div class=\"tab-content\">\r\n <!-- Minutes-->\r\n <div class=\"tab-pane\" *ngIf=\"!options.hideMinutesTab\" [ngClass]=\"{'active': activeTab === 'minutes'}\">\r\n <div class=\"well well-small\">\r\n Every\r\n <select class=\"minutes\" [disabled]=\"disabled || activeTab !== 'minutes'\" (change)=\"regenerateCron()\"\r\n [(ngModel)]=\"state.minutes.minutes\" [ngClass]=\"options.formSelectClass\">\r\n <option *ngFor=\"let minute of selectOptions.minutes\" [ngValue]=\"minute\">\r\n {{minute}}\r\n </option>\r\n </select> minute(s)\r\n <span *ngIf=\"!options.hideSeconds\">on second</span>\r\n <select class=\"seconds\" *ngIf=\"!options.hideSeconds\" [disabled]=\"disabled || activeTab !== 'minutes'\"\r\n (change)=\"regenerateCron()\" [(ngModel)]=\"state.minutes.seconds\" [ngClass]=\"options.formSelectClass\">\r\n <option *ngFor=\"let second of selectOptions.seconds\" [ngValue]=\"second\">\r\n {{second}}\r\n </option>\r\n </select>\r\n </div>\r\n </div>\r\n\r\n <!-- Hourly-->\r\n <div class=\"tab-pane\" *ngIf=\"!options.hideHourlyTab\" [ngClass]=\"{'active': activeTab === 'hourly'}\">\r\n <div class=\"well well-small\">\r\n Every\r\n <select class=\"hours\" [disabled]=\"disabled || activeTab !== 'hourly'\" (change)=\"regenerateCron()\"\r\n [(ngModel)]=\"state.hourly.hours\" [ngClass]=\"options.formSelectClass\">\r\n <option *ngFor=\"let hour of selectOptions.hours\" [ngValue]=\"hour\">\r\n {{hour}}\r\n </option>\r\n </select> hour(s) on minute\r\n <select class=\"minutes\" [disabled]=\"disabled || activeTab !== 'hourly'\" (change)=\"regenerateCron()\"\r\n [(ngModel)]=\"state.hourly.minutes\" [ngClass]=\"options.formSelectClass\">\r\n <option *ngFor=\"let minute of selectOptions.fullMinutes\" [ngValue]=\"minute\">\r\n {{minute}}\r\n </option>\r\n </select>\r\n <span *ngIf=\"!options.hideSeconds\">and second</span>\r\n <select class=\"seconds\" *ngIf=\"!options.hideSeconds\" [disabled]=\"disabled || activeTab !== 'hourly'\"\r\n (change)=\"regenerateCron()\" [(ngModel)]=\"state.hourly.seconds\" [ngClass]=\"options.formSelectClass\">\r\n <option *ngFor=\"let second of selectOptions.seconds\" [ngValue]=\"second\">\r\n {{second}}\r\n </option>\r\n </select>\r\n </div>\r\n </div>\r\n\r\n <!-- Daily-->\r\n <div class=\"tab-pane\" *ngIf=\"!options.hideDailyTab\" [ngClass]=\"{'active': activeTab === 'daily'}\">\r\n <div class=\"well well-small\">\r\n <input type=\"radio\" name=\"daily-radio\" value=\"everyDays\" [disabled]=\"disabled\" (change)=\"regenerateCron()\"\r\n [(ngModel)]=\"state.daily.subTab\" value=\"everyDays\" [disabled]=\"disabled\" (change)=\"regenerateCron()\"\r\n [(ngModel)]=\"state.daily.subTab\" [ngClass]=\"state.formRadioClass\" checked=\"checked\">\r\n Every\r\n <select class=\"days\" [disabled]=\"disabled || activeTab !== 'daily' || state.daily.subTab !== 'everyDays'\"\r\n (change)=\"regenerateCron()\" [(ngModel)]=\"state.daily.everyDays.days\" [ngClass]=\"options.formSelectClass\">\r\n <option *ngFor=\"let monthDay of selectOptions.monthDays\" [ngValue]=\"monthDay\">\r\n {{monthDay}}\r\n </option>\r\n </select> day(s) at\r\n\r\n <cron-time-picker [disabled]=\"disabled || activeTab !== 'daily' || state.daily.subTab !== 'everyDays'\"\r\n (change)=\"regenerateCron()\" [(time)]=\"state.daily.everyDays\" [selectClass]=\"options.formSelectClass\"\r\n [use24HourTime]=\"options.use24HourTime\" [hideSeconds]=\"options.hideSeconds\">\r\n </cron-time-picker>\r\n </div>\r\n\r\n <div class=\"well well-small\">\r\n <input type=\"radio\" name=\"daily-radio\" value=\"everyWeekDay\" [disabled]=\"disabled\" (change)=\"regenerateCron()\"\r\n [(ngModel)]=\"state.daily.subTab\" [ngClass]=\"state.formRadioClass\"> Every working day at\r\n <cron-time-picker [disabled]=\"disabled || activeTab !== 'daily' || state.daily.subTab !== 'everyWeekDay'\"\r\n (change)=\"regenerateCron()\" [(time)]=\"state.daily.everyWeekDay\" [selectClass]=\"options.formSelectClass\"\r\n [use24HourTime]=\"options.use24HourTime\" [hideSeconds]=\"options.hideSeconds\">\r\n </cron-time-picker>\r\n </div>\r\n </div>\r\n\r\n <!-- Weekly-->\r\n <div class=\"tab-pane\" *ngIf=\"!options.hideWeeklyTab\" [ngClass]=\"{'active': activeTab === 'weekly'}\">\r\n <div class=\"well well-small\">\r\n <div class=\"row\">\r\n <div class=\"col-sm-6\">\r\n <label class=\"advanced-cron-editor-label\"><input type=\"checkbox\" [disabled]=\"disabled || activeTab !== 'weekly'\" (change)=\"regenerateCron()\"\r\n [(ngModel)]=\"state.weekly.MON\" [ngClass]=\"options.formCheckboxClass\"> Monday</label>\r\n </div>\r\n <div class=\"col-sm-6\">\r\n <label class=\"advanced-cron-editor-label\"><input type=\"checkbox\" [disabled]=\"disabled || activeTab !== 'weekly'\" (change)=\"regenerateCron()\"\r\n [(ngModel)]=\"state.weekly.TUE\" [ngClass]=\"options.formCheckboxClass\"> Tuesday</label>\r\n </div>\r\n <div class=\"col-sm-6\">\r\n <label class=\"advanced-cron-editor-label\"><input type=\"checkbox\" [disabled]=\"disabled || activeTab !== 'weekly'\" (change)=\"regenerateCron()\"\r\n [(ngModel)]=\"state.weekly.WED\" [ngClass]=\"options.formCheckboxClass\"> Wednesday</label>\r\n </div>\r\n <div class=\"col-sm-6\">\r\n <label class=\"advanced-cron-editor-label\"><input type=\"checkbox\" [disabled]=\"disabled || activeTab !== 'weekly'\" (change)=\"regenerateCron()\"\r\n [(ngModel)]=\"state.weekly.THU\" [ngClass]=\"options.formCheckboxClass\"> Thursday</label>\r\n </div>\r\n <div class=\"col-sm-6\">\r\n <label class=\"advanced-cron-editor-label\"><input type=\"checkbox\" [disabled]=\"disabled || activeTab !== 'weekly'\" (change)=\"regenerateCron()\"\r\n [(ngModel)]=\"state.weekly.FRI\" [ngClass]=\"options.formCheckboxClass\"> Friday</label>\r\n </div>\r\n <div class=\"col-sm-6\">\r\n <label class=\"advanced-cron-editor-label\"><input type=\"checkbox\" [disabled]=\"disabled || activeTab !== 'weekly'\" (change)=\"regenerateCron()\"\r\n [(ngModel)]=\"state.weekly.SAT\" [ngClass]=\"options.formCheckboxClass\"> Saturday</label>\r\n </div>\r\n <div class=\"col-sm-6\">\r\n <label class=\"advanced-cron-editor-label\"><input type=\"checkbox\" [disabled]=\"disabled || activeTab !== 'weekly'\" (change)=\"regenerateCron()\"\r\n [(ngModel)]=\"state.weekly.SUN\" [ngClass]=\"options.formCheckboxClass\"> Sunday</label>\r\n </div>\r\n </div>\r\n <div class=\"row\">\r\n <div class=\"col-sm-6\">\r\n at\r\n <cron-time-picker [disabled]=\"disabled || activeTab !== 'weekly'\" (change)=\"regenerateCron()\"\r\n [(time)]=\"state.weekly\" [selectClass]=\"options.formSelectClass\" [use24HourTime]=\"options.use24HourTime\"\r\n [hideSeconds]=\"options.hideSeconds\">\r\n </cron-time-picker>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n\r\n <!-- Monthly-->\r\n <div class=\"tab-pane\" *ngIf=\"!options.hideMonthlyTab\" [ngClass]=\"{'active': activeTab === 'monthly'}\">\r\n <div class=\"well well-small\">\r\n <input type=\"radio\" name=\"monthly-radio\" value=\"specificDay\" [disabled]=\"disabled\" (change)=\"regenerateCron()\"\r\n [(ngModel)]=\"state.monthly.subTab\" [ngClass]=\"state.formRadioClass\"> On the\r\n <select class=\"month-days\" [disabled]=\"disabled || activeTab !== 'monthly' || state.monthly.subTab !== 'specificDay'\"\r\n (change)=\"regenerateCron()\" [(ngModel)]=\"state.monthly.specificDay.day\" [ngClass]=\"options.formSelectClass\">\r\n <option *ngFor=\"let monthDaysWithLast of selectOptions.monthDaysWithLasts\" [ngValue]=\"monthDaysWithLast\">\r\n {{monthDayDisplay(monthDaysWithLast)}}\r\n </option>\r\n </select> of every\r\n <select class=\"months-small\" [disabled]=\"disabled || activeTab !== 'monthly' || state.monthly.subTab !== 'specificDay'\"\r\n (change)=\"regenerateCron()\" [(ngModel)]=\"state.monthly.specificDay.months\" [ngClass]=\"options.formSelectClass\">\r\n <option *ngFor=\"let month of selectOptions.months\" [ngValue]=\"month\">\r\n {{month}}\r\n </option>\r\n </select> month(s) at\r\n <cron-time-picker [disabled]=\"disabled || activeTab !== 'monthly' || state.monthly.subTab !== 'specificDay'\"\r\n (change)=\"regenerateCron()\" [(time)]=\"state.monthly.specificDay\" [selectClass]=\"options.formSelectClass\"\r\n [use24HourTime]=\"options.use24HourTime\" [hideSeconds]=\"options.hideSeconds\">\r\n </cron-time-picker> \r\n <label class=\"advanced-cron-editor-label\"><input type=\"checkbox\" [disabled]=\"disabled || activeTab !== 'monthly' || state.monthly.subTab !== 'specificDay'\" \r\n (change)=\"regenerateCron()\" [(ngModel)]=\"state.monthly.runOnWeekday\" [ngClass]=\"options.formCheckboxClass\"> during the nearest weekday</label>\r\n </div>\r\n <div class=\"well well-small\">\r\n <input type=\"radio\" name=\"monthly-radio\" value=\"specificWeekDay\" [disabled]=\"disabled\" (change)=\"regenerateCron()\"\r\n [(ngModel)]=\"state.monthly.subTab\" [ngClass]=\"state.formRadioClass\">\r\n On the\r\n <select class=\"day-order-in-month\" [disabled]=\"disabled || activeTab !== 'monthly' || state.monthly.subTab !== 'specificWeekDay'\"\r\n (change)=\"regenerateCron()\" [(ngModel)]=\"state.monthly.specificWeekDay.monthWeek\" [ngClass]=\"options.formSelectClass\">\r\n <option *ngFor=\"let monthWeek of selectOptions.monthWeeks\" [ngValue]=\"monthWeek\">\r\n {{monthWeekDisplay(monthWeek)}}\r\n </option>\r\n </select>\r\n <select class=\"week-days\" [disabled]=\"disabled || activeTab !== 'monthly' || state.monthly.subTab !== 'specificWeekDay'\"\r\n (change)=\"regenerateCron()\" [(ngModel)]=\"state.monthly.specificWeekDay.day\" [ngClass]=\"options.formSelectClass\">\r\n <option *ngFor=\"let day of selectOptions.days\" [ngValue]=\"day\">\r\n {{dayDisplay(day)}}\r\n </option>\r\n </select> of every\r\n <select class=\"months-small\" [disabled]=\"disabled || activeTab !== 'monthly' || state.monthly.subTab !== 'specificWeekDay'\"\r\n (change)=\"regenerateCron()\" [(ngModel)]=\"state.monthly.specificWeekDay.months\" [ngClass]=\"options.formSelectClass\">\r\n <option *ngFor=\"let month of selectOptions.months\" [ngValue]=\"month\">\r\n {{month}}\r\n </option>\r\n </select> month(s) starting in\r\n <select class=\"months\" [disabled]=\"disabled || activeTab !== 'monthly' || state.monthly.subTab !== 'specificWeekDay'\"\r\n (change)=\"regenerateCron()\" [(ngModel)]=\"state.monthly.specificWeekDay.startMonth\" [ngClass]=\"options.formSelectClass\">\r\n <option *ngFor=\"let month of selectOptions.months\" [ngValue]=\"month\">\r\n {{monthDisplay(month)}}\r\n </option>\r\n </select>\r\n \r\n at\r\n <cron-time-picker [disabled]=\"disabled || activeTab !== 'monthly' || state.monthly.subTab !== 'specificWeekDay'\"\r\n (change)=\"regenerateCron()\" [(time)]=\"state.monthly.specificWeekDay\" [selectClass]=\"options.formSelectClass\"\r\n [use24HourTime]=\"options.use24HourTime\" [hideSeconds]=\"options.hideSeconds\">\r\n </cron-time-picker>\r\n </div>\r\n </div>\r\n\r\n <!-- Yearly-->\r\n <div class=\"tab-pane\" *ngIf=\"!options.hideYearlyTab\" [ngClass]=\"{'active': activeTab === 'yearly'}\">\r\n <div class=\"well well-small\">\r\n <input type=\"radio\" name=\"yearly-radio\" value=\"specificMonthDay\" [disabled]=\"disabled\" (change)=\"regenerateCron()\"\r\n [(ngModel)]=\"state.yearly.subTab\" [ngClass]=\"state.formRadioClass\">\r\n Every\r\n <select class=\"months\" [disabled]=\"disabled || activeTab !== 'yearly' || state.yearly.subTab !== 'specificMonthDay'\"\r\n (change)=\"regenerateCron()\" [(ngModel)]=\"state.yearly.specificMonthDay.month\" [ngClass]=\"options.formSelectClass\">\r\n <option *ngFor=\"let month of selectOptions.months\" [ngValue]=\"month\">\r\n {{monthDisplay(month)}}\r\n </option>\r\n </select> on the\r\n <select class=\"month-days\" [disabled]=\"disabled || activeTab !== 'yearly' || state.yearly.subTab !== 'specificMonthDay'\"\r\n (change)=\"regenerateCron()\" [(ngModel)]=\"state.yearly.specificMonthDay.day\" [ngClass]=\"options.formSelectClass\">\r\n <option *ngFor=\"let monthDaysWithLast of selectOptions.monthDaysWithLasts\" [ngValue]=\"monthDaysWithLast\">\r\n {{monthDayDisplay(monthDaysWithLast)}}\r\n </option>\r\n </select> at\r\n <cron-time-picker [disabled]=\"disabled || activeTab !== 'yearly' || state.yearly.subTab !== 'specificMonthDay'\"\r\n (change)=\"regenerateCron()\" [(time)]=\"state.yearly.specificMonthDay\" [selectClass]=\"options.formSelectClass\"\r\n [use24HourTime]=\"options.use24HourTime\" [hideSeconds]=\"options.hideSeconds\">\r\n </cron-time-picker> \r\n <label class=\"advanced-cron-editor-label\"><input type=\"checkbox\" (change)=\"regenerateCron()\"\r\n [(ngModel)]=\"state.yearly.runOnWeekday\" [ngClass]=\"options.formCheckboxClass\"> during the nearest weekday</label>\r\n </div>\r\n <div class=\"well well-small\">\r\n <input type=\"radio\" name=\"yearly-radio\" value=\"specificMonthWeek\" [disabled]=\"disabled\"\r\n (change)=\"regenerateCron()\" [(ngModel)]=\"state.yearly.subTab\" [ngClass]=\"state.formRadioClass\">\r\n On the\r\n <select class=\"day-order-in-month\" [disabled]=\"disabled || activeTab !== 'yearly' || state.yearly.subTab !== 'specificMonthWeek'\"\r\n (change)=\"regenerateCron()\" [(ngModel)]=\"state.yearly.specificMonthWeek.monthWeek\"\r\n [ngClass]=\"options.formSelectClass\">\r\n <option *ngFor=\"let monthWeek of selectOptions.monthWeeks\" [ngValue]=\"monthWeek\">\r\n {{monthWeekDisplay(monthWeek)}}\r\n </option>\r\n </select>\r\n <select class=\"week-days\" [disabled]=\"disabled || activeTab !== 'yearly' || state.yearly.subTab !== 'specificMonthWeek'\"\r\n (change)=\"regenerateCron()\" [(ngModel)]=\"state.yearly.specificMonthWeek.day\" [ngClass]=\"options.formSelectClass\">\r\n <option *ngFor=\"let day of selectOptions.days\" [ngValue]=\"day\">\r\n {{dayDisplay(day)}}\r\n </option>\r\n </select> of\r\n <select class=\"months\" [disabled]=\"disabled || activeTab