+ {/* Connection fields */}
+ {watchedMode === "tcp" ? (
+
+ (
+
+
+ {t("healthHostname")}
+
+
+
+ handleChange(
+ "hcHostname",
+ e.target.value,
+ (v) =>
+ field.onChange(
+ e
+ )
+ )
+ }
+ />
+
+
+
+ )}
+ />
+ (
+
+
+ {t("healthPort")}
+
+
+ {
+ const value =
+ e.target.value;
+ handleChange(
+ "hcPort",
+ value,
+ field.onChange
+ );
+ }}
+ />
+
+
+
+ )}
+ />
+
+ ) : (
+
+ (
+
+
+ {t("healthScheme")}
+
+
+
+
+ )}
+ />
+ (
+
+
+ {t("healthHostname")}
+
+
+
+ handleChange(
+ "hcHostname",
+ e.target.value,
+ (v) =>
+ field.onChange(
+ e
+ )
+ )
+ }
+ />
+
+
+
+ )}
+ />
+ (
+
+
+ {t("healthPort")}
+
+
+ {
+ const value =
+ e.target.value;
+ handleChange(
+ "hcPort",
+ value,
+ field.onChange
+ );
+ }}
+ />
+
+
+
+ )}
+ />
+
+ )}
+
+ {/* HTTP Method + Path + Timeout (shown when not TCP) */}
+ {watchedMode !== "tcp" && (
+
+ (
+
+
+ {t("httpMethod")}
+
+
+
+
+ )}
+ />
+ (
+
+
+ {t("healthCheckPath")}
+
+
+
+ handleChange(
+ "hcPath",
+ e.target.value,
+ (v) =>
+ field.onChange(
+ e
+ )
+ )
+ }
+ />
+
+
+
+ )}
+ />
+ (
+
+
+ {t("timeoutSeconds")}
+
+
+ {
+ const value =
+ parseInt(
+ e.target
+ .value
+ );
+ handleChange(
+ "hcTimeout",
+ value,
+ field.onChange
+ );
+ }}
+ />
+
+
+
+ )}
+ />
+
+ )}
+
+ {/* TCP timeout (shown only for TCP) */}
+ {watchedMode === "tcp" && (
(
- {t("expectedResponseCodes")}
+ {t("timeoutSeconds")}
{
- const val =
- e.target.value;
- const value = val
- ? parseInt(val)
- : null;
+ const value = parseInt(
+ e.target.value
+ );
handleChange(
- "hcStatus",
+ "hcTimeout",
+ value,
+ field.onChange
+ );
+ }}
+ />
+
+
+
+ )}
+ />
+ )}
+
+ {/* Healthy interval + healthy threshold */}
+
+ (
+
+
+ {t("healthyIntervalSeconds")}
+
+
+ {
+ const value = parseInt(
+ e.target.value
+ );
+ handleChange(
+ "hcInterval",
value,
field.onChange
);
@@ -680,25 +537,26 @@ export function HealthCheckFormFields({
/>
(
- {t("tlsServerName")}
+ {t("healthyThreshold")}
+ onChange={(e) => {
+ const value = parseInt(
+ e.target.value
+ );
handleChange(
- "hcTlsServerName",
- e.target.value,
- (v) =>
- field.onChange(
- e
- )
- )
- }
+ "hcHealthyThreshold",
+ value,
+ field.onChange
+ );
+ }}
/>
@@ -707,60 +565,200 @@ export function HealthCheckFormFields({
/>
- {/* Follow Redirects inline toggle */}
- (
-
-
- {t("followRedirects")}
-
-
-
- handleChange(
- "hcFollowRedirects",
- value,
- field.onChange
- )
- }
- />
-
-
- )}
- />
+ {/* Unhealthy interval + unhealthy threshold */}
+
+ (
+
+
+ {t("unhealthyIntervalSeconds")}
+
+
+ {
+ const value = parseInt(
+ e.target.value
+ );
+ handleChange(
+ "hcUnhealthyInterval",
+ value,
+ field.onChange
+ );
+ }}
+ />
+
+
+
+ )}
+ />
+ (
+
+
+ {t("unhealthyThreshold")}
+
+
+ {
+ const value = parseInt(
+ e.target.value
+ );
+ handleChange(
+ "hcUnhealthyThreshold",
+ value,
+ field.onChange
+ );
+ }}
+ />
+
+
+
+ )}
+ />
+
- {/* Custom Headers */}
- (
-
-
- {t("customHeaders")}
-
-
-
- handleChange(
- "hcHeaders",
- value,
- field.onChange
- )
- }
- rows={4}
- />
-
-
- {t("customHeadersDescription")}
-
-
-
- )}
- />
+ {/* HTTP-only fields */}
+ {watchedMode !== "tcp" && (
+ <>
+ {/* Expected Response Codes + TLS Server Name */}
+
+ (
+
+
+ {t(
+ "expectedResponseCodes"
+ )}
+
+
+ {
+ const val =
+ e.target
+ .value;
+ const value =
+ val
+ ? parseInt(
+ val
+ )
+ : null;
+ handleChange(
+ "hcStatus",
+ value,
+ field.onChange
+ );
+ }}
+ />
+
+
+
+ )}
+ />
+ (
+
+
+ {t("tlsServerName")}
+
+
+
+ handleChange(
+ "hcTlsServerName",
+ e.target
+ .value,
+ (v) =>
+ field.onChange(
+ e
+ )
+ )
+ }
+ />
+
+
+
+ )}
+ />
+
+
+ {/* Follow Redirects inline toggle */}
+ (
+
+
+ {t("followRedirects")}
+
+
+
+ handleChange(
+ "hcFollowRedirects",
+ value,
+ field.onChange
+ )
+ }
+ />
+
+
+ )}
+ />
+
+ {/* Custom Headers */}
+ (
+
+
+ {t("customHeaders")}
+
+
+
+ handleChange(
+ "hcHeaders",
+ value,
+ field.onChange
+ )
+ }
+ rows={4}
+ />
+
+
+ {t(
+ "customHeadersDescription"
+ )}
+
+
+
+ )}
+ />
+ >
+ )}
>
)}
diff --git a/src/components/S3DestinationCredenza.tsx b/src/components/S3DestinationCredenza.tsx
new file mode 100644
index 000000000..d94293cf0
--- /dev/null
+++ b/src/components/S3DestinationCredenza.tsx
@@ -0,0 +1,93 @@
+"use client";
+
+import { useState, useEffect } from "react";
+import {
+ Credenza,
+ CredenzaBody,
+ CredenzaClose,
+ CredenzaContent,
+ CredenzaDescription,
+ CredenzaFooter,
+ CredenzaHeader,
+ CredenzaTitle
+} from "@app/components/Credenza";
+import { Button } from "@app/components/ui/button";
+import { Plus, X, KeyRound, ExternalLink } from "lucide-react";
+import Link from "next/link";
+import { useTranslations } from "next-intl";
+
+export interface S3DestinationCredenzaProps {
+ open: boolean;
+ onOpenChange: (open: boolean) => void;
+ editing: any;
+ orgId: string;
+ onSaved: () => void;
+}
+
+export function S3DestinationCredenza({
+ open,
+ onOpenChange,
+ editing,
+ orgId,
+ onSaved,
+}: S3DestinationCredenzaProps) {
+ const t = useTranslations();
+
+ return (
+