UNPKG

ngx-ntk-cron-editor

Version:

Angular cron editor

977 lines (968 loc) 94.7 kB
import * as i0 from '@angular/core'; import { EventEmitter, Component, Output, Input, Injectable, NgModule } from '@angular/core'; import * as i3 from '@angular/common'; import { CommonModule } from '@angular/common'; import * as i4 from '@angular/forms'; import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms'; import { distinctUntilChanged } from 'rxjs'; import * as i1 from '@ngx-translate/core'; import { TranslateService, TranslateModule } from '@ngx-translate/core'; import { HttpClientModule } from '@angular/common/http'; // @dynamic class Utils { /** This returns a range of numbers. Starts from 0 if 'startFrom' is not set */ static getRange(startFrom, until) { return Array.from({ length: (until + 1 - startFrom) }, (_, k) => k + startFrom); } static isObject(value) { return typeof value === 'object' && value !== null; } static merge(target, ...sources) { for (const source of sources) { for (const [key, value] of Object.entries(source)) { if (Utils.isObject(target[key]) && Utils.isObject(value)) { Utils.merge(target[key], value); } else { target[key] = value; } } } return target; } } class TimePickerComponent { constructor() { this.change = new EventEmitter(); } ngOnInit() { this.hours = this.use24HourTime ? Utils.getRange(0, 23) : Utils.getRange(0, 12); this.minutes = Utils.getRange(0, 59); this.seconds = Utils.getRange(0, 59); this.hourTypes = ['AM', 'PM']; } } TimePickerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TimePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); TimePickerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TimePickerComponent, selector: "cron-time-picker", inputs: { disabled: "disabled", time: "time", selectClass: "selectClass", use24HourTime: "use24HourTime", hideSeconds: "hideSeconds" }, outputs: { change: "change" }, ngImport: i0, template: "<!-- hour -->\r\n<select class=\"timeFormControl\" (change)=\"change.emit()\" [(ngModel)]=\"time.hours\" [disabled]=\"disabled\" [ngClass]=\"selectClass\">\r\n <option *ngFor=\"let hour of hours\" [ngValue]=\"hour\">{{hour}}</option>\r\n</select>\r\n\r\n<!-- minute -->\r\n<select class=\"timeFormControl\" (change)=\"change.emit()\" [(ngModel)]=\"time.minutes\" [disabled]=\"disabled\" [ngClass]=\"selectClass\">\r\n <option *ngFor=\"let minute of minutes\" [ngValue]=\"minute\">{{minute}}</option>\r\n</select>\r\n\r\n<!-- second -->\r\n<select class=\"timeFormControl\" (change)=\"change.emit()\" [(ngModel)]=\"time.seconds\" [disabled]=\"disabled\" *ngIf=\"!hideSeconds\"\r\n [ngClass]=\"selectClass\">\r\n <option *ngFor=\"let second of seconds\" [ngValue]=\"second\">{{second}}</option>\r\n</select>\r\n\r\n<!-- am/pm -->\r\n<select class=\"timeFormControl\" (change)=\"change.emit()\" [(ngModel)]=\"time.hourTypes\" [disabled]=\"disabled\" *ngIf=\"!use24HourTime\"\r\n [ngClass]=\"selectClass\">\r\n <option *ngFor=\"let hourType of hourTypes\" [ngValue]=\"hourType\">{{ hourType}}</option>\r\n</select>\r\n", styles: [".timeFormControl{width:70px;display:inline}\n"], dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i4.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i4.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TimePickerComponent, decorators: [{ type: Component, args: [{ selector: 'cron-time-picker', template: "<!-- hour -->\r\n<select class=\"timeFormControl\" (change)=\"change.emit()\" [(ngModel)]=\"time.hours\" [disabled]=\"disabled\" [ngClass]=\"selectClass\">\r\n <option *ngFor=\"let hour of hours\" [ngValue]=\"hour\">{{hour}}</option>\r\n</select>\r\n\r\n<!-- minute -->\r\n<select class=\"timeFormControl\" (change)=\"change.emit()\" [(ngModel)]=\"time.minutes\" [disabled]=\"disabled\" [ngClass]=\"selectClass\">\r\n <option *ngFor=\"let minute of minutes\" [ngValue]=\"minute\">{{minute}}</option>\r\n</select>\r\n\r\n<!-- second -->\r\n<select class=\"timeFormControl\" (change)=\"change.emit()\" [(ngModel)]=\"time.seconds\" [disabled]=\"disabled\" *ngIf=\"!hideSeconds\"\r\n [ngClass]=\"selectClass\">\r\n <option *ngFor=\"let second of seconds\" [ngValue]=\"second\">{{second}}</option>\r\n</select>\r\n\r\n<!-- am/pm -->\r\n<select class=\"timeFormControl\" (change)=\"change.emit()\" [(ngModel)]=\"time.hourTypes\" [disabled]=\"disabled\" *ngIf=\"!use24HourTime\"\r\n [ngClass]=\"selectClass\">\r\n <option *ngFor=\"let hourType of hourTypes\" [ngValue]=\"hourType\">{{ hourType}}</option>\r\n</select>\r\n", styles: [".timeFormControl{width:70px;display:inline}\n"] }] }], propDecorators: { change: [{ type: Output }], disabled: [{ type: Input }], time: [{ type: Input }], selectClass: [{ type: Input }], use24HourTime: [{ type: Input }], hideSeconds: [{ type: Input }] } }); const defaultCronOptions = { formInputClass: "form-control cron-editor-input", formSelectClass: "form-select cron-editor-select", formRadioClass: "cron-editor-radio", formCheckboxClass: "form-check-input cron-editor-checkbox", defaultTime: "10:00:00", use24HourTime: true, hideMinutesTab: false, hideHourlyTab: false, hideDailyTab: false, hideWeeklyTab: false, hideMonthlyTab: false, hideYearlyTab: false, hideAdvancedTab: false, hideSeconds: true, removeSeconds: true, removeYears: true, }; const Days = { 'SUN': 'Sunday', 'MON': 'Monday', 'TUE': 'Tuesday', 'WED': 'Wednesday', 'THU': 'Thursday', 'FRI': 'Friday', 'SAT': 'Saturday' }; const MonthWeeks = { '#1': 'First', '#2': 'Second', '#3': 'Third', '#4': 'Fourth', '#5': 'Fifth', 'L': 'Last' }; var Months; (function (Months) { Months[Months["January"] = 1] = "January"; Months[Months["February"] = 2] = "February"; Months[Months["March"] = 3] = "March"; Months[Months["April"] = 4] = "April"; Months[Months["May"] = 5] = "May"; Months[Months["June"] = 6] = "June"; Months[Months["July"] = 7] = "July"; Months[Months["August"] = 8] = "August"; Months[Months["September"] = 9] = "September"; Months[Months["October"] = 10] = "October"; Months[Months["November"] = 11] = "November"; Months[Months["December"] = 12] = "December"; })(Months || (Months = {})); const ru = { CRON: { TABS: { MINUTES: 'Минута', HOURLY: 'Час', DAILY: 'День', WEEKLY: 'Неделя', MONTHLY: 'Месяц', YEARLY: 'Год', ADVANCED: 'Продвинутый' }, MINUTES: { EVERY: 'Каждые(-ую)', MINUTES: 'минут(-у)', ON_SECOND: 'в секунду:' }, HOURLY: { EVERY: 'Каждый(-ые)', HOURS: 'час(-ов)', ON_MINUTE: 'в минуту:', ON_SECOND: 'и секунду:' }, DAILY: { EVERY: 'Каждый', DAYS: 'день в', WORKING_DAY: 'Каждый рабочий день в' }, WEEKLY: { AT: 'в' }, MONTHLY: { ON: 'В', OF_EVERY: 'каждый(-ые)', MONTHS: 'месяц(-ев)', NEAREST_WEEKDAY: 'в ближайший будний день', AT: 'в', STARTING_IN: 'начиная с' }, YEARLY: { EVERY: 'Каждый', ON: 'в', AT: 'в', OF: '', NEAREST_WEEKDAY: 'в ближайший будний день' }, ADVANCED: { CRON: 'Cron-выражение' }, MONTH_DAY: { LAST_DAY: 'Последний день', LAST_WEEKDAY: 'Последний рабочий день', FIRST_WEEKDAY: 'Первый рабочий день', DAY_N: '{{n}}-й день' }, MONTH_WEEK: { FIRST: 'Первый', SECOND: 'Второй', THIRD: 'Третий', FOURTH: 'Четвертый', FIFTH: 'Пятый', LAST: 'Последний' }, MONTH: { JANUARY: 'Январь', FEBRUARY: 'Февраль', MARCH: 'Март', APRIL: 'Апрель', MAY: 'Май', JUNE: 'Июнь', JULY: 'Июль', AUGUST: 'Август', SEPTEMBER: 'Сентябрь', OCTOBER: 'Октябрь', NOVEMBER: 'Ноябрь', DECEMBER: 'Декабрь' }, WEEK: { MON: 'Понедельник', TUE: 'Вторник', WED: 'Среда', THU: 'Четверг', FRI: 'Пятница', SAT: 'Суббота', SUN: 'Воскресенье', }, HOUR_TYPES: { AM: 'ДП', PM: 'ПП' }, VALIDATION_MESSAGE: { NULL: 'Cron-выражение не может быть null', SEGMENTS: 'Неверное cron-выражение, должно быть {{n}} сегментов' } } }; const en = { CRON: { TABS: { MINUTES: 'Minutes', HOURLY: 'Hourly', DAILY: 'Daily', WEEKLY: 'Weekly', MONTHLY: 'Monthly', YEARLY: 'Yearly', ADVANCED: 'Advanced' }, MINUTES: { EVERY: 'Every', MINUTES: 'minute(s)', ON_SECOND: 'on second' }, HOURLY: { EVERY: 'Every', HOURS: 'hour(s)', ON_MINUTE: 'on minute', ON_SECOND: 'and second' }, DAILY: { EVERY: 'Every', DAYS: 'day(s) at', WORKING_DAY: 'Every working day at' }, WEEKLY: { AT: 'at' }, MONTHLY: { ON: 'On the', OF_EVERY: 'of every', MONTHS: 'month(s)', NEAREST_WEEKDAY: 'during the nearest weekday', AT: 'at', STARTING_IN: 'starting in' }, YEARLY: { EVERY: 'Every', ON: 'on the', AT: 'at', OF: 'of', NEAREST_WEEKDAY: 'during the nearest weekday' }, ADVANCED: { CRON: 'Cron Expression' }, MONTH_DAY: { LAST_DAY: 'Last Day', LAST_WEEKDAY: 'Last Weekday', FIRST_WEEKDAY: 'First Weekday', DAY_N: 'Day {{n}}' }, MONTH_WEEK: { FIRST: 'First', SECOND: 'Second', THIRD: 'Third', FOURTH: 'Fourth', FIFTH: 'Fifth', LAST: 'Last' }, MONTH: { JANUARY: 'January', FEBRUARY: 'February', MARCH: 'March', APRIL: 'April', MAY: 'May', JUNE: 'June', JULY: 'July', AUGUST: 'August', SEPTEMBER: 'September', OCTOBER: 'October', NOVEMBER: 'November', DECEMBER: 'December' }, WEEK: { MON: 'Monday', TUE: 'Tuesday', WED: 'Wednesday', THU: 'Thursday', FRI: 'Friday', SAT: 'Saturday', SUN: 'Sunday', }, HOUR_TYPES: { AM: 'AM', PM: 'PM' }, VALIDATION_MESSAGE: { NULL: 'Cron expression cannot be null', SEGMENTS: 'Invalid cron expression, there must be {{n}} segments' } } }; const fa = { CRON: { TABS: { MINUTES: 'دقیقه', HOURLY: 'ساعت', DAILY: 'روز', WEEKLY: 'هفتگی', MONTHLY: 'ماهیانه', YEARLY: 'سالیانه', ADVANCED: 'Advanced' }, MINUTES: { EVERY: 'هر', MINUTES: 'minute(s)', ON_SECOND: 'on second' }, HOURLY: { EVERY: 'هر', HOURS: 'hour(s)', ON_MINUTE: 'on minute', ON_SECOND: 'and second' }, DAILY: { EVERY: 'هر', DAYS: 'day(s) at', WORKING_DAY: 'Every working day at' }, WEEKLY: { AT: 'at' }, MONTHLY: { ON: 'On the', OF_EVERY: 'of every', MONTHS: 'month(s)', NEAREST_WEEKDAY: 'during the nearest weekday', AT: 'at', STARTING_IN: 'starting in' }, YEARLY: { EVERY: 'هر', ON: 'on the', AT: 'at', OF: 'of', NEAREST_WEEKDAY: 'during the nearest weekday' }, ADVANCED: { CRON: 'Cron Expression' }, MONTH_DAY: { LAST_DAY: 'روز آخر', LAST_WEEKDAY: 'روز هفته گذشته', FIRST_WEEKDAY: 'روز اول هفته', DAY_N: 'Day {{n}}' }, MONTH_WEEK: { FIRST: 'اولین', SECOND: 'دومین', THIRD: 'سوم', FOURTH: 'چهارم', FIFTH: 'پنجم', LAST: 'آخر' }, MONTH: { JANUARY: 'January', FEBRUARY: 'February', MARCH: 'March', APRIL: 'April', MAY: 'May', JUNE: 'June', JULY: 'July', AUGUST: 'August', SEPTEMBER: 'September', OCTOBER: 'October', NOVEMBER: 'November', DECEMBER: 'December' }, WEEK: { MON: 'دوشنبه', TUE: 'سه شنبه', WED: 'چهارشنبه', THU: 'پنج شنبه', FRI: 'جمعه', SAT: 'شنبه', SUN: 'یکشنبه', }, HOUR_TYPES: { AM: 'صبح', PM: 'عصر' }, VALIDATION_MESSAGE: { NULL: 'Cron expression cannot be null', SEGMENTS: 'Invalid cron expression, there must be {{n}} segments' } } }; class TranslateUiService { constructor(translateService) { this.translateService = translateService; this.availableLanguages = { en, ru, fa }; } init(language = null) { if (language) { //initialize one specific language this.translateService.setTranslation(language, this.availableLanguages[language], true); } else { //initialize all Object.keys(this.availableLanguages).forEach((language) => { this.translateService.setTranslation(language, this.availableLanguages[language], true); }); } } } TranslateUiService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TranslateUiService, deps: [{ token: i1.TranslateService }], target: i0.ɵɵFactoryTarget.Injectable }); TranslateUiService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TranslateUiService }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TranslateUiService, decorators: [{ type: Injectable }], ctorParameters: function () { return [{ type: i1.TranslateService }]; } }); class CronEditorComponent { set language(value) { this._language = value; this.translateUiService.init(value); this.translate.use(this.language); } get language() { return this._language; } get cron() { return this.localCron; } set cron(value) { this.localCron = value; } constructor(translate, translateUiService) { this.translate = translate; this.translateUiService = translateUiService; this.id = ++CronEditorComponent.nextId; this._language = 'en'; // @Input({ // transform: (value: CronOptionModel | null) => { // if (value) return value; // return defaultCronOptions; // }, // }) this.options = defaultCronOptions; // the name is an Angular convention, @Input variable name + "Change" suffix this.cronChange = new EventEmitter(); this.selectOptions = this.getSelectOptions(); } ngOnInit() { if (this.options.removeSeconds) { this.options.hideSeconds = true; } this.state = this.getDefaultState(); this.handleModelChange(this.cron); } ngOnChanges(changes) { const newCron = changes["cron"]; if (newCron && !newCron.firstChange) { this.handleModelChange(this.cron); } } writeValue(cronExpression) { this.handleModelChange(cronExpression); } registerOnChange(onChange) { this.cronChange.subscribe({ next: (cronExpression) => { onChange(cronExpression); this.validate(cronExpression); }, }); } registerOnTouched(onTouched) { this.cronChange.pipe(distinctUntilChanged()).subscribe(onTouched); } setDisabledState(isDisabled) { this.disabled = isDisabled; } setActiveTab(tab) { if (!this.disabled) { this.activeTab = tab; this.regenerateCron(); } } dayDisplay(day) { return Days[day]; } monthWeekDisplay(monthWeekNumber) { return MonthWeeks[monthWeekNumber]; } monthDisplay(month) { return Months[month]; } monthDayDisplay(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`; } } regenerateCron() { this.isDirty = true; const oldCron = this.localCron; 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": const days = this.selectOptions.days .reduce((acc, day) => (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": const 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 const 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"); } if (oldCron !== this.cron) { this.cronChange.emit(this.cron); } } getAmPmHour(hour) { return this.options.use24HourTime ? hour : ((hour + 11) % 12) + 1; } getHourType(hour) { return this.options.use24HourTime ? undefined : hour >= 12 ? "PM" : "AM"; } hourToCron(hour, hourType) { if (this.options.use24HourTime) { return hour; } else { return hourType === "AM" ? hour === 12 ? 0 : hour : hour === 12 ? 12 : hour + 12; } } handleModelChange(cron) { if (this.isDirty) { this.isDirty = false; return; } else { this.isDirty = false; } this.validate(cron); const oldValue = this.localCron; let cronSeven = cron; if (this.options.removeSeconds) { cronSeven = `0 ${cron}`; } if (this.options.removeYears) { cronSeven = `${cronSeven} *`; } const [seconds, minutes, hours, dayOfMonth, month, dayOfWeek] = cronSeven.split(" "); 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)); const 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"; const 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((weekDay) => (this.state.weekly[weekDay] = false)); dayOfWeek .split(",") .forEach((weekDay) => (this.state.weekly[weekDay] = true)); const 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+(L|LW|W)? 1\/\d+ \?/)) { this.activeTab = "monthly"; this.state.monthly.subTab = "specificDay"; const wIndex = dayOfMonth.indexOf("W"); if (wIndex !== -1) { this.state.monthly.specificDay.day = dayOfMonth.split("W")[0]; this.state.monthly.runOnWeekday = true; } else { this.state.monthly.specificDay.day = dayOfMonth; this.state.monthly.runOnWeekday = false; } this.state.monthly.specificDay.months = Number(month.substring(2)); const 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) \*/)) { const day = dayOfWeek.substr(0, 3); const 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) { const [startMonth, months] = month.split("/").map(Number); this.state.monthly.specificWeekDay.months = months; this.state.monthly.specificWeekDay.startMonth = startMonth; } const 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; } const 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) \*/)) { const day = dayOfWeek.substr(0, 3); const 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); const 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; } if (oldValue !== this.cron) { this.cronChange.emit(this.cron); } } validate(cron) { this.state.validation.isValid = false; this.state.validation.errorMessage = ""; if (!cron) { this.state.validation.errorMessage = "Cron expression cannot be null"; return; } const cronParts = cron.split(" "); let 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; } getDefaultAdvancedCronExpression() { 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"; } getDefaultState() { const [defaultHours, defaultMinutes, defaultSeconds] = this.options.defaultTime.split(":").map(Number); 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: "", }, }; } getOrdinalSuffix(value) { if (value.length > 1) { const secondToLastDigit = value.charAt(value.length - 2); if (secondToLastDigit === "1") { return "th"; } } const lastDigit = value.charAt(value.length - 1); switch (lastDigit) { case "1": return "st"; case "2": return "nd"; case "3": return "rd"; default: return "th"; } } getSelectOptions() { 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: [...Utils.getRange(1, 31).map(String), "L"], hourTypes: ["AM", "PM"], }; } } CronEditorComponent.nextId = 0; CronEditorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CronEditorComponent, deps: [{ token: i1.TranslateService }, { token: TranslateUiService }], target: i0.ɵɵFactoryTarget.Component }); CronEditorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: CronEditorComponent, selector: "cron-editor", inputs: { language: "language", disabled: "disabled", options: "options", cron: "cron" }, outputs: { cronChange: "cronChange" }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: CronEditorComponent, multi: true, }, ], usesOnChanges: true, ngImport: i0, template: "<!-- Tabs -->\r\n<ul class=\"nav nav-tabs\" role=\"tablist\">\r\n <li class=\"nav-item\" *ngIf=\"!options.hideMinutesTab\">\r\n <a class=\"nav-link\" [ngClass]=\"{ active: activeTab === 'minutes' }\" aria-controls=\"minutes\" role=\"tab\"\r\n data-bs-toggle=\"tab\" (click)=\"setActiveTab('minutes')\">\r\n {{'CRON.TABS.MINUTES'|translate}}\r\n </a>\r\n </li>\r\n\r\n <li class=\"nav-item\" *ngIf=\"!options.hideHourlyTab\">\r\n <a class=\"nav-link\" [ngClass]=\"{ active: activeTab === 'hourly' }\" aria-controls=\"hourly\" role=\"tab\"\r\n data-bs-toggle=\"tab\" (click)=\"setActiveTab('hourly')\">\r\n {{'CRON.TABS.HOURLY'|translate}}\r\n </a>\r\n </li>\r\n\r\n <li class=\"nav-item\" *ngIf=\"!options.hideDailyTab\">\r\n <a class=\"nav-link\" [ngClass]=\"{ active: activeTab === 'daily' }\" aria-controls=\"daily\" role=\"tab\"\r\n data-bs-toggle=\"tab\" (click)=\"setActiveTab('daily')\">\r\n {{'CRON.TABS.DAILY'|translate}}\r\n </a>\r\n </li>\r\n\r\n <li class=\"nav-item\" *ngIf=\"!options.hideWeeklyTab\">\r\n <a class=\"nav-link\" [ngClass]=\"{ active: activeTab === 'weekly' }\" aria-controls=\"weekly\" role=\"tab\"\r\n data-bs-toggle=\"tab\" (click)=\"setActiveTab('weekly')\">\r\n {{'CRON.TABS.WEEKLY'|translate}}\r\n </a>\r\n </li>\r\n\r\n <li class=\"nav-item\" *ngIf=\"!options.hideMonthlyTab\">\r\n <a class=\"nav-link\" [ngClass]=\"{ active: activeTab === 'monthly' }\" aria-controls=\"monthly\" role=\"tab\"\r\n data-bs-toggle=\"tab\" (click)=\"setActiveTab('monthly')\">\r\n {{'CRON.TABS.MONTHLY'|translate}}\r\n </a>\r\n </li>\r\n\r\n <li class=\"nav-item\" *ngIf=\"!options.hideYearlyTab\">\r\n <a class=\"nav-link\" [ngClass]=\"{ active: activeTab === 'yearly' }\" aria-controls=\"yearly\" role=\"tab\"\r\n data-bs-toggle=\"tab\" (click)=\"setActiveTab('yearly')\">\r\n {{'CRON.TABS.YEARLY'|translate}}\r\n </a>\r\n </li>\r\n\r\n <li class=\"nav-item\" *ngIf=\"!options.hideAdvancedTab\">\r\n <a class=\"nav-link\" [ngClass]=\"{ active: activeTab === 'advanced' }\" aria-controls=\"advanced\" role=\"tab\"\r\n data-bs-toggle=\"tab\" (click)=\"setActiveTab('advanced')\">\r\n {{'CRON.TABS.ADVANCED'|translate}}\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-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=\"card card-body bg-light\">\r\n {{'CRON.MINUTES.EVERY'|translate}}\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 | number:'2.0' }}\r\n </option>\r\n </select>\r\n {{'CRON.MINUTES.MINUTES'|translate}}\r\n <span *ngIf=\"!options.hideSeconds\">{{'CRON.MINUTES.ON_SECOND'|translate}}</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 | number:'2.0' }}\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=\"card card-body bg-light\">\r\n {{'CRON.HOURLY.EVERY'|translate}}\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>\r\n {{'CRON.HOURLY.HOURS'|translate}}\r\n {{'CRON.HOURLY.ON_MINUTE'|translate}}\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 | number:'2.0' }}\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=\"card card-body bg-light\">\r\n <input type=\"radio\" name=\"daily-radio\" value=\"everyDays\" [disabled]=\"disabled\" (change)=\"regenerateCron()\"\r\n [(ngModel)]=\"state.daily.subTab\" [ngClass]=\"state.formRadioClass\" checked=\"checked\" />\r\n {{'CRON.DAILY.EVERY'|translate}}\r\n <select class=\"days\" [disabled]=\"\r\n disabled ||\r\n activeTab !== 'daily' ||\r\n state.daily.subTab !== 'everyDays'\r\n \" (change)=\"regenerateCron()\" [(ngModel)]=\"state.daily.everyDays.days\"\r\n [ngClass]=\"options.formSelectClass\">\r\n <option *ngFor=\"let monthDay of selectOptions.monthDays\" [ngValue]=\"monthDay\">\r\n {{ monthDay }}\r\n </option>\r\n </select>\r\n {{'CRON.DAILY.DAYS'|translate}}\r\n <cron-time-picker [disabled]=\"\r\n disabled ||\r\n activeTab !== 'daily' ||\r\n 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=\"card card-body bg-light\">\r\n <input type=\"radio\" name=\"daily-radio\" value=\"everyWeekDay\" [disabled]=\"disabled\"\r\n (change)=\"regenerateCron()\" [(ngModel)]=\"state.daily.subTab\" [ngClass]=\"state.formRadioClass\" />\r\n {{'CRON.DAILY.WORKING_DAY'|translate}}\r\n <cron-time-picker [disabled]=\"\r\n disabled ||\r\n activeTab !== 'daily' ||\r\n 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=\"card card-body bg-light\">\r\n <div class=\"row\">\r\n <div class=\"col-sm-6\">\r\n <label class=\"advanced-cron-editor-label\"><input type=\"checkbox\"\r\n [disabled]=\"disabled || activeTab !== 'weekly'\" (change)=\"regenerateCron()\"\r\n [(ngModel)]=\"state.weekly.MON\" [ngClass]=\"options.formCheckboxClass\" />\r\n {{'CRON.WEEK.MON'|translate}}</label>\r\n </div>\r\n <div class=\"col-sm-6\">\r\n <label class=\"advanced-cron-editor-label\"><input type=\"checkbox\"\r\n [disabled]=\"disabled || activeTab !== 'weekly'\" (change)=\"regenerateCron()\"\r\n [(ngModel)]=\"state.weekly.TUE\" [ngClass]=\"options.form