diff --git a/ui/litellm-dashboard/.eslintrc.json b/ui/litellm-dashboard/.eslintrc.json index b10717340cf..95ff35094ab 100644 --- a/ui/litellm-dashboard/.eslintrc.json +++ b/ui/litellm-dashboard/.eslintrc.json @@ -68,6 +68,7 @@ "src/components/guardrails/GuardrailTestPlayground.tsx", "src/components/vector_store_management/S3VectorsConfig.tsx", "src/components/mcp_tools/mcp_server_cost_config.tsx", + "src/components/view_logs/GuardrailViewer/CompliancePanel.tsx", "src/components/prompts/prompt_editor_view/PromptEditorHeader.tsx", "src/components/prompts/prompt_editor_view/VersionHistorySidePanel.tsx", "src/app/(dashboard)/teams/components/TeamsTable/ModelsCell.tsx", diff --git a/ui/litellm-dashboard/src/components/view_logs/GuardrailViewer/CompliancePanel.tsx b/ui/litellm-dashboard/src/components/view_logs/GuardrailViewer/CompliancePanel.tsx index cd36030e512..f5311c18fc1 100644 --- a/ui/litellm-dashboard/src/components/view_logs/GuardrailViewer/CompliancePanel.tsx +++ b/ui/litellm-dashboard/src/components/view_logs/GuardrailViewer/CompliancePanel.tsx @@ -1,5 +1,12 @@ import React, { useState, useEffect } from "react"; -import { Tooltip } from "antd"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import { CheckCircle2, ChevronDown, Loader2, XCircle } from "lucide-react"; +import { cn } from "@/lib/utils"; import { checkEuAiActCompliance, checkGdprCompliance, @@ -14,35 +21,11 @@ interface CompliancePanelProps { user?: string; model?: string; startTime?: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any metadata?: Record; }; } -// -- Icons -- - -const CheckIcon = () => ( - - - - -); - -const CrossIcon = () => ( - - - - -); - -const SpinnerIcon = () => ( - - - - -); - -// -- Sub-components -- - const ComplianceCard = ({ title, data, @@ -57,71 +40,88 @@ const ComplianceCard = ({ const [expanded, setExpanded] = useState(false); return ( -
+
setExpanded(!expanded)} >
{loading ? ( - + ) : error ? ( - - -- - + + + + -- + + {error} + + ) : data?.compliant ? ( - + ) : ( - + )} - {title} + {title}
{!loading && !error && data && ( {data.compliant ? "COMPLIANT" : "NON-COMPLIANT"} )} {error && ( - + UNAVAILABLE )} - - - +
{expanded && ( -
- {loading &&

Checking compliance...

} - {error &&

{error}

} +
+ {loading && ( +

+ Checking compliance... +

+ )} + {error &&

{error}

} {data && (
{data.checks.map((check, idx) => (
- {check.passed ? : } + {check.passed ? ( + + ) : ( + + )}
- {check.check_name} - {check.article} + + {check.check_name} + + + {check.article} +
-

{check.detail}

+

+ {check.detail} +

))} @@ -133,10 +133,13 @@ const ComplianceCard = ({ ); }; -// -- Main Component -- - -const CompliancePanel: React.FC = ({ accessToken, logEntry }) => { - const [euAiActData, setEuAiActData] = useState(null); +const CompliancePanel: React.FC = ({ + accessToken, + logEntry, +}) => { + const [euAiActData, setEuAiActData] = useState( + null, + ); const [gdprData, setGdprData] = useState(null); const [euAiActLoading, setEuAiActLoading] = useState(false); const [gdprLoading, setGdprLoading] = useState(false); @@ -158,20 +161,24 @@ const CompliancePanel: React.FC = ({ accessToken, logEntry setEuAiActError(null); checkEuAiActCompliance(accessToken, payload) .then(setEuAiActData) - .catch((err) => setEuAiActError(err.message || "Failed to check EU AI Act compliance")) + .catch((err) => + setEuAiActError(err.message || "Failed to check EU AI Act compliance"), + ) .finally(() => setEuAiActLoading(false)); setGdprLoading(true); setGdprError(null); checkGdprCompliance(accessToken, payload) .then(setGdprData) - .catch((err) => setGdprError(err.message || "Failed to check GDPR compliance")) + .catch((err) => + setGdprError(err.message || "Failed to check GDPR compliance"), + ) .finally(() => setGdprLoading(false)); }, [accessToken, logEntry]); return (
-

+

Regulatory Compliance