From d9564ed6fea37bbe55e60e4153ac8e8184916464 Mon Sep 17 00:00:00 2001 From: miloschwartz Date: Thu, 13 Nov 2025 22:04:29 -0500 Subject: [PATCH] improve spacing and colors --- messages/en-US.json | 6 + src/components/ResourceInfoBox.tsx | 12 +- src/components/ResourcesTable.tsx | 218 +++++++++++++++++------------ 3 files changed, 143 insertions(+), 93 deletions(-) diff --git a/messages/en-US.json b/messages/en-US.json index 7f877984..08d4e21a 100644 --- a/messages/en-US.json +++ b/messages/en-US.json @@ -1525,6 +1525,12 @@ "resourcesTableTheseResourcesForUseWith": "These resources are for use with", "resourcesTableClients": "Clients", "resourcesTableAndOnlyAccessibleInternally": "and are only accessible internally when connected with a client.", + "resourcesTableNoTargets": "No targets", + "resourcesTableHealthy": "Healthy", + "resourcesTableDegraded": "Degraded", + "resourcesTableOffline": "Offline", + "resourcesTableUnknown": "Unknown", + "resourcesTableNotMonitored": "Not monitored", "editInternalResourceDialogEditClientResource": "Edit Client Resource", "editInternalResourceDialogUpdateResourceProperties": "Update the resource properties and target configuration for {resourceName}.", "editInternalResourceDialogResourceProperties": "Resource Properties", diff --git a/src/components/ResourceInfoBox.tsx b/src/components/ResourceInfoBox.tsx index a75ca78c..0696c605 100644 --- a/src/components/ResourceInfoBox.tsx +++ b/src/components/ResourceInfoBox.tsx @@ -53,8 +53,8 @@ export default function ResourceInfoBox({ }: ResourceInfoBoxType) { authInfo.sso || authInfo.whitelist || authInfo.headerAuth ? ( -
- +
+ {t("protected")}
) : ( @@ -163,13 +163,13 @@ export default function ResourceInfoBox({ }: ResourceInfoBoxType) { {t("visibility")} {resource.enabled ? ( -
- +
+ {t("enabled")}
) : ( -
- +
+ {t("disabled")}
)} diff --git a/src/components/ResourcesTable.tsx b/src/components/ResourcesTable.tsx index 252ac7d2..171f3491 100644 --- a/src/components/ResourcesTable.tsx +++ b/src/components/ResourcesTable.tsx @@ -17,7 +17,7 @@ import { DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, - DropdownMenuCheckboxItem, + DropdownMenuCheckboxItem } from "@app/components/ui/dropdown-menu"; import { Button } from "@app/components/ui/button"; import { @@ -36,7 +36,7 @@ import { Wifi, WifiOff, CheckCircle2, - XCircle, + XCircle } from "lucide-react"; import Link from "next/link"; import { useRouter } from "next/navigation"; @@ -75,13 +75,12 @@ import EditInternalResourceDialog from "@app/components/EditInternalResourceDial import CreateInternalResourceDialog from "@app/components/CreateInternalResourceDialog"; import { Alert, AlertDescription } from "@app/components/ui/alert"; - export type TargetHealth = { targetId: number; ip: string; port: number; enabled: boolean; - healthStatus?: 'healthy' | 'unhealthy' | 'unknown'; + healthStatus?: "healthy" | "unhealthy" | "unknown"; }; export type ResourceRow = { @@ -102,45 +101,55 @@ export type ResourceRow = { targets?: TargetHealth[]; }; - -function getOverallHealthStatus(targets?: TargetHealth[]): 'online' | 'degraded' | 'offline' | 'unknown' { +function getOverallHealthStatus( + targets?: TargetHealth[] +): "online" | "degraded" | "offline" | "unknown" { if (!targets || targets.length === 0) { - return 'unknown'; + return "unknown"; } - const monitoredTargets = targets.filter(t => t.enabled && t.healthStatus && t.healthStatus !== 'unknown'); + const monitoredTargets = targets.filter( + (t) => t.enabled && t.healthStatus && t.healthStatus !== "unknown" + ); if (monitoredTargets.length === 0) { - return 'unknown'; + return "unknown"; } - const healthyCount = monitoredTargets.filter(t => t.healthStatus === 'healthy').length; - const unhealthyCount = monitoredTargets.filter(t => t.healthStatus === 'unhealthy').length; + const healthyCount = monitoredTargets.filter( + (t) => t.healthStatus === "healthy" + ).length; + const unhealthyCount = monitoredTargets.filter( + (t) => t.healthStatus === "unhealthy" + ).length; if (healthyCount === monitoredTargets.length) { - return 'online'; + return "online"; } else if (unhealthyCount === monitoredTargets.length) { - return 'offline'; + return "offline"; } else { - return 'degraded'; + return "degraded"; } } -function StatusIcon({ status, className = "" }: { - status: 'online' | 'degraded' | 'offline' | 'unknown'; +function StatusIcon({ + status, + className = "" +}: { + status: "online" | "degraded" | "offline" | "unknown"; className?: string; }) { const iconClass = `h-4 w-4 ${className}`; switch (status) { - case 'online': + case "online": return ; - case 'degraded': + case "degraded": return ; - case 'offline': + case "offline": return ; - case 'unknown': - return ; + case "unknown": + return ; default: return null; } @@ -171,15 +180,14 @@ type ResourcesTableProps = { }; }; - const STORAGE_KEYS = { - PAGE_SIZE: 'datatable-page-size', + PAGE_SIZE: "datatable-page-size", getTablePageSize: (tableId?: string) => tableId ? `datatable-${tableId}-page-size` : STORAGE_KEYS.PAGE_SIZE }; const getStoredPageSize = (tableId?: string, defaultSize = 20): number => { - if (typeof window === 'undefined') return defaultSize; + if (typeof window === "undefined") return defaultSize; try { const key = STORAGE_KEYS.getTablePageSize(tableId); @@ -191,24 +199,22 @@ const getStoredPageSize = (tableId?: string, defaultSize = 20): number => { } } } catch (error) { - console.warn('Failed to read page size from localStorage:', error); + console.warn("Failed to read page size from localStorage:", error); } return defaultSize; }; const setStoredPageSize = (pageSize: number, tableId?: string): void => { - if (typeof window === 'undefined') return; + if (typeof window === "undefined") return; try { const key = STORAGE_KEYS.getTablePageSize(tableId); localStorage.setItem(key, pageSize.toString()); } catch (error) { - console.warn('Failed to save page size to localStorage:', error); + console.warn("Failed to save page size to localStorage:", error); } }; - - export default function ResourcesTable({ resources, internalResources, @@ -224,12 +230,11 @@ export default function ResourcesTable({ const api = createApiClient({ env }); - const [proxyPageSize, setProxyPageSize] = useState(() => - getStoredPageSize('proxy-resources', 20) + getStoredPageSize("proxy-resources", 20) ); const [internalPageSize, setInternalPageSize] = useState(() => - getStoredPageSize('internal-resources', 20) + getStoredPageSize("internal-resources", 20) ); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); @@ -247,8 +252,10 @@ export default function ResourcesTable({ defaultSort ? [defaultSort] : [] ); - const [proxyColumnVisibility, setProxyColumnVisibility] = useState({}); - const [internalColumnVisibility, setInternalColumnVisibility] = useState({}); + const [proxyColumnVisibility, setProxyColumnVisibility] = + useState({}); + const [internalColumnVisibility, setInternalColumnVisibility] = + useState({}); const [proxyColumnFilters, setProxyColumnFilters] = useState([]); @@ -427,24 +434,34 @@ export default function ResourcesTable({ return (
- No targets + + {t("resourcesTableNoTargets")} +
); } - const monitoredTargets = targets.filter(t => t.enabled && t.healthStatus && t.healthStatus !== 'unknown'); - const unknownTargets = targets.filter(t => !t.enabled || !t.healthStatus || t.healthStatus === 'unknown'); + const monitoredTargets = targets.filter( + (t) => t.enabled && t.healthStatus && t.healthStatus !== "unknown" + ); + const unknownTargets = targets.filter( + (t) => !t.enabled || !t.healthStatus || t.healthStatus === "unknown" + ); return ( - @@ -453,16 +470,29 @@ export default function ResourcesTable({ {monitoredTargets.length > 0 && ( <> {monitoredTargets.map((target) => ( - +
{`${target.ip}:${target.port}`}
- + {target.healthStatus}
@@ -472,13 +502,21 @@ export default function ResourcesTable({ {unknownTargets.length > 0 && ( <> {unknownTargets.map((target) => ( - +
- + {`${target.ip}:${target.port}`}
- {!target.enabled ? 'Disabled' : 'Not monitored'} + {!target.enabled + ? t("disabled") + : t("resourcesTableNotMonitored")}
))} @@ -489,7 +527,6 @@ export default function ResourcesTable({ ); } - const proxyColumns: ColumnDef[] = [ { accessorKey: "name", @@ -512,7 +549,15 @@ export default function ResourcesTable({ header: t("protocol"), cell: ({ row }) => { const resourceRow = row.original; - return {resourceRow.http ? (resourceRow.ssl ? "HTTPS" : "HTTP") : resourceRow.protocol.toUpperCase()}; + return ( + + {resourceRow.http + ? resourceRow.ssl + ? "HTTPS" + : "HTTP" + : resourceRow.protocol.toUpperCase()} + + ); } }, { @@ -538,7 +583,12 @@ export default function ResourcesTable({ sortingFn: (rowA, rowB) => { const statusA = getOverallHealthStatus(rowA.original.targets); const statusB = getOverallHealthStatus(rowB.original.targets); - const statusOrder = { online: 3, degraded: 2, offline: 1, unknown: 0 }; + const statusOrder = { + online: 3, + degraded: 2, + offline: 1, + unknown: 0 + }; return statusOrder[statusA] - statusOrder[statusB]; } }, @@ -589,13 +639,13 @@ export default function ResourcesTable({ return (
{resourceRow.authState === "protected" ? ( - - + + {t("protected")} ) : resourceRow.authState === "not_protected" ? ( - - + + {t("notProtected")} ) : ( @@ -841,12 +891,12 @@ export default function ResourcesTable({ const handleProxyPageSizeChange = (newPageSize: number) => { setProxyPageSize(newPageSize); - setStoredPageSize(newPageSize, 'proxy-resources'); + setStoredPageSize(newPageSize, "proxy-resources"); }; const handleInternalPageSizeChange = (newPageSize: number) => { setInternalPageSize(newPageSize); - setStoredPageSize(newPageSize, 'internal-resources'); + setStoredPageSize(newPageSize, "internal-resources"); }; return ( @@ -860,12 +910,8 @@ export default function ResourcesTable({ }} dialog={
-

- {t("resourceQuestionRemove")} -

-

- {t("resourceMessageRemove")} -

+

{t("resourceQuestionRemove")}

+

{t("resourceMessageRemove")}

} buttonText={t("resourceDeleteConfirm")} @@ -884,12 +930,8 @@ export default function ResourcesTable({ }} dialog={
-

- {t("resourceQuestionRemove")} -

-

- {t("resourceMessageRemove")} -

+

{t("resourceQuestionRemove")}

+

{t("resourceMessageRemove")}

} buttonText={t("resourceDeleteConfirm")} @@ -939,9 +981,7 @@ export default function ResourcesTable({ {t("refresh")}
-
- {getActionButton()} -
+
{getActionButton()}
@@ -960,12 +1000,12 @@ export default function ResourcesTable({ {header.isPlaceholder ? null : flexRender( - header - .column - .columnDef - .header, - header.getContext() - )} + header + .column + .columnDef + .header, + header.getContext() + )} ) )} @@ -1023,7 +1063,9 @@ export default function ResourcesTable({
@@ -1061,12 +1103,12 @@ export default function ResourcesTable({ {header.isPlaceholder ? null : flexRender( - header - .column - .columnDef - .header, - header.getContext() - )} + header + .column + .columnDef + .header, + header.getContext() + )} ) )} @@ -1124,7 +1166,9 @@ export default function ResourcesTable({