Cleaning up ui

This commit is contained in:
Owen
2026-04-17 17:01:55 -07:00
parent 0872fd5818
commit 74165aa1cc
6 changed files with 863 additions and 871 deletions

View File

@@ -1848,8 +1848,8 @@
"retryAttempts": "Retry Attempts", "retryAttempts": "Retry Attempts",
"expectedResponseCodes": "Expected Response Codes", "expectedResponseCodes": "Expected Response Codes",
"expectedResponseCodesDescription": "HTTP status code that indicates healthy status. If left blank, 200-300 is considered healthy.", "expectedResponseCodesDescription": "HTTP status code that indicates healthy status. If left blank, 200-300 is considered healthy.",
"customHeaders": "Custom Headers", "customHeaders": "Custom Request Headers",
"customHeadersDescription": "Headers new line separated: Header-Name: value", "customHeadersDescription": "Request headers sent to the downstream targets. Headers new line separated: Header-Name: value",
"headersValidationError": "Headers must be in the format: Header-Name: value", "headersValidationError": "Headers must be in the format: Header-Name: value",
"saveHealthCheck": "Save Health Check", "saveHealthCheck": "Save Health Check",
"healthCheckSaved": "Health Check Saved", "healthCheckSaved": "Health Check Saved",

View File

@@ -0,0 +1,39 @@
"use client";
import { KeyRound, ExternalLink } from "lucide-react";
import Link from "next/link";
export function ContactSalesBanner() {
return (
<div className="rounded-md border border-black-500/30 bg-linear-to-br from-black-500/10 via-background to-background overflow-hidden">
<div className="py-3 px-4">
<div className="flex items-center gap-2.5 text-sm text-muted-foreground">
<KeyRound className="size-4 shrink-0 text-black-500" />
<span>
Contact sales to enable this feature.{" "}
<Link
href="https://click.fossorial.io/ep922"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 font-medium text-black-600 underline"
>
Book a demo
<ExternalLink className="size-3.5 shrink-0" />
</Link>
{" or "}
<Link
href="https://pangolin.net/contact"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 font-medium text-black-600 underline"
>
contact us
<ExternalLink className="size-3.5 shrink-0" />
</Link>
.
</span>
</div>
</div>
</div>
);
}

View File

@@ -12,8 +12,7 @@ import {
CredenzaTitle CredenzaTitle
} from "@app/components/Credenza"; } from "@app/components/Credenza";
import { Button } from "@app/components/ui/button"; import { Button } from "@app/components/ui/button";
import { Plus, X, KeyRound, ExternalLink } from "lucide-react"; import { ContactSalesBanner } from "@app/components/ContactSalesBanner";
import Link from "next/link";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
export interface DatadogDestinationCredenzaProps { export interface DatadogDestinationCredenzaProps {
@@ -50,36 +49,7 @@ export function DatadogDestinationCredenza({
</CredenzaHeader> </CredenzaHeader>
<CredenzaBody> <CredenzaBody>
<div className="rounded-md border border-black-500/30 bg-linear-to-br from-black-500/10 via-background to-background overflow-hidden"> <ContactSalesBanner />
<div className="py-3 px-4">
<div className="flex items-center gap-2.5 text-sm text-muted-foreground">
<KeyRound className="size-4 shrink-0 text-black-500" />
<span>
Contact sales to enable this feature.{" "}
<Link
href="https://click.fossorial.io/ep922"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 font-medium text-black-600 underline"
>
Book a demo
<ExternalLink className="size-3.5 shrink-0" />
</Link>
{" or "}
<Link
href="https://pangolin.net/contact"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 font-medium text-black-600 underline"
>
contact us
<ExternalLink className="size-3.5 shrink-0" />
</Link>
.
</span>
</div>
</div>
</div>
</CredenzaBody> </CredenzaBody>
<CredenzaFooter> <CredenzaFooter>

View File

@@ -40,8 +40,7 @@ import { toast } from "@app/hooks/useToast";
import { createApiClient, formatAxiosError } from "@app/lib/api"; import { createApiClient, formatAxiosError } from "@app/lib/api";
import { useEnvContext } from "@app/hooks/useEnvContext"; import { useEnvContext } from "@app/hooks/useEnvContext";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { ExternalLink, KeyRound } from "lucide-react"; import { ContactSalesBanner } from "@app/components/ContactSalesBanner";
import Link from "next/link";
export type HealthCheckConfig = { export type HealthCheckConfig = {
hcEnabled: boolean; hcEnabled: boolean;
@@ -273,12 +272,10 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
hcUnhealthyInterval: hcUnhealthyInterval:
initialValues.hcUnhealthyInterval ?? 30, initialValues.hcUnhealthyInterval ?? 30,
hcTimeout: initialValues.hcTimeout ?? 5, hcTimeout: initialValues.hcTimeout ?? 5,
hcHealthyThreshold: hcHealthyThreshold: initialValues.hcHealthyThreshold ?? 1,
initialValues.hcHealthyThreshold ?? 1,
hcUnhealthyThreshold: hcUnhealthyThreshold:
initialValues.hcUnhealthyThreshold ?? 1, initialValues.hcUnhealthyThreshold ?? 1,
hcFollowRedirects: hcFollowRedirects: initialValues.hcFollowRedirects ?? true,
initialValues.hcFollowRedirects ?? true,
hcTlsServerName: initialValues.hcTlsServerName ?? "", hcTlsServerName: initialValues.hcTlsServerName ?? "",
hcStatus: initialValues.hcStatus ?? null, hcStatus: initialValues.hcStatus ?? null,
hcHeaders: parsedHeaders hcHeaders: parsedHeaders
@@ -415,25 +412,6 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
: undefined : undefined
} }
> >
<HorizontalTabs
clientSide
items={[
{
title: t("healthCheckTabStrategy"),
href: ""
},
{
title: t("healthCheckTabConnection"),
href: ""
},
{
title: t("healthCheckTabAdvanced"),
href: ""
}
]}
>
{/* ── Strategy tab ──────────────────────── */}
<div className="space-y-4 mt-4 p-1">
{/* Name (submit mode only) */} {/* Name (submit mode only) */}
{mode === "submit" && ( {mode === "submit" && (
<FormField <FormField
@@ -442,14 +420,14 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
render={({ field }) => ( render={({ field }) => (
<FormItem> <FormItem>
<FormLabel> <FormLabel>
{t( {t("standaloneHcNameLabel")}
"standaloneHcNameLabel"
)}
</FormLabel> </FormLabel>
<FormControl> <FormControl>
<Input <Input
{...field} {...field}
value={field.value as string} value={
field.value as string
}
placeholder={t( placeholder={t(
"standaloneHcNamePlaceholder" "standaloneHcNamePlaceholder"
)} )}
@@ -461,6 +439,29 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
/> />
)} )}
<div className="mt-5">
<HorizontalTabs
clientSide
items={[
{
title: t("healthCheckTabStrategy"),
href: ""
},
{
title: t(
"healthCheckTabConnection"
),
href: ""
},
{
title: t("healthCheckTabAdvanced"),
href: ""
}
]}
>
{/* ── Strategy tab ──────────────────────── */}
<div className="space-y-4 mt-4 p-1">
{/* Enable toggle (autoSave mode only) */} {/* Enable toggle (autoSave mode only) */}
{mode === "autoSave" && ( {mode === "autoSave" && (
<FormField <FormField
@@ -540,7 +541,9 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
) )
} }
]} ]}
value={field.value} value={
field.value
}
onChange={( onChange={(
value value
) => ) =>
@@ -557,41 +560,6 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
)} )}
/> />
)} )}
{/* Contact-sales banner for SNMP / ICMP */}
{showFields && isSnmpOrIcmp && (
<div className="rounded-md border border-black-500/30 bg-linear-to-br from-black-500/10 via-background to-background overflow-hidden">
<div className="py-3 px-4">
<div className="flex items-center gap-2.5 text-sm text-muted-foreground">
<KeyRound className="size-4 shrink-0 text-black-500" />
<span>
Contact sales to enable
this feature.{" "}
<Link
href="https://click.fossorial.io/ep922"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 font-medium text-black-600 underline"
>
Book a demo
<ExternalLink className="size-3.5 shrink-0" />
</Link>
{" or "}
<Link
href="https://pangolin.net/contact"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 font-medium text-black-600 underline"
>
contact us
<ExternalLink className="size-3.5 shrink-0" />
</Link>
.
</span>
</div>
</div>
</div>
)}
</div> </div>
{/* ── Connection tab ────────────────────── */} {/* ── Connection tab ────────────────────── */}
@@ -602,15 +570,24 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
</p> </p>
)} )}
{/* Contact-sales banner for SNMP / ICMP */}
{showFields && isSnmpOrIcmp && (
<ContactSalesBanner />
)}
{showFields && !isSnmpOrIcmp && ( {showFields && !isSnmpOrIcmp && (
<> <>
{/* Scheme / Hostname / Port */} {/* Scheme / Hostname / Port */}
{isTcp ? ( {isTcp ? (
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<FormField <FormField
control={form.control} control={
form.control
}
name="hcHostname" name="hcHostname"
render={({ field }) => ( render={({
field
}) => (
<FormItem> <FormItem>
<FormLabel> <FormLabel>
{t( {t(
@@ -641,9 +618,13 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
)} )}
/> />
<FormField <FormField
control={form.control} control={
form.control
}
name="hcPort" name="hcPort"
render={({ field }) => ( render={({
field
}) => (
<FormItem> <FormItem>
<FormLabel> <FormLabel>
{t( {t(
@@ -654,7 +635,9 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
<Input <Input
{...field} {...field}
type="number" type="number"
min={1} min={
1
}
max={ max={
65535 65535
} }
@@ -679,9 +662,13 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
) : ( ) : (
<div className="grid grid-cols-1 md:grid-cols-3 gap-4"> <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<FormField <FormField
control={form.control} control={
form.control
}
name="hcScheme" name="hcScheme"
render={({ field }) => ( render={({
field
}) => (
<FormItem> <FormItem>
<FormLabel> <FormLabel>
{t( {t(
@@ -725,9 +712,13 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
)} )}
/> />
<FormField <FormField
control={form.control} control={
form.control
}
name="hcHostname" name="hcHostname"
render={({ field }) => ( render={({
field
}) => (
<FormItem> <FormItem>
<FormLabel> <FormLabel>
{t( {t(
@@ -758,9 +749,13 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
)} )}
/> />
<FormField <FormField
control={form.control} control={
form.control
}
name="hcPort" name="hcPort"
render={({ field }) => ( render={({
field
}) => (
<FormItem> <FormItem>
<FormLabel> <FormLabel>
{t( {t(
@@ -771,7 +766,9 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
<Input <Input
{...field} {...field}
type="number" type="number"
min={1} min={
1
}
max={ max={
65535 65535
} }
@@ -799,9 +796,13 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
{!isTcp && ( {!isTcp && (
<div className="grid grid-cols-1 md:grid-cols-3 gap-4"> <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<FormField <FormField
control={form.control} control={
form.control
}
name="hcMethod" name="hcMethod"
render={({ field }) => ( render={({
field
}) => (
<FormItem> <FormItem>
<FormLabel> <FormLabel>
{t( {t(
@@ -854,9 +855,13 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
)} )}
/> />
<FormField <FormField
control={form.control} control={
form.control
}
name="hcPath" name="hcPath"
render={({ field }) => ( render={({
field
}) => (
<FormItem> <FormItem>
<FormLabel> <FormLabel>
{t( {t(
@@ -887,9 +892,13 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
)} )}
/> />
<FormField <FormField
control={form.control} control={
form.control
}
name="hcTimeout" name="hcTimeout"
render={({ field }) => ( render={({
field
}) => (
<FormItem> <FormItem>
<FormLabel> <FormLabel>
{t( {t(
@@ -960,12 +969,6 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
)} )}
</> </>
)} )}
{showFields && isSnmpOrIcmp && (
<p className="text-sm text-muted-foreground">
{t("healthCheckStrategyNotAvailable")}
</p>
)}
</div> </div>
{/* ── Advanced tab ──────────────────────── */} {/* ── Advanced tab ──────────────────────── */}
@@ -976,6 +979,11 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
</p> </p>
)} )}
{/* Contact-sales banner for SNMP / ICMP */}
{showFields && isSnmpOrIcmp && (
<ContactSalesBanner />
)}
{showFields && !isSnmpOrIcmp && ( {showFields && !isSnmpOrIcmp && (
<> <>
{/* Healthy interval + threshold */} {/* Healthy interval + threshold */}
@@ -1210,9 +1218,13 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
{/* Follow redirects */} {/* Follow redirects */}
<FormField <FormField
control={form.control} control={
form.control
}
name="hcFollowRedirects" name="hcFollowRedirects"
render={({ field }) => ( render={({
field
}) => (
<FormItem className="flex flex-row items-center justify-between rounded-lg border p-3"> <FormItem className="flex flex-row items-center justify-between rounded-lg border p-3">
<FormLabel className="cursor-pointer"> <FormLabel className="cursor-pointer">
{t( {t(
@@ -1241,9 +1253,13 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
{/* Custom headers */} {/* Custom headers */}
<FormField <FormField
control={form.control} control={
form.control
}
name="hcHeaders" name="hcHeaders"
render={({ field }) => ( render={({
field
}) => (
<FormItem> <FormItem>
<FormLabel> <FormLabel>
{t( {t(
@@ -1264,7 +1280,9 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
field.onChange field.onChange
) )
} }
rows={4} rows={
4
}
/> />
</FormControl> </FormControl>
<FormDescription> <FormDescription>
@@ -1280,14 +1298,9 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
)} )}
</> </>
)} )}
{showFields && isSnmpOrIcmp && (
<p className="text-sm text-muted-foreground">
{t("healthCheckStrategyNotAvailable")}
</p>
)}
</div> </div>
</HorizontalTabs> </HorizontalTabs>
</div>
</form> </form>
</Form> </Form>
</CredenzaBody> </CredenzaBody>

View File

@@ -150,7 +150,7 @@ export default function HealthChecksTable({
</Button> </Button>
), ),
cell: ({ row }) => ( cell: ({ row }) => (
<span>{row.original.name}</span> <span>{row.original.name ? row.original.name : "-"}</span>
) )
}, },
{ {

View File

@@ -1,6 +1,6 @@
"use client"; "use client";
import { useState, useEffect } from "react";
import { import {
Credenza, Credenza,
CredenzaBody, CredenzaBody,
@@ -12,8 +12,7 @@ import {
CredenzaTitle CredenzaTitle
} from "@app/components/Credenza"; } from "@app/components/Credenza";
import { Button } from "@app/components/ui/button"; import { Button } from "@app/components/ui/button";
import { Plus, X, KeyRound, ExternalLink } from "lucide-react"; import { ContactSalesBanner } from "@app/components/ContactSalesBanner";
import Link from "next/link";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
export interface S3DestinationCredenzaProps { export interface S3DestinationCredenzaProps {
@@ -50,36 +49,7 @@ export function S3DestinationCredenza({
</CredenzaHeader> </CredenzaHeader>
<CredenzaBody> <CredenzaBody>
<div className="rounded-md border border-black-500/30 bg-linear-to-br from-black-500/10 via-background to-background overflow-hidden"> <ContactSalesBanner />
<div className="py-3 px-4">
<div className="flex items-center gap-2.5 text-sm text-muted-foreground">
<KeyRound className="size-4 shrink-0 text-black-500" />
<span>
Contact sales to enable this feature.{" "}
<Link
href="https://click.fossorial.io/ep922"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 font-medium text-black-600 underline"
>
Book a demo
<ExternalLink className="size-3.5 shrink-0" />
</Link>
{" or "}
<Link
href="https://pangolin.net/contact"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 font-medium text-black-600 underline"
>
contact us
<ExternalLink className="size-3.5 shrink-0" />
</Link>
.
</span>
</div>
</div>
</div>
</CredenzaBody> </CredenzaBody>
<CredenzaFooter> <CredenzaFooter>