-
-
-
-
-
-
+
diff --git a/src/VueCronEditorBootstrap.vue b/src/VueCronEditorBootstrap.vue
index 2dc031e..dd5c811 100644
--- a/src/VueCronEditorBootstrap.vue
+++ b/src/VueCronEditorBootstrap.vue
@@ -1,204 +1,151 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+ {{ translate('every') }}
+
+ {{ translate('mminutes') }}
+
+
+
+
+
+
+ {{ translate('every') }}
+
+ {{ translate('hoursOnMinute') }}
+
+
+
+
+
+
+
+ {{ translate('every') }}
+
+ {{ translate('daysAt') }}
+
+
+
+
+
+
+
+ {{ translate('every') }}
+ {{ translate('sun') }}
+ {{ translate('mon') }}
+ {{ translate('tue') }}
+ {{ translate('wed') }}
+ {{ translate('thu') }}
+ {{ translate('fri') }}
+ {{ translate('sat') }}
+ {{ translate('at') }}
+
+
+
+
+
+
+
+ {{ translate('onThe') }}
+
+ {{ translate('dayOfEvery') }}
+
+ {{ translate('monthsAt') }}
+
+
+
+
+
+
+
+ {{ translate('cronExpression') }}
+
+ {{ explanation }}
+
+
+
+
diff --git a/src/core/cronExpressions.ts b/src/core/cronExpressions.ts
index d7a6f39..037d0d0 100644
--- a/src/core/cronExpressions.ts
+++ b/src/core/cronExpressions.ts
@@ -1,135 +1,147 @@
interface MinutesTabUpdatedEvent {
- type: "minutes";
- minuteInterval: number;
+ type: 'minutes'
+ minuteInterval: number
}
+
interface HourlyTabUpdatedEvent {
- type: "hourly";
- minutes: number;
- hourInterval: number;
+ type: 'hourly'
+ minutes: number
+ hourInterval: number
}
+
interface DailyTabUpdatedEvent {
- type: "daily";
- minutes: number;
- hours: number;
- dayInterval: number;
+ type: 'daily'
+ minutes: number
+ hours: number
+ dayInterval: number
}
+
interface WeeklyTabUpdatedEvent {
- type: "weekly";
- minutes: number;
- hours: number;
- days: string[];
+ type: 'weekly'
+ minutes: number
+ hours: number
+ days: string[]
}
+
interface MonthlyTabUpdatedEvent {
- type: "monthly";
- minutes: number;
- hours: number;
- day: number;
- monthInterval: number;
+ type: 'monthly'
+ minutes: number
+ hours: number
+ day: number
+ monthInterval: number
}
interface AdvancedTabUpdatedEvent {
- type: "advanced";
- cronExpression: string;
+ type: 'advanced'
+ cronExpression: string
}
export type TabUpdatedEvent =
- | MinutesTabUpdatedEvent
- | HourlyTabUpdatedEvent
- | DailyTabUpdatedEvent
- | WeeklyTabUpdatedEvent
- | MonthlyTabUpdatedEvent
- | AdvancedTabUpdatedEvent;
+ | MinutesTabUpdatedEvent
+ | HourlyTabUpdatedEvent
+ | DailyTabUpdatedEvent
+ | WeeklyTabUpdatedEvent
+ | MonthlyTabUpdatedEvent
+ | AdvancedTabUpdatedEvent
-export type TabKey = TabUpdatedEvent[keyof TabUpdatedEvent];
+export type TabKey = TabUpdatedEvent[keyof TabUpdatedEvent]
export const buildExpression = (event: TabUpdatedEvent): string => {
- if (event.type === "minutes") {
- return `*/${event.minuteInterval} * * * *`;
- }
- if (event.type === "hourly") {
- return `${event.minutes} */${event.hourInterval} * * *`;
- }
- if (event.type === "daily") {
- return `${event.minutes} ${event.hours} */${event.dayInterval} * *`;
- }
- if (event.type === "weekly") {
- return (
- `${event.minutes} ${event.hours} * * ` +
- `${event.days
- .filter(d => d)
- .sort()
- .join()}`
- );
- }
- if (event.type === "monthly") {
- return `${event.minutes} ${event.hours} ${event.day} */${event.monthInterval} *`;
- }
- if (event.type === "advanced") {
- return event.cronExpression;
- }
- throw `unknown event type: ${event}`;
-};
+ if (event.type === 'minutes') {
+ return `*/${event.minuteInterval} * * * *`
+ }
+
+ if (event.type === 'hourly') {
+ return `${event.minutes} */${event.hourInterval} * * *`
+ }
+
+ if (event.type === 'daily') {
+ return `${event.minutes} ${event.hours} */${event.dayInterval} * *`
+ }
+
+ if (event.type === 'weekly') {
+ return (
+ `${event.minutes} ${event.hours} * * ` +
+ `${event.days
+ .filter(d => d)
+ .sort()
+ .join()}`
+ )
+ }
+
+ if (event.type === 'monthly') {
+ return `${event.minutes} ${event.hours} ${event.day} */${event.monthInterval} *`
+ }
+
+ if (event.type === 'advanced') {
+ return event.cronExpression
+ }
+
+ throw `unknown event type: ${event}`
+}
export const parseExpression = (expression: string): TabUpdatedEvent => {
- let groups = null;
+ let groups = null
- if (expression.split(" ").length != 5) {
- return {
- type: "advanced",
- cronExpression: expression
- };
- }
- if ((groups = expression.match(/^\*\/(\d+) \* \* \* \*$/))) {
- return {
- type: "minutes",
- minuteInterval: Number(groups[1])
- };
- }
- if ((groups = expression.match(/^(\d+) \*\/(\d+) \* \* \*$/))) {
- return {
- type: "hourly",
- minutes: Number(groups[1]),
- hourInterval: Number(groups[2])
- };
- }
- if ((groups = expression.match(/^(\d+) (\d+) \*\/(\d+) \* \*$/))) {
- return {
- type: "daily",
- minutes: Number(groups[1]),
- hours: Number(groups[2]),
- dayInterval: Number(groups[3])
- };
- }
- if (
- (groups = expression.match(
- /^(\d+) (\d+) \* \* (\d)(,\d)?(,\d)?(,\d)?(,\d)?(,\d)?(,\d)?$/
- ))
- ) {
- const optionalDaysBeginIndex = 4;
- const matchesEndIndex = 10;
- return {
- type: "weekly",
- minutes: Number(groups[1]),
- hours: Number(groups[2]),
- days: [groups[3]].concat(
- groups
- .slice(optionalDaysBeginIndex, matchesEndIndex)
- .map(d => d && d.replace(/,/, ""))
- .filter(d => d)
- )
- };
- }
- if ((groups = expression.match(/^(\d+) (\d+) (\d+) \*\/(\d+) \*$/))) {
- return {
- type: "monthly",
- minutes: Number(groups[1]),
- hours: Number(groups[2]),
- day: Number(groups[3]),
- monthInterval: Number(groups[4])
- };
- }
+ if (expression!.split(' ').length != 5) {
return {
- type: "advanced",
- cronExpression: expression
- };
-};
+ type: 'advanced',
+ cronExpression: expression
+ }
+ }
+
+ if ((groups = expression.match(/^\*\/(\d+) \* \* \* \*$/))) {
+ return {
+ type: 'minutes',
+ minuteInterval: Number(groups[1])
+ }
+ }
+
+ if ((groups = expression.match(/^(\d+) \*\/(\d+) \* \* \*$/))) {
+ return {
+ type: 'hourly',
+ minutes: Number(groups[1]),
+ hourInterval: Number(groups[2])
+ }
+ }
+
+ if ((groups = expression.match(/^(\d+) (\d+) \*\/(\d+) \* \*$/))) {
+ return {
+ type: 'daily',
+ minutes: Number(groups[1]),
+ hours: Number(groups[2]),
+ dayInterval: Number(groups[3])
+ }
+ }
+
+ if ((groups = expression.match(/^(\d+) (\d+) \* \* (\d)(,\d)?(,\d)?(,\d)?(,\d)?(,\d)?(,\d)?$/))) {
+ const optionalDaysBeginIndex = 4
+ const matchesEndIndex = 10
+ return {
+ type: 'weekly',
+ minutes: Number(groups[1]),
+ hours: Number(groups[2]),
+ days: [groups[3]].concat(
+ groups
+ .slice(optionalDaysBeginIndex, matchesEndIndex)
+ .map(d => d && d.replace(/,/, ''))
+ .filter(d => d)
+ )
+ }
+ }
+
+ if ((groups = expression.match(/^(\d+) (\d+) (\d+) \*\/(\d+) \*$/))) {
+ return {
+ type: 'monthly',
+ minutes: Number(groups[1]),
+ hours: Number(groups[2]),
+ day: Number(groups[3]),
+ monthInterval: Number(groups[4])
+ }
+ }
+
+ return {
+ type: 'advanced',
+ cronExpression: expression
+ }
+}
diff --git a/src/core/i18n.ts b/src/core/i18n.ts
index c4f3989..3d92740 100644
--- a/src/core/i18n.ts
+++ b/src/core/i18n.ts
@@ -1,64 +1,64 @@
export const defaultLocales: Record
> = {
- en: {
- every: "Every",
- mminutes: "minute(s)",
- hoursOnMinute: "hour(s) on minute",
- daysAt: "day(s) at",
- at: "at",
- onThe: "On the",
- dayOfEvery: "day, of every",
- monthsAt: "month(s), at",
- everyDay: "Every",
- mon: "Mon",
- tue: "Tue",
- wed: "Wed",
- thu: "Thu",
- fri: "Fri",
- sat: "Sat",
- sun: "Sun",
- hasToBeBetween: "Has to be between",
- and: "and",
- minutes: "MINUTES",
- hourly: "HOURLY",
- daily: "DAILY",
- weekly: "WEEKLY",
- monthly: "MONTHLY",
- advanced: "ADVANCED",
- cronExpression: "cron expression:"
- },
- pl: {
- every: "Co",
- mminutes: "minut",
- hoursOnMinute: "godzin w minucie",
- daysAt: "dni o",
- at: "o",
- onThe: "",
- dayOfEvery: "dzień miesiąca, co",
- monthsAt: "miesięcy, o godzinie",
- everyDay: "W każdy",
- mon: "Pon",
- tue: "Wt",
- wed: "Śr",
- thu: "Czw",
- fri: "Pt",
- sat: "So",
- sun: "Nie",
- hasToBeBetween: "Wymagana wartość pomiędzy",
- and: "i",
- minutes: "Minuty",
- hourly: "Godziny",
- daily: "Dni",
- weekly: "Tygodnie",
- monthly: "Miesiące",
- advanced: "Zaawansowane",
- cronExpression: "Wyrażenie cron:"
- }
-};
+ en: {
+ every: 'Every',
+ mminutes: 'minute(s)',
+ hoursOnMinute: 'hour(s) on minute',
+ daysAt: 'day(s) at',
+ at: 'at',
+ onThe: 'On the',
+ dayOfEvery: 'day, of every',
+ monthsAt: 'month(s), at',
+ everyDay: 'Every',
+ mon: 'Mon',
+ tue: 'Tue',
+ wed: 'Wed',
+ thu: 'Thu',
+ fri: 'Fri',
+ sat: 'Sat',
+ sun: 'Sun',
+ hasToBeBetween: 'Has to be between',
+ and: 'and',
+ minutes: 'MINUTES',
+ hourly: 'HOURLY',
+ daily: 'DAILY',
+ weekly: 'WEEKLY',
+ monthly: 'MONTHLY',
+ advanced: 'ADVANCED',
+ cronExpression: 'cron expression:'
+ },
+ pl: {
+ every: 'Co',
+ mminutes: 'minut',
+ hoursOnMinute: 'godzin w minucie',
+ daysAt: 'dni o',
+ at: 'o',
+ onThe: '',
+ dayOfEvery: 'dzień miesiąca, co',
+ monthsAt: 'miesięcy, o godzinie',
+ everyDay: 'W każdy',
+ mon: 'Pon',
+ tue: 'Wt',
+ wed: 'Śr',
+ thu: 'Czw',
+ fri: 'Pt',
+ sat: 'So',
+ sun: 'Nie',
+ hasToBeBetween: 'Wymagana wartość pomiędzy',
+ and: 'i',
+ minutes: 'Minuty',
+ hourly: 'Godziny',
+ daily: 'Dni',
+ weekly: 'Tygodnie',
+ monthly: 'Miesiące',
+ advanced: 'Zaawansowane',
+ cronExpression: 'Wyrażenie cron:'
+ }
+}
export function createI18n(
- customLocales: Record>,
- locale: string
+ customLocales: Record>,
+ locale: string
): Record {
- const allLocales = { ...defaultLocales, ...customLocales };
- return allLocales[locale];
+ const allLocales = { ...defaultLocales, ...customLocales }
+ return allLocales[locale]
}
diff --git a/src/core/vueCronEditorMixin.ts b/src/core/vueCronEditorMixin.ts
index 9139a2a..9192f1b 100644
--- a/src/core/vueCronEditorMixin.ts
+++ b/src/core/vueCronEditorMixin.ts
@@ -4,143 +4,151 @@
* Functionality dependent on UI frameworks should be implemented in derived components
*/
-import {
- buildExpression,
- parseExpression,
- TabUpdatedEvent,
- TabKey
-} from "./cronExpressions";
-import * as cronValidator from "cron-validator";
-import * as cronstrue from "cronstrue/i18n";
-import { createI18n } from "./i18n";
+import { buildExpression, parseExpression, TabUpdatedEvent, TabKey } from './cronExpressions'
+import * as cronValidator from 'cron-validator'
+import * as cronstrue from 'cronstrue/i18n'
+import { createI18n } from './i18n'
-import Vue from "vue";
+import Vue from 'vue'
const initialData: Record = {
- minutes: {
- type: "minutes",
- minuteInterval: 1
- },
- hourly: {
- type: "hourly",
- minutes: 0,
- hourInterval: 1
- },
- daily: {
- type: "daily",
- minutes: 0,
- hours: 0,
- dayInterval: 1
- },
- weekly: {
- type: "weekly",
- minutes: 0,
- hours: 0,
- days: ["1"]
- },
- monthly: {
- type: "monthly",
- hours: 0,
- minutes: 0,
- day: 1,
- monthInterval: 1
- },
- advanced: {
- type: "advanced",
- cronExpression: ""
- }
-};
+ minutes: {
+ type: 'minutes',
+ minuteInterval: 1
+ },
+ hourly: {
+ type: 'hourly',
+ minutes: 0,
+ hourInterval: 1
+ },
+ daily: {
+ type: 'daily',
+ minutes: 0,
+ hours: 0,
+ dayInterval: 1
+ },
+ weekly: {
+ type: 'weekly',
+ minutes: 0,
+ hours: 0,
+ days: ['1']
+ },
+ monthly: {
+ type: 'monthly',
+ hours: 0,
+ minutes: 0,
+ day: 1,
+ monthInterval: 1
+ },
+ advanced: {
+ type: 'advanced',
+ cronExpression: ''
+ }
+}
interface ComponentData {
- editorData: Object;
- currentTab: TabKey;
- innerValue: string | null;
- i18n: Record | null;
+ editorData: any
+ currentTab: TabKey
+ innerValue: string | null
+ i18n: Record | null
}
export default Vue.extend({
- created() {
- this.i18n = createI18n(this.customLocales, this.locale);
- this.innerValue = this.value;
- this.__loadDataFromExpression();
- },
- props: {
- value: { type: String, default: "*/1 * * * *" },
- isAdvancedTabVisible: { type: Boolean, default: true },
- preserveStateOnSwitchToAdvanced: { type: Boolean, default: false },
- locale: { type: String, default: "en" },
- customLocales: { type: Object, default: null }
- },
- data() {
- return {
- innerValue: "*/1 * * * *",
- editorData: Object.assign({}, initialData.minutes),
- currentTab: "minutes",
- i18n: null
- };
- },
- computed: {
- explanation(): string {
- if (!this.innerValue) return "";
- return (cronstrue as any).toString(this.innerValue, {
- locale: this.locale
- });
- }
- },
- methods: {
- _$t(key: string) {
- return this.i18n![key];
- },
- __loadDataFromExpression() {
- const tabData = parseExpression(this.value);
- this.$data.editorData = { ...tabData };
+ props: {
+ value: { type: String, default: '*/1 * * * *' },
+ isAdvancedTabVisible: { type: Boolean, default: true },
+ preserveStateOnSwitchToAdvanced: { type: Boolean, default: false },
+ locale: { type: String, default: 'en' },
+ customLocales: { type: Object, default: null }
+ },
- this.currentTab = tabData.type;
- },
- __updateCronExpression(event: TabUpdatedEvent) {
- const cronExpression = buildExpression({
- ...event
- });
-
- if (cronValidator.isValidCron(cronExpression)) {
- this.innerValue = cronExpression;
- this.$emit("input", cronExpression);
- } else {
- this.innerValue = null;
- this.$emit("input", null);
- }
- },
- _resetToTab(tabKey: TabKey) {
- this.currentTab = tabKey;
- if (this.preserveStateOnSwitchToAdvanced && tabKey === "advanced") {
- this.$data.editorData = {
- type: "advanced",
- cronExpression: this.innerValue
- };
- return;
- }
-
- const tabData = parseExpression(this.value);
- if (tabKey == tabData.type) return;
-
- this.$data.editorData = Object.assign({}, initialData[tabKey]);
- this.__updateCronExpression(initialData[tabKey]);
- }
- },
- watch: {
- value: {
- handler() {
- if (this.value == this.innerValue) {
- return;
- }
- this.__loadDataFromExpression();
- }
- },
- editorData: {
- deep: true,
- handler(changedData) {
- this.__updateCronExpression(changedData);
- }
- }
+ data() {
+ return {
+ innerValue: '*/1 * * * *',
+ editorData: Object.assign({}, initialData.minutes),
+ currentTab: 'minutes',
+ i18n: null
}
-});
+ },
+
+ computed: {
+ explanation(): string {
+ if (!this.innerValue) {
+ return ''
+ }
+
+ return (cronstrue as any).toString(this.innerValue, {
+ locale: this.locale
+ })
+ }
+ },
+
+ watch: {
+ value: {
+ handler() {
+ if (this.value == this.innerValue) {
+ return
+ }
+ this.loadDataFromExpression()
+ }
+ },
+
+ editorData: {
+ deep: true,
+ handler(changedData) {
+ this.updateCronExpression(changedData)
+ }
+ }
+ },
+
+ created() {
+ this.i18n = createI18n(this.customLocales, this.locale)
+ this.innerValue = this.value
+ this.loadDataFromExpression()
+ },
+
+ methods: {
+ translate(key: string) {
+ return this.i18n![key]
+ },
+
+ loadDataFromExpression() {
+ const tabData = parseExpression(this.value)
+ this.editorData = { ...tabData }
+ this.currentTab = tabData.type
+ },
+
+ updateCronExpression(event: TabUpdatedEvent) {
+ const cronExpression = buildExpression({ ...event })
+
+ if (cronValidator.isValidCron(cronExpression)) {
+ this.innerValue = cronExpression
+ this.$emit('input', cronExpression)
+ } else {
+ this.innerValue = null
+ this.$emit('input', null)
+ }
+ },
+
+ resetToTab(tabKey: TabKey) {
+ this.currentTab = tabKey
+
+ if (this.preserveStateOnSwitchToAdvanced && tabKey === 'advanced') {
+ this.editorData = {
+ type: 'advanced',
+ cronExpression: this.innerValue
+ }
+ return
+ }
+
+ const tabData = parseExpression(this.value)
+ if (tabKey == tabData.type) {
+ this.editorData = Object.assign({}, tabData)
+ return
+ }
+
+ this.editorData = Object.assign({}, initialData[tabKey])
+ this.updateCronExpression(initialData[tabKey])
+ }
+ }
+})
diff --git a/src/main.ts b/src/main.ts
index 1f4f28e..fca74cf 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,8 +1,8 @@
-import Vue from "vue";
-import App from "./App.vue";
+import Vue from 'vue'
+import App from './App.vue'
-Vue.config.productionTip = false;
+Vue.config.productionTip = false
new Vue({
- render: h => h(App)
-}).$mount("#app");
+ render: h => h(App)
+}).$mount('#app')
diff --git a/src/shims-tsx.d.ts b/src/shims-tsx.d.ts
index 67a8308..f6deec4 100644
--- a/src/shims-tsx.d.ts
+++ b/src/shims-tsx.d.ts
@@ -1,13 +1,15 @@
-import Vue, { VNode } from "vue";
+import Vue, { VNode } from 'vue'
declare global {
- namespace JSX {
- // tslint:disable no-empty-interface
- interface Element extends VNode {}
- // tslint:disable no-empty-interface
- interface ElementClass extends Vue {}
- interface IntrinsicElements {
- [elem: string]: any;
- }
+ namespace JSX {
+ // tslint:disable no-empty-interface
+ type Element = VNode
+
+ // tslint:disable no-empty-interface
+ type ElementClass = Vue
+
+ interface IntrinsicElements {
+ [elem: string]: any
}
+ }
}
diff --git a/src/shims-vue.d.ts b/src/shims-vue.d.ts
index d6e6b86..d9f24fa 100644
--- a/src/shims-vue.d.ts
+++ b/src/shims-vue.d.ts
@@ -1,4 +1,4 @@
-declare module "*.vue" {
- import Vue from "vue";
- export default Vue;
+declare module '*.vue' {
+ import Vue from 'vue'
+ export default Vue
}
diff --git a/tsconfig.json b/tsconfig.json
index 495a508..2de178a 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -10,30 +10,12 @@
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
- "types": [
- "webpack-env",
- "jest"
- ],
+ "types": ["webpack-env", "jest"],
"paths": {
- "@/*": [
- "src/*"
- ]
+ "@/*": ["src/*"]
},
- "lib": [
- "esnext",
- "dom",
- "dom.iterable",
- "scripthost"
- ]
+ "lib": ["esnext", "dom", "dom.iterable", "scripthost"]
},
- "include": [
- "src/**/*.ts",
- "src/**/*.tsx",
- "src/**/*.vue",
- "tests/**/*.ts",
- "tests/**/*.tsx"
- ],
- "exclude": [
- "node_modules"
- ]
-}
\ No newline at end of file
+ "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "tests/**/*.ts", "tests/**/*.tsx"],
+ "exclude": ["node_modules"]
+}
diff --git a/vue.config.js b/vue.config.js
index bd1f8a3..08d9312 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -1,4 +1,4 @@
module.exports = {
- publicPath: "/vue-cron-editor-bootstrap",
- css: { extract: false }
+ publicPath: '/vue-cron-editor-bootstrap',
+ css: { extract: false },
};