main
vue 148 lines 3.61 KB
Raw
1 <template>
2 <n-spin :show="loading" class="job-form">
3 <n-form ref="formRef" :label-width="80" :model="form" :rules>
4 <div class="flex flex-col gap-1">
5 <n-form-item label="Time interval (minutes)" path="time_interval" class="grow">
6 <n-input-number
7 v-model:value="form.time_interval"
8 :min="1"
9 placeholder="Input time in minutes"
10 clearable
11 class="w-full"
12 />
13 </n-form-item>
14
15 <div class="flex items-center justify-end gap-3">
16 <n-button :disabled="loading" @click="reset()">Reset</n-button>
17 <n-button
18 type="primary"
19 :disabled="!isValid"
20 :loading="submitting"
21 @click="validate(() => submit())"
22 >
23 Submit
24 </n-button>
25 </div>
26 </div>
27 </n-form>
28 </n-spin>
29 </template>
30
31 <script setup lang="ts">
32 import type { FormInst, FormItemRule, FormRules, FormValidationError, MessageReactive } from "naive-ui"
33 import type { UpdateJobPayload } from "@/api/endpoints/scheduler"
34 import type { Job } from "@/types/scheduler.d"
35 import _get from "lodash/get"
36 import _trim from "lodash/trim"
37 import { NButton, NForm, NFormItem, NInputNumber, NSpin, useMessage } from "naive-ui"
38 import { computed, ref, toRefs } from "vue"
39 import Api from "@/api"
40
41 const props = defineProps<{ job: Job }>()
42 const emit = defineEmits<{
43 (e: "updated", value: UpdateJobPayload): void
44 }>()
45
46 const { job } = toRefs(props)
47
48 const submitting = ref(false)
49 const loading = computed(() => submitting.value)
50 const message = useMessage()
51 const form = ref<UpdateJobPayload>(getClearForm())
52 const formRef = ref<FormInst | null>(null)
53
54 const rules: FormRules = {
55 time_interval: {
56 required: true,
57 validator: validatorNumber("Alert Priority", "Required"),
58 trigger: ["input", "blur"]
59 }
60 }
61
62 const isValid = computed(() => {
63 let valid = true
64
65 for (const key in rules) {
66 const rule = rules[key] as FormRules
67
68 if (rule.required && !_trim(_get(form.value, key))) {
69 valid = false
70 }
71 }
72
73 return valid
74 })
75
76 const INTEGER_STRING_REGEX = /^\d*$/
77
78 function validatorNumber(fieldName: string, defaultMessage?: string) {
79 return (_rule: FormItemRule, value: string) => {
80 if (!value) {
81 return new Error(defaultMessage || `${fieldName} is required`)
82 } else if (!INTEGER_STRING_REGEX.test(value)) {
83 return new Error(`${fieldName} should be an integer`)
84 } else if (Number(value) < 1) {
85 return new Error(`${fieldName} should be above 1`)
86 }
87 return true
88 }
89 }
90
91 let validationMessage: MessageReactive | null = null
92
93 function validate(cb?: () => void) {
94 if (!formRef.value) return
95
96 formRef.value.validate((errors?: Array<FormValidationError>) => {
97 if (!errors) {
98 validationMessage?.destroy()
99 validationMessage = null
100 if (cb) cb()
101 } else {
102 if (!validationMessage) {
103 validationMessage = message.warning("You must fill in the required fields correctly.")
104 }
105 return false
106 }
107 })
108 }
109
110 function getClearForm(): UpdateJobPayload {
111 return {
112 time_interval: job.value.time_interval || 1,
113 extra_data: ""
114 }
115 }
116
117 function reset() {
118 if (!loading.value) {
119 resetForm()
120 formRef.value?.restoreValidation()
121 }
122 }
123
124 function resetForm() {
125 form.value = getClearForm()
126 }
127
128 function submit() {
129 submitting.value = true
130
131 Api.scheduler
132 .updateJob(job.value.id, form.value)
133 .then(res => {
134 if (res.data.success) {
135 message.success(res.data?.message || `Job "${job.value.name}" updated successfully`)
136 emit("updated", form.value)
137 } else {
138 message.warning(res.data?.message || "An error occurred. Please try again later.")
139 }
140 })
141 .catch(err => {
142 message.error(err.response?.data?.message || "An error occurred. Please try again later.")
143 })
144 .finally(() => {
145 submitting.value = false
146 })
147 }
148 </script>