Skip to content

Commit

Permalink
Merge branch 'main' of github.com:l3montree-dev/devguard-web
Browse files Browse the repository at this point in the history
  • Loading branch information
timbastin committed Oct 29, 2024
2 parents c1d52ef + 070f20c commit ae20e70
Show file tree
Hide file tree
Showing 10 changed files with 190 additions and 131 deletions.
69 changes: 31 additions & 38 deletions src/components/overview/RiskDistributionDiagram.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,52 +24,45 @@ import {
ChartTooltipContent,
} from "@/components/ui/chart";
import { RiskDistribution } from "@/types/api/api";
import { beautifyScannerId } from "@/utils/common";
import { uniq } from "lodash";
import { generateColor } from "@/utils/view";

// { range: "0-2", scanner1: 186, scanner2: 80 },
const combineRanges = (data: RiskDistribution[]) => {
const uniqueRanges = ["LOW", "MEDIUM", "HIGH", "CRITICAL"];
const scanner = uniq(data.map((item) => item.scannerId));
return uniqueRanges.map((range) => {
const rangeData = data.filter((item) => item.severity === range);
const rangeDataScanner = scanner.map((scannerId) => {
const scannerData = rangeData.find(
(item) => item.scannerId === scannerId,
);
return {
scannerId,
count: scannerData ? scannerData.count : 0,
};
});
const low = data
.map((el) => ({ [el.id]: el.low }))
.reduce((acc, el) => ({ ...acc, ...el }), { range: "LOW" });

return rangeDataScanner.reduce((acc, item) => {
return {
...acc,
range,
[item.scannerId]: item.count,
};
}, {});
});
const medium = data
.map((el) => ({ [el.id]: el.medium }))
.reduce((acc, el) => ({ ...acc, ...el }), { range: "MEDIUM" });

const high = data
.map((el) => ({ [el.id]: el.high }))
.reduce((acc, el) => ({ ...acc, ...el }), { range: "HIGH" });

const critical = data
.map((el) => ({ [el.id]: el.critical }))
.reduce((acc, el) => ({ ...acc, ...el }), { range: "CRITICAL" });

return [{ ...low }, medium, high, critical];
};

export function RiskDistributionDiagram({
data,
}: {
data: RiskDistribution[];
}) {
const chartConfig = uniq(data.map((item) => item.scannerId))
.sort()
.reduce(
(acc, scannerId, i) => ({
...acc,
[scannerId]: {
label: beautifyScannerId(scannerId),
color: `hsl(var(--chart-${i + 1}))`,
},
}),
{} as any,
);
const chartConfig = data.reduce(
(acc, el, i) => ({
...acc,
[el.id]: {
label: el.label,
color: generateColor(el.label),
},
}),
{} as any,
);

const chartData = combineRanges(data);

Expand Down Expand Up @@ -105,12 +98,12 @@ export function RiskDistributionDiagram({
content={<ChartTooltipContent className="bg-background" />}
/>
<ChartLegend content={<ChartLegendContent />} />
{Object.keys(chartConfig).map((scannerId, i, arr) => (
{Object.keys(chartConfig).map((id, i, arr) => (
<Bar
key={scannerId}
dataKey={scannerId}
key={id}
dataKey={id}
radius={4}
fill={chartConfig[scannerId].color}
fill={chartConfig[id].color}
/>
))}
</BarChart>
Expand Down
9 changes: 5 additions & 4 deletions src/components/overview/RiskHistoryDiagram.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
ChartTooltipContent,
} from "@/components/ui/chart";
import { RiskHistory } from "@/types/api/api";
import { generateColor } from "@/utils/view";
import { useMemo } from "react";
import {
Area,
Expand Down Expand Up @@ -69,7 +70,7 @@ export function RiskHistoryChart({
...acc,
[d.label]: {
label: d.label,
color: "hsl(var(--chart-" + i + "))",
color: generateColor(d.label),
},
}),
{},
Expand Down Expand Up @@ -117,12 +118,12 @@ export function RiskHistoryChart({
>
<stop
offset="5%"
stopColor={"hsl(var(--chart-" + (i + 1) + "))"}
stopColor={generateColor(d.label)}
stopOpacity={0.8}
/>
<stop
offset="95%"
stopColor={"hsl(var(--chart-" + (i + 1) + "))"}
stopColor={generateColor(d.label)}
stopOpacity={0.1}
/>
</linearGradient>
Expand All @@ -133,7 +134,7 @@ export function RiskHistoryChart({
key={d.label}
dataKey={d.label}
type="monotone"
stroke={"hsl(var(--chart-" + (i + 1) + "))"}
stroke={generateColor(d.label)}
strokeWidth={2}
fill={"url(#fill-" + (i + 1) + ")"}
fillOpacity={0.4}
Expand Down
16 changes: 9 additions & 7 deletions src/components/overview/VulnerableComponents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
import { ComponentRisk } from "@/types/api/api";
import { beautifyPurl, classNames, extractVersion } from "@/utils/common";
import EcosystemImage from "../common/EcosystemImage";
import { Badge } from "../ui/badge";

export interface ChartConfig {
[key: string]: {
Expand All @@ -35,16 +36,19 @@ export function VulnerableComponents({ data }: { data: ComponentRisk }) {
</CardDescription>
</CardHeader>
<CardContent>
<div className="flex flex-col gap-6">
<div className="flex flex-col gap-2">
{d.slice(0, 5).map((item, index) => (
<div
key={item.componentName}
className={classNames("flex items-center gap-4")}
className={classNames(
"flex items-center gap-2",
"-mx-2 rounded-lg px-2 py-2 !text-card-foreground transition-all",
)}
>
<div className="rounded-full bg-muted p-2">
<div className="rounded-full p-2">
<EcosystemImage size={20} packageName={item.componentName} />
</div>
<div className="grid gap-1">
<div className="grid">
<p className="text-sm font-medium leading-none">
{beautifyPurl(item.componentName)}
</p>
Expand All @@ -53,9 +57,7 @@ export function VulnerableComponents({ data }: { data: ComponentRisk }) {
</p>
</div>
<div className="ml-auto font-medium">
{" "}
{item.risk.toFixed(2)}{" "}
<small className="text-muted-foreground">Risk</small>
<Badge variant={"secondary"}>{item.risk.toFixed(2)} Risk</Badge>
</div>
</div>
))}
Expand Down
2 changes: 1 addition & 1 deletion src/components/ui/avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const AvatarFallback = React.forwardRef<
<AvatarPrimitive.Fallback
ref={ref}
className={cn(
"flex h-full w-full items-center justify-center rounded-full bg-muted",
"flex h-full w-full items-center justify-center rounded-full bg-secondary text-secondary-foreground",
className,
)}
{...props}
Expand Down
96 changes: 56 additions & 40 deletions src/pages/[organizationSlug]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,22 @@ import { FunctionComponent } from "react";
import Page from "../../components/Page";
import { withOrgs } from "../../decorators/withOrgs";
import { withSession } from "../../decorators/withSession";
import { useActiveOrg } from "../../hooks/useActiveOrg";

import { useOrganizationMenu } from "@/hooks/useOrganizationMenu";
import Link from "next/link";
import AverageFixingTimeChart from "@/components/overview/AverageFixingTimeChart";
import FlawAggregationState from "@/components/overview/FlawAggregationState";
import { RiskDistributionDiagram } from "@/components/overview/RiskDistributionDiagram";
import { RiskHistoryChart } from "@/components/overview/RiskHistoryDiagram";
import { Badge } from "@/components/ui/badge";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { withOrganization } from "@/decorators/withOrganization";
import { useOrganizationMenu } from "@/hooks/useOrganizationMenu";
import { getApiClientFromContext } from "@/services/devGuardApi";
import {
AssetDTO,
AverageFixingTime,
Expand All @@ -36,21 +46,9 @@ import {
RiskDistribution,
RiskHistory,
} from "@/types/api/api";
import { Project } from "@/types/common";
import AverageFixingTimeChart from "@/components/overview/AverageFixingTimeChart";
import FlawAggregationState from "@/components/overview/FlawAggregationState";
import { RiskDistributionDiagram } from "@/components/overview/RiskDistributionDiagram";
import { RiskHistoryChart } from "@/components/overview/RiskHistoryDiagram";
import {
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
} from "@/components/ui/card";
import { classNames, beautifyPurl } from "@/utils/common";
import { Avatar, AvatarFallback } from "@radix-ui/react-avatar";
import { getApiClientFromContext } from "@/services/devGuardApi";
import { classNames } from "@/utils/common";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import Link from "next/link";

interface Props {
organization: OrganizationDTO & {
Expand All @@ -61,7 +59,12 @@ interface Props {
>;
};
riskDistribution: RiskDistribution[] | null;
riskHistory: Array<{ history: RiskHistory[]; label: string }>;
riskHistory: Array<{
history: RiskHistory[];
label: string;
slug: string;
description: string;
}>;
flawCountByScanner: FlawCountByScanner;
dependencyCountByScanType: DependencyCountByScanType;
flawAggregationStateAndChange: FlawAggregationStateAndChange;
Expand Down Expand Up @@ -129,32 +132,43 @@ const Home: FunctionComponent<Props> = ({
</CardDescription>
</CardHeader>
<CardContent>
<div className="flex flex-col gap-6">
<div className="flex flex-col gap-2">
{riskHistory.slice(0, 5).map((r) => (
<div
key={r.label}
className={classNames("flex items-center gap-4")}
<Link
href={organization.slug + "/projects/" + r.slug}
key={r.slug}
className="-mx-2 rounded-lg px-2 py-2 !text-card-foreground transition-all hover:bg-background hover:no-underline"
>
<div className="rounded-full bg-muted p-1">
<div
key={r.label}
className={classNames("flex items-center gap-4")}
>
<Avatar>
<AvatarFallback className="flex h-8 w-8 flex-row items-center justify-center">
{r.label[0]}
</AvatarFallback>
<AvatarFallback>{r.label[0]}</AvatarFallback>
</Avatar>

<div className="grid ">
<p className="text-sm font-medium leading-none">
{r.label}
</p>
<small className="line-clamp-1 text-ellipsis text-muted-foreground">
{r.description}
</small>
</div>
<div className="ml-auto font-medium">
<Badge
className="whitespace-nowrap"
variant="secondary"
>
{" "}
{r.history[r.history.length - 1]?.sumOpenRisk.toFixed(
2,
) ?? "0.00"}{" "}
Risk
</Badge>
</div>
</div>
<div className="grid gap-1">
<p className="text-sm font-medium leading-none">
{r.label}
</p>
</div>
<div className="ml-auto font-medium">
{" "}
{r.history[r.history.length - 1]?.sumOpenRisk.toFixed(
2,
) ?? "0.00"}{" "}
<small className="text-muted-foreground">Risk</small>
</div>
</div>
</Link>
))}
</div>
<div className="flex items-center gap-4"></div>
Expand Down Expand Up @@ -315,6 +329,8 @@ export const getServerSideProps = middleware(
riskHistory: riskHistory.map((r) => ({
label: r.project.name,
history: r.riskHistory,
slug: r.project.slug,
description: r.project.description,
})),
flawAggregationStateAndChange,
avgLowFixingTime,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import AverageFixingTimeChart from "@/components/overview/AverageFixingTimeChart

interface Props {
componentRisk: ComponentRisk;
riskDistribution: RiskDistribution[] | null;
riskDistribution: RiskDistribution | null;
riskHistory: RiskHistory[];
flawCountByScanner: FlawCountByScanner;
dependencyCountByScanType: DependencyCountByScanType;
Expand Down Expand Up @@ -122,7 +122,9 @@ const Index: FunctionComponent<Props> = ({
/>
<div className="grid grid-cols-3 gap-4">
<div className="col-span-2">
<RiskDistributionDiagram data={riskDistribution ?? []} />
<RiskDistributionDiagram
data={riskDistribution ? [riskDistribution] : []}
/>
</div>
<VulnerableComponents data={componentRisk} />
</div>
Expand All @@ -149,7 +151,7 @@ const Index: FunctionComponent<Props> = ({
/>
</div>
<RiskHistoryChart
data={[{ label: "Total Risk", history: riskHistory }]}
data={[{ label: asset.name, history: riskHistory }]}
/>
{/* <div className="grid grid-cols-3 gap-4">
<div className="col-span-2"></div>
Expand Down
Loading

0 comments on commit ae20e70

Please sign in to comment.