From 4dbb7c7bb7218628bae71c70e719571fe54da0a7 Mon Sep 17 00:00:00 2001 From: "Hugo P.Brito" Date: Wed, 6 May 2026 09:34:20 +0100 Subject: [PATCH] fix(ui): restore View Resource action in findings drawer Reapplies the View Resource link that was inadvertently dropped while removing this PR's overlap with #10847. That feature is already on master and removing it here would have regressed the findings drawer. Restores buildResourceDetailHref, the resourceDetailHref binding, the JSX action below the resource actions menu, and the original positive assertion in the drawer test. --- .../resource-detail-drawer-content.test.tsx | 21 +++++++++++++--- .../resource-detail-drawer-content.tsx | 24 +++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/ui/components/findings/table/resource-detail-drawer/resource-detail-drawer-content.test.tsx b/ui/components/findings/table/resource-detail-drawer/resource-detail-drawer-content.test.tsx index 1b95b18748..663cabf732 100644 --- a/ui/components/findings/table/resource-detail-drawer/resource-detail-drawer-content.test.tsx +++ b/ui/components/findings/table/resource-detail-drawer/resource-detail-drawer-content.test.tsx @@ -408,7 +408,7 @@ const mockFinding: ResourceDrawerFinding = { }; describe("ResourceDetailDrawerContent — resource navigation", () => { - it("should not render resource navigation from the recommendation drawer", () => { + it("should render a View Resource link below the resource actions menu", () => { // Given render( { />, ); + // When + const viewResourceLink = screen.getByRole("link", { + name: "View Resource", + }); + const resourceActionsMenu = screen.getByRole("menu", { + name: "Resource actions", + }); + // Then + expect(viewResourceLink).toHaveAttribute( + "href", + "/resources?resourceId=res-1", + ); + expect(viewResourceLink).toHaveAttribute("target", "_blank"); + expect(viewResourceLink).toHaveAttribute("rel", "noopener noreferrer"); expect( - screen.queryByRole("link", { name: "View Resource" }), - ).not.toBeInTheDocument(); + resourceActionsMenu.compareDocumentPosition(viewResourceLink) & + Node.DOCUMENT_POSITION_FOLLOWING, + ).not.toBe(0); }); }); const mockResourceRow: FindingResourceRow = { diff --git a/ui/components/findings/table/resource-detail-drawer/resource-detail-drawer-content.tsx b/ui/components/findings/table/resource-detail-drawer/resource-detail-drawer-content.tsx index 94d071ad91..f9ab4fe130 100644 --- a/ui/components/findings/table/resource-detail-drawer/resource-detail-drawer-content.tsx +++ b/ui/components/findings/table/resource-detail-drawer/resource-detail-drawer-content.tsx @@ -304,6 +304,12 @@ function buildComplianceDetailHref({ return `/compliance/${encodeURIComponent(framework)}?${params.toString()}`; } +function buildResourceDetailHref(resourceId: string): string { + const params = new URLSearchParams(); + params.set("resourceId", resourceId); + return `/resources?${params.toString()}`; +} + interface ResourceDetailDrawerContentProps { isLoading: boolean; isNavigating: boolean; @@ -421,6 +427,9 @@ export function ResourceDetailDrawerContent({ const nativeIacConfig = resolveNativeIacConfig(providerType); const showOverviewCheckMetaContent = showCheckMetaContent; const showOverviewFindingContent = Boolean(f); + const resourceDetailHref = f?.resourceId + ? buildResourceDetailHref(f.resourceId) + : null; const findingRecommendationUrl = f?.remediation.recommendation.url; const checkRecommendationUrl = checkMeta.remediation.recommendation.url; const recommendationUrl = isNonEmptyString(findingRecommendationUrl) @@ -775,6 +784,21 @@ export function ResourceDetailDrawerContent({ )} + + {resourceDetailHref && ( +
+ +
+ )} )}