mirror of
https://github.com/fosrl/pangolin.git
synced 2026-05-30 04:32:53 +00:00
Working on alerting
This commit is contained in:
@@ -32,7 +32,7 @@ import { processAlerts } from "../processAlerts";
|
|||||||
export async function fireHealthCheckHealthyAlert(
|
export async function fireHealthCheckHealthyAlert(
|
||||||
orgId: string,
|
orgId: string,
|
||||||
healthCheckId: number,
|
healthCheckId: number,
|
||||||
healthCheckName?: string,
|
healthCheckName?: string | null,
|
||||||
extra?: Record<string, unknown>
|
extra?: Record<string, unknown>
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
try {
|
try {
|
||||||
@@ -68,7 +68,7 @@ export async function fireHealthCheckHealthyAlert(
|
|||||||
export async function fireHealthCheckNotHealthyAlert(
|
export async function fireHealthCheckNotHealthyAlert(
|
||||||
orgId: string,
|
orgId: string,
|
||||||
healthCheckId: number,
|
healthCheckId: number,
|
||||||
healthCheckName?: string,
|
healthCheckName?: string | null,
|
||||||
extra?: Record<string, unknown>
|
extra?: Record<string, unknown>
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -212,6 +212,7 @@ export async function buildTargetConfigurationForNewtClient(siteId: number) {
|
|||||||
hcUnhealthyInterval: targetHealthCheck.hcUnhealthyInterval,
|
hcUnhealthyInterval: targetHealthCheck.hcUnhealthyInterval,
|
||||||
hcTimeout: targetHealthCheck.hcTimeout,
|
hcTimeout: targetHealthCheck.hcTimeout,
|
||||||
hcHeaders: targetHealthCheck.hcHeaders,
|
hcHeaders: targetHealthCheck.hcHeaders,
|
||||||
|
hcFollowRedirects: targetHealthCheck.hcFollowRedirects,
|
||||||
hcMethod: targetHealthCheck.hcMethod,
|
hcMethod: targetHealthCheck.hcMethod,
|
||||||
hcTlsServerName: targetHealthCheck.hcTlsServerName,
|
hcTlsServerName: targetHealthCheck.hcTlsServerName,
|
||||||
hcStatus: targetHealthCheck.hcStatus,
|
hcStatus: targetHealthCheck.hcStatus,
|
||||||
@@ -284,6 +285,7 @@ export async function buildTargetConfigurationForNewtClient(siteId: number) {
|
|||||||
hcUnhealthyInterval: target.hcUnhealthyInterval, // in seconds
|
hcUnhealthyInterval: target.hcUnhealthyInterval, // in seconds
|
||||||
hcTimeout: target.hcTimeout, // in seconds
|
hcTimeout: target.hcTimeout, // in seconds
|
||||||
hcHeaders: hcHeadersSend,
|
hcHeaders: hcHeadersSend,
|
||||||
|
hcFollowRedirects: target.hcFollowRedirects,
|
||||||
hcMethod: target.hcMethod,
|
hcMethod: target.hcMethod,
|
||||||
hcTlsServerName: target.hcTlsServerName,
|
hcTlsServerName: target.hcTlsServerName,
|
||||||
hcStatus: target.hcStatus,
|
hcStatus: target.hcStatus,
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ export async function addTargets(
|
|||||||
hcUnhealthyInterval: hc.hcUnhealthyInterval, // in seconds
|
hcUnhealthyInterval: hc.hcUnhealthyInterval, // in seconds
|
||||||
hcTimeout: hc.hcTimeout, // in seconds
|
hcTimeout: hc.hcTimeout, // in seconds
|
||||||
hcHeaders: hcHeadersSend,
|
hcHeaders: hcHeadersSend,
|
||||||
|
hcFollowRedirects: hc.hcFollowRedirects,
|
||||||
hcMethod: hc.hcMethod,
|
hcMethod: hc.hcMethod,
|
||||||
hcStatus: hcStatus,
|
hcStatus: hcStatus,
|
||||||
hcTlsServerName: hc.hcTlsServerName,
|
hcTlsServerName: hc.hcTlsServerName,
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ interface TargetHealthStatus {
|
|||||||
hcUnhealthyInterval?: number;
|
hcUnhealthyInterval?: number;
|
||||||
hcTimeout?: number;
|
hcTimeout?: number;
|
||||||
hcHeaders?: any;
|
hcHeaders?: any;
|
||||||
|
hcFollowRedirects?: boolean;
|
||||||
hcMethod?: string;
|
hcMethod?: string;
|
||||||
hcTlsServerName?: string;
|
hcTlsServerName?: string;
|
||||||
hcHealthyThreshold?: number;
|
hcHealthyThreshold?: number;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import SettingsSectionTitle from "@app/components/SettingsSectionTitle";
|
import SettingsSectionTitle from "@app/components/SettingsSectionTitle";
|
||||||
import AlertingRulesTable from "@app/components/AlertingRulesTable";
|
import AlertingRulesTable from "@app/components/AlertingRulesTable";
|
||||||
import StandaloneHealthChecksTable from "@app/components/StandaloneHealthChecksTable";
|
import HealthChecksTable from "@app/components/HealthChecksTable";
|
||||||
import { HorizontalTabs, TabItem } from "@app/components/HorizontalTabs";
|
import { HorizontalTabs, TabItem } from "@app/components/HorizontalTabs";
|
||||||
import { getTranslations } from "next-intl/server";
|
import { getTranslations } from "next-intl/server";
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ export default async function AlertingPage(props: AlertingPageProps) {
|
|||||||
/>
|
/>
|
||||||
<HorizontalTabs items={tabs} clientSide>
|
<HorizontalTabs items={tabs} clientSide>
|
||||||
<AlertingRulesTable orgId={params.orgId} />
|
<AlertingRulesTable orgId={params.orgId} />
|
||||||
<StandaloneHealthChecksTable orgId={params.orgId} />
|
<HealthChecksTable orgId={params.orgId} />
|
||||||
</HorizontalTabs>
|
</HorizontalTabs>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -640,10 +640,10 @@ function ProxyResourceTargetsForm({
|
|||||||
hcInterval: null,
|
hcInterval: null,
|
||||||
hcTimeout: null,
|
hcTimeout: null,
|
||||||
hcHeaders: null,
|
hcHeaders: null,
|
||||||
|
hcFollowRedirects: null,
|
||||||
hcScheme: null,
|
hcScheme: null,
|
||||||
hcHostname: null,
|
hcHostname: null,
|
||||||
hcPort: null,
|
hcPort: null,
|
||||||
hcFollowRedirects: null,
|
|
||||||
hcHealth: "unknown",
|
hcHealth: "unknown",
|
||||||
hcStatus: null,
|
hcStatus: null,
|
||||||
hcMode: null,
|
hcMode: null,
|
||||||
|
|||||||
@@ -2,28 +2,11 @@
|
|||||||
|
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Input } from "@/components/ui/input";
|
|
||||||
import {
|
|
||||||
Select,
|
|
||||||
SelectContent,
|
|
||||||
SelectItem,
|
|
||||||
SelectTrigger,
|
|
||||||
SelectValue
|
|
||||||
} from "@/components/ui/select";
|
|
||||||
import { Switch } from "@/components/ui/switch";
|
|
||||||
import { HeadersInput } from "@app/components/HeadersInput";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import {
|
import { Form } from "@/components/ui/form";
|
||||||
Form,
|
import { HealthCheckFormFields } from "@app/components/HealthCheckFormFields";
|
||||||
FormControl,
|
|
||||||
FormDescription,
|
|
||||||
FormField,
|
|
||||||
FormItem,
|
|
||||||
FormLabel,
|
|
||||||
FormMessage
|
|
||||||
} from "@/components/ui/form";
|
|
||||||
import {
|
import {
|
||||||
Credenza,
|
Credenza,
|
||||||
CredenzaBody,
|
CredenzaBody,
|
||||||
@@ -59,7 +42,7 @@ type HealthCheckConfig = {
|
|||||||
type HealthCheckDialogProps = {
|
type HealthCheckDialogProps = {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
setOpen: (val: boolean) => void;
|
setOpen: (val: boolean) => void;
|
||||||
targetId: number;
|
orgId: string;
|
||||||
targetAddress: string;
|
targetAddress: string;
|
||||||
targetMethod?: string;
|
targetMethod?: string;
|
||||||
initialConfig?: Partial<HealthCheckConfig>;
|
initialConfig?: Partial<HealthCheckConfig>;
|
||||||
@@ -69,7 +52,7 @@ type HealthCheckDialogProps = {
|
|||||||
export default function HealthCheckDialog({
|
export default function HealthCheckDialog({
|
||||||
open,
|
open,
|
||||||
setOpen,
|
setOpen,
|
||||||
targetId,
|
orgId,
|
||||||
targetAddress,
|
targetAddress,
|
||||||
targetMethod,
|
targetMethod,
|
||||||
initialConfig,
|
initialConfig,
|
||||||
@@ -185,9 +168,6 @@ export default function HealthCheckDialog({
|
|||||||
});
|
});
|
||||||
}, [open]);
|
}, [open]);
|
||||||
|
|
||||||
const watchedEnabled = form.watch("hcEnabled");
|
|
||||||
const watchedMode = form.watch("hcMode");
|
|
||||||
|
|
||||||
const handleFieldChange = async (fieldName: string, value: any) => {
|
const handleFieldChange = async (fieldName: string, value: any) => {
|
||||||
try {
|
try {
|
||||||
const currentValues = form.getValues();
|
const currentValues = form.getValues();
|
||||||
@@ -227,659 +207,10 @@ export default function HealthCheckDialog({
|
|||||||
<CredenzaBody>
|
<CredenzaBody>
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form className="space-y-6">
|
<form className="space-y-6">
|
||||||
{/* Enable Health Checks */}
|
<HealthCheckFormFields
|
||||||
<FormField
|
form={form}
|
||||||
control={form.control}
|
onFieldChange={handleFieldChange}
|
||||||
name="hcEnabled"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
|
|
||||||
<div className="space-y-0.5">
|
|
||||||
<FormLabel>
|
|
||||||
{t("enableHealthChecks")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"enableHealthChecksDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
</div>
|
|
||||||
<FormControl>
|
|
||||||
<Switch
|
|
||||||
checked={field.value}
|
|
||||||
onCheckedChange={(value) => {
|
|
||||||
field.onChange(value);
|
|
||||||
handleFieldChange(
|
|
||||||
"hcEnabled",
|
|
||||||
value
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{watchedEnabled && (
|
|
||||||
<div className="space-y-4">
|
|
||||||
{/* Mode */}
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcMode"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("healthCheckMode")}
|
|
||||||
</FormLabel>
|
|
||||||
<Select
|
|
||||||
onValueChange={(value) => {
|
|
||||||
field.onChange(value);
|
|
||||||
handleFieldChange(
|
|
||||||
"hcMode",
|
|
||||||
value
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
value={field.value}
|
|
||||||
>
|
|
||||||
<FormControl>
|
|
||||||
<SelectTrigger>
|
|
||||||
<SelectValue />
|
|
||||||
</SelectTrigger>
|
|
||||||
</FormControl>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="http">
|
|
||||||
HTTP
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="tcp">
|
|
||||||
TCP
|
|
||||||
</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"healthCheckModeDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Connection fields */}
|
|
||||||
{watchedMode === "tcp" ? (
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcHostname"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("healthHostname")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
{...field}
|
|
||||||
onChange={(
|
|
||||||
e
|
|
||||||
) => {
|
|
||||||
field.onChange(
|
|
||||||
e
|
|
||||||
);
|
|
||||||
handleFieldChange(
|
|
||||||
"hcHostname",
|
|
||||||
e.target
|
|
||||||
.value
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcPort"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("healthPort")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
{...field}
|
|
||||||
onChange={(
|
|
||||||
e
|
|
||||||
) => {
|
|
||||||
const value =
|
|
||||||
e.target
|
|
||||||
.value;
|
|
||||||
field.onChange(
|
|
||||||
value
|
|
||||||
);
|
|
||||||
handleFieldChange(
|
|
||||||
"hcPort",
|
|
||||||
value
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcScheme"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("healthScheme")}
|
|
||||||
</FormLabel>
|
|
||||||
<Select
|
|
||||||
onValueChange={(
|
|
||||||
value
|
|
||||||
) => {
|
|
||||||
field.onChange(
|
|
||||||
value
|
|
||||||
);
|
|
||||||
handleFieldChange(
|
|
||||||
"hcScheme",
|
|
||||||
value
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
defaultValue={
|
|
||||||
field.value
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<FormControl>
|
|
||||||
<SelectTrigger>
|
|
||||||
<SelectValue
|
|
||||||
placeholder={t(
|
|
||||||
"healthSelectScheme"
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</SelectTrigger>
|
|
||||||
</FormControl>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="http">
|
|
||||||
HTTP
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="https">
|
|
||||||
HTTPS
|
|
||||||
</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcHostname"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("healthHostname")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
{...field}
|
|
||||||
onChange={(
|
|
||||||
e
|
|
||||||
) => {
|
|
||||||
field.onChange(
|
|
||||||
e
|
|
||||||
);
|
|
||||||
handleFieldChange(
|
|
||||||
"hcHostname",
|
|
||||||
e.target
|
|
||||||
.value
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcPort"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("healthPort")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
{...field}
|
|
||||||
onChange={(
|
|
||||||
e
|
|
||||||
) => {
|
|
||||||
const value =
|
|
||||||
e.target
|
|
||||||
.value;
|
|
||||||
field.onChange(
|
|
||||||
value
|
|
||||||
);
|
|
||||||
handleFieldChange(
|
|
||||||
"hcPort",
|
|
||||||
value
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcPath"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("healthCheckPath")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
{...field}
|
|
||||||
onChange={(
|
|
||||||
e
|
|
||||||
) => {
|
|
||||||
field.onChange(
|
|
||||||
e
|
|
||||||
);
|
|
||||||
handleFieldChange(
|
|
||||||
"hcPath",
|
|
||||||
e.target
|
|
||||||
.value
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* HTTP Method */}
|
|
||||||
{watchedMode !== "tcp" && (
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcMethod"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("httpMethod")}
|
|
||||||
</FormLabel>
|
|
||||||
<Select
|
|
||||||
onValueChange={(
|
|
||||||
value
|
|
||||||
) => {
|
|
||||||
field.onChange(
|
|
||||||
value
|
|
||||||
);
|
|
||||||
handleFieldChange(
|
|
||||||
"hcMethod",
|
|
||||||
value
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
defaultValue={
|
|
||||||
field.value
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<FormControl>
|
|
||||||
<SelectTrigger>
|
|
||||||
<SelectValue
|
|
||||||
placeholder={t(
|
|
||||||
"selectHttpMethod"
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</SelectTrigger>
|
|
||||||
</FormControl>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="GET">
|
|
||||||
GET
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="POST">
|
|
||||||
POST
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="HEAD">
|
|
||||||
HEAD
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="PUT">
|
|
||||||
PUT
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="DELETE">
|
|
||||||
DELETE
|
|
||||||
</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Check Interval, Unhealthy Interval, and Timeout */}
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcInterval"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t(
|
|
||||||
"healthyIntervalSeconds"
|
|
||||||
)}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
type="number"
|
|
||||||
{...field}
|
|
||||||
onChange={(e) => {
|
|
||||||
const value =
|
|
||||||
parseInt(
|
|
||||||
e.target
|
|
||||||
.value
|
|
||||||
);
|
|
||||||
field.onChange(
|
|
||||||
value
|
|
||||||
);
|
|
||||||
handleFieldChange(
|
|
||||||
"hcInterval",
|
|
||||||
value
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcUnhealthyInterval"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t(
|
|
||||||
"unhealthyIntervalSeconds"
|
|
||||||
)}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
type="number"
|
|
||||||
{...field}
|
|
||||||
onChange={(e) => {
|
|
||||||
const value =
|
|
||||||
parseInt(
|
|
||||||
e.target
|
|
||||||
.value
|
|
||||||
);
|
|
||||||
field.onChange(
|
|
||||||
value
|
|
||||||
);
|
|
||||||
handleFieldChange(
|
|
||||||
"hcUnhealthyInterval",
|
|
||||||
value
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcTimeout"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("timeoutSeconds")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
type="number"
|
|
||||||
{...field}
|
|
||||||
onChange={(e) => {
|
|
||||||
const value =
|
|
||||||
parseInt(
|
|
||||||
e.target
|
|
||||||
.value
|
|
||||||
);
|
|
||||||
field.onChange(
|
|
||||||
value
|
|
||||||
);
|
|
||||||
handleFieldChange(
|
|
||||||
"hcTimeout",
|
|
||||||
value
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Healthy and Unhealthy Thresholds */}
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcHealthyThreshold"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("healthyThreshold")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
type="number"
|
|
||||||
{...field}
|
|
||||||
onChange={(e) => {
|
|
||||||
const value =
|
|
||||||
parseInt(
|
|
||||||
e.target
|
|
||||||
.value
|
|
||||||
);
|
|
||||||
field.onChange(
|
|
||||||
value
|
|
||||||
);
|
|
||||||
handleFieldChange(
|
|
||||||
"hcHealthyThreshold",
|
|
||||||
value
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"healthyThresholdDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcUnhealthyThreshold"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("unhealthyThreshold")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
type="number"
|
|
||||||
{...field}
|
|
||||||
onChange={(e) => {
|
|
||||||
const value =
|
|
||||||
parseInt(
|
|
||||||
e.target
|
|
||||||
.value
|
|
||||||
);
|
|
||||||
field.onChange(
|
|
||||||
value
|
|
||||||
);
|
|
||||||
handleFieldChange(
|
|
||||||
"hcUnhealthyThreshold",
|
|
||||||
value
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"unhealthyThresholdDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* HTTP-only fields */}
|
|
||||||
{watchedMode !== "tcp" && (
|
|
||||||
<>
|
|
||||||
{/* Expected Response Codes */}
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcStatus"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t(
|
|
||||||
"expectedResponseCodes"
|
|
||||||
)}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
type="number"
|
|
||||||
{...field}
|
|
||||||
value={
|
|
||||||
field.value ||
|
|
||||||
""
|
|
||||||
}
|
|
||||||
onChange={(
|
|
||||||
e
|
|
||||||
) => {
|
|
||||||
const value =
|
|
||||||
parseInt(
|
|
||||||
e
|
|
||||||
.target
|
|
||||||
.value
|
|
||||||
);
|
|
||||||
field.onChange(
|
|
||||||
value
|
|
||||||
);
|
|
||||||
handleFieldChange(
|
|
||||||
"hcStatus",
|
|
||||||
value
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"expectedResponseCodesDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* TLS Server Name (SNI) */}
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcTlsServerName"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("tlsServerName")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
{...field}
|
|
||||||
onChange={(
|
|
||||||
e
|
|
||||||
) => {
|
|
||||||
field.onChange(
|
|
||||||
e
|
|
||||||
);
|
|
||||||
handleFieldChange(
|
|
||||||
"hcTlsServerName",
|
|
||||||
e.target
|
|
||||||
.value
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"tlsServerNameDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Custom Headers */}
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcHeaders"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("customHeaders")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<HeadersInput
|
|
||||||
value={
|
|
||||||
field.value
|
|
||||||
}
|
|
||||||
onChange={(
|
|
||||||
value
|
|
||||||
) => {
|
|
||||||
field.onChange(
|
|
||||||
value
|
|
||||||
);
|
|
||||||
handleFieldChange(
|
|
||||||
"hcHeaders",
|
|
||||||
value
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
rows={4}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"customHeadersDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
</CredenzaBody>
|
</CredenzaBody>
|
||||||
|
|||||||
548
src/components/HealthCheckFormFields.tsx
Normal file
548
src/components/HealthCheckFormFields.tsx
Normal file
@@ -0,0 +1,548 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { UseFormReturn } from "react-hook-form";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue
|
||||||
|
} from "@/components/ui/select";
|
||||||
|
import { Switch } from "@/components/ui/switch";
|
||||||
|
import { HeadersInput } from "@app/components/HeadersInput";
|
||||||
|
import {
|
||||||
|
FormControl,
|
||||||
|
FormDescription,
|
||||||
|
FormField,
|
||||||
|
FormItem,
|
||||||
|
FormLabel,
|
||||||
|
FormMessage
|
||||||
|
} from "@/components/ui/form";
|
||||||
|
|
||||||
|
type HealthCheckFormFieldsProps = {
|
||||||
|
form: UseFormReturn<any>;
|
||||||
|
onFieldChange?: (fieldName: string, value: any) => void;
|
||||||
|
showNameField?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function HealthCheckFormFields({
|
||||||
|
form,
|
||||||
|
onFieldChange,
|
||||||
|
showNameField
|
||||||
|
}: HealthCheckFormFieldsProps) {
|
||||||
|
const t = useTranslations();
|
||||||
|
|
||||||
|
const watchedEnabled = form.watch("hcEnabled");
|
||||||
|
const watchedMode = form.watch("hcMode");
|
||||||
|
|
||||||
|
const handleChange = (fieldName: string, value: any, fieldOnChange: (v: any) => void) => {
|
||||||
|
fieldOnChange(value);
|
||||||
|
if (onFieldChange) {
|
||||||
|
onFieldChange(fieldName, value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* Name */}
|
||||||
|
{showNameField && (
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="name"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("standaloneHcNameLabel")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
{...field}
|
||||||
|
placeholder={t("standaloneHcNamePlaceholder")}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Enable Health Checks */}
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="hcEnabled"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
|
||||||
|
<div className="space-y-0.5">
|
||||||
|
<FormLabel>{t("enableHealthChecks")}</FormLabel>
|
||||||
|
<FormDescription>
|
||||||
|
{t("enableHealthChecksDescription")}
|
||||||
|
</FormDescription>
|
||||||
|
</div>
|
||||||
|
<FormControl>
|
||||||
|
<Switch
|
||||||
|
checked={field.value}
|
||||||
|
onCheckedChange={(value) =>
|
||||||
|
handleChange("hcEnabled", value, field.onChange)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{watchedEnabled && (
|
||||||
|
<div className="space-y-4">
|
||||||
|
{/* Mode */}
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="hcMode"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("healthCheckMode")}</FormLabel>
|
||||||
|
<Select
|
||||||
|
onValueChange={(value) =>
|
||||||
|
handleChange("hcMode", value, field.onChange)
|
||||||
|
}
|
||||||
|
value={field.value}
|
||||||
|
>
|
||||||
|
<FormControl>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
</FormControl>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="http">HTTP</SelectItem>
|
||||||
|
<SelectItem value="tcp">TCP</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<FormDescription>
|
||||||
|
{t("healthCheckModeDescription")}
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Connection fields */}
|
||||||
|
{watchedMode === "tcp" ? (
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="hcHostname"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("healthHostname")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
{...field}
|
||||||
|
onChange={(e) =>
|
||||||
|
handleChange(
|
||||||
|
"hcHostname",
|
||||||
|
e.target.value,
|
||||||
|
(v) => field.onChange(e)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="hcPort"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("healthPort")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
{...field}
|
||||||
|
onChange={(e) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
handleChange("hcPort", value, field.onChange);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="hcScheme"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("healthScheme")}</FormLabel>
|
||||||
|
<Select
|
||||||
|
onValueChange={(value) =>
|
||||||
|
handleChange("hcScheme", value, field.onChange)
|
||||||
|
}
|
||||||
|
value={field.value}
|
||||||
|
>
|
||||||
|
<FormControl>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue
|
||||||
|
placeholder={t("healthSelectScheme")}
|
||||||
|
/>
|
||||||
|
</SelectTrigger>
|
||||||
|
</FormControl>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="http">HTTP</SelectItem>
|
||||||
|
<SelectItem value="https">HTTPS</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="hcHostname"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("healthHostname")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
{...field}
|
||||||
|
onChange={(e) =>
|
||||||
|
handleChange(
|
||||||
|
"hcHostname",
|
||||||
|
e.target.value,
|
||||||
|
(v) => field.onChange(e)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="hcPort"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("healthPort")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
{...field}
|
||||||
|
onChange={(e) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
handleChange("hcPort", value, field.onChange);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="hcPath"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("healthCheckPath")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
{...field}
|
||||||
|
onChange={(e) =>
|
||||||
|
handleChange(
|
||||||
|
"hcPath",
|
||||||
|
e.target.value,
|
||||||
|
(v) => field.onChange(e)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* HTTP Method */}
|
||||||
|
{watchedMode !== "tcp" && (
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="hcMethod"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("httpMethod")}</FormLabel>
|
||||||
|
<Select
|
||||||
|
onValueChange={(value) =>
|
||||||
|
handleChange("hcMethod", value, field.onChange)
|
||||||
|
}
|
||||||
|
value={field.value}
|
||||||
|
>
|
||||||
|
<FormControl>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue
|
||||||
|
placeholder={t("selectHttpMethod")}
|
||||||
|
/>
|
||||||
|
</SelectTrigger>
|
||||||
|
</FormControl>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="GET">GET</SelectItem>
|
||||||
|
<SelectItem value="POST">POST</SelectItem>
|
||||||
|
<SelectItem value="HEAD">HEAD</SelectItem>
|
||||||
|
<SelectItem value="PUT">PUT</SelectItem>
|
||||||
|
<SelectItem value="DELETE">DELETE</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Check Interval, Unhealthy Interval, and Timeout */}
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="hcInterval"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("healthyIntervalSeconds")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
type="number"
|
||||||
|
{...field}
|
||||||
|
onChange={(e) => {
|
||||||
|
const value = parseInt(e.target.value);
|
||||||
|
handleChange("hcInterval", value, field.onChange);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="hcUnhealthyInterval"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("unhealthyIntervalSeconds")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
type="number"
|
||||||
|
{...field}
|
||||||
|
onChange={(e) => {
|
||||||
|
const value = parseInt(e.target.value);
|
||||||
|
handleChange(
|
||||||
|
"hcUnhealthyInterval",
|
||||||
|
value,
|
||||||
|
field.onChange
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="hcTimeout"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("timeoutSeconds")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
type="number"
|
||||||
|
{...field}
|
||||||
|
onChange={(e) => {
|
||||||
|
const value = parseInt(e.target.value);
|
||||||
|
handleChange("hcTimeout", value, field.onChange);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Healthy and Unhealthy Thresholds */}
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="hcHealthyThreshold"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("healthyThreshold")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
type="number"
|
||||||
|
{...field}
|
||||||
|
onChange={(e) => {
|
||||||
|
const value = parseInt(e.target.value);
|
||||||
|
handleChange(
|
||||||
|
"hcHealthyThreshold",
|
||||||
|
value,
|
||||||
|
field.onChange
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
{t("healthyThresholdDescription")}
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="hcUnhealthyThreshold"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("unhealthyThreshold")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
type="number"
|
||||||
|
{...field}
|
||||||
|
onChange={(e) => {
|
||||||
|
const value = parseInt(e.target.value);
|
||||||
|
handleChange(
|
||||||
|
"hcUnhealthyThreshold",
|
||||||
|
value,
|
||||||
|
field.onChange
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
{t("unhealthyThresholdDescription")}
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* HTTP-only fields */}
|
||||||
|
{watchedMode !== "tcp" && (
|
||||||
|
<>
|
||||||
|
{/* Expected Response Code */}
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="hcStatus"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("expectedResponseCodes")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
type="number"
|
||||||
|
value={field.value ?? ""}
|
||||||
|
onChange={(e) => {
|
||||||
|
const val = e.target.value;
|
||||||
|
const value = val ? parseInt(val) : null;
|
||||||
|
handleChange("hcStatus", value, field.onChange);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
{t("expectedResponseCodesDescription")}
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* TLS Server Name */}
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="hcTlsServerName"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("tlsServerName")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
{...field}
|
||||||
|
onChange={(e) =>
|
||||||
|
handleChange(
|
||||||
|
"hcTlsServerName",
|
||||||
|
e.target.value,
|
||||||
|
(v) => field.onChange(e)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
{t("tlsServerNameDescription")}
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Custom Headers */}
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="hcHeaders"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>{t("customHeaders")}</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<HeadersInput
|
||||||
|
value={field.value}
|
||||||
|
onChange={(value) =>
|
||||||
|
handleChange(
|
||||||
|
"hcHeaders",
|
||||||
|
value,
|
||||||
|
field.onChange
|
||||||
|
)
|
||||||
|
}
|
||||||
|
rows={4}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormDescription>
|
||||||
|
{t("customHeadersDescription")}
|
||||||
|
</FormDescription>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Follow Redirects */}
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="hcFollowRedirects"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
|
||||||
|
<div className="space-y-0.5">
|
||||||
|
<FormLabel>{t("followRedirects")}</FormLabel>
|
||||||
|
<FormDescription>
|
||||||
|
{t("followRedirectsDescription")}
|
||||||
|
</FormDescription>
|
||||||
|
</div>
|
||||||
|
<FormControl>
|
||||||
|
<Switch
|
||||||
|
checked={field.value}
|
||||||
|
onCheckedChange={(value) =>
|
||||||
|
handleChange(
|
||||||
|
"hcFollowRedirects",
|
||||||
|
value,
|
||||||
|
field.onChange
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|||||||
import { ArrowUpDown, MoreHorizontal } from "lucide-react";
|
import { ArrowUpDown, MoreHorizontal } from "lucide-react";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import HealthCheckDialog from "./HealthCheckDialog";
|
||||||
|
|
||||||
type StandaloneHealthChecksTableProps = {
|
type StandaloneHealthChecksTableProps = {
|
||||||
orgId: string;
|
orgId: string;
|
||||||
@@ -62,7 +63,7 @@ function HealthBadge({ health }: { health: HealthCheckRow["hcHealth"] }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function StandaloneHealthChecksTable({
|
export default function HealthChecksTable({
|
||||||
orgId
|
orgId
|
||||||
}: StandaloneHealthChecksTableProps) {
|
}: StandaloneHealthChecksTableProps) {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { ColumnDef } from "@tanstack/react-table";
|
|
||||||
import { ExtendedColumnDef } from "@app/components/ui/data-table";
|
import { ExtendedColumnDef } from "@app/components/ui/data-table";
|
||||||
import { DataTable } from "@app/components/ui/data-table";
|
import { DataTable } from "@app/components/ui/data-table";
|
||||||
import { Button } from "@app/components/ui/button";
|
import { Button } from "@app/components/ui/button";
|
||||||
|
|||||||
@@ -2,28 +2,11 @@
|
|||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Input } from "@/components/ui/input";
|
|
||||||
import {
|
|
||||||
Select,
|
|
||||||
SelectContent,
|
|
||||||
SelectItem,
|
|
||||||
SelectTrigger,
|
|
||||||
SelectValue
|
|
||||||
} from "@/components/ui/select";
|
|
||||||
import { Switch } from "@/components/ui/switch";
|
|
||||||
import { HeadersInput } from "@app/components/HeadersInput";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import {
|
import { Form } from "@/components/ui/form";
|
||||||
Form,
|
import { HealthCheckFormFields } from "@app/components/HealthCheckFormFields";
|
||||||
FormControl,
|
|
||||||
FormDescription,
|
|
||||||
FormField,
|
|
||||||
FormItem,
|
|
||||||
FormLabel,
|
|
||||||
FormMessage
|
|
||||||
} from "@/components/ui/form";
|
|
||||||
import {
|
import {
|
||||||
Credenza,
|
Credenza,
|
||||||
CredenzaBody,
|
CredenzaBody,
|
||||||
@@ -209,9 +192,6 @@ export default function StandaloneHealthCheckCredenza({
|
|||||||
}
|
}
|
||||||
}, [open]);
|
}, [open]);
|
||||||
|
|
||||||
const watchedEnabled = form.watch("hcEnabled");
|
|
||||||
const watchedMode = form.watch("hcMode");
|
|
||||||
|
|
||||||
const onSubmit = async (values: FormValues) => {
|
const onSubmit = async (values: FormValues) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
@@ -286,553 +266,7 @@ export default function StandaloneHealthCheckCredenza({
|
|||||||
onSubmit={form.handleSubmit(onSubmit)}
|
onSubmit={form.handleSubmit(onSubmit)}
|
||||||
className="space-y-6"
|
className="space-y-6"
|
||||||
>
|
>
|
||||||
{/* Name */}
|
<HealthCheckFormFields form={form} showNameField />
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="name"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("standaloneHcNameLabel")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
{...field}
|
|
||||||
placeholder={t(
|
|
||||||
"standaloneHcNamePlaceholder"
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Enable Health Check */}
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcEnabled"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
|
|
||||||
<div className="space-y-0.5">
|
|
||||||
<FormLabel>
|
|
||||||
{t("enableHealthChecks")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"enableHealthChecksDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
</div>
|
|
||||||
<FormControl>
|
|
||||||
<Switch
|
|
||||||
checked={field.value}
|
|
||||||
onCheckedChange={field.onChange}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{watchedEnabled && (
|
|
||||||
<div className="space-y-4">
|
|
||||||
{/* Mode */}
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcMode"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("healthCheckMode")}
|
|
||||||
</FormLabel>
|
|
||||||
<Select
|
|
||||||
onValueChange={
|
|
||||||
field.onChange
|
|
||||||
}
|
|
||||||
value={field.value}
|
|
||||||
>
|
|
||||||
<FormControl>
|
|
||||||
<SelectTrigger>
|
|
||||||
<SelectValue />
|
|
||||||
</SelectTrigger>
|
|
||||||
</FormControl>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="http">
|
|
||||||
HTTP
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="tcp">
|
|
||||||
TCP
|
|
||||||
</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"healthCheckModeDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Connection fields */}
|
|
||||||
{watchedMode === "tcp" ? (
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcHostname"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("healthHostname")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input {...field} />
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcPort"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("healthPort")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input {...field} />
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcScheme"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("healthScheme")}
|
|
||||||
</FormLabel>
|
|
||||||
<Select
|
|
||||||
onValueChange={
|
|
||||||
field.onChange
|
|
||||||
}
|
|
||||||
value={field.value}
|
|
||||||
>
|
|
||||||
<FormControl>
|
|
||||||
<SelectTrigger>
|
|
||||||
<SelectValue
|
|
||||||
placeholder={t(
|
|
||||||
"healthSelectScheme"
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</SelectTrigger>
|
|
||||||
</FormControl>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="http">
|
|
||||||
HTTP
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="https">
|
|
||||||
HTTPS
|
|
||||||
</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcHostname"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("healthHostname")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input {...field} />
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcPort"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("healthPort")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input {...field} />
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcPath"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("healthCheckPath")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input {...field} />
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* HTTP Method */}
|
|
||||||
{watchedMode !== "tcp" && (
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcMethod"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("httpMethod")}
|
|
||||||
</FormLabel>
|
|
||||||
<Select
|
|
||||||
onValueChange={
|
|
||||||
field.onChange
|
|
||||||
}
|
|
||||||
value={field.value}
|
|
||||||
>
|
|
||||||
<FormControl>
|
|
||||||
<SelectTrigger>
|
|
||||||
<SelectValue
|
|
||||||
placeholder={t(
|
|
||||||
"selectHttpMethod"
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</SelectTrigger>
|
|
||||||
</FormControl>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="GET">
|
|
||||||
GET
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="POST">
|
|
||||||
POST
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="HEAD">
|
|
||||||
HEAD
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="PUT">
|
|
||||||
PUT
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="DELETE">
|
|
||||||
DELETE
|
|
||||||
</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Check Interval, Unhealthy Interval, and Timeout */}
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcInterval"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t(
|
|
||||||
"healthyIntervalSeconds"
|
|
||||||
)}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
type="number"
|
|
||||||
{...field}
|
|
||||||
onChange={(e) =>
|
|
||||||
field.onChange(
|
|
||||||
parseInt(
|
|
||||||
e.target
|
|
||||||
.value
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcUnhealthyInterval"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t(
|
|
||||||
"unhealthyIntervalSeconds"
|
|
||||||
)}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
type="number"
|
|
||||||
{...field}
|
|
||||||
onChange={(e) =>
|
|
||||||
field.onChange(
|
|
||||||
parseInt(
|
|
||||||
e.target
|
|
||||||
.value
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcTimeout"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("timeoutSeconds")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
type="number"
|
|
||||||
{...field}
|
|
||||||
onChange={(e) =>
|
|
||||||
field.onChange(
|
|
||||||
parseInt(
|
|
||||||
e.target
|
|
||||||
.value
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Healthy and Unhealthy Thresholds */}
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcHealthyThreshold"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("healthyThreshold")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
type="number"
|
|
||||||
{...field}
|
|
||||||
onChange={(e) =>
|
|
||||||
field.onChange(
|
|
||||||
parseInt(
|
|
||||||
e.target
|
|
||||||
.value
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"healthyThresholdDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcUnhealthyThreshold"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("unhealthyThreshold")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
type="number"
|
|
||||||
{...field}
|
|
||||||
onChange={(e) =>
|
|
||||||
field.onChange(
|
|
||||||
parseInt(
|
|
||||||
e.target
|
|
||||||
.value
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"unhealthyThresholdDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* HTTP-only fields */}
|
|
||||||
{watchedMode !== "tcp" && (
|
|
||||||
<>
|
|
||||||
{/* Expected Response Code */}
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcStatus"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t(
|
|
||||||
"expectedResponseCodes"
|
|
||||||
)}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
type="number"
|
|
||||||
value={
|
|
||||||
field.value ??
|
|
||||||
""
|
|
||||||
}
|
|
||||||
onChange={(
|
|
||||||
e
|
|
||||||
) => {
|
|
||||||
const val =
|
|
||||||
e.target
|
|
||||||
.value;
|
|
||||||
field.onChange(
|
|
||||||
val
|
|
||||||
? parseInt(
|
|
||||||
val
|
|
||||||
)
|
|
||||||
: null
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"expectedResponseCodesDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* TLS Server Name */}
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcTlsServerName"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("tlsServerName")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input {...field} />
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"tlsServerNameDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Custom Headers */}
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcHeaders"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>
|
|
||||||
{t("customHeaders")}
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<HeadersInput
|
|
||||||
value={
|
|
||||||
field.value
|
|
||||||
}
|
|
||||||
onChange={
|
|
||||||
field.onChange
|
|
||||||
}
|
|
||||||
rows={4}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"customHeadersDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Follow Redirects */}
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="hcFollowRedirects"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
|
|
||||||
<div className="space-y-0.5">
|
|
||||||
<FormLabel>
|
|
||||||
{t(
|
|
||||||
"followRedirects"
|
|
||||||
)}
|
|
||||||
</FormLabel>
|
|
||||||
<FormDescription>
|
|
||||||
{t(
|
|
||||||
"followRedirectsDescription"
|
|
||||||
)}
|
|
||||||
</FormDescription>
|
|
||||||
</div>
|
|
||||||
<FormControl>
|
|
||||||
<Switch
|
|
||||||
checked={
|
|
||||||
field.value
|
|
||||||
}
|
|
||||||
onCheckedChange={
|
|
||||||
field.onChange
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
</CredenzaBody>
|
</CredenzaBody>
|
||||||
|
|||||||
Reference in New Issue
Block a user