| 1 | <template> |
| 2 | <n-spin :show="loading" class="customer-provisioning-default-settings-form"> |
| 3 | <n-form ref="formRef" :label-width="80" :model="form" :rules> |
| 4 | <div class="flex flex-col gap-4"> |
| 5 | <div class="flex flex-wrap gap-4"> |
| 6 | <div v-for="(_, key) of form" :key class="grow"> |
| 7 | <n-form-item :label="fieldsMeta[key].label" :path="key" class="grow"> |
| 8 | <n-input |
| 9 | v-model:value.trim="form[key]" |
| 10 | :placeholder="fieldsMeta[key].placeholder" |
| 11 | clearable |
| 12 | /> |
| 13 | </n-form-item> |
| 14 | </div> |
| 15 | </div> |
| 16 | <div class="flex justify-between gap-4"> |
| 17 | <div class="flex gap-4"> |
| 18 | <slot name="additionalActions"></slot> |
| 19 | </div> |
| 20 | <div class="flex gap-4"> |
| 21 | <n-button :disabled="loading" @click="reset()">Reset</n-button> |
| 22 | <n-button |
| 23 | type="primary" |
| 24 | :disabled="!isValid" |
| 25 | :loading="submittingDefaultSettings" |
| 26 | @click="validate()" |
| 27 | > |
| 28 | Submit |
| 29 | </n-button> |
| 30 | </div> |
| 31 | </div> |
| 32 | </div> |
| 33 | </n-form> |
| 34 | </n-spin> |
| 35 | </template> |
| 36 | |
| 37 | <script setup lang="ts"> |
| 38 | import type { FormInst, FormItemRule, FormRules, FormValidationError } from "naive-ui" |
| 39 | import type { CustomerProvisioningDefaultSettings } from "@/types/customers.d" |
| 40 | import _get from "lodash/get" |
| 41 | import _trim from "lodash/trim" |
| 42 | import { NButton, NForm, NFormItem, NInput, NSpin, useMessage } from "naive-ui" |
| 43 | import isIP from "validator/es/lib/isIP" |
| 44 | import isURL from "validator/es/lib/isURL" |
| 45 | import { computed, onBeforeMount, onMounted, ref, watch } from "vue" |
| 46 | import Api from "@/api" |
| 47 | |
| 48 | const emit = defineEmits<{ |
| 49 | (e: "update:loading", value: boolean): void |
| 50 | ( |
| 51 | e: "mounted", |
| 52 | value: { |
| 53 | load: () => void |
| 54 | } |
| 55 | ): void |
| 56 | }>() |
| 57 | |
| 58 | const loadingDefaultSettings = ref(false) |
| 59 | const submittingDefaultSettings = ref(false) |
| 60 | const loading = computed(() => loadingDefaultSettings.value || submittingDefaultSettings.value) |
| 61 | const message = useMessage() |
| 62 | const form = ref<Omit<CustomerProvisioningDefaultSettings, "id">>(getClearForm()) |
| 63 | const formRef = ref<FormInst | null>(null) |
| 64 | const entityId = ref(0) |
| 65 | |
| 66 | const rules: FormRules = { |
| 67 | cluster_name: { |
| 68 | message: "Please input the Cluster Name", |
| 69 | trigger: ["input", "blur"] |
| 70 | }, |
| 71 | cluster_key: { |
| 72 | message: "Please input the Cluster Key", |
| 73 | trigger: ["input", "blur"] |
| 74 | }, |
| 75 | master_ip: { |
| 76 | validator: validateIp, |
| 77 | trigger: ["blur"] |
| 78 | }, |
| 79 | grafana_url: { |
| 80 | validator: validateUrl, |
| 81 | trigger: ["blur"] |
| 82 | }, |
| 83 | wazuh_worker_hostname: { |
| 84 | message: "Please input the Wazuh Worker Hostname", |
| 85 | trigger: ["input", "blur"] |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | const fieldsMeta = { |
| 90 | cluster_name: { |
| 91 | label: "Cluster Name", |
| 92 | placeholder: "Insert the Cluster Name" |
| 93 | }, |
| 94 | cluster_key: { |
| 95 | label: "Cluster Key", |
| 96 | placeholder: "Insert the Cluster Key" |
| 97 | }, |
| 98 | master_ip: { |
| 99 | label: "Master IP", |
| 100 | placeholder: "Insert the Master IP" |
| 101 | }, |
| 102 | grafana_url: { |
| 103 | label: "Grafana URL", |
| 104 | placeholder: "Insert the Grafana URL" |
| 105 | }, |
| 106 | wazuh_worker_hostname: { |
| 107 | label: "Wazuh Worker Hostname", |
| 108 | placeholder: "Insert the Wazuh Worker Hostname" |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | const isValid = computed(() => { |
| 113 | let valid = true |
| 114 | |
| 115 | for (const key in rules) { |
| 116 | const rule = rules[key] as FormRules |
| 117 | |
| 118 | if (rule.required && !_trim(_get(form.value, key))) { |
| 119 | valid = false |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | return valid |
| 124 | }) |
| 125 | |
| 126 | function validate() { |
| 127 | if (!formRef.value) return |
| 128 | |
| 129 | formRef.value.validate((errors?: Array<FormValidationError>) => { |
| 130 | if (!errors) { |
| 131 | submit() |
| 132 | } else { |
| 133 | message.warning("You must fill in the required fields correctly.") |
| 134 | return false |
| 135 | } |
| 136 | }) |
| 137 | } |
| 138 | |
| 139 | function getClearForm(settings?: Partial<CustomerProvisioningDefaultSettings>) { |
| 140 | const payload = { |
| 141 | cluster_name: settings?.cluster_name || "", |
| 142 | cluster_key: settings?.cluster_key || "", |
| 143 | master_ip: settings?.master_ip || "", |
| 144 | grafana_url: settings?.grafana_url || "", |
| 145 | wazuh_worker_hostname: settings?.wazuh_worker_hostname || "" |
| 146 | } |
| 147 | return payload |
| 148 | } |
| 149 | |
| 150 | function reset() { |
| 151 | if (!loading.value) { |
| 152 | resetForm() |
| 153 | formRef.value?.restoreValidation() |
| 154 | } |
| 155 | } |
| 156 | |
| 157 | function resetForm() { |
| 158 | form.value = getClearForm() |
| 159 | } |
| 160 | |
| 161 | function submit() { |
| 162 | submittingDefaultSettings.value = true |
| 163 | |
| 164 | const method = entityId.value ? "updateProvisioningDefaultSettings" : "setProvisioningDefaultSettings" |
| 165 | |
| 166 | const payload = { |
| 167 | id: entityId.value || 0, |
| 168 | clusterName: form.value.cluster_name, |
| 169 | clusterKey: form.value.cluster_key, |
| 170 | masterIp: form.value.master_ip, |
| 171 | grafanaUrl: form.value.grafana_url, |
| 172 | wazuhWorkerHostname: form.value.wazuh_worker_hostname |
| 173 | } |
| 174 | |
| 175 | Api.customers[method](payload) |
| 176 | .then(res => { |
| 177 | if (res.data.success) { |
| 178 | entityId.value = res.data.customer_provisioning_default_settings.id |
| 179 | message.success(res.data?.message || "Customer Provisioning Default Settings updated successfully") |
| 180 | } else { |
| 181 | message.warning(res.data?.message || "An error occurred. Please try again later.") |
| 182 | } |
| 183 | }) |
| 184 | .catch(err => { |
| 185 | message.error(err.response?.data?.message || "An error occurred. Please try again later.") |
| 186 | }) |
| 187 | .finally(() => { |
| 188 | submittingDefaultSettings.value = false |
| 189 | }) |
| 190 | } |
| 191 | |
| 192 | function setForm(settings?: CustomerProvisioningDefaultSettings) { |
| 193 | form.value = getClearForm(settings) |
| 194 | } |
| 195 | |
| 196 | function validateIp(_rule: FormItemRule, value: string) { |
| 197 | if (value && !isIP(value)) { |
| 198 | return new Error("Please input a valid IP Address") |
| 199 | } |
| 200 | |
| 201 | return true |
| 202 | } |
| 203 | |
| 204 | function validateUrl(_rule: FormItemRule, value: string) { |
| 205 | if (value && !isURL(value, { require_tld: false })) { |
| 206 | return new Error("Please input a valid URL") |
| 207 | } |
| 208 | |
| 209 | return true |
| 210 | } |
| 211 | |
| 212 | function getProvisioningDefaultSettings() { |
| 213 | loadingDefaultSettings.value = true |
| 214 | |
| 215 | Api.customers |
| 216 | .getProvisioningDefaultSettings() |
| 217 | .then(res => { |
| 218 | if (res.data.success) { |
| 219 | entityId.value = res.data.customer_provisioning_default_settings.id || 0 |
| 220 | setForm(res.data?.customer_provisioning_default_settings) |
| 221 | } |
| 222 | }) |
| 223 | .finally(() => { |
| 224 | loadingDefaultSettings.value = false |
| 225 | }) |
| 226 | } |
| 227 | |
| 228 | function load() { |
| 229 | if (!loadingDefaultSettings.value) { |
| 230 | getProvisioningDefaultSettings() |
| 231 | } |
| 232 | } |
| 233 | |
| 234 | watch(loading, val => { |
| 235 | emit("update:loading", val) |
| 236 | }) |
| 237 | |
| 238 | onBeforeMount(() => { |
| 239 | getProvisioningDefaultSettings() |
| 240 | }) |
| 241 | |
| 242 | onMounted(() => { |
| 243 | emit("mounted", { |
| 244 | load |
| 245 | }) |
| 246 | }) |
| 247 | </script> |