2
0
mirror of https://github.com/tenrok/vue-cron-editor-bootstrap.git synced 2026-05-15 11:59:45 +03:00

rename package

This commit is contained in:
2022-11-09 19:49:47 +03:00
parent 42e11a5b93
commit c6417fea48
29 changed files with 12429 additions and 76074 deletions
+3
View File
@@ -0,0 +1,3 @@
module.exports = {
presets: ['@vue/cli-plugin-babel/preset']
}
+1
View File
@@ -1,2 +1,3 @@
> 1%
last 2 versions
not dead
+19
View File
@@ -0,0 +1,19 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
# Matches multiple files with brace expansion notation
# Set default charset
[*]
charset = utf-8
# Space indentation
[*]
indent_style = space
indent_size = 2
+2
View File
@@ -0,0 +1,2 @@
node_modules
/dist
+24 -24
View File
@@ -1,25 +1,25 @@
const isProd = process.env.NODE_ENV === 'production'
module.exports = {
root: true,
env: {
node: true
},
extends: ["plugin:vue/essential", "@vue/prettier", "@vue/typescript"],
rules: {
"no-console": process.env.NODE_ENV === "production" ? "error" : "off",
"no-debugger": process.env.NODE_ENV === "production" ? "error" : "off"
},
parserOptions: {
parser: "@typescript-eslint/parser"
},
overrides: [
{
files: [
"**/__tests__/*.{j,t}s?(x)",
"**/tests/unit/**/*.spec.{j,t}s?(x)"
],
env: {
jest: true
}
}
]
};
root: true,
env: {
node: true,
},
parser: 'vue-eslint-parser',
parserOptions: {
parser: '@typescript-eslint/parser',
},
extends: [
'plugin:vue/recommended',
'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin
],
rules: {
curly: 'warn',
'no-console': isProd ? 'error' : 'off',
'no-debugger': isProd ? 'error' : 'off',
'vue/max-attributes-per-line': 'off',
'vue/singleline-html-element-content-newline': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
},
}
+6 -2
View File
@@ -1,5 +1,4 @@
.DS_Store
node_modules
# local env files
.env.local
@@ -18,4 +17,9 @@ yarn-error.log*
*.njsproj
*.sln
*.sw?
.vs/
# npm
node_modules
# Output directories
/dist
+8
View File
@@ -0,0 +1,8 @@
// https://prettier.io/docs/en/options.html
module.exports = {
arrowParens: 'avoid', // Include parentheses around a sole arrow function parameter
printWidth: 120, // Specify the line length that the printer will wrap on
semi: false, // Print semicolons at the ends of statements
singleQuote: true // Use single quotes instead of double quotes
}
-3
View File
@@ -1,3 +0,0 @@
{
"tabWidth": 4
}
-3
View File
@@ -1,3 +0,0 @@
module.exports = {
presets: ["@vue/cli-plugin-babel/preset"]
};
-17
View File
@@ -1,17 +0,0 @@
<meta charset="utf-8">
<title>vueCronEditorBootstrap demo</title>
<script src="https://unpkg.com/vue"></script>
<script src="./vueCronEditorBootstrap.umd.js"></script>
<div id="app">
<demo></demo>
</div>
<script>
new Vue({
components: {
demo: vueCronEditorBootstrap
}
}).$mount('#app')
</script>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-21376
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-3
View File
@@ -1,3 +0,0 @@
module.exports = {
preset: "@vue/cli-plugin-unit-jest/presets/typescript-and-babel"
};
+11829 -32657
View File
File diff suppressed because it is too large Load Diff
+24 -29
View File
@@ -1,5 +1,5 @@
{
"name": "vue-cron-editor-bootstrap",
"name": "@tenrok/vue-cron-editor-bootstrap",
"version": "0.2.1",
"private": false,
"main": "dist/vueCronEditorBootstrap.umd.js",
@@ -9,38 +9,33 @@
"./sfc": "src/VueCronEditorBootstrap.vue"
},
"scripts": {
"serve": "vue-cli-service serve",
"build:npm": "vue-cli-service build --target lib --name vueCronEditorBootstrap src/VueCronEditorBootstrap.vue"
"build:npm": "vue-cli-service build --target lib --name vueCronEditorBootstrap src/VueCronEditorBootstrap.vue",
"lint": "vue-cli-service lint --fix",
"serve": "vue-cli-service serve"
},
"dependencies": {
"core-js": "^3.6.5",
"cron-validator": "^1.1.1",
"cronstrue": "^1.94.0",
"vue": "^2.6.10"
"core-js": "^3.26.0",
"cron-validator": "^1.3.1",
"cronstrue": "^2.14.0",
"vue": "^2.7.14"
},
"devDependencies": {
"@types/jest": "^24.0.19",
"@vue/cli-plugin-babel": "^4.3.1",
"@vue/cli-plugin-eslint": "^4.3.1",
"@vue/cli-plugin-typescript": "^4.3.1",
"@vue/cli-plugin-unit-jest": "^4.3.1",
"@vue/cli-service": "^4.3.1",
"@vue/eslint-config-prettier": "^5.0.0",
"@vue/eslint-config-typescript": "^4.0.0",
"@vue/test-utils": "1.0.0-beta.33",
"eslint": "^5.16.0",
"eslint-plugin-prettier": "^3.1.3",
"eslint-plugin-vue": "^5.0.0",
"gh-pages": "^2.2.0",
"link-parent-bin": "^1.0.2",
"lint-staged": "^10.2.4",
"prettier": "^1.19.1",
"sass": "^1.46.0",
"sass-loader": "^8.0.2",
"standard-version": "^8.0.0",
"typescript": "~3.5.3",
"vue-template-compiler": "^2.6.10",
"bootstrap-vue": "^2.21.2"
"@typescript-eslint/eslint-plugin": "^5.42.1",
"@typescript-eslint/parser": "^5.42.1",
"@vue/cli-plugin-babel": "^5.0.8",
"@vue/cli-plugin-eslint": "^5.0.8",
"@vue/cli-plugin-typescript": "^5.0.8",
"@vue/cli-service": "^5.0.8",
"@vue/eslint-config-typescript": "^11.0.2",
"eslint": "^7.32.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-vue": "^9.6.0",
"prettier": "^2.7.1",
"typescript": "^4.8.4",
"vue-template-compiler": "^2.7.14"
},
"peerDependencies": {
"bootstrap-vue": "^2.23.1"
},
"author": "alexmfreitas",
"license": "MIT",
+21 -23
View File
@@ -1,30 +1,28 @@
<template>
<div id="app">
<div class="flex-xl-nowrap">
<main class="main-content py-3 ml-auto px-4" role="main">
<VueCronEditorBootstrap
:preserveStateOnSwitchToAdvanced="true"
v-model="sample1CronExpression"
></VueCronEditorBootstrap>
<b-form-input v-model="sample1CronExpression" />
</main>
</div>
<div id="app">
<div class="p-3">
<VueCronEditorBootstrap v-model="sample1CronExpression" preserve-state-on-switch-to-advanced />
<b-form-input v-model="sample1CronExpression" readonly />
</div>
</div>
</template>
<script>
import VueCronEditorBootstrap from "./VueCronEditorBootstrap.vue";
import { BFormInput } from "bootstrap-vue";
import "bootstrap/dist/css/bootstrap.css";
import "bootstrap-vue/dist/bootstrap-vue.css";
import VueCronEditorBootstrap from './VueCronEditorBootstrap.vue'
import { BFormInput } from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
export default {
name: "App",
components: {
VueCronEditorBootstrap,
BFormInput
},
data: () => ({
sample1CronExpression: "4 4 * * 0,2,3,5"
})
};
name: 'App',
components: {
VueCronEditorBootstrap,
BFormInput,
},
data: () => ({
sample1CronExpression: '4 4 * * 0,2,3,5',
}),
}
</script>
+143 -196
View File
@@ -1,204 +1,151 @@
<template>
<b-tabs v-model="activeTab" @input="reset" content-class="mt-3 mb-3">
<b-tab :value="0" :title="_$t('minutes')" class="minutes-tab">
<div class="row">
<div class="col d-flex" style="align-items: center;">
<label class="me-2">{{ _$t("every") }}</label>
<b-form-input
type="number"
v-model="editorData.minuteInterval"
v-bind:style="{ width: '80px' }"
/>
<label class="me-2 ms-2">{{ _$t("mminutes") }}</label>
</div>
</div>
</b-tab>
<b-tab :value="1" :title="_$t('hourly')" class="hourly-tab">
<div class="row">
<div class="col d-flex" style="align-items: center;">
<label class="me-2">{{ _$t("every") }}</label>
<b-form-input
type="number"
v-model="editorData.hourInterval"
v-bind:style="{ width: '80px' }"
/>
<label class="me-2 ms-2">{{
_$t("hoursOnMinute")
}}</label>
<b-form-input
type="number"
max="59"
min="0"
v-model="editorData.minutes"
v-bind:style="{ width: '80px' }"
/>
</div>
</div>
</b-tab>
<b-tab :value="2" :title="_$t('daily')" class="daily-tab">
<div class="row">
<div class="col d-flex" style="align-items: center;">
<label class="me-2">{{ _$t("every") }}</label>
<b-form-input
type="number"
v-model="editorData.dayInterval"
v-bind:style="{ width: '80px' }"
/>
<label class="me-2 ms-2">{{
_$t("daysAt")
}}</label>
<b-form-timepicker
:value="dateTime"
:hour12="false"
@input="setDateTime"
style="width: auto; display: flex;"
/>
</div>
</div>
</b-tab>
<b-tab :value="3" :title="_$t('weekly')" class="weekly-tab">
<div class="row">
<div class="col d-flex" style="align-items: center;">
<label class="me-2">{{ _$t("every") }}</label>
<div class="form-check form-switch me-2">
<input :id="`toggle-editor-0`" type="checkbox" class="form-check-input" value="0" v-model="editorData.days">
<label class="form-check-label" :for="`toggle-editor-0`">{{ _$t("sun") }}</label>
</div>
<div class="form-check form-switch me-2">
<input :id="`toggle-editor-1`" type="checkbox" class="form-check-input" value="1" v-model="editorData.days">
<label class="form-check-label" :for="`toggle-editor-1`">{{ _$t("mon") }}</label>
</div>
<div class="form-check form-switch me-2">
<input :id="`toggle-editor-2`" type="checkbox" class="form-check-input" value="2" v-model="editorData.days">
<label class="form-check-label" :for="`toggle-editor-2`">{{ _$t("tue") }}</label>
</div>
<div class="form-check form-switch me-2">
<input :id="`toggle-editor-3`" type="checkbox" class="form-check-input" value="3" v-model="editorData.days">
<label class="form-check-label" :for="`toggle-editor-3`">{{ _$t("wed") }}</label>
</div>
<div class="form-check form-switch me-2">
<input :id="`toggle-editor-4`" type="checkbox" class="form-check-input" value="4" v-model="editorData.days">
<label class="form-check-label" :for="`toggle-editor-4`">{{ _$t("thu") }}</label>
</div>
<div class="form-check form-switch me-2">
<input :id="`toggle-editor-5`" type="checkbox" class="form-check-input" value="5" v-model="editorData.days">
<label class="form-check-label" :for="`toggle-editor-5`">{{ _$t("fri") }}</label>
</div>
<div class="form-check form-switch me-2">
<input :id="`toggle-editor-6`" type="checkbox" class="form-check-input" value="6" v-model="editorData.days">
<label class="form-check-label" :for="`toggle-editor-6`">{{ _$t("sat") }}</label>
</div>
<label class="me-2">{{ _$t("at") }}</label>
<b-form-timepicker
:value="dateTime"
@input="setDateTime"
:hour12="false"
style="width: auto; display: flex;"
/>
</div>
</div>
</b-tab>
<b-tab :value="4" :title="_$t('monthly')" class="monthly-tab">
<div class="row">
<div class="col d-flex" style="align-items: center;">
<label class="me-2">{{ _$t("onThe") }}</label>
<b-form-input
type="number"
v-model="editorData.day"
v-bind:style="{ width: '80px' }"
/>
<label class="me-2 ms-2">{{
_$t("dayOfEvery")
}}</label>
<b-form-input
type="number"
v-model="editorData.monthInterval"
v-bind:style="{ width: '80px' }"
/><label class="me-2 ms-2">{{
_$t("monthsAt")
}}</label>
<b-form-timepicker
:value="dateTime"
@input="setDateTime"
:hour12="false"
style="width: auto; display: flex;"
/>
</div>
</div>
</b-tab>
<b-tab :value="4" :title="_$t('advanced')" class="advanced-tab">
<div class="row">
<div class="col d-flex" style="align-items: center;">
<label class="me-2">{{
_$t("cronExpression")
}}</label>
<b-form-input v-model="editorData.cronExpression" style="width:auto"/>
<label class="me-2 ms-2">
{{ explanation }}
</label>
</div>
</div>
</b-tab>
</b-tabs>
<b-tabs v-model="activeTabIndex" content-class="p-2" @input="reset">
<b-tab :value="0" :title="translate('minutes')" class="minutes-tab">
<b-row>
<b-col class="d-flex align-items-center">
<span class="mr-2">{{ translate('every') }}</span>
<b-form-input
v-model="editorData.minuteInterval"
type="number"
min="1"
max="59"
class="mr-2"
style="width: 80px"
/>
<span>{{ translate('mminutes') }}</span>
</b-col>
</b-row>
</b-tab>
<b-tab :value="1" :title="translate('hourly')" class="hourly-tab">
<b-row>
<b-col class="d-flex align-items-center">
<span class="mr-2">{{ translate('every') }}</span>
<b-form-input
v-model="editorData.hourInterval"
type="number"
min="1"
max="24"
class="mr-2"
style="width: 80px"
/>
<span class="mr-2">{{ translate('hoursOnMinute') }}</span>
<b-form-input v-model="editorData.minutes" type="number" min="0" max="59" style="width: 80px" />
</b-col>
</b-row>
</b-tab>
<b-tab :value="2" :title="translate('daily')" class="daily-tab">
<b-row>
<b-col class="d-flex align-items-center">
<span class="mr-2">{{ translate('every') }}</span>
<b-form-input v-model="editorData.dayInterval" type="number" class="mr-2" style="width: 80px" />
<span class="mr-2">{{ translate('daysAt') }}</span>
<b-form-timepicker :value="dateTime" :hour12="false" style="width: auto" @input="setDateTime" />
</b-col>
</b-row>
</b-tab>
<b-tab :value="3" :title="translate('weekly')" class="weekly-tab">
<b-row>
<b-col class="d-flex align-items-center">
<span class="mr-2">{{ translate('every') }}</span>
<b-form-checkbox v-model="editorData.days" value="0" class="mr-2">{{ translate('sun') }}</b-form-checkbox>
<b-form-checkbox v-model="editorData.days" value="1" class="mr-2">{{ translate('mon') }}</b-form-checkbox>
<b-form-checkbox v-model="editorData.days" value="2" class="mr-2">{{ translate('tue') }}</b-form-checkbox>
<b-form-checkbox v-model="editorData.days" value="3" class="mr-2">{{ translate('wed') }}</b-form-checkbox>
<b-form-checkbox v-model="editorData.days" value="4" class="mr-2">{{ translate('thu') }}</b-form-checkbox>
<b-form-checkbox v-model="editorData.days" value="5" class="mr-2">{{ translate('fri') }}</b-form-checkbox>
<b-form-checkbox v-model="editorData.days" value="6" class="mr-2">{{ translate('sat') }}</b-form-checkbox>
<span class="mr-2">{{ translate('at') }}</span>
<b-form-timepicker :value="dateTime" :hour12="false" style="width: auto" @input="setDateTime" />
</b-col>
</b-row>
</b-tab>
<b-tab :value="4" :title="translate('monthly')" class="monthly-tab">
<b-row>
<b-col class="d-flex align-items-center">
<span class="mr-2">{{ translate('onThe') }}</span>
<b-form-input v-model="editorData.day" type="number" class="mr-2" style="width: 80px" />
<span class="mr-2">{{ translate('dayOfEvery') }}</span>
<b-form-input v-model="editorData.monthInterval" type="number" class="mr-2" style="width: 80px" />
<span class="mr-2">{{ translate('monthsAt') }}</span>
<b-form-timepicker :value="dateTime" :hour12="false" style="width: auto" @input="setDateTime" />
</b-col>
</b-row>
</b-tab>
<b-tab :value="5" :title="translate('advanced')" class="advanced-tab">
<b-row>
<b-col class="d-flex" style="align-items: center">
<span class="mr-2">{{ translate('cronExpression') }}</span>
<b-form-input v-model="editorData.cronExpression" class="mr-2" style="width: auto" />
<span>{{ explanation }}</span>
</b-col>
</b-row>
</b-tab>
</b-tabs>
</template>
<script>
import vueCronEditorMixin from "./core/vueCronEditorMixin";
import {
BTabs,
BTab,
BFormInput,
BFormTimepicker,
} from "bootstrap-vue";
import vueCronEditorMixin from './core/vueCronEditorMixin'
import { BTabs, BTab, BRow, BCol, BFormCheckbox, BFormInput, BFormTimepicker } from 'bootstrap-vue'
export default {
name: "VueCronEditorBootstrap",
mixins: [vueCronEditorMixin],
components: {
BFormInput,
BTabs,
BTab,
BFormTimepicker
},
data: () => ({
activeTab: null,
tabs: [
{ id: 0, key: "minutes" },
{ id: 1, key: "hourly" },
{ id: 2, key: "daily" },
{ id: 3, key: "weekly" },
{ id: 4, key: "monthly" },
{ id: 5, key: "advanced" }
]
}),
mounted() {
this.activeTab = this.tabs.find(t => t.key === this.currentTab).id;
},
watch: {
currentTab() {
this.activeTab = this.tabs.find(t => t.key === this.currentTab).id;
}
},
computed: {
dateTime() {
let dateTime = `${this.editorData.hours}:${this.editorData.minutes}:00`;
return dateTime;
}
},
methods: {
reset(e) {
const tabKey = this.tabs.find(t => t.id === e).key;
this._resetToTab(tabKey);
},
setDateTime(e) {
if (e == null) {
return;
}
const splittedTime = e.split(":");
name: 'VueCronEditorBootstrap',
this.editorData.hours = splittedTime[0];
this.editorData.minutes = splittedTime[1];
}
}
};
components: {
BTabs,
BTab,
BRow,
BCol,
BFormCheckbox,
BFormInput,
BFormTimepicker,
},
mixins: [vueCronEditorMixin],
data: () => ({
activeTabIndex: null,
tabs: [
{ idx: 0, key: 'minutes' },
{ idx: 1, key: 'hourly' },
{ idx: 2, key: 'daily' },
{ idx: 3, key: 'weekly' },
{ idx: 4, key: 'monthly' },
{ idx: 5, key: 'advanced' },
],
}),
computed: {
dateTime() {
return `${this.editorData.hours}:${this.editorData.minutes}:00`
},
},
watch: {
currentTab() {
this.activeTabIndex = this.tabs.find(t => t.key === this.currentTab).idx
},
},
created() {
this.activeTabIndex = this.tabs.find(t => t.key === this.currentTab).idx
},
methods: {
reset(tabIndex) {
const tab = this.tabs.find(t => t.idx === tabIndex)
if (tab) {
this.resetToTab(tab.key)
}
},
setDateTime(time) {
if (time == null) {
return
}
const splittedTime = time.split(':')
this.editorData.hours = splittedTime[0]
this.editorData.minutes = splittedTime[1]
},
},
}
</script>
+125 -113
View File
@@ -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
}
}
+59 -59
View File
@@ -1,64 +1,64 @@
export const defaultLocales: Record<string, Record<string, string>> = {
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<string, Record<string, string>>,
locale: string
customLocales: Record<string, Record<string, string>>,
locale: string
): Record<string, string> {
const allLocales = { ...defaultLocales, ...customLocales };
return allLocales[locale];
const allLocales = { ...defaultLocales, ...customLocales }
return allLocales[locale]
}
+138 -130
View File
@@ -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<TabKey, TabUpdatedEvent> = {
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<string, string> | null;
editorData: any
currentTab: TabKey
innerValue: string | null
i18n: Record<string, string> | 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 <ComponentData>{
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 <ComponentData>{
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])
}
}
})
+5 -5
View File
@@ -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')
+11 -9
View File
@@ -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
}
}
}
+3 -3
View File
@@ -1,4 +1,4 @@
declare module "*.vue" {
import Vue from "vue";
export default Vue;
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}
+6 -24
View File
@@ -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"
]
}
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "tests/**/*.ts", "tests/**/*.tsx"],
"exclude": ["node_modules"]
}
+2 -2
View File
@@ -1,4 +1,4 @@
module.exports = {
publicPath: "/vue-cron-editor-bootstrap",
css: { extract: false }
publicPath: '/vue-cron-editor-bootstrap',
css: { extract: false },
};