mirror of
https://github.com/fosrl/pangolin.git
synced 2026-05-18 23:05:21 +00:00
Add translations
This commit is contained in:
@@ -3142,5 +3142,35 @@
|
|||||||
"idpDeleteAllOrgsMenu": "Delete",
|
"idpDeleteAllOrgsMenu": "Delete",
|
||||||
"publicIpEndpoint": "Endpoint",
|
"publicIpEndpoint": "Endpoint",
|
||||||
"lastTriggeredAt": "Last Trigger",
|
"lastTriggeredAt": "Last Trigger",
|
||||||
"reject": "Reject"
|
"reject": "Reject",
|
||||||
|
"uptimeDaysAgo": "{count} days ago",
|
||||||
|
"uptimeToday": "Today",
|
||||||
|
"uptimeNoDataAvailable": "No data available",
|
||||||
|
"uptimeSuffix": "uptime",
|
||||||
|
"uptimeDowntimeSuffix": "downtime",
|
||||||
|
"uptimeTooltipUptimeLabel": "Uptime",
|
||||||
|
"uptimeTooltipDowntimeLabel": "Downtime",
|
||||||
|
"uptimeOngoing": "ongoing",
|
||||||
|
"uptimeNoMonitoringData": "No monitoring data",
|
||||||
|
"uptimeNoData": "No data",
|
||||||
|
"uptimeMiniBarDown": "Down",
|
||||||
|
"uptimeSectionTitle": "Uptime",
|
||||||
|
"uptimeSectionDescription": "Site availability over the last {days} days.",
|
||||||
|
"uptimeAddAlert": "Add Alert",
|
||||||
|
"uptimeViewAlerts": "View Alerts",
|
||||||
|
"uptimeCreateEmailAlert": "Create Email Alert",
|
||||||
|
"uptimeAlertDescriptionSite": "Get notified by email when this site goes offline or comes back online.",
|
||||||
|
"uptimeAlertDescriptionResource": "Get notified by email when this resource goes offline or comes back online.",
|
||||||
|
"uptimeAlertNamePlaceholder": "Alert name",
|
||||||
|
"uptimeAdditionalEmails": "Additional Emails",
|
||||||
|
"uptimeCreateAlert": "Create Alert",
|
||||||
|
"uptimeAlertNoRecipients": "No recipients",
|
||||||
|
"uptimeAlertNoRecipientsDescription": "Please add at least one user, role, or email to notify.",
|
||||||
|
"uptimeAlertCreated": "Alert created",
|
||||||
|
"uptimeAlertCreatedDescription": "You will be notified when this changes status.",
|
||||||
|
"uptimeAlertCreateFailed": "Failed to create alert",
|
||||||
|
"webhookUrlLabel": "URL",
|
||||||
|
"webhookHeaderKeyPlaceholder": "Key",
|
||||||
|
"webhookHeaderValuePlaceholder": "Value",
|
||||||
|
"alertLabel": "Alert"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import { orgQueries } from "@app/lib/queries";
|
|||||||
import { PaidFeaturesAlert } from "@app/components/PaidFeaturesAlert";
|
import { PaidFeaturesAlert } from "@app/components/PaidFeaturesAlert";
|
||||||
import { usePaidStatus } from "@app/hooks/usePaidStatus";
|
import { usePaidStatus } from "@app/hooks/usePaidStatus";
|
||||||
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
interface UptimeAlertSectionProps {
|
interface UptimeAlertSectionProps {
|
||||||
orgId: string;
|
orgId: string;
|
||||||
@@ -50,6 +51,7 @@ export default function UptimeAlertSection({
|
|||||||
resourceId,
|
resourceId,
|
||||||
days = 90
|
days = 90
|
||||||
}: UptimeAlertSectionProps) {
|
}: UptimeAlertSectionProps) {
|
||||||
|
const t = useTranslations();
|
||||||
const api = createApiClient(useEnvContext());
|
const api = createApiClient(useEnvContext());
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const { isPaidUser } = usePaidStatus();
|
const { isPaidUser } = usePaidStatus();
|
||||||
@@ -57,7 +59,7 @@ export default function UptimeAlertSection({
|
|||||||
|
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [name, setName] = useState(
|
const [name, setName] = useState(
|
||||||
`${siteId ? "Site" : "Resource"} ${startingName} Alert`
|
`${siteId ? t("site") : t("resource")} ${startingName} ${t("alertLabel")}`
|
||||||
);
|
);
|
||||||
const [userTags, setUserTags] = useState<Tag[]>([]);
|
const [userTags, setUserTags] = useState<Tag[]>([]);
|
||||||
const [roleTags, setRoleTags] = useState<Tag[]>([]);
|
const [roleTags, setRoleTags] = useState<Tag[]>([]);
|
||||||
@@ -112,9 +114,8 @@ export default function UptimeAlertSection({
|
|||||||
) {
|
) {
|
||||||
toast({
|
toast({
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
title: "No recipients",
|
title: t("uptimeAlertNoRecipients"),
|
||||||
description:
|
description: t("uptimeAlertNoRecipientsDescription")
|
||||||
"Please add at least one user, role, or email to notify."
|
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -136,12 +137,12 @@ export default function UptimeAlertSection({
|
|||||||
});
|
});
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: "Alert created",
|
title: t("uptimeAlertCreated"),
|
||||||
description: "You will be notified when this changes status."
|
description: t("uptimeAlertCreatedDescription")
|
||||||
});
|
});
|
||||||
|
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
setName("Uptime Alert");
|
setName(t("uptimeSectionTitle"));
|
||||||
setUserTags([]);
|
setUserTags([]);
|
||||||
setRoleTags([]);
|
setRoleTags([]);
|
||||||
setEmailTags([]);
|
setEmailTags([]);
|
||||||
@@ -156,8 +157,8 @@ export default function UptimeAlertSection({
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
toast({
|
toast({
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
title: "Failed to create alert",
|
title: t("uptimeAlertCreateFailed"),
|
||||||
description: formatAxiosError(e, "An error occurred.")
|
description: formatAxiosError(e, t("errorOccurred"))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
@@ -174,19 +175,19 @@ export default function UptimeAlertSection({
|
|||||||
const alertButton = alertRulesLoading ? (
|
const alertButton = alertRulesLoading ? (
|
||||||
<Button variant="outline" type="button" loading aria-busy="true">
|
<Button variant="outline" type="button" loading aria-busy="true">
|
||||||
<BellPlus className="size-4 mr-2" />
|
<BellPlus className="size-4 mr-2" />
|
||||||
Add Alert
|
{t("uptimeAddAlert")}
|
||||||
</Button>
|
</Button>
|
||||||
) : hasRules ? (
|
) : hasRules ? (
|
||||||
<Button variant="outline" asChild>
|
<Button variant="outline" asChild>
|
||||||
<Link href={rulesListHref}>
|
<Link href={rulesListHref}>
|
||||||
<BellRing className="size-4 mr-2" />
|
<BellRing className="size-4 mr-2" />
|
||||||
View Alerts
|
{t("uptimeViewAlerts")}
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<Button variant="outline" onClick={() => setOpen(true)}>
|
<Button variant="outline" onClick={() => setOpen(true)}>
|
||||||
<BellPlus className="size-4 mr-2" />
|
<BellPlus className="size-4 mr-2" />
|
||||||
Add Alert
|
{t("uptimeAddAlert")}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -196,9 +197,11 @@ export default function UptimeAlertSection({
|
|||||||
<SettingsSectionHeader>
|
<SettingsSectionHeader>
|
||||||
<div className="flex justify-between items-start">
|
<div className="flex justify-between items-start">
|
||||||
<div>
|
<div>
|
||||||
<SettingsSectionTitle>Uptime</SettingsSectionTitle>
|
<SettingsSectionTitle>
|
||||||
|
{t("uptimeSectionTitle")}
|
||||||
|
</SettingsSectionTitle>
|
||||||
<SettingsSectionDescription>
|
<SettingsSectionDescription>
|
||||||
Availability over the last {days} days
|
{t("uptimeSectionDescription", { days })}
|
||||||
</SettingsSectionDescription>
|
</SettingsSectionDescription>
|
||||||
</div>
|
</div>
|
||||||
{alertButton}
|
{alertButton}
|
||||||
@@ -216,11 +219,13 @@ export default function UptimeAlertSection({
|
|||||||
<Credenza open={open} onOpenChange={setOpen}>
|
<Credenza open={open} onOpenChange={setOpen}>
|
||||||
<CredenzaContent>
|
<CredenzaContent>
|
||||||
<CredenzaHeader>
|
<CredenzaHeader>
|
||||||
<CredenzaTitle>Create Email Alert</CredenzaTitle>
|
<CredenzaTitle>
|
||||||
|
{t("uptimeCreateEmailAlert")}
|
||||||
|
</CredenzaTitle>
|
||||||
<CredenzaDescription>
|
<CredenzaDescription>
|
||||||
Get notified by email when this{" "}
|
{siteId
|
||||||
{siteId ? "site" : "resource"} goes offline or comes
|
? t("uptimeAlertDescriptionSite")
|
||||||
back online.
|
: t("uptimeAlertDescriptionResource")}
|
||||||
</CredenzaDescription>
|
</CredenzaDescription>
|
||||||
</CredenzaHeader>
|
</CredenzaHeader>
|
||||||
<CredenzaBody>
|
<CredenzaBody>
|
||||||
@@ -232,20 +237,22 @@ export default function UptimeAlertSection({
|
|||||||
>
|
>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="alert-name">Name</Label>
|
<Label htmlFor="alert-name">
|
||||||
|
{t("name")}
|
||||||
|
</Label>
|
||||||
<Input
|
<Input
|
||||||
id="alert-name"
|
id="alert-name"
|
||||||
value={name}
|
value={name}
|
||||||
onChange={(e) => setName(e.target.value)}
|
onChange={(e) => setName(e.target.value)}
|
||||||
placeholder="Alert name"
|
placeholder={t("uptimeAlertNamePlaceholder")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label>Notify Users</Label>
|
<Label>{t("alertingNotifyUsers")}</Label>
|
||||||
<TagInput
|
<TagInput
|
||||||
activeTagIndex={activeUserTagIndex}
|
activeTagIndex={activeUserTagIndex}
|
||||||
setActiveTagIndex={setActiveUserTagIndex}
|
setActiveTagIndex={setActiveUserTagIndex}
|
||||||
placeholder="Select users..."
|
placeholder={t("alertingSelectUsers")}
|
||||||
size="sm"
|
size="sm"
|
||||||
tags={userTags}
|
tags={userTags}
|
||||||
setTags={(newTags) => {
|
setTags={(newTags) => {
|
||||||
@@ -263,11 +270,11 @@ export default function UptimeAlertSection({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label>Notify Roles</Label>
|
<Label>{t("alertingNotifyRoles")}</Label>
|
||||||
<TagInput
|
<TagInput
|
||||||
activeTagIndex={activeRoleTagIndex}
|
activeTagIndex={activeRoleTagIndex}
|
||||||
setActiveTagIndex={setActiveRoleTagIndex}
|
setActiveTagIndex={setActiveRoleTagIndex}
|
||||||
placeholder="Select roles..."
|
placeholder={t("alertingSelectRoles")}
|
||||||
size="sm"
|
size="sm"
|
||||||
tags={roleTags}
|
tags={roleTags}
|
||||||
setTags={(newTags) => {
|
setTags={(newTags) => {
|
||||||
@@ -285,11 +292,11 @@ export default function UptimeAlertSection({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label>Additional Emails</Label>
|
<Label>{t("uptimeAdditionalEmails")}</Label>
|
||||||
<TagInput
|
<TagInput
|
||||||
activeTagIndex={activeEmailTagIndex}
|
activeTagIndex={activeEmailTagIndex}
|
||||||
setActiveTagIndex={setActiveEmailTagIndex}
|
setActiveTagIndex={setActiveEmailTagIndex}
|
||||||
placeholder="Enter email addresses..."
|
placeholder={t("alertingEmailPlaceholder")}
|
||||||
size="sm"
|
size="sm"
|
||||||
tags={emailTags}
|
tags={emailTags}
|
||||||
setTags={(newTags) => {
|
setTags={(newTags) => {
|
||||||
@@ -313,14 +320,14 @@ export default function UptimeAlertSection({
|
|||||||
</CredenzaBody>
|
</CredenzaBody>
|
||||||
<CredenzaFooter>
|
<CredenzaFooter>
|
||||||
<CredenzaClose asChild>
|
<CredenzaClose asChild>
|
||||||
<Button variant="outline">Cancel</Button>
|
<Button variant="outline">{t("cancel")}</Button>
|
||||||
</CredenzaClose>
|
</CredenzaClose>
|
||||||
<Button
|
<Button
|
||||||
onClick={handleSubmit}
|
onClick={handleSubmit}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
disabled={loading || !isPaid}
|
disabled={loading || !isPaid}
|
||||||
>
|
>
|
||||||
Create Alert
|
{t("uptimeCreateAlert")}
|
||||||
</Button>
|
</Button>
|
||||||
</CredenzaFooter>
|
</CredenzaFooter>
|
||||||
</CredenzaContent>
|
</CredenzaContent>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||||
import { createApiClient } from "@app/lib/api";
|
import { createApiClient } from "@app/lib/api";
|
||||||
import { cn } from "@app/lib/cn";
|
import { cn } from "@app/lib/cn";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
function formatDuration(seconds: number): string {
|
function formatDuration(seconds: number): string {
|
||||||
if (seconds === 0) return "0s";
|
if (seconds === 0) return "0s";
|
||||||
@@ -63,6 +64,7 @@ export default function UptimeBar({
|
|||||||
title,
|
title,
|
||||||
className
|
className
|
||||||
}: UptimeBarProps) {
|
}: UptimeBarProps) {
|
||||||
|
const t = useTranslations();
|
||||||
const api = createApiClient(useEnvContext());
|
const api = createApiClient(useEnvContext());
|
||||||
|
|
||||||
const siteQuery = useQuery({
|
const siteQuery = useQuery({
|
||||||
@@ -104,7 +106,7 @@ export default function UptimeBar({
|
|||||||
<div
|
<div
|
||||||
className="flex items-center gap-4 text-sm ml-auto"
|
className="flex items-center gap-4 text-sm ml-auto"
|
||||||
aria-busy="true"
|
aria-busy="true"
|
||||||
aria-label="Loading uptime summary"
|
aria-label={t("loading")}
|
||||||
>
|
>
|
||||||
<span className="h-4 w-[4.5rem] shrink-0 rounded-md bg-muted animate-pulse" />
|
<span className="h-4 w-[4.5rem] shrink-0 rounded-md bg-muted animate-pulse" />
|
||||||
<span className="h-4 w-[7rem] shrink-0 rounded-md bg-muted animate-pulse" />
|
<span className="h-4 w-[7rem] shrink-0 rounded-md bg-muted animate-pulse" />
|
||||||
@@ -122,8 +124,8 @@ export default function UptimeBar({
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between text-xs text-muted-foreground">
|
<div className="flex justify-between text-xs text-muted-foreground">
|
||||||
<span>{days} days ago</span>
|
<span>{t("uptimeDaysAgo", { count: days })}</span>
|
||||||
<span>Today</span>
|
<span>{t("uptimeToday")}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -145,7 +147,7 @@ export default function UptimeBar({
|
|||||||
<span className="font-semibold text-foreground">
|
<span className="font-semibold text-foreground">
|
||||||
{data.overallUptimePercent.toFixed(2)}%
|
{data.overallUptimePercent.toFixed(2)}%
|
||||||
</span>{" "}
|
</span>{" "}
|
||||||
uptime
|
{t("uptimeSuffix")}
|
||||||
</span>
|
</span>
|
||||||
{data.totalDowntimeSeconds > 0 && (
|
{data.totalDowntimeSeconds > 0 && (
|
||||||
<span className="text-muted-foreground">
|
<span className="text-muted-foreground">
|
||||||
@@ -154,14 +156,14 @@ export default function UptimeBar({
|
|||||||
data.totalDowntimeSeconds
|
data.totalDowntimeSeconds
|
||||||
)}
|
)}
|
||||||
</span>{" "}
|
</span>{" "}
|
||||||
downtime
|
{t("uptimeDowntimeSuffix")}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{allNoData && (
|
{allNoData && (
|
||||||
<span className="text-muted-foreground text-xs">
|
<span className="text-muted-foreground text-xs">
|
||||||
No data available
|
{t("uptimeNoDataAvailable")}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -188,7 +190,7 @@ export default function UptimeBar({
|
|||||||
</div>
|
</div>
|
||||||
{day.status !== "no_data" && (
|
{day.status !== "no_data" && (
|
||||||
<div className="text-xs text-primary-foreground/80">
|
<div className="text-xs text-primary-foreground/80">
|
||||||
Uptime:{" "}
|
{t("uptimeTooltipUptimeLabel")}:{" "}
|
||||||
<span className="font-medium text-primary-foreground">
|
<span className="font-medium text-primary-foreground">
|
||||||
{day.uptimePercent.toFixed(1)}%
|
{day.uptimePercent.toFixed(1)}%
|
||||||
</span>
|
</span>
|
||||||
@@ -196,7 +198,7 @@ export default function UptimeBar({
|
|||||||
)}
|
)}
|
||||||
{day.totalDowntimeSeconds > 0 && (
|
{day.totalDowntimeSeconds > 0 && (
|
||||||
<div className="text-xs text-primary-foreground/80">
|
<div className="text-xs text-primary-foreground/80">
|
||||||
Downtime:{" "}
|
{t("uptimeTooltipDowntimeLabel")}:{" "}
|
||||||
<span className="font-medium text-primary-foreground">
|
<span className="font-medium text-primary-foreground">
|
||||||
{formatDuration(
|
{formatDuration(
|
||||||
day.totalDowntimeSeconds
|
day.totalDowntimeSeconds
|
||||||
@@ -214,7 +216,7 @@ export default function UptimeBar({
|
|||||||
{formatTime(w.start)}
|
{formatTime(w.start)}
|
||||||
{w.end
|
{w.end
|
||||||
? ` – ${formatTime(w.end)}`
|
? ` – ${formatTime(w.end)}`
|
||||||
: " – ongoing"}{" "}
|
: ` – ${t("uptimeOngoing")}`}{" "}
|
||||||
<span className="capitalize">
|
<span className="capitalize">
|
||||||
({w.status})
|
({w.status})
|
||||||
</span>
|
</span>
|
||||||
@@ -224,7 +226,7 @@ export default function UptimeBar({
|
|||||||
)}
|
)}
|
||||||
{day.status === "no_data" && (
|
{day.status === "no_data" && (
|
||||||
<div className="text-xs text-primary-foreground/60">
|
<div className="text-xs text-primary-foreground/60">
|
||||||
No monitoring data
|
{t("uptimeNoMonitoringData")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
@@ -234,9 +236,9 @@ export default function UptimeBar({
|
|||||||
|
|
||||||
{/* Date labels */}
|
{/* Date labels */}
|
||||||
<div className="flex justify-between text-xs text-muted-foreground">
|
<div className="flex justify-between text-xs text-muted-foreground">
|
||||||
<span>{days} days ago</span>
|
<span>{t("uptimeDaysAgo", { count: days })}</span>
|
||||||
<span>Today</span>
|
<span>{t("uptimeToday")}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||||
import { createApiClient } from "@app/lib/api";
|
import { createApiClient } from "@app/lib/api";
|
||||||
import { cn } from "@app/lib/cn";
|
import { cn } from "@app/lib/cn";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
function formatDuration(seconds: number): string {
|
function formatDuration(seconds: number): string {
|
||||||
if (seconds === 0) return "0s";
|
if (seconds === 0) return "0s";
|
||||||
@@ -51,6 +52,7 @@ export default function UptimeMiniBar({
|
|||||||
healthCheckId,
|
healthCheckId,
|
||||||
days = 30
|
days = 30
|
||||||
}: UptimeMiniBarProps) {
|
}: UptimeMiniBarProps) {
|
||||||
|
const t = useTranslations();
|
||||||
const api = createApiClient(useEnvContext());
|
const api = createApiClient(useEnvContext());
|
||||||
|
|
||||||
const siteQuery = useQuery({
|
const siteQuery = useQuery({
|
||||||
@@ -105,7 +107,7 @@ export default function UptimeMiniBar({
|
|||||||
<span
|
<span
|
||||||
className="inline-flex min-w-[7ch] items-center justify-end text-xs text-muted-foreground whitespace-nowrap"
|
className="inline-flex min-w-[7ch] items-center justify-end text-xs text-muted-foreground whitespace-nowrap"
|
||||||
aria-busy="true"
|
aria-busy="true"
|
||||||
aria-label="Loading uptime"
|
aria-label={t("loading")}
|
||||||
>
|
>
|
||||||
<span className="h-4 w-[5.5ch] max-w-full rounded bg-muted animate-pulse" />
|
<span className="h-4 w-[5.5ch] max-w-full rounded bg-muted animate-pulse" />
|
||||||
</span>
|
</span>
|
||||||
@@ -136,12 +138,12 @@ export default function UptimeMiniBar({
|
|||||||
</div>
|
</div>
|
||||||
<div className="text-xs text-primary-foreground/80">
|
<div className="text-xs text-primary-foreground/80">
|
||||||
{day.status === "no_data"
|
{day.status === "no_data"
|
||||||
? "No data"
|
? t("uptimeNoData")
|
||||||
: `${day.uptimePercent.toFixed(1)}% uptime`}
|
: `${day.uptimePercent.toFixed(1)}% ${t("uptimeSuffix")}`}
|
||||||
</div>
|
</div>
|
||||||
{day.totalDowntimeSeconds > 0 && (
|
{day.totalDowntimeSeconds > 0 && (
|
||||||
<div className="text-xs text-primary-foreground/70">
|
<div className="text-xs text-primary-foreground/70">
|
||||||
Down:{" "}
|
{t("uptimeMiniBarDown")}:{" "}
|
||||||
{formatDuration(day.totalDowntimeSeconds)}
|
{formatDuration(day.totalDowntimeSeconds)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -151,9 +153,9 @@ export default function UptimeMiniBar({
|
|||||||
</div>
|
</div>
|
||||||
<span className="text-xs text-muted-foreground whitespace-nowrap">
|
<span className="text-xs text-muted-foreground whitespace-nowrap">
|
||||||
{allNoData
|
{allNoData
|
||||||
? "No data"
|
? t("uptimeNoData")
|
||||||
: `${data.overallUptimePercent.toFixed(1)}%`}
|
: `${data.overallUptimePercent.toFixed(1)}%`}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -714,7 +714,7 @@ function WebhookActionFields({
|
|||||||
name={`actions.${index}.url`}
|
name={`actions.${index}.url`}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>URL</FormLabel>
|
<FormLabel>{t("webhookUrlLabel")}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
{...field}
|
{...field}
|
||||||
@@ -961,7 +961,7 @@ function WebhookHeadersField({
|
|||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="flex-1">
|
<FormItem className="flex-1">
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} placeholder="Key" />
|
<Input {...field} placeholder={t("webhookHeaderKeyPlaceholder")} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
@@ -972,7 +972,7 @@ function WebhookHeadersField({
|
|||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="flex-1">
|
<FormItem className="flex-1">
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} placeholder="Value" />
|
<Input {...field} placeholder={t("webhookHeaderValuePlaceholder")} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user