diff --git a/client/components/modals/libraries/EditModal.vue b/client/components/modals/libraries/EditModal.vue index d305678d..6d52a3b1 100644 --- a/client/components/modals/libraries/EditModal.vue +++ b/client/components/modals/libraries/EditModal.vue @@ -46,12 +46,12 @@ export default { id: 'settings', title: 'Settings', component: 'modals-libraries-library-settings' + }, + { + id: 'schedule', + title: 'Schedule', + component: 'modals-libraries-schedule-scan' } - // { - // id: 'schedule', - // title: 'Schedule', - // component: 'modals-libraries-schedule-scan' - // } ], libraryCopy: null } diff --git a/client/components/modals/libraries/ScheduleScan.vue b/client/components/modals/libraries/ScheduleScan.vue index 799c8e5d..743b6970 100644 --- a/client/components/modals/libraries/ScheduleScan.vue +++ b/client/components/modals/libraries/ScheduleScan.vue @@ -27,6 +27,10 @@ export default { methods: { toggleEnableAutoScan(v) { if (!v) this.updatedCron(null) + else if (!this.cronExpression) { + this.cronExpression = '0 0 * * 1' + this.updatedCron(this.cronExpression) + } }, updatedCron(expression) { this.$emit('update', { diff --git a/client/components/widgets/CronExpressionBuilder.vue b/client/components/widgets/CronExpressionBuilder.vue index 973f861c..3e3f261b 100644 --- a/client/components/widgets/CronExpressionBuilder.vue +++ b/client/components/widgets/CronExpressionBuilder.vue @@ -1,26 +1,39 @@ @@ -42,7 +55,9 @@ export default { cronExpression: '0 0 * * *', customCronExpression: '0 0 * * *', customCronError: '', - isValidating: false + isValidating: false, + validatedCron: null, + isValid: true } }, computed: { @@ -120,6 +135,9 @@ export default { this.selectedWeekdays.sort() this.cronExpression = `${this.selectedMinute} ${this.selectedHour} * * ${this.selectedWeekdays.join(',')}` this.customCronExpression = this.cronExpression + this.validatedCron = this.cronExpression + this.isValid = true + this.customCronError = '' this.$emit('input', this.cronExpression) }, minuteBlur() { @@ -144,13 +162,15 @@ export default { } this.updateCron() }, - simpleValidateCustomCron() { - return this.customCronExpression && this.customCronExpression.split(' ').length === 5 - }, - cronExpressionBlur() { + async cronExpressionBlur() { this.customCronError = '' - if (!this.simpleValidateCustomCron()) { + if (!this.customCronExpression || this.customCronExpression.split(' ').length !== 5) { this.customCronError = 'Invalid cron expression' + this.isValid = false + return + } else if (this.customCronExpression.split(' ')[0] === '*') { + this.customCronError = 'Cannot use * in minutes position' + this.isValid = false return } @@ -160,29 +180,65 @@ export default { this.selectedMinute = 0 this.cronExpression = this.customCronExpression } - this.$emit('input', this.cronExpression) + + if (!this.validatedCron || this.validatedCron !== this.cronExpression) { + const validationPayload = await this.validateCron() + this.isValid = validationPayload.isValid + this.validatedCron = this.cronExpression + this.customCronError = validationPayload.error || '' + } + + if (this.isValid) { + this.$emit('input', this.cronExpression) + } }, validateCron() { this.isValidating = true - this.$axios + return this.$axios .$post('/api/validate-cron', { expression: this.customCronExpression }) .then(() => { - this.$toast.success('Cron expression is valid!') this.isValidating = false + return { + isValid: true + } }) .catch((error) => { console.error('Invalid cron', error) var errMsg = error.response ? error.response.data || '' : '' - this.$toast.error('Invalid cron: ' + errMsg) this.isValidating = false + return { + isValid: false, + error: errMsg || 'Invalid cron expression' + } }) }, init() { if (!this.value) return // TODO: parse - // const pieces = this.value.split(' ') - // this.selectedMinute = Number(pieces[0]) + const pieces = this.value.split(' ') + if (pieces.length !== 5) { + console.error('Invalid cron expression input', this.value) + return + } + var isCustomCron = false + if (isNaN(pieces[0]) || isNaN(pieces[1])) { + isCustomCron = true + } else if (pieces[2] !== '*' || pieces[3] !== '*') { + isCustomCron = true + } else if (pieces[4].split(',').some((num) => isNaN(num))) { + isCustomCron = true + } + + if (isCustomCron) { + this.showAdvancedView = true + } else { + this.selectedWeekdays = pieces[4].split(',').map((num) => Number(num)) + this.selectedHour = pieces[1] + this.selectedMinute = pieces[0] + } + this.cronExpression = this.value + this.customCronExpression = this.value } }, mounted() {