2
0
mirror of https://github.com/tenrok/vue-cron-editor-bootstrap.git synced 2026-06-20 20:10:34 +03:00

externals deps

This commit is contained in:
2023-10-24 17:33:53 +03:00
parent 265f507e33
commit aa72b053bd
21 changed files with 20771 additions and 20698 deletions
+1 -1
View File
@@ -1,3 +1,3 @@
module.exports = { module.exports = {
presets: ['@vue/cli-plugin-babel/preset'], presets: ['@vue/cli-plugin-babel/preset'],
} }
+10 -3
View File
@@ -1,8 +1,15 @@
# http://editorconfig.org
root = true root = true
[*] [*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf end_of_line = lf
insert_final_newline = true insert_final_newline = true
charset = utf-8 trim_trailing_whitespace = true
indent_style = tab
indent_size = 2 [*.md]
insert_final_newline = false
trim_trailing_whitespace = false
+2 -2
View File
@@ -1,3 +1,3 @@
node_modules node_modules
/demo /demo/
/dist /dist/
+18 -18
View File
@@ -1,22 +1,22 @@
const isProduction = process.env.NODE_ENV === 'production' const isProduction = process.env.NODE_ENV === 'production'
module.exports = { module.exports = {
root: true, root: true,
env: { env: {
node: true, node: true,
}, },
parserOptions: { parserOptions: {
parser: '@typescript-eslint/parser', parser: '@typescript-eslint/parser',
ecmaVersion: 2020, ecmaVersion: 2020,
}, },
extends: ['plugin:vue/recommended', 'eslint:recommended', '@vue/typescript/recommended', 'plugin:prettier/recommended'], extends: ['plugin:vue/recommended', 'eslint:recommended', '@vue/typescript/recommended', 'plugin:prettier/recommended'],
rules: { rules: {
curly: 'warn', curly: 'warn',
'no-console': isProduction ? 'error' : 'off', 'no-console': isProduction ? 'error' : 'off',
'no-debugger': isProduction ? 'error' : 'off', 'no-debugger': isProduction ? 'error' : 'off',
'vue/max-attributes-per-line': 'off', 'vue/max-attributes-per-line': 'off',
'vue/singleline-html-element-content-newline': 'off', 'vue/singleline-html-element-content-newline': 'off',
'@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-non-null-assertion': 'off', '@typescript-eslint/no-non-null-assertion': 'off',
}, },
} }
+9 -6
View File
@@ -1,9 +1,12 @@
// https://prettier.io/docs/en/options.html // https://prettier.io/docs/en/options.html
module.exports = { /** @type {import("prettier").Config} */
arrowParens: 'avoid', const config = {
printWidth: 140, arrowParens: 'avoid',
semi: false, printWidth: 180,
singleQuote: true, semi: false,
useTabs: true, singleQuote: true,
vueIndentScriptAndStyle: true,
} }
module.exports = config
+5 -1
View File
@@ -1,3 +1,7 @@
{ {
"recommendations": ["editorconfig.editorconfig", "esbenp.prettier-vscode"] "recommendations": [
"editorconfig.editorconfig",
"esbenp.prettier-vscode",
"octref.vetur"
]
} }
+18 -7
View File
@@ -1,9 +1,20 @@
{ {
"editor.fontFamily": "'Fira Code', Consolas, 'Courier New', monospace", "editor.fontFamily": "'Fira Code', Consolas, 'Courier New', monospace",
"editor.fontLigatures": true, "editor.fontLigatures": true,
"editor.fontWeight": "400", "editor.fontWeight": "400",
"editor.foldingStrategy": "indentation", "editor.foldingStrategy": "indentation",
"editor.formatOnSave": true, "editor.formatOnSave": true,
"editor.rulers": [140], "editor.rulers": [
"editor.defaultFormatter": "esbenp.prettier-vscode" 180
],
"editor.defaultFormatter": "octref.vetur",
"[json]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
"[jsonc]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
} }
+5 -5
View File
@@ -25,17 +25,17 @@ npm install @tenrok/vue-cron-editor-bootstrap --save
``` ```
<template> <template>
<VueCronEditorBootstrap v-model="cronExpression" /> <VueCronEditor v-model="cronExpression" />
{{cronExpression}} {{cronExpression}}
</template> </template>
<script> <script>
import VueCronEditorBootstrap from '@tenrok/vue-cron-editor-bootstrap'; import VueCronEditor from '@tenrok/vue-cron-editor-bootstrap';
export default { export default {
name: 'App', name: 'App',
components: { components: {
VueCronEditorBootstrap VueCronEditor
}, },
data() { data() {
return { return {
@@ -57,7 +57,7 @@ To preserve expression on switch to **advanced** tab set the `preserveStateOnSwi
The language of the component can be selected with the `locale` prop. The language of the component can be selected with the `locale` prop.
``` ```
<VueCronEditorBootstrap <VueCronEditor
v-model="expression" v-model="expression"
locale="pl" locale="pl"
/> />
@@ -71,7 +71,7 @@ Currently supported languages:
Custom locales can be provided via a `customLocales` prop: Custom locales can be provided via a `customLocales` prop:
``` ```
<VueCronEditorBootstrap <VueCronEditor
v-model="expression" v-model="expression"
locale="test" locale="test"
:custom-locales="{ :custom-locales="{
+152
View File
@@ -0,0 +1,152 @@
<template>
<b-tabs v-model="activeTabIndex" content-class="p-2" @input="reset">
<b-tab :value="0" :title="translate('minutes')" class="minutes-tab">
<div class="row">
<div class="col d-flex align-items-center">
<span class="mr-1">{{ translate('every') }}</span>
<b-form-input v-model="editorData.minuteInterval" type="number" min="1" max="59" class="mr-1" style="width: 80px" />
<span>{{ translate('mminutes') }}</span>
</div>
</div>
</b-tab>
<b-tab :value="1" :title="translate('hourly')" class="hourly-tab">
<div class="row">
<div class="col d-flex align-items-center">
<span class="mr-1">{{ translate('every') }}</span>
<b-form-input v-model="editorData.hourInterval" type="number" min="1" max="24" class="mr-1" style="width: 80px" />
<span class="mr-1">{{ translate('hoursOnMinute') }}</span>
<b-form-input v-model="editorData.minutes" type="number" min="0" max="59" style="width: 80px" />
</div>
</div>
</b-tab>
<b-tab :value="2" :title="translate('daily')" class="daily-tab">
<div class="row">
<div class="col d-flex align-items-center">
<span class="mr-1">{{ translate('every') }}</span>
<b-form-input v-model="editorData.dayInterval" type="number" class="mr-1" style="width: 80px" />
<span class="mr-1">{{ translate('daysAt') }}</span>
<b-form-timepicker :value="dateTime" :hour12="false" now-button style="width: auto" @input="setDateTime" />
</div>
</div>
</b-tab>
<b-tab :value="3" :title="translate('weekly')" class="weekly-tab">
<div class="row">
<div class="col d-flex align-items-center">
<span class="mr-3">{{ translate('onlyOn') }}</span>
<!-- <b-form-checkbox v-model="editorData.days" value="0" class="mr-3">{{ translate('sun') }}</b-form-checkbox> -->
<!-- <b-form-checkbox v-model="editorData.days" value="1" class="mr-3">{{ translate('mon') }}</b-form-checkbox> -->
<!-- <b-form-checkbox v-model="editorData.days" value="2" class="mr-3">{{ translate('tue') }}</b-form-checkbox> -->
<!-- <b-form-checkbox v-model="editorData.days" value="3" class="mr-3">{{ translate('wed') }}</b-form-checkbox> -->
<!-- <b-form-checkbox v-model="editorData.days" value="4" class="mr-3">{{ translate('thu') }}</b-form-checkbox> -->
<!-- <b-form-checkbox v-model="editorData.days" value="5" class="mr-3">{{ translate('fri') }}</b-form-checkbox> -->
<!-- <b-form-checkbox v-model="editorData.days" value="6" class="mr-3">{{ translate('sat') }}</b-form-checkbox> -->
<div v-for="(a, idx) in uids" :key="`${a[0]}`" class="mr-3 custom-control custom-checkbox">
<input :id="`${a[1]}`" v-model="editorData.days" type="checkbox" class="custom-control-input" :value="`${idx}`" />
<label class="custom-control-label" :for="`${a[1]}`">{{ translate(a[0]) }}</label>
</div>
<span class="mr-1">{{ translate('at') }}</span>
<b-form-timepicker :value="dateTime" :hour12="false" now-button style="width: auto" @input="setDateTime" />
</div>
</div>
</b-tab>
<b-tab :value="4" :title="translate('monthly')" class="monthly-tab">
<div class="row">
<div class="col d-flex align-items-center">
<span class="mr-1">{{ translate('onThe') }}</span>
<b-form-input v-model="editorData.day" type="number" min="1" max="31" class="mr-1" style="width: 80px" />
<span class="mr-1">{{ translate('dayOfEvery') }}</span>
<b-form-input v-model="editorData.monthInterval" type="number" min="1" class="mr-1" style="width: 80px" />
<span class="mr-1">{{ translate('monthsAt') }}</span>
<b-form-timepicker :value="dateTime" :hour12="false" now-button style="width: auto" @input="setDateTime" />
</div>
</div>
</b-tab>
<b-tab :value="5" :title="translate('advanced')" class="advanced-tab">
<div class="row">
<div class="col d-flex 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>
</div>
</div>
</b-tab>
</b-tabs>
</template>
<script lang="ts">
import VueCronEditorMixin from '../core/vueCronEditorMixin'
import { BTabs, BTab, BFormInput, BFormTimepicker } from '@tenrok/bootstrap-vue'
import { TabKey } from 'lib/core/cronExpressions'
interface Tab {
idx: number
key: string
}
interface Data {
activeTabIndex?: number
tabs: Tab[]
uids: string[][]
}
export default VueCronEditorMixin.extend({
components: {
BTabs,
BTab,
BFormInput,
BFormTimepicker,
},
data(): Data {
return {
activeTabIndex: undefined,
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' },
],
uids: ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'].map(x => [x, crypto.randomUUID()]),
}
},
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: number) {
const tab = this.tabs.find(t => t.idx === tabIndex)
if (tab) {
this.resetToTab(tab.key as TabKey)
}
},
setDateTime(time: string) {
if (time == null) {
return
}
const splittedTime = time.split(':')
this.editorData.hours = splittedTime[0]
this.editorData.minutes = splittedTime[1]
},
},
})
</script>
-141
View File
@@ -1,141 +0,0 @@
<template>
<b-tabs v-model="activeTabIndex" content-class="p-2" @input="reset">
<b-tab :value="0" :title="translate('minutes')" class="minutes-tab">
<div class="row">
<div class="col d-flex align-items-center">
<span class="mr-1">{{ translate('every') }}</span>
<b-form-input v-model="editorData.minuteInterval" type="number" min="1" max="59" class="mr-1" style="width: 80px" />
<span>{{ translate('mminutes') }}</span>
</div>
</div>
</b-tab>
<b-tab :value="1" :title="translate('hourly')" class="hourly-tab">
<div class="row">
<div class="col d-flex align-items-center">
<span class="mr-1">{{ translate('every') }}</span>
<b-form-input v-model="editorData.hourInterval" type="number" min="1" max="24" class="mr-1" style="width: 80px" />
<span class="mr-1">{{ translate('hoursOnMinute') }}</span>
<b-form-input v-model="editorData.minutes" type="number" min="0" max="59" style="width: 80px" />
</div>
</div>
</b-tab>
<b-tab :value="2" :title="translate('daily')" class="daily-tab">
<div class="row">
<div class="col d-flex align-items-center">
<span class="mr-1">{{ translate('every') }}</span>
<b-form-input v-model="editorData.dayInterval" type="number" class="mr-1" style="width: 80px" />
<span class="mr-1">{{ translate('daysAt') }}</span>
<b-form-timepicker :value="dateTime" :hour12="false" now-button style="width: auto" @input="setDateTime" />
</div>
</div>
</b-tab>
<b-tab :value="3" :title="translate('weekly')" class="weekly-tab">
<div class="row">
<div class="col d-flex align-items-center">
<span class="mr-3">{{ translate('onlyOn') }}</span>
<!-- <b-form-checkbox v-model="editorData.days" value="0" class="mr-3">{{ translate('sun') }}</b-form-checkbox> -->
<!-- <b-form-checkbox v-model="editorData.days" value="1" class="mr-3">{{ translate('mon') }}</b-form-checkbox> -->
<!-- <b-form-checkbox v-model="editorData.days" value="2" class="mr-3">{{ translate('tue') }}</b-form-checkbox> -->
<!-- <b-form-checkbox v-model="editorData.days" value="3" class="mr-3">{{ translate('wed') }}</b-form-checkbox> -->
<!-- <b-form-checkbox v-model="editorData.days" value="4" class="mr-3">{{ translate('thu') }}</b-form-checkbox> -->
<!-- <b-form-checkbox v-model="editorData.days" value="5" class="mr-3">{{ translate('fri') }}</b-form-checkbox> -->
<!-- <b-form-checkbox v-model="editorData.days" value="6" class="mr-3">{{ translate('sat') }}</b-form-checkbox> -->
<div v-for="(a, idx) in uids" :key="`${a[0]}`" class="mr-3 custom-control custom-checkbox">
<input :id="`${a[1]}`" v-model="editorData.days" type="checkbox" class="custom-control-input" :value="`${idx}`" />
<label class="custom-control-label" :for="`${a[1]}`">{{ translate(a[0]) }}</label>
</div>
<span class="mr-1">{{ translate('at') }}</span>
<b-form-timepicker :value="dateTime" :hour12="false" now-button style="width: auto" @input="setDateTime" />
</div>
</div>
</b-tab>
<b-tab :value="4" :title="translate('monthly')" class="monthly-tab">
<div class="row">
<div class="col d-flex align-items-center">
<span class="mr-1">{{ translate('onThe') }}</span>
<b-form-input v-model="editorData.day" type="number" min="1" max="31" class="mr-1" style="width: 80px" />
<span class="mr-1">{{ translate('dayOfEvery') }}</span>
<b-form-input v-model="editorData.monthInterval" type="number" min="1" class="mr-1" style="width: 80px" />
<span class="mr-1">{{ translate('monthsAt') }}</span>
<b-form-timepicker :value="dateTime" :hour12="false" now-button style="width: auto" @input="setDateTime" />
</div>
</div>
</b-tab>
<b-tab :value="5" :title="translate('advanced')" class="advanced-tab">
<div class="row">
<div class="col d-flex 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>
</div>
</div>
</b-tab>
</b-tabs>
</template>
<script>
import vueCronEditorMixin from '../core/vueCronEditorMixin'
import { BTabs, BTab, BFormInput, BFormTimepicker } from '@tenrok/bootstrap-vue'
export default {
name: 'VueCronEditorBootstrap',
components: {
BTabs,
BTab,
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' },
],
uids: ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'].map(x => [x, crypto.randomUUID()]),
}),
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>
+106 -112
View File
@@ -1,151 +1,145 @@
interface MinutesTabUpdatedEvent { interface MinutesTabUpdatedEvent {
type: 'minutes' type: 'minutes'
minuteInterval: number minuteInterval: number
} }
interface HourlyTabUpdatedEvent { interface HourlyTabUpdatedEvent {
type: 'hourly' type: 'hourly'
minutes: number minutes: number
hourInterval: number hourInterval: number
} }
interface DailyTabUpdatedEvent { interface DailyTabUpdatedEvent {
type: 'daily' type: 'daily'
minutes: number minutes: number
hours: number hours: number
dayInterval: number dayInterval: number
} }
interface WeeklyTabUpdatedEvent { interface WeeklyTabUpdatedEvent {
type: 'weekly' type: 'weekly'
minutes: number minutes: number
hours: number hours: number
days: string[] days: string[]
} }
interface MonthlyTabUpdatedEvent { interface MonthlyTabUpdatedEvent {
type: 'monthly' type: 'monthly'
minutes: number minutes: number
hours: number hours: number
day: number day: number
monthInterval: number monthInterval: number
} }
interface AdvancedTabUpdatedEvent { interface AdvancedTabUpdatedEvent {
type: 'advanced' type: 'advanced'
cronExpression: string cronExpression: string
} }
export type TabUpdatedEvent = 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 => { export const buildExpression = (event: TabUpdatedEvent): string => {
if (event.type === 'minutes') { if (event.type === 'minutes') {
return `*/${event.minuteInterval} * * * *` return `*/${event.minuteInterval} * * * *`
} }
if (event.type === 'hourly') { if (event.type === 'hourly') {
return `${event.minutes} */${event.hourInterval} * * *` return `${event.minutes} */${event.hourInterval} * * *`
} }
if (event.type === 'daily') { if (event.type === 'daily') {
return `${event.minutes} ${event.hours} */${event.dayInterval} * *` return `${event.minutes} ${event.hours} */${event.dayInterval} * *`
} }
if (event.type === 'weekly') { if (event.type === 'weekly') {
if ([0, 7].includes(event.days.length)) { if ([0, 7].includes(event.days.length)) {
return `${event.minutes} ${event.hours} * * *` return `${event.minutes} ${event.hours} * * *`
} else { } else {
return ( return (
`${event.minutes} ${event.hours} * * ` + `${event.minutes} ${event.hours} * * ` +
`${event.days `${event.days
.filter(d => d) .filter(d => d)
.sort() .sort()
.join()}` .join()}`
) )
} }
} }
if (event.type === 'monthly') { if (event.type === 'monthly') {
return `${event.minutes} ${event.hours} ${event.day} */${event.monthInterval} *` return `${event.minutes} ${event.hours} ${event.day} */${event.monthInterval} *`
} }
if (event.type === 'advanced') { if (event.type === 'advanced') {
return event.cronExpression return event.cronExpression
} }
throw `unknown event type: ${event}` throw `unknown event type: ${event}`
} }
export const parseExpression = (expression: string): TabUpdatedEvent => { export const parseExpression = (expression: string): TabUpdatedEvent => {
let groups = null let groups: RegExpMatchArray | null
if (expression!.split(' ').length != 5) { if (expression!.split(' ').length != 5) {
return { return {
type: 'advanced', type: 'advanced',
cronExpression: expression, cronExpression: expression,
} }
} }
if ((groups = expression.match(/^\*\/(\d+) \* \* \* \*$/))) { if ((groups = expression.match(/^\*\/(\d+) \* \* \* \*$/))) {
return { return {
type: 'minutes', type: 'minutes',
minuteInterval: Number(groups[1]), minuteInterval: Number(groups[1]),
} }
} }
if ((groups = expression.match(/^(\d+) \*\/(\d+) \* \* \*$/))) { if ((groups = expression.match(/^(\d+) \*\/(\d+) \* \* \*$/))) {
return { return {
type: 'hourly', type: 'hourly',
minutes: Number(groups[1]), minutes: Number(groups[1]),
hourInterval: Number(groups[2]), hourInterval: Number(groups[2]),
} }
} }
if ((groups = expression.match(/^(\d+) (\d+) \*\/(\d+) \* \*$/))) { if ((groups = expression.match(/^(\d+) (\d+) \*\/(\d+) \* \*$/))) {
return { return {
type: 'daily', type: 'daily',
minutes: Number(groups[1]), minutes: Number(groups[1]),
hours: Number(groups[2]), hours: Number(groups[2]),
dayInterval: Number(groups[3]), dayInterval: Number(groups[3]),
} }
} }
if ((groups = expression.match(/^(\d+) (\d+) \* \* (\d)(,\d)?(,\d)?(,\d)?(,\d)?(,\d)?(,\d)?$/))) { if ((groups = expression.match(/^(\d+) (\d+) \* \* (\d)(,\d)?(,\d)?(,\d)?(,\d)?(,\d)?(,\d)?$/))) {
const optionalDaysBeginIndex = 4 const optionalDaysBeginIndex = 4
const matchesEndIndex = 10 const matchesEndIndex = 10
return { return {
type: 'weekly', type: 'weekly',
minutes: Number(groups[1]), minutes: Number(groups[1]),
hours: Number(groups[2]), hours: Number(groups[2]),
days: [groups[3]].concat( days: [groups[3]].concat(
groups groups
.slice(optionalDaysBeginIndex, matchesEndIndex) .slice(optionalDaysBeginIndex, matchesEndIndex)
.map(d => d && d.replace(/,/, '')) .map(d => d && d.replace(/,/, ''))
.filter(d => d) .filter(d => d)
), ),
} }
} }
if ((groups = expression.match(/^(\d+) (\d+) (\d+) \*\/(\d+) \*$/))) { if ((groups = expression.match(/^(\d+) (\d+) (\d+) \*\/(\d+) \*$/))) {
return { return {
type: 'monthly', type: 'monthly',
minutes: Number(groups[1]), minutes: Number(groups[1]),
hours: Number(groups[2]), hours: Number(groups[2]),
day: Number(groups[3]), day: Number(groups[3]),
monthInterval: Number(groups[4]), monthInterval: Number(groups[4]),
} }
} }
return { return {
type: 'advanced', type: 'advanced',
cronExpression: expression, cronExpression: expression,
} }
} }
+58 -58
View File
@@ -1,63 +1,63 @@
export const defaultLocales: Record<string, Record<string, string>> = { export const defaultLocales: Record<string, Record<string, string>> = {
en: { en: {
every: 'Every', every: 'Every',
mminutes: 'minute(s)', mminutes: 'minute(s)',
hoursOnMinute: 'hour(s) on minute', hoursOnMinute: 'hour(s) on minute',
daysAt: 'day(s) at', daysAt: 'day(s) at',
at: 'at', at: 'at',
onThe: 'On the', onThe: 'On the',
dayOfEvery: 'day, of every', dayOfEvery: 'day, of every',
monthsAt: 'month(s), at', monthsAt: 'month(s), at',
// everyDay: 'Every', // everyDay: 'Every',
mon: 'Mon', mon: 'Mon',
tue: 'Tue', tue: 'Tue',
wed: 'Wed', wed: 'Wed',
thu: 'Thu', thu: 'Thu',
fri: 'Fri', fri: 'Fri',
sat: 'Sat', sat: 'Sat',
sun: 'Sun', sun: 'Sun',
// hasToBeBetween: 'Has to be between', // hasToBeBetween: 'Has to be between',
// and: 'and', // and: 'and',
minutes: 'MINUTES', minutes: 'MINUTES',
hourly: 'HOURLY', hourly: 'HOURLY',
daily: 'DAILY', daily: 'DAILY',
weekly: 'WEEKLY', weekly: 'WEEKLY',
monthly: 'MONTHLY', monthly: 'MONTHLY',
advanced: 'ADVANCED', advanced: 'ADVANCED',
cronExpression: 'cron expression:', cronExpression: 'cron expression:',
onlyOn: 'Only on', onlyOn: 'Only on',
}, },
pl: { pl: {
every: 'Co', every: 'Co',
mminutes: 'minut', mminutes: 'minut',
hoursOnMinute: 'godzin w minucie', hoursOnMinute: 'godzin w minucie',
daysAt: 'dni o', daysAt: 'dni o',
at: 'o', at: 'o',
onThe: '', onThe: '',
dayOfEvery: 'dzień miesiąca, co', dayOfEvery: 'dzień miesiąca, co',
monthsAt: 'miesięcy, o godzinie', monthsAt: 'miesięcy, o godzinie',
// everyDay: 'W każdy', // everyDay: 'W każdy',
mon: 'Pon', mon: 'Pon',
tue: 'Wt', tue: 'Wt',
wed: 'Śr', wed: 'Śr',
thu: 'Czw', thu: 'Czw',
fri: 'Pt', fri: 'Pt',
sat: 'So', sat: 'So',
sun: 'Nie', sun: 'Nie',
// hasToBeBetween: 'Wymagana wartość pomiędzy', // hasToBeBetween: 'Wymagana wartość pomiędzy',
// and: 'i', // and: 'i',
minutes: 'Minuty', minutes: 'Minuty',
hourly: 'Godziny', hourly: 'Godziny',
daily: 'Dni', daily: 'Dni',
weekly: 'Tygodnie', weekly: 'Tygodnie',
monthly: 'Miesiące', monthly: 'Miesiące',
advanced: 'Zaawansowane', advanced: 'Zaawansowane',
cronExpression: 'Wyrażenie cron:', cronExpression: 'Wyrażenie cron:',
onlyOn: 'Co', onlyOn: 'Co',
}, },
} }
export function createI18n(customLocales: Record<string, Record<string, string>>, locale: string): Record<string, string> { export function createI18n(customLocales: Record<string, Record<string, string>>, locale: string): Record<string, string> {
const allLocales = { ...defaultLocales, ...customLocales } const allLocales = { ...defaultLocales, ...customLocales }
return allLocales[locale] return allLocales[locale]
} }
+119 -119
View File
@@ -12,143 +12,143 @@ import { createI18n } from './i18n'
import Vue from 'vue' import Vue from 'vue'
const initialData: Record<TabKey, TabUpdatedEvent> = { const initialData: Record<TabKey, TabUpdatedEvent> = {
minutes: { minutes: {
type: 'minutes', type: 'minutes',
minuteInterval: 1, minuteInterval: 1,
}, },
hourly: { hourly: {
type: 'hourly', type: 'hourly',
minutes: 0, minutes: 0,
hourInterval: 1, hourInterval: 1,
}, },
daily: { daily: {
type: 'daily', type: 'daily',
minutes: 0, minutes: 0,
hours: 0, hours: 0,
dayInterval: 1, dayInterval: 1,
}, },
weekly: { weekly: {
type: 'weekly', type: 'weekly',
minutes: 0, minutes: 0,
hours: 0, hours: 0,
days: ['1'], days: ['1'],
}, },
monthly: { monthly: {
type: 'monthly', type: 'monthly',
hours: 0, hours: 0,
minutes: 0, minutes: 0,
day: 1, day: 1,
monthInterval: 1, monthInterval: 1,
}, },
advanced: { advanced: {
type: 'advanced', type: 'advanced',
cronExpression: '', cronExpression: '',
}, },
} }
interface ComponentData { interface ComponentData {
editorData: any editorData: any
currentTab: TabKey currentTab: TabKey
innerValue: string | null innerValue: string | null
i18n: Record<string, string> | null i18n: Record<string, string> | null
} }
export default Vue.extend({ export default Vue.extend({
props: { props: {
value: { type: String, default: '*/1 * * * *' }, value: { type: String, default: '*/1 * * * *' },
isAdvancedTabVisible: { type: Boolean, default: true }, isAdvancedTabVisible: { type: Boolean, default: true },
preserveStateOnSwitchToAdvanced: { type: Boolean, default: false }, preserveStateOnSwitchToAdvanced: { type: Boolean, default: false },
locale: { type: String, default: 'en' }, locale: { type: String, default: 'en' },
customLocales: { type: Object, default: null }, customLocales: { type: Object, default: null },
}, },
data() { data(): ComponentData {
return <ComponentData>{ return {
innerValue: '*/1 * * * *', innerValue: '*/1 * * * *',
editorData: Object.assign({}, initialData.minutes), editorData: Object.assign({}, initialData.minutes),
currentTab: 'minutes', currentTab: 'minutes',
i18n: null, i18n: null,
} }
}, },
computed: { computed: {
explanation(): string { explanation(): string {
if (!this.innerValue) { if (!this.innerValue) {
return '' return ''
} }
return (cronstrue as any).toString(this.innerValue, { return (cronstrue as any).toString(this.innerValue, {
locale: this.locale, locale: this.locale,
}) })
}, },
}, },
watch: { watch: {
value: { value: {
handler() { handler() {
if (this.value == this.innerValue) { if (this.value == this.innerValue) {
return return
} }
this.loadDataFromExpression() this.loadDataFromExpression()
}, },
}, },
editorData: { editorData: {
deep: true, deep: true,
handler(changedData) { handler(changedData) {
this.updateCronExpression(changedData) this.updateCronExpression(changedData)
}, },
}, },
}, },
created() { created() {
this.i18n = createI18n(this.customLocales, this.locale) this.i18n = createI18n(this.customLocales, this.locale)
this.innerValue = this.value this.innerValue = this.value
this.loadDataFromExpression() this.loadDataFromExpression()
}, },
methods: { methods: {
translate(key: string) { translate(key: string) {
return this.i18n![key] return this.i18n![key]
}, },
loadDataFromExpression() { loadDataFromExpression() {
const tabData = parseExpression(this.value) const tabData = parseExpression(this.value)
this.editorData = { ...tabData } this.editorData = { ...tabData }
this.currentTab = tabData.type this.currentTab = tabData.type
}, },
updateCronExpression(event: TabUpdatedEvent) { updateCronExpression(event: TabUpdatedEvent) {
const cronExpression = buildExpression({ ...event }) const cronExpression = buildExpression({ ...event })
if (cronValidator.isValidCron(cronExpression)) { if (cronValidator.isValidCron(cronExpression)) {
this.innerValue = cronExpression this.innerValue = cronExpression
this.$emit('input', cronExpression) this.$emit('input', cronExpression)
} else { } else {
this.innerValue = null this.innerValue = null
this.$emit('input', null) this.$emit('input', null)
} }
}, },
resetToTab(tabKey: TabKey) { resetToTab(tabKey: TabKey) {
this.currentTab = tabKey this.currentTab = tabKey
if (this.preserveStateOnSwitchToAdvanced && tabKey === 'advanced') { if (this.preserveStateOnSwitchToAdvanced && tabKey === 'advanced') {
this.editorData = { this.editorData = {
type: 'advanced', type: 'advanced',
cronExpression: this.innerValue, cronExpression: this.innerValue,
} }
return return
} }
const tabData = parseExpression(this.value) const tabData = parseExpression(this.value)
if (tabKey == tabData.type) { if (tabKey == tabData.type) {
this.editorData = Object.assign({}, tabData) this.editorData = Object.assign({}, tabData)
return return
} }
this.editorData = Object.assign({}, initialData[tabKey]) this.editorData = Object.assign({}, initialData[tabKey])
this.updateCronExpression(initialData[tabKey]) this.updateCronExpression(initialData[tabKey])
}, },
}, },
}) })
+11 -14
View File
@@ -1,18 +1,15 @@
import _Vue from 'vue' import { VueConstructor, PluginObject } from 'vue'
import VueCronEditorBootstrap from './components/VueCronEditorBootstrap.vue' import VueCronEditor from './components/VueCronEditor.vue'
const components = [VueCronEditorBootstrap] const components: { [key: string]: VueConstructor } = { VueCronEditor }
class CronEditorPluginOptions {} const VueCronEditorPlugin: PluginObject<any> = {
install(Vue) {
type CronEditorPlugin = { for (const key in components) {
install(vue: typeof _Vue, options?: CronEditorPluginOptions): void Vue.component(key, components[key])
}
},
} }
const instance: CronEditorPlugin = { export default VueCronEditor
install(vue) { export { VueCronEditor, VueCronEditorPlugin }
components.forEach(component => vue.component(component.name, component))
},
}
export default instance
+20141 -20113
View File
File diff suppressed because it is too large Load Diff
+57 -55
View File
@@ -1,57 +1,59 @@
{ {
"name": "@tenrok/vue-cron-editor-bootstrap", "name": "@tenrok/vue-cron-editor-bootstrap",
"version": "0.2.3", "version": "0.3.0",
"homepage": "https://github.com/tenrok/vue-cron-editor-bootstrap", "homepage": "https://github.com/tenrok/vue-cron-editor-bootstrap",
"bugs": { "bugs": {
"url": "https://github.com/tenrok/vue-cron-editor-bootstrap/issues" "url": "https://github.com/tenrok/vue-cron-editor-bootstrap/issues"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/tenrok/vue-cron-editor-bootstrap.git" "url": "git+https://github.com/tenrok/vue-cron-editor-bootstrap.git"
}, },
"license": "MIT", "license": "MIT",
"author": { "author": {
"name": "alexmfreitas", "name": "alexmfreitas",
"url": "https://github.com/alexmfreitas" "url": "https://github.com/alexmfreitas"
}, },
"contributors": [ "contributors": [
{ {
"name": "Sergey Solodyagin", "name": "Sergey Solodyagin",
"url": "https://github.com/solodyagin" "url": "https://github.com/solodyagin"
} }
], ],
"main": "dist/vue-cron-editor-bootstrap.umd.min.js", "main": "dist/vue-cron-editor-bootstrap.umd.min.js",
"files": [ "files": [
"dist/vue-cron-editor-bootstrap.*" "dist/vue-cron-editor-bootstrap.*"
], ],
"scripts": { "scripts": {
"build": "vue-cli-service build --target lib --name vue-cron-editor-bootstrap lib/index.ts", "build": "vue-cli-service build --target lib --name vue-cron-editor-bootstrap lib/index.ts",
"demo:build": "vue-cli-service build", "demo:build": "vue-cli-service build",
"lint": "vue-cli-service lint --fix", "lint": "vue-cli-service lint --fix",
"serve": "vue-cli-service serve --open" "serve": "vue-cli-service serve --open"
}, },
"dependencies": { "dependencies": {
"bootstrap": "^4.6.0", "bootstrap": "^4.6.0",
"core-js": "^3.29.0", "core-js": "^3.33.1",
"cron-validator": "^1.3.1", "cron-validator": "^1.3.1",
"cronstrue": "^2.14.0", "cronstrue": "^2.14.0",
"vue": "^2.7.14", "vue": "^2.7.15"
"@tenrok/bootstrap-vue": "^2.23.2" },
}, "devDependencies": {
"devDependencies": { "@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/eslint-plugin": "^5.50.0", "@typescript-eslint/parser": "^5.62.0",
"@typescript-eslint/parser": "^5.50.0", "@vue/cli-plugin-babel": "^5.0.8",
"@vue/cli-plugin-babel": "^5.0.8", "@vue/cli-plugin-eslint": "^5.0.8",
"@vue/cli-plugin-eslint": "^5.0.8", "@vue/cli-plugin-typescript": "^5.0.8",
"@vue/cli-plugin-typescript": "^5.0.8", "@vue/cli-service": "^5.0.8",
"@vue/cli-service": "^5.0.8", "@vue/eslint-config-typescript": "^11.0.3",
"@vue/eslint-config-typescript": "^11.0.2", "eslint": "^8.52.0",
"eslint": "^8.33.0", "eslint-config-prettier": "^9.0.0",
"eslint-config-prettier": "^8.6.0", "eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-vue": "^9.18.0",
"eslint-plugin-vue": "^9.17.0", "prettier": "^2.8.8",
"prettier": "^2.8.8", "typescript": "^4.9.5",
"typescript": "^4.9.5", "vue-template-compiler": "^2.7.15"
"vue-template-compiler": "^2.7.14" },
} "peerDependencies": {
"@tenrok/bootstrap-vue": "^2.23.2"
}
} }
+12 -12
View File
@@ -1,18 +1,18 @@
<template> <template>
<div id="app"> <div id="app">
<div class="p-3"> <div class="p-3">
<vue-cron-editor-bootstrap v-model="sample1CronExpression" preserve-state-on-switch-to-advanced /> <vue-cron-editor v-model="sample1CronExpression" preserve-state-on-switch-to-advanced />
<b-form-input v-model="sample1CronExpression" readonly /> <input v-model="sample1CronExpression" class="form-control" type="text" readonly />
</div> </div>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'App', name: 'App',
data: () => ({ data: () => ({
sample1CronExpression: '4 4 * * 0,2,3,5', sample1CronExpression: '4 4 * * 0,2,3,5',
}), }),
} }
</script> </script>
+3 -5
View File
@@ -1,16 +1,14 @@
import Vue from 'vue' import Vue from 'vue'
import App from './App.vue' import App from './App.vue'
import VueCronEditorBootstrap from '../lib' import { VueCronEditorPlugin } from '../lib'
Vue.use(VueCronEditorBootstrap) Vue.use(VueCronEditorPlugin)
import { BFormInput } from '@tenrok/bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css' import 'bootstrap/dist/css/bootstrap.css'
import '@tenrok/bootstrap-vue/dist/bootstrap-vue.css' import '@tenrok/bootstrap-vue/dist/bootstrap-vue.css'
Vue.component('BFormInput', BFormInput)
Vue.config.productionTip = false Vue.config.productionTip = false
new Vue({ new Vue({
render: h => h(App), render: h => h(App),
}).$mount('#app') }).$mount('#app')
+2 -2
View File
@@ -1,4 +1,4 @@
declare module '*.vue' { declare module '*.vue' {
import Vue from 'vue' import Vue from 'vue'
export default Vue export default Vue
} }
+24 -14
View File
@@ -1,16 +1,26 @@
{ {
"compilerOptions": { "compilerOptions": {
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"baseUrl": ".", "baseUrl": ".",
"moduleResolution": "node", "moduleResolution": "node",
"outDir": "dist", "outDir": "dist",
"removeComments": true, "removeComments": true,
"sourceMap": true, "sourceMap": true,
"target": "esnext", "strict": true,
"paths": { "target": "esnext",
"@/*": ["src/*"] "paths": {
} "@/*": [
}, "src/*"
"include": ["lib/**/*.ts", "src/**/*.ts", "src/**/*.vue"], ]
"exclude": ["node_modules"] }
},
"include": [
"lib/**/*.ts",
"src/**/*.ts",
"src/**/*.vue"
],
"exclude": [
"node_modules",
"dist"
]
} }
+14 -6
View File
@@ -2,10 +2,18 @@ const isProduction = process.env.NODE_ENV === 'production'
const isBuildLib = (process.env.npm_lifecycle_script || '').indexOf('--target lib') > 0 const isBuildLib = (process.env.npm_lifecycle_script || '').indexOf('--target lib') > 0
module.exports = { module.exports = {
publicPath: isProduction ? '/vue-cron-editor-bootstrap/' : '', publicPath: isProduction ? '/vue-cron-editor-bootstrap/' : '',
outputDir: isBuildLib ? 'dist' : 'demo', outputDir: isBuildLib ? 'dist' : 'demo',
css: { css: {
extract: true, extract: true,
}, },
productionSourceMap: false, productionSourceMap: false,
chainWebpack: config => {
if (isProduction) {
config.externals({
'@tenrok/bootstrap-vue': '@tenrok/bootstrap-vue',
})
// config.merge({ devtool: 'source-map' })
}
},
} }