diff --git a/messages/en-US.json b/messages/en-US.json index 33003e434..0b4dde100 100644 --- a/messages/en-US.json +++ b/messages/en-US.json @@ -3027,5 +3027,7 @@ "httpDestUpdatedSuccess": "Destination updated successfully", "httpDestCreatedSuccess": "Destination created successfully", "httpDestUpdateFailed": "Failed to update destination", - "httpDestCreateFailed": "Failed to create destination" + "httpDestCreateFailed": "Failed to create destination", + "followRedirects": "Follow Redirects", + "followRedirectsDescription": "Automatically follow HTTP redirects for requests." } diff --git a/src/app/[orgId]/settings/resources/proxy/[niceId]/proxy/page.tsx b/src/app/[orgId]/settings/resources/proxy/[niceId]/proxy/page.tsx index 8c3d4910c..f43ad1543 100644 --- a/src/app/[orgId]/settings/resources/proxy/[niceId]/proxy/page.tsx +++ b/src/app/[orgId]/settings/resources/proxy/[niceId]/proxy/page.tsx @@ -1,6 +1,6 @@ "use client"; -import HealthCheckDialog from "@/components/HealthCheckDialog"; +import HealthCheckCredenza from "@/components/HealthCheckCredenza"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { @@ -965,10 +965,10 @@ function ProxyResourceTargetsForm({ {selectedTargetForHealthCheck && ( - {selectedTargetForHealthCheck && ( - void; + orgId?: string; + targetAddress: string; + targetMethod?: string; + initialConfig?: Partial; + onChanges: (config: HealthCheckConfig) => Promise; + } + | { + mode: "submit"; + open: boolean; + setOpen: (v: boolean) => void; + orgId: string; + initialValues?: HealthCheckRow | null; + onSaved: () => void; + }; + +const DEFAULT_VALUES = { + name: "", + hcEnabled: true, + hcMode: "http", + hcScheme: "https", + hcMethod: "GET", + hcHostname: "", + hcPort: "", + hcPath: "/", + hcInterval: 30, + hcUnhealthyInterval: 30, + hcTimeout: 5, + hcHealthyThreshold: 1, + hcUnhealthyThreshold: 1, + hcFollowRedirects: true, + hcTlsServerName: "", + hcStatus: null as number | null, + hcHeaders: [] as { name: string; value: string }[] +}; + +export function HealthCheckCredenza(props: HealthCheckCredenzaProps) { + const { mode, open, setOpen, orgId } = props; + + const t = useTranslations(); + const api = createApiClient(useEnvContext()); + const [loading, setLoading] = useState(false); + + const healthCheckSchema = z + .object({ + ...(mode === "submit" + ? { + name: z + .string() + .min(1, { message: t("standaloneHcNameLabel") }) + } + : {}), + hcEnabled: z.boolean(), + hcPath: z.string().optional(), + hcMethod: z.string().optional(), + hcInterval: z + .int() + .positive() + .min(5, { message: t("healthCheckIntervalMin") }), + hcTimeout: z + .int() + .positive() + .min(1, { message: t("healthCheckTimeoutMin") }), + hcStatus: z.int().positive().min(100).optional().nullable(), + hcHeaders: z + .array(z.object({ name: z.string(), value: z.string() })) + .nullable() + .optional(), + hcScheme: z.string().optional(), + hcHostname: z.string(), + hcPort: z + .string() + .min(1, { message: t("healthCheckPortInvalid") }) + .refine( + (val) => { + const port = parseInt(val); + return port > 0 && port <= 65535; + }, + { message: t("healthCheckPortInvalid") } + ), + hcFollowRedirects: z.boolean(), + hcMode: z.string(), + hcUnhealthyInterval: z.int().positive().min(5), + hcTlsServerName: z.string(), + hcHealthyThreshold: z + .int() + .positive() + .min(1, { message: t("healthCheckHealthyThresholdMin") }), + hcUnhealthyThreshold: z + .int() + .positive() + .min(1, { message: t("healthCheckUnhealthyThresholdMin") }) + }) + .superRefine((data, ctx) => { + if (data.hcMode !== "tcp") { + if (!data.hcPath || data.hcPath.length < 1) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: t("healthCheckPathRequired"), + path: ["hcPath"] + }); + } + if (!data.hcMethod || data.hcMethod.length < 1) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: t("healthCheckMethodRequired"), + path: ["hcMethod"] + }); + } + } + }); + + type FormValues = z.infer; + + const form = useForm({ + resolver: zodResolver(healthCheckSchema), + defaultValues: mode === "submit" ? DEFAULT_VALUES : {} + }); + + useEffect(() => { + if (!open) return; + + if (mode === "autoSave") { + const { initialConfig, targetMethod } = props; + + const getDefaultScheme = () => { + if (initialConfig?.hcScheme) return initialConfig.hcScheme; + if (targetMethod === "https") return "https"; + return "http"; + }; + + form.reset({ + hcEnabled: initialConfig?.hcEnabled, + hcPath: initialConfig?.hcPath, + hcMethod: initialConfig?.hcMethod, + hcInterval: initialConfig?.hcInterval, + hcTimeout: initialConfig?.hcTimeout, + hcStatus: initialConfig?.hcStatus, + hcHeaders: initialConfig?.hcHeaders, + hcScheme: getDefaultScheme(), + hcHostname: initialConfig?.hcHostname, + hcPort: initialConfig?.hcPort + ? initialConfig.hcPort.toString() + : "", + hcFollowRedirects: initialConfig?.hcFollowRedirects, + hcMode: initialConfig?.hcMode ?? "http", + hcUnhealthyInterval: initialConfig?.hcUnhealthyInterval, + hcTlsServerName: initialConfig?.hcTlsServerName ?? "", + hcHealthyThreshold: initialConfig?.hcHealthyThreshold ?? 1, + hcUnhealthyThreshold: initialConfig?.hcUnhealthyThreshold ?? 1 + }); + } else { + const { initialValues } = props; + + if (initialValues) { + let parsedHeaders: { name: string; value: string }[] = []; + if (initialValues.hcHeaders) { + try { + parsedHeaders = JSON.parse(initialValues.hcHeaders); + } catch { + parsedHeaders = []; + } + } + + form.reset({ + name: initialValues.name, + hcEnabled: initialValues.hcEnabled, + hcMode: initialValues.hcMode ?? "http", + hcScheme: initialValues.hcScheme ?? "https", + hcMethod: initialValues.hcMethod ?? "GET", + hcHostname: initialValues.hcHostname ?? "", + hcPort: initialValues.hcPort + ? initialValues.hcPort.toString() + : "", + hcPath: initialValues.hcPath ?? "/", + hcInterval: initialValues.hcInterval ?? 30, + hcUnhealthyInterval: + initialValues.hcUnhealthyInterval ?? 30, + hcTimeout: initialValues.hcTimeout ?? 5, + hcHealthyThreshold: + initialValues.hcHealthyThreshold ?? 1, + hcUnhealthyThreshold: + initialValues.hcUnhealthyThreshold ?? 1, + hcFollowRedirects: + initialValues.hcFollowRedirects ?? true, + hcTlsServerName: initialValues.hcTlsServerName ?? "", + hcStatus: initialValues.hcStatus ?? null, + hcHeaders: parsedHeaders + }); + } else { + form.reset(DEFAULT_VALUES); + } + } + }, [open]); + + const handleFieldChange = async (fieldName: string, value: any) => { + if (mode !== "autoSave") return; + try { + const currentValues = form.getValues(); + const updatedValues = { ...currentValues, [fieldName]: value }; + + const configToSend: HealthCheckConfig = { + ...updatedValues, + hcPath: updatedValues.hcPath ?? "", + hcMethod: updatedValues.hcMethod ?? "", + hcPort: parseInt(updatedValues.hcPort), + hcStatus: updatedValues.hcStatus || null, + hcHealthyThreshold: updatedValues.hcHealthyThreshold, + hcUnhealthyThreshold: updatedValues.hcUnhealthyThreshold + }; + + await props.onChanges(configToSend); + } catch (error) { + toast({ + title: t("healthCheckError"), + description: t("healthCheckErrorDescription"), + variant: "destructive" + }); + } + }; + + const onSubmit = async (values: FormValues) => { + if (mode !== "submit") return; + const { initialValues, onSaved } = props; + + setLoading(true); + try { + const payload = { + name: (values as any).name, + hcEnabled: values.hcEnabled, + hcMode: values.hcMode, + hcScheme: values.hcScheme, + hcMethod: values.hcMethod, + hcHostname: values.hcHostname, + hcPort: parseInt(values.hcPort), + hcPath: values.hcPath ?? "", + hcInterval: values.hcInterval, + hcUnhealthyInterval: values.hcUnhealthyInterval, + hcTimeout: values.hcTimeout, + hcHealthyThreshold: values.hcHealthyThreshold, + hcUnhealthyThreshold: values.hcUnhealthyThreshold, + hcFollowRedirects: values.hcFollowRedirects, + hcTlsServerName: values.hcTlsServerName, + hcStatus: values.hcStatus || null, + hcHeaders: + values.hcHeaders && values.hcHeaders.length > 0 + ? JSON.stringify(values.hcHeaders) + : null + }; + + if (initialValues) { + await api.post( + `/org/${orgId}/health-check/${initialValues.targetHealthCheckId}`, + payload + ); + } else { + await api.put(`/org/${orgId}/health-check`, payload); + } + + toast({ title: t("standaloneHcSaved") }); + onSaved(); + setOpen(false); + } catch (e) { + toast({ + title: t("error"), + description: formatAxiosError(e), + variant: "destructive" + }); + } finally { + setLoading(false); + } + }; + + const isEditing = mode === "submit" && !!(props as any).initialValues; + + const title = + mode === "autoSave" + ? t("configureHealthCheck") + : isEditing + ? t("standaloneHcEditTitle") + : t("standaloneHcCreateTitle"); + + const description = + mode === "autoSave" + ? t("configureHealthCheckDescription", { + target: (props as any).targetAddress + }) + : t("standaloneHcDescription"); + + return ( + + + + {title} + {description} + + +
+ + + + +
+ + {mode === "autoSave" ? ( + + ) : ( + <> + + + + + + )} + +
+
+ ); +} + +export default HealthCheckCredenza; \ No newline at end of file diff --git a/src/components/HealthCheckDialog.tsx b/src/components/HealthCheckDialog.tsx deleted file mode 100644 index d441cdaf3..000000000 --- a/src/components/HealthCheckDialog.tsx +++ /dev/null @@ -1,223 +0,0 @@ -"use client"; - -import { useEffect } from "react"; -import { Button } from "@/components/ui/button"; -import { z } from "zod"; -import { useForm } from "react-hook-form"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { Form } from "@/components/ui/form"; -import { HealthCheckFormFields } from "@app/components/HealthCheckFormFields"; -import { - Credenza, - CredenzaBody, - CredenzaClose, - CredenzaContent, - CredenzaDescription, - CredenzaFooter, - CredenzaHeader, - CredenzaTitle -} from "@/components/Credenza"; -import { toast } from "@/hooks/useToast"; -import { useTranslations } from "next-intl"; - -type HealthCheckConfig = { - hcEnabled: boolean; - hcPath: string; - hcMethod: string; - hcInterval: number; - hcTimeout: number; - hcStatus: number | null; - hcHeaders?: { name: string; value: string }[] | null; - hcScheme?: string; - hcHostname: string; - hcPort: number; - hcFollowRedirects: boolean; - hcMode: string; - hcUnhealthyInterval: number; - hcTlsServerName: string; - hcHealthyThreshold: number; - hcUnhealthyThreshold: number; -}; - -type HealthCheckDialogProps = { - open: boolean; - setOpen: (val: boolean) => void; - orgId: string; - targetAddress: string; - targetMethod?: string; - initialConfig?: Partial; - onChanges: (config: HealthCheckConfig) => Promise; -}; - -export default function HealthCheckDialog({ - open, - setOpen, - orgId, - targetAddress, - targetMethod, - initialConfig, - onChanges -}: HealthCheckDialogProps) { - const t = useTranslations(); - - const healthCheckSchema = z - .object({ - hcEnabled: z.boolean(), - hcPath: z.string().optional(), - hcMethod: z.string().optional(), - hcInterval: z - .int() - .positive() - .min(5, { message: t("healthCheckIntervalMin") }), - hcTimeout: z - .int() - .positive() - .min(1, { message: t("healthCheckTimeoutMin") }), - hcStatus: z.int().positive().min(100).optional().nullable(), - hcHeaders: z - .array(z.object({ name: z.string(), value: z.string() })) - .nullable() - .optional(), - hcScheme: z.string().optional(), - hcHostname: z.string(), - hcPort: z - .string() - .min(1, { message: t("healthCheckPortInvalid") }) - .refine( - (val) => { - const port = parseInt(val); - return port > 0 && port <= 65535; - }, - { - message: t("healthCheckPortInvalid") - } - ), - hcFollowRedirects: z.boolean(), - hcMode: z.string(), - hcUnhealthyInterval: z.int().positive().min(5), - hcTlsServerName: z.string(), - hcHealthyThreshold: z - .int() - .positive() - .min(1, { - message: t("healthCheckHealthyThresholdMin") - }), - hcUnhealthyThreshold: z - .int() - .positive() - .min(1, { - message: t("healthCheckUnhealthyThresholdMin") - }) - }) - .superRefine((data, ctx) => { - if (data.hcMode !== "tcp") { - if (!data.hcPath || data.hcPath.length < 1) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: t("healthCheckPathRequired"), - path: ["hcPath"] - }); - } - if (!data.hcMethod || data.hcMethod.length < 1) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: t("healthCheckMethodRequired"), - path: ["hcMethod"] - }); - } - } - }); - - const form = useForm>({ - resolver: zodResolver(healthCheckSchema), - defaultValues: {} - }); - - useEffect(() => { - if (!open) return; - - const getDefaultScheme = () => { - if (initialConfig?.hcScheme) { - return initialConfig.hcScheme; - } - if (targetMethod === "https") { - return "https"; - } - return "http"; - }; - - form.reset({ - hcEnabled: initialConfig?.hcEnabled, - hcPath: initialConfig?.hcPath, - hcMethod: initialConfig?.hcMethod, - hcInterval: initialConfig?.hcInterval, - hcTimeout: initialConfig?.hcTimeout, - hcStatus: initialConfig?.hcStatus, - hcHeaders: initialConfig?.hcHeaders, - hcScheme: getDefaultScheme(), - hcHostname: initialConfig?.hcHostname, - hcPort: initialConfig?.hcPort - ? initialConfig.hcPort.toString() - : "", - hcFollowRedirects: initialConfig?.hcFollowRedirects, - hcMode: initialConfig?.hcMode ?? "http", - hcUnhealthyInterval: initialConfig?.hcUnhealthyInterval, - hcTlsServerName: initialConfig?.hcTlsServerName ?? "", - hcHealthyThreshold: initialConfig?.hcHealthyThreshold ?? 1, - hcUnhealthyThreshold: initialConfig?.hcUnhealthyThreshold ?? 1 - }); - }, [open]); - - const handleFieldChange = async (fieldName: string, value: any) => { - try { - const currentValues = form.getValues(); - const updatedValues = { ...currentValues, [fieldName]: value }; - - const configToSend: HealthCheckConfig = { - ...updatedValues, - hcPath: updatedValues.hcPath ?? "", - hcMethod: updatedValues.hcMethod ?? "", - hcPort: parseInt(updatedValues.hcPort), - hcStatus: updatedValues.hcStatus || null, - hcHealthyThreshold: updatedValues.hcHealthyThreshold, - hcUnhealthyThreshold: updatedValues.hcUnhealthyThreshold - }; - - await onChanges(configToSend); - } catch (error) { - toast({ - title: t("healthCheckError"), - description: t("healthCheckErrorDescription"), - variant: "destructive" - }); - } - }; - - return ( - - - - {t("configureHealthCheck")} - - {t("configureHealthCheckDescription", { - target: targetAddress - })} - - - -
- - - - -
- - - -
-
- ); -} diff --git a/src/components/HealthCheckFormFields.tsx b/src/components/HealthCheckFormFields.tsx index 9873f9c5d..db98948db 100644 --- a/src/components/HealthCheckFormFields.tsx +++ b/src/components/HealthCheckFormFields.tsx @@ -25,16 +25,19 @@ type HealthCheckFormFieldsProps = { form: UseFormReturn; onFieldChange?: (fieldName: string, value: any) => void; showNameField?: boolean; + hideEnabledField?: boolean; }; export function HealthCheckFormFields({ form, onFieldChange, - showNameField + showNameField, + hideEnabledField }: HealthCheckFormFieldsProps) { const t = useTranslations(); const watchedEnabled = form.watch("hcEnabled"); + const showFields = hideEnabledField || watchedEnabled; const watchedMode = form.watch("hcMode"); const handleChange = (fieldName: string, value: any, fieldOnChange: (v: any) => void) => { @@ -67,30 +70,32 @@ export function HealthCheckFormFields({ )} {/* Enable Health Checks */} - ( - -
- {t("enableHealthChecks")} - - {t("enableHealthChecksDescription")} - -
- - - handleChange("hcEnabled", value, field.onChange) - } - /> - -
- )} - /> + {!hideEnabledField && ( + ( + +
+ {t("enableHealthChecks")} + + {t("enableHealthChecksDescription")} + +
+ + + handleChange("hcEnabled", value, field.onChange) + } + /> + +
+ )} + /> + )} - {watchedEnabled && ( + {showFields && (
{/* Mode */} )} - { setCredenzaOpen(val); diff --git a/src/components/StandaloneHealthCheckCredenza.tsx b/src/components/StandaloneHealthCheckCredenza.tsx deleted file mode 100644 index 99260707d..000000000 --- a/src/components/StandaloneHealthCheckCredenza.tsx +++ /dev/null @@ -1,290 +0,0 @@ -"use client"; - -import { useEffect, useState } from "react"; -import { Button } from "@/components/ui/button"; -import { z } from "zod"; -import { useForm } from "react-hook-form"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { Form } from "@/components/ui/form"; -import { HealthCheckFormFields } from "@app/components/HealthCheckFormFields"; -import { - Credenza, - CredenzaBody, - CredenzaClose, - CredenzaContent, - CredenzaDescription, - CredenzaFooter, - CredenzaHeader, - CredenzaTitle -} from "@/components/Credenza"; -import { toast } from "@app/hooks/useToast"; -import { createApiClient, formatAxiosError } from "@app/lib/api"; -import { useEnvContext } from "@app/hooks/useEnvContext"; -import { useTranslations } from "next-intl"; - -export type HealthCheckRow = { - targetHealthCheckId: number; - name: string; - hcEnabled: boolean; - hcHealth: "unknown" | "healthy" | "unhealthy"; - hcMode: string | null; - hcHostname: string | null; - hcPort: number | null; - hcPath: string | null; - hcScheme: string | null; - hcMethod: string | null; - hcInterval: number | null; - hcUnhealthyInterval: number | null; - hcTimeout: number | null; - hcHeaders: string | null; - hcFollowRedirects: boolean | null; - hcStatus: number | null; - hcTlsServerName: string | null; - hcHealthyThreshold: number | null; - hcUnhealthyThreshold: number | null; -}; - -type StandaloneHealthCheckCredenzaProps = { - open: boolean; - setOpen: (v: boolean) => void; - orgId: string; - initialValues?: HealthCheckRow | null; - onSaved: () => void; -}; - -const DEFAULT_VALUES = { - name: "", - hcEnabled: true, - hcMode: "http", - hcScheme: "https", - hcMethod: "GET", - hcHostname: "", - hcPort: "", - hcPath: "/", - hcInterval: 30, - hcUnhealthyInterval: 30, - hcTimeout: 5, - hcHealthyThreshold: 1, - hcUnhealthyThreshold: 1, - hcFollowRedirects: true, - hcTlsServerName: "", - hcStatus: null as number | null, - hcHeaders: [] as { name: string; value: string }[] -}; - -export default function StandaloneHealthCheckCredenza({ - open, - setOpen, - orgId, - initialValues, - onSaved -}: StandaloneHealthCheckCredenzaProps) { - const t = useTranslations(); - const api = createApiClient(useEnvContext()); - const [loading, setLoading] = useState(false); - - const healthCheckSchema = z - .object({ - name: z.string().min(1, { message: t("standaloneHcNameLabel") }), - hcEnabled: z.boolean(), - hcPath: z.string().optional(), - hcMethod: z.string().optional(), - hcInterval: z - .int() - .positive() - .min(5, { message: t("healthCheckIntervalMin") }), - hcTimeout: z - .int() - .positive() - .min(1, { message: t("healthCheckTimeoutMin") }), - hcStatus: z.int().positive().min(100).optional().nullable(), - hcHeaders: z - .array(z.object({ name: z.string(), value: z.string() })) - .nullable() - .optional(), - hcScheme: z.string().optional(), - hcHostname: z.string(), - hcPort: z - .string() - .min(1, { message: t("healthCheckPortInvalid") }) - .refine( - (val) => { - const port = parseInt(val); - return port > 0 && port <= 65535; - }, - { message: t("healthCheckPortInvalid") } - ), - hcFollowRedirects: z.boolean(), - hcMode: z.string(), - hcUnhealthyInterval: z.int().positive().min(5), - hcTlsServerName: z.string(), - hcHealthyThreshold: z - .int() - .positive() - .min(1, { message: t("healthCheckHealthyThresholdMin") }), - hcUnhealthyThreshold: z - .int() - .positive() - .min(1, { message: t("healthCheckUnhealthyThresholdMin") }) - }) - .superRefine((data, ctx) => { - if (data.hcMode !== "tcp") { - if (!data.hcPath || data.hcPath.length < 1) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: t("healthCheckPathRequired"), - path: ["hcPath"] - }); - } - if (!data.hcMethod || data.hcMethod.length < 1) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: t("healthCheckMethodRequired"), - path: ["hcMethod"] - }); - } - } - }); - - type FormValues = z.infer; - - const form = useForm({ - resolver: zodResolver(healthCheckSchema), - defaultValues: DEFAULT_VALUES - }); - - useEffect(() => { - if (!open) return; - - if (initialValues) { - let parsedHeaders: { name: string; value: string }[] = []; - if (initialValues.hcHeaders) { - try { - parsedHeaders = JSON.parse(initialValues.hcHeaders); - } catch { - parsedHeaders = []; - } - } - - form.reset({ - name: initialValues.name, - hcEnabled: initialValues.hcEnabled, - hcMode: initialValues.hcMode ?? "http", - hcScheme: initialValues.hcScheme ?? "https", - hcMethod: initialValues.hcMethod ?? "GET", - hcHostname: initialValues.hcHostname ?? "", - hcPort: initialValues.hcPort - ? initialValues.hcPort.toString() - : "", - hcPath: initialValues.hcPath ?? "/", - hcInterval: initialValues.hcInterval ?? 30, - hcUnhealthyInterval: initialValues.hcUnhealthyInterval ?? 30, - hcTimeout: initialValues.hcTimeout ?? 5, - hcHealthyThreshold: initialValues.hcHealthyThreshold ?? 1, - hcUnhealthyThreshold: initialValues.hcUnhealthyThreshold ?? 1, - hcFollowRedirects: initialValues.hcFollowRedirects ?? true, - hcTlsServerName: initialValues.hcTlsServerName ?? "", - hcStatus: initialValues.hcStatus ?? null, - hcHeaders: parsedHeaders - }); - } else { - form.reset(DEFAULT_VALUES); - } - }, [open]); - - const onSubmit = async (values: FormValues) => { - setLoading(true); - try { - const payload = { - name: values.name, - hcEnabled: values.hcEnabled, - hcMode: values.hcMode, - hcScheme: values.hcScheme, - hcMethod: values.hcMethod, - hcHostname: values.hcHostname, - hcPort: parseInt(values.hcPort), - hcPath: values.hcPath ?? "", - hcInterval: values.hcInterval, - hcUnhealthyInterval: values.hcUnhealthyInterval, - hcTimeout: values.hcTimeout, - hcHealthyThreshold: values.hcHealthyThreshold, - hcUnhealthyThreshold: values.hcUnhealthyThreshold, - hcFollowRedirects: values.hcFollowRedirects, - hcTlsServerName: values.hcTlsServerName, - hcStatus: values.hcStatus || null, - hcHeaders: - values.hcHeaders && values.hcHeaders.length > 0 - ? JSON.stringify(values.hcHeaders) - : null - }; - - if (initialValues) { - await api.post( - `/org/${orgId}/health-check/${initialValues.targetHealthCheckId}`, - payload - ); - } else { - await api.put( - `/org/${orgId}/health-check`, - payload - ); - } - - toast({ title: t("standaloneHcSaved") }); - onSaved(); - setOpen(false); - } catch (e) { - toast({ - title: t("error"), - description: formatAxiosError(e), - variant: "destructive" - }); - } finally { - setLoading(false); - } - }; - - const isEditing = !!initialValues; - - return ( - - - - - {isEditing - ? t("standaloneHcEditTitle") - : t("standaloneHcCreateTitle")} - - - {t("standaloneHcDescription")} - - - -
- - - - -
- - - - - - -
-
- ); -}