;
+}) {
+ const resolvedSearchParams = await searchParams;
+
+ return (
+
+
+ }
+ >
+
+
+
+
+ );
+}
+
+const SSRCheckFindings = async ({
+ searchParams,
+}: {
+ searchParams: SearchParamsProps | undefined | null;
+}) => {
+ const filters = pickFilterParams(searchParams);
+
+ const findingsByStatus = await getFindingsByStatus({ filters });
+
+ if (!findingsByStatus) {
+ return (
+
+
Failed to load findings data
+
+ );
+ }
+
+ const {
+ fail = 0,
+ pass = 0,
+ muted_new = 0,
+ muted_changed = 0,
+ fail_new = 0,
+ pass_new = 0,
+ } = findingsByStatus?.data?.attributes || {};
+
+ const mutedTotal = muted_new + muted_changed;
+
+ return (
+
+ );
+};
diff --git a/ui/components/graphs/donut-chart.tsx b/ui/components/graphs/donut-chart.tsx
index ea5ff49e5f..b82387944f 100644
--- a/ui/components/graphs/donut-chart.tsx
+++ b/ui/components/graphs/donut-chart.tsx
@@ -21,44 +21,39 @@ interface DonutChartProps {
}
const CustomTooltip = ({ active, payload }: any) => {
- if (active && payload && payload.length) {
- const data = payload[0].payload;
- return (
-
-
-
-
- {data.percentage}% {data.name}
-
-
- {data.change !== undefined && (
-
-
- {data.change > 0 ? "+" : ""}
- {data.change}%
- {" "}
- Since last scan
-
- )}
+ if (!active || !payload || !payload.length) return null;
+
+ const entry = payload[0];
+ const name = entry.name;
+ const percentage = entry.payload?.percentage;
+ const color = entry.color || entry.payload?.color;
+ const change = entry.payload?.change;
+
+ return (
+
+
+
+
+ {percentage}%
+
+
{name}
- );
- }
- return null;
+
+ {change !== undefined && (
+ <>
+
+ {change > 0 ? "+" : ""}
+ {change}%
+
+ Since Last Scan
+ >
+ )}
+
+
+ );
};
const CustomLegend = ({ payload }: any) => {
@@ -72,8 +67,8 @@ const CustomLegend = ({ payload }: any) => {
export function DonutChart({
data,
- innerRadius = 80,
- outerRadius = 120,
+ innerRadius = 68,
+ outerRadius = 86,
showLegend = true,
centerLabel,
}: DonutChartProps) {
@@ -108,7 +103,7 @@ export function DonutChart({
}));
return (
-
+ <>
{chartData.map((entry, index) => {
const opacity =
@@ -157,9 +152,9 @@ export function DonutChart({
{formattedValue}
@@ -167,8 +162,9 @@ export function DonutChart({
{centerLabel.label}
@@ -183,6 +179,6 @@ export function DonutChart({
{showLegend && }
-
+ >
);
}
diff --git a/ui/components/graphs/shared/chart-tooltip.tsx b/ui/components/graphs/shared/chart-tooltip.tsx
index 432a15713d..558da987fe 100644
--- a/ui/components/graphs/shared/chart-tooltip.tsx
+++ b/ui/components/graphs/shared/chart-tooltip.tsx
@@ -29,7 +29,7 @@ export function ChartTooltip({
return (
)}
-
+
{label || data.name}
-
+
{typeof data.value === "number"
? data.value.toLocaleString()
: data.value}
@@ -62,11 +59,8 @@ export function ChartTooltip({
{data.newFindings !== undefined && data.newFindings > 0 && (
-
-
+
+
{data.newFindings} New Findings
@@ -74,11 +68,8 @@ export function ChartTooltip({
{data.new !== undefined && data.new > 0 && (
-
-
+
+
{data.new} New
@@ -86,21 +77,15 @@ export function ChartTooltip({
{data.muted !== undefined && data.muted > 0 && (
-
-
+
+
{data.muted} Muted
)}
{data.change !== undefined && (
-
+
{data.change > 0 ? "+" : ""}
{data.change}%
@@ -125,17 +110,8 @@ export function MultiSeriesChartTooltip({
}
return (
-
-
+
+
{label}
@@ -145,20 +121,14 @@ export function MultiSeriesChartTooltip({
className="h-2 w-2 rounded-full"
style={{ backgroundColor: entry.color }}
/>
-
+
{entry.name}:
-
+
{entry.value}
{entry.payload[`${entry.dataKey}_change`] && (
-
+
({entry.payload[`${entry.dataKey}_change`] > 0 ? "+" : ""}
{entry.payload[`${entry.dataKey}_change`]}%)
diff --git a/ui/components/primitives.ts b/ui/components/primitives.ts
deleted file mode 100644
index 04b1f22594..0000000000
--- a/ui/components/primitives.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-import { tv } from "tailwind-variants";
-
-export const title = tv({
- base: "tracking-tight inline font-semibold",
- variants: {
- color: {
- violet: "from-[#FF1CF7] to-[#b249f8]",
- yellow: "from-[#FF705B] to-[#FFB457]",
- blue: "from-[#5EA2EF] to-[#0072F5]",
- cyan: "from-[#00b7fa] to-[#01cfea]",
- green: "from-[#6FEE8D] to-[#17c964]",
- pink: "from-[#FF72E1] to-[#F54C7A]",
- foreground: "dark:from-[#FFFFFF] dark:to-[#4B4B4B]",
- },
- size: {
- sm: "text-3xl lg:text-4xl",
- md: "text-[2.3rem] lg:text-5xl leading-9",
- lg: "text-4xl lg:text-6xl",
- },
- fullWidth: {
- true: "w-full block",
- },
- },
- defaultVariants: {
- size: "md",
- },
- compoundVariants: [
- {
- color: [
- "violet",
- "yellow",
- "blue",
- "cyan",
- "green",
- "pink",
- "foreground",
- ],
- class: "bg-clip-text text-transparent bg-linear-to-b",
- },
- ],
-});
-
-export const subtitle = tv({
- base: "w-full md:w-1/2 my-2 text-lg lg:text-xl text-default-600 block max-w-full",
- variants: {
- fullWidth: {
- true: "w-full!",
- },
- },
- defaultVariants: {
- fullWidth: true,
- },
-});
diff --git a/ui/components/shadcn/README.md b/ui/components/shadcn/README.md
index 1bd28c8883..af3bc0348d 100644
--- a/ui/components/shadcn/README.md
+++ b/ui/components/shadcn/README.md
@@ -4,13 +4,18 @@ This directory contains all shadcn/ui based components for the Prowler applicati
## Directory Structure
+Example of a custom component:
+
```
shadcn/
-├── card.tsx # shadcn Card component
-├── resource-stats-card/ # Custom ResourceStatsCard built on shadcn
-│ ├── resource-stats-card.tsx
-│ ├── resource-stats-card.example.tsx
-│ └── index.ts
+├── card/
+│ ├── base-card/
+│ │ ├── base-card.tsx
+│ ├── card/
+│ │ ├── card.tsx
+│ └── resource-stats-card/
+│ ├── resource-stats-card.tsx
+│ ├── resource-stats-card.example.tsx
├── index.ts # Barrel exports
└── README.md
```
diff --git a/ui/components/shadcn/card/base-card/base-card.tsx b/ui/components/shadcn/card/base-card/base-card.tsx
new file mode 100644
index 0000000000..946e0cc184
--- /dev/null
+++ b/ui/components/shadcn/card/base-card/base-card.tsx
@@ -0,0 +1,36 @@
+import { cva, type VariantProps } from "class-variance-authority";
+
+import { cn } from "@/lib/utils";
+
+import { Card } from "../card";
+
+const baseCardVariants = cva("", {
+ variants: {
+ variant: {
+ default:
+ "border-slate-200 bg-white dark:border-zinc-900 dark:bg-stone-950",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ },
+});
+
+interface BaseCardProps
+ extends React.ComponentProps,
+ VariantProps {}
+
+const BaseCard = ({ className, variant, ...props }: BaseCardProps) => {
+ return (
+
+ );
+};
+
+export { BaseCard };
diff --git a/ui/components/shadcn/card.tsx b/ui/components/shadcn/card/card.tsx
similarity index 89%
rename from ui/components/shadcn/card.tsx
rename to ui/components/shadcn/card/card.tsx
index a1b4a7742d..4165221253 100644
--- a/ui/components/shadcn/card.tsx
+++ b/ui/components/shadcn/card/card.tsx
@@ -1,5 +1,3 @@
-import * as React from "react";
-
import { cn } from "@/lib/utils";
function Card({ className, ...props }: React.ComponentProps<"div">) {
@@ -20,7 +18,7 @@ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
) {
return (
);
diff --git a/ui/components/shadcn/resource-stats-card/resource-stats-card-container.tsx b/ui/components/shadcn/card/resource-stats-card/resource-stats-card-container.tsx
similarity index 100%
rename from ui/components/shadcn/resource-stats-card/resource-stats-card-container.tsx
rename to ui/components/shadcn/card/resource-stats-card/resource-stats-card-container.tsx
diff --git a/ui/components/shadcn/resource-stats-card/resource-stats-card-content.tsx b/ui/components/shadcn/card/resource-stats-card/resource-stats-card-content.tsx
similarity index 89%
rename from ui/components/shadcn/resource-stats-card/resource-stats-card-content.tsx
rename to ui/components/shadcn/card/resource-stats-card/resource-stats-card-content.tsx
index d165eb7944..7f7c0358d9 100644
--- a/ui/components/shadcn/resource-stats-card/resource-stats-card-content.tsx
+++ b/ui/components/shadcn/card/resource-stats-card/resource-stats-card-content.tsx
@@ -33,11 +33,11 @@ const badgeVariants = cva(
{
variants: {
variant: {
- [CardVariant.default]: "bg-[#535359]",
- [CardVariant.fail]: "bg-[#432232]",
- [CardVariant.pass]: "bg-[#204237]",
- [CardVariant.warning]: "bg-[#3d3520]",
- [CardVariant.info]: "bg-[#1e3a5f]",
+ [CardVariant.default]: "bg-slate-100 dark:bg-[#535359]",
+ [CardVariant.fail]: "bg-red-100 dark:bg-[#432232]",
+ [CardVariant.pass]: "bg-green-100 dark:bg-[#204237]",
+ [CardVariant.warning]: "bg-amber-100 dark:bg-[#3d3520]",
+ [CardVariant.info]: "bg-blue-100 dark:bg-[#1e3a5f]",
},
size: {
sm: "px-1 text-xs",
@@ -66,7 +66,7 @@ const badgeIconVariants = cva("", {
});
const labelTextVariants = cva(
- "leading-6 font-semibold text-zinc-300 dark:text-zinc-300",
+ "leading-6 font-semibold text-slate-900 dark:text-zinc-300 whitespace-nowrap",
{
variants: {
size: {
@@ -81,7 +81,7 @@ const labelTextVariants = cva(
},
);
-const statIconVariants = cva("text-zinc-300 dark:text-zinc-300", {
+const statIconVariants = cva("text-slate-600 dark:text-zinc-300", {
variants: {
size: {
sm: "h-2.5 w-2.5",
@@ -95,7 +95,7 @@ const statIconVariants = cva("text-zinc-300 dark:text-zinc-300", {
});
const statLabelVariants = cva(
- "leading-5 font-medium text-zinc-300 dark:text-zinc-300",
+ "leading-5 font-medium text-slate-700 dark:text-zinc-300",
{
variants: {
size: {
diff --git a/ui/components/shadcn/resource-stats-card/resource-stats-card-divider.tsx b/ui/components/shadcn/card/resource-stats-card/resource-stats-card-divider.tsx
similarity index 100%
rename from ui/components/shadcn/resource-stats-card/resource-stats-card-divider.tsx
rename to ui/components/shadcn/card/resource-stats-card/resource-stats-card-divider.tsx
diff --git a/ui/components/shadcn/resource-stats-card/resource-stats-card-header.tsx b/ui/components/shadcn/card/resource-stats-card/resource-stats-card-header.tsx
similarity index 100%
rename from ui/components/shadcn/resource-stats-card/resource-stats-card-header.tsx
rename to ui/components/shadcn/card/resource-stats-card/resource-stats-card-header.tsx
diff --git a/ui/components/shadcn/resource-stats-card/resource-stats-card.tsx b/ui/components/shadcn/card/resource-stats-card/resource-stats-card.tsx
similarity index 98%
rename from ui/components/shadcn/resource-stats-card/resource-stats-card.tsx
rename to ui/components/shadcn/card/resource-stats-card/resource-stats-card.tsx
index 7acbd103e3..4a1520d44d 100644
--- a/ui/components/shadcn/resource-stats-card/resource-stats-card.tsx
+++ b/ui/components/shadcn/card/resource-stats-card/resource-stats-card.tsx
@@ -111,7 +111,7 @@ export const ResourceStatsCard = ({
{header &&
}
{emptyState ? (
@@ -141,7 +141,7 @@ export const ResourceStatsCard = ({
{header &&
}
{emptyState ? (
diff --git a/ui/components/shadcn/card/stats-container.tsx b/ui/components/shadcn/card/stats-container.tsx
new file mode 100644
index 0000000000..9d37a60897
--- /dev/null
+++ b/ui/components/shadcn/card/stats-container.tsx
@@ -0,0 +1,25 @@
+import { cn } from "@/lib/utils";
+
+interface StatsContainerProps extends React.HTMLAttributes
{
+ children: React.ReactNode;
+}
+
+const StatsContainer = ({
+ className,
+ children,
+ ...props
+}: StatsContainerProps) => {
+ return (
+
+ {children}
+
+ );
+};
+
+export { StatsContainer };
diff --git a/ui/components/shadcn/index.ts b/ui/components/shadcn/index.ts
index 4291e07d5a..d29dc6f1dc 100644
--- a/ui/components/shadcn/index.ts
+++ b/ui/components/shadcn/index.ts
@@ -1,21 +1,8 @@
-export {
- Card,
- CardContent,
- CardDescription,
- CardFooter,
- CardHeader,
- CardTitle,
-} from "./card";
-export {
- ResourceStatsCard,
- ResourceStatsCardContainer,
- type ResourceStatsCardContainerProps,
- ResourceStatsCardContent,
- type ResourceStatsCardContentProps,
- ResourceStatsCardDivider,
- type ResourceStatsCardDividerProps,
- ResourceStatsCardHeader,
- type ResourceStatsCardHeaderProps,
- type ResourceStatsCardProps,
- type StatItem,
-} from "./resource-stats-card";
+export * from "./card/base-card/base-card";
+export * from "./card/card";
+export * from "./card/resource-stats-card/resource-stats-card";
+export * from "./card/resource-stats-card/resource-stats-card-container";
+export * from "./card/resource-stats-card/resource-stats-card-content";
+export * from "./card/resource-stats-card/resource-stats-card-divider";
+export * from "./card/resource-stats-card/resource-stats-card-header";
+export * from "./card/stats-container";
diff --git a/ui/components/shadcn/resource-stats-card/index.ts b/ui/components/shadcn/resource-stats-card/index.ts
deleted file mode 100644
index c049987ae0..0000000000
--- a/ui/components/shadcn/resource-stats-card/index.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-export type { ResourceStatsCardProps } from "./resource-stats-card";
-export { ResourceStatsCard } from "./resource-stats-card";
-export type { ResourceStatsCardContainerProps } from "./resource-stats-card-container";
-export { ResourceStatsCardContainer } from "./resource-stats-card-container";
-export type {
- ResourceStatsCardContentProps,
- StatItem,
-} from "./resource-stats-card-content";
-export { ResourceStatsCardContent } from "./resource-stats-card-content";
-export type { ResourceStatsCardDividerProps } from "./resource-stats-card-divider";
-export { ResourceStatsCardDivider } from "./resource-stats-card-divider";
-export type { ResourceStatsCardHeaderProps } from "./resource-stats-card-header";
-export { ResourceStatsCardHeader } from "./resource-stats-card-header";
diff --git a/ui/components/ui/chart/Chart.tsx b/ui/components/ui/chart/Chart.tsx
index fec25668b6..014fbc009d 100644
--- a/ui/components/ui/chart/Chart.tsx
+++ b/ui/components/ui/chart/Chart.tsx
@@ -70,6 +70,7 @@ const ChartContainer = React.forwardRef<
);
});
+
ChartContainer.displayName = "Chart";
const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
@@ -184,7 +185,7 @@ const ChartTooltipContent = React.forwardRef<
diff --git a/ui/components/ui/custom/custom-button.tsx b/ui/components/ui/custom/custom-button.tsx
index 19d50ba686..8f71aabf24 100644
--- a/ui/components/ui/custom/custom-button.tsx
+++ b/ui/components/ui/custom/custom-button.tsx
@@ -86,7 +86,7 @@ export const CustomButton = React.forwardRef<
) => (