Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/api-client/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const API_ENDPOINTS = {
MCP_CLASSIFIER_PIPELINE_DEBUG: "/analyzeClassifierPipeline",
EVENTS: "/events",
EVENT: "/event",
EVENT_RESOURCES: "/eventResources",
CLASSIFIERS: "/classifiers",
CLASSIFIER: "/classifier",
STATS: "/stats",
Expand Down
Binary file added src/assets/admiral-sveltopus.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions src/lib/components/ui/feedback/emptyData.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { CircleOff, FilterX } from "lucide-react";
import { FilterX } from "lucide-react";
import { Button } from "@/lib/components/ui/inputs/button";
import { RefreshButton } from "@/modules/common/components/actions/RefreshButton";
import mascot from "@/assets/admiral-sveltopus.png";

type EmptyDataProps = {
name: string;
Expand All @@ -17,9 +18,8 @@ export const EmptyData = ({
<>
<div className="w-full mt-16 flex items-center flex-wrap justify-center gap-10">
<div className="grid gap-4 w-64">
<div className="w-20 h-20 mx-auto bg-slate-50 dark:bg-slate-800 rounded-full justify-center items-center inline-flex">
<CircleOff className="w-10 h-10 text-gray-500" />
</div>
{/* Decorative: the text below says what is missing */}
<img src={mascot} alt="" className="w-32 h-32 mx-auto" />
<div>
<h2 className="text-center text-base font-semibold leading-relaxed pb-1">
There’s no {name} found.
Expand Down
10 changes: 10 additions & 0 deletions src/lib/components/ui/layout/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Badge } from "@/lib/components/ui/data-display/badge";
import React from "react";
import { cn } from "@/lib/utils";
import { Book, LifeBuoy, ExternalLink } from "lucide-react";
import mascot from "@/assets/admiral-sveltopus.png";

interface SidebarProps {
isOpen: boolean;
Expand Down Expand Up @@ -129,6 +130,15 @@ export function Sidebar({ isOpen }: SidebarProps) {
</div>

<div className={cn("p-4 mb-2 mt-auto", !isOpen && "px-2 pb-4")}>
{/* Decorative. Only when expanded and the window is tall enough: the sidebar clips what does not fit,
and Docs and Support must stay visible */}
{isOpen && (
<img
src={mascot}
alt=""
className="mx-auto mb-4 hidden h-24 w-24 [@media(min-height:700px)]:block"
/>
)}
{/* Separator before Support/Docs */}
<div className="h-px bg-border w-full mb-6 opacity-50"></div>

Expand Down
4 changes: 4 additions & 0 deletions src/locales/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@
"trigger_event": "تشغيل الحدث",
"resources": "الموارد",
"no_resources": "لم يتم العثور على موارد",
"matching_resources": "الموارد المطابقة",
"matching_resources_count": "الموارد المطابقة: {{count}}",
"matching_resources_no_match": "لا توجد موارد مطابقة لهذه المرشحات.",
"matching_resources_error": "تعذّر تحميل الموارد المطابقة.",
"running": "جاري التشغيل",
"no_resource_selectors": "لم يتم تحديد محددات الموارد.",
"resource_selector": "محدد الموارد",
Expand Down
4 changes: 4 additions & 0 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@
"trigger_event": "Trigger Event",
"resources": "Resources",
"no_resources": "No resources found",
"matching_resources": "Matching resources",
"matching_resources_count": "Matching resources: {{count}}",
"matching_resources_no_match": "No matching resources for the filters.",
"matching_resources_error": "The matching resources could not be loaded.",
"running": "Running",
"no_resource_selectors": "No resource selectors defined.",
"resource_selector": "Resource Selector",
Expand Down
4 changes: 4 additions & 0 deletions src/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@
"trigger_event": "Déclencher l'événement",
"resources": "Ressources",
"no_resources": "Aucune ressource trouvée",
"matching_resources": "Ressources correspondantes",
"matching_resources_count": "Ressources correspondantes : {{count}}",
"matching_resources_no_match": "Aucune ressource correspondante pour ces filtres.",
"matching_resources_error": "Les ressources correspondantes n'ont pas pu être chargées.",
"running": "En cours",
"no_resource_selectors": "Aucun sélecteur de ressource défini.",
"resource_selector": "Sélecteur de ressource",
Expand Down
36 changes: 36 additions & 0 deletions src/modules/enterprise/EnterprisePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import {
CheckCircle2,
Zap,
CalendarDays,
HeartPulse,
Lock,
PackageCheck,
Compass,
} from "lucide-react";
import { Button } from "@/lib/components/ui/inputs/button";
import { Logo } from "@/lib/components/assets/logo/logo";
Expand Down Expand Up @@ -59,6 +63,22 @@ const FEATURES: Feature[] = [
tag: "Deployment",
href: "https://projectsveltos.io/latest/deployment_order/progressive_rollout/",
},
{
title: "Job-Based Health Validation",
description:
"Run a Kubernetes Job after a deployment, such as a smoke test or a connectivity probe, and use its outcome as the health check.",
icon: HeartPulse,
tag: "Health",
href: "https://projectsveltos.io/latest/addons/clusterprofile/#job-based-health-validation",
},
{
title: "Least-Privilege Agents",
description:
"Limit drift detection and the agents to specific namespaces instead of cluster-wide access. One annotation configures both.",
icon: Lock,
tag: "Security",
href: "https://projectsveltos.io/latest/features/configuration_drift/#namespace-scoped-watch-mode",
},
{
title: "AI-Powered Management",
description:
Expand All @@ -79,6 +99,22 @@ const FEATURES: Feature[] = [
tag: "Support",
href: "https://website.projectsveltos.io/pricing/",
},
{
title: "Priority Patches & Feature Delivery",
description:
"CVE-patched images before the next release, with your bug fixes and feature requests prioritized.",
icon: PackageCheck,
tag: "Support",
href: "https://website.projectsveltos.io/pricing/",
},
{
title: "Architectural Guidance",
description:
"Expert guidance on architecture and best practices for running Sveltos in production.",
icon: Compass,
tag: "Support",
href: "https://website.projectsveltos.io/pricing/",
},
];

const TRUST_ITEMS = [
Expand Down
48 changes: 27 additions & 21 deletions src/modules/events/event-details/components/ClusterMatchCard.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { useNavigate } from "react-router-dom";
import { ExternalLink } from "lucide-react";
import { Button } from "@/lib/components/ui/inputs/button";
import { ClusterEventMatch, Resource } from "@/types/event.types";
import { ClusterEventMatch } from "@/types/event.types";
import { Badge } from "@/lib/components/ui/data-display/badge";
import { FailedFlag } from "@/lib/components/ui/data-display/failed-flag";
import { ReadyFlag } from "@/lib/components/ui/data-display/ready-flag";
import { useTranslation } from "react-i18next";
import { McpButton } from "@/lib/components/ui/inputs/mcp-button";
import * as React from "react";
import { EventResourcesDialog } from "@/modules/events/event-details/components/EventResourcesDialog";
import { useEventClusterDebugMcp } from "@/modules/events/hooks/debugMcp";
import { typeFromPath } from "@/utils/GetPathFromType";
import { getClusterInfoType } from "@/utils/GetClusterInfoType";
Expand All @@ -21,6 +22,7 @@ export const ClusterMatchCard = ({
}) => {
const { t } = useTranslation();
const navigate = useNavigate();
const [resourcesOpen, setResourcesOpen] = React.useState(false);

const McpQuery = useEventClusterDebugMcp({
namespace: cluster.clusterNamespace,
Expand Down Expand Up @@ -59,27 +61,31 @@ export const ClusterMatchCard = ({
</Button>
</div>
<div className="flex-grow text-sm">
<div className="text-xs text-muted-foreground mb-1">
{t("common.resources")}
</div>
<div className="space-y-1">
{cluster.resources?.map((res: Resource, idx: number) => (
<div
key={idx}
className="bg-muted/30 p-1.5 rounded text-xs font-mono flex items-center justify-between"
{cluster.matchingResourcesCount > 0 ? (
<>
<Button
variant="outline"
size="sm"
onClick={() => setResourcesOpen(true)}
>
<span>
{res.kind}/{res.name}
</span>
<span className="text-muted-foreground">{res.namespace}</span>
</div>
))}
{(!cluster.resources || cluster.resources.length === 0) && (
<div className="text-muted-foreground italic text-xs">
{t("common.no_resources")}
</div>
)}
</div>
{t("common.matching_resources_count", {
count: cluster.matchingResourcesCount,
})}
</Button>
<EventResourcesDialog
open={resourcesOpen}
onOpenChange={setResourcesOpen}
eventName={eventName}
clusterNamespace={cluster.clusterNamespace}
clusterName={cluster.clusterName}
clusterType={typeFromPath(cluster.clusterKind)}
/>
</>
) : (
<div className="text-muted-foreground italic text-xs">
{t("common.no_resources")}
</div>
)}
</div>
<div className="flex items-center gap-2 mt-4">
<Badge variant="secondary" className="flex items-center gap-2">
Expand Down
Loading
Loading