diff --git a/src/app/(loading-group)/[organizationSlug]/projects/[projectSlug]/overview/page.tsx b/src/app/(loading-group)/[organizationSlug]/projects/[projectSlug]/overview/page.tsx
index cb133f6d..2b2649d8 100644
--- a/src/app/(loading-group)/[organizationSlug]/projects/[projectSlug]/overview/page.tsx
+++ b/src/app/(loading-group)/[organizationSlug]/projects/[projectSlug]/overview/page.tsx
@@ -1,7 +1,8 @@
"use client";
+import { usePathname, useSearchParams } from "next/navigation";
import { groupBy, shuffle } from "lodash";
-import { useRouter, useSearchParams } from "next/navigation";
+import { useRouter } from "next/navigation";
import { useEffect, useMemo } from "react";
import useSWR from "swr";
import { QueryArtifactSelector } from "../../../../../../components/ArtifactSelector";
@@ -14,7 +15,7 @@ import CVERainbowBadge from "../../../../../../components/CVERainbowBadge";
import Page from "../../../../../../components/Page";
import { RiskHistoryDistributionDiagram } from "../../../../../../components/RiskHistoryDistributionDiagram";
import SeverityCard from "../../../../../../components/SeverityCard";
-import { Button } from "../../../../../../components/ui/button";
+import { AsyncButton, Button } from "../../../../../../components/ui/button";
import {
Card,
CardContent,
@@ -54,6 +55,11 @@ import {
} from "../../../../../../utils/view";
import useRouterQuery from "../../../../../../hooks/useRouterQuery";
import Link from "next/link";
+import { toast } from "sonner";
+import { useActiveProject } from "@/hooks/useActiveProject";
+import { useActiveAsset } from "@/hooks/useActiveAsset";
+import { useActiveAssetVersion } from "@/hooks/useActiveAssetVersion";
+import { browserApiClient } from "../../../../../../services/devGuardApi";
const OverviewPage = () => {
const search = useSearchParams();
@@ -185,6 +191,8 @@ const OverviewPage = () => {
const [mode, setMode] = useViewMode("devguard-view-mode");
const activeOrg = useActiveOrg();
const projectMenu = useProjectMenu();
+ const asset = useActiveAsset();
+ const assetVersion = useActiveAssetVersion();
const router = useRouter();
const contentTree = useOrganization().contentTree;
@@ -258,6 +266,35 @@ const OverviewPage = () => {
return latestRiskHistory.sort(sorter).slice(0, 7);
}, [completeRiskHistory, mode]);
+ const selectedArtifact = useSearchParams()?.get("artifact") || undefined;
+ const pathname = usePathname();
+
+ const downloadSBOMReport = async () => {
+ try {
+ const response = await browserApiClient(
+ `/organizations/${organizationSlug}/projects/${projectSlug}/releases/${releaseId}/sbom.json/`,
+ { method: "GET", signal: AbortSignal.timeout(60 * 8 * 1000) },
+ );
+ if (!response.ok) {
+ toast.error(
+ "Failed to download SBOM report. Please try again later.",
+ );
+ return;
+ }
+ const blob = await response.blob();
+ const url = window.URL.createObjectURL(blob);
+ const link = document.createElement("a");
+ link.href = url;
+ // add download attribute to the link
+ link.download = `${releaseId}.json`;
+ document.body.appendChild(link);
+ link.click();
+ document.body.removeChild(link);
+ } catch (error) {
+ toast.error("Failed to download SBOM. Please try again later.");
+ }
+ };
+
if (releases?.data.length === 0) {
return (