feat(ui): expand finding groups from deep links

This commit is contained in:
Hugo P.Brito committed 2026-07-16 09:56:29 +01:00
1 parent fea4ce2048
commit 999a8d1428
3 files changed
+122 -1

No files matched your search

+5
View File
@@ -145,6 +145,10 @@ const SSRDataTable = async ({
}) => {
const page = parseInt(searchParams.page?.toString() || "1", 10);
const pageSize = parseInt(searchParams.pageSize?.toString() || "10", 10);
const expandedCheckIdParam = searchParams.expandedCheckId;
const expandedCheckId = Array.isArray(expandedCheckIdParam)
? expandedCheckIdParam[0]
: expandedCheckIdParam;
const { encodedSort } = extractSortAndKey(searchParams);
const hasHistoricalData = hasDateOrScanFilter(filters);
@@ -178,6 +182,7 @@ const SSRDataTable = async ({
metadata={findingGroupsData?.meta}
resolvedFilters={filters}
hasHistoricalData={hasHistoricalData}
expandedCheckId={expandedCheckId}
/>
</>
);
@@ -318,6 +318,97 @@ describe("FindingsGroupTable", () => {
});
});
describe("expanded deep link", () => {
it("opens the matching drillable group from expandedCheckId", () => {
// Given
const data = [
{ checkId: "check-a", resourcesTotal: 1 },
{ checkId: "check-b", resourcesTotal: 1 },
] as unknown as Parameters<typeof FindingsGroupTable>[0]["data"];
render(
<FindingsGroupTable
data={data}
resolvedFilters={{}}
hasHistoricalData={false}
expandedCheckId="check-b"
/>,
);
// Then
expect(
screen.getByRole("button", { name: "Select finding-1" }),
).toBeInTheDocument();
});
it("ignores a missing expandedCheckId", () => {
// Given
const data = [
{ checkId: "check-a", resourcesTotal: 1 },
] as unknown as Parameters<typeof FindingsGroupTable>[0]["data"];
render(
<FindingsGroupTable
data={data}
resolvedFilters={{}}
hasHistoricalData={false}
expandedCheckId="check-missing"
/>,
);
// Then
expect(
screen.queryByRole("button", { name: "Select finding-1" }),
).not.toBeInTheDocument();
});
it("ignores a non-drillable expandedCheckId", () => {
// Given
const data = [
{ checkId: "check-a", resourcesTotal: 0 },
] as unknown as Parameters<typeof FindingsGroupTable>[0]["data"];
render(
<FindingsGroupTable
data={data}
resolvedFilters={{}}
hasHistoricalData={false}
expandedCheckId="check-a"
/>,
);
// Then
expect(
screen.queryByRole("button", { name: "Select finding-1" }),
).not.toBeInTheDocument();
});
it("allows manual collapse after opening from expandedCheckId", async () => {
// Given
const user = userEvent.setup();
const data = [
{ checkId: "check-a", resourcesTotal: 1 },
] as unknown as Parameters<typeof FindingsGroupTable>[0]["data"];
render(
<FindingsGroupTable
data={data}
resolvedFilters={{}}
hasHistoricalData={false}
expandedCheckId="check-a"
/>,
);
// When
await user.click(screen.getByRole("button", { name: "Expand check-a" }));
// Then
expect(
screen.queryByRole("button", { name: "Select finding-1" }),
).not.toBeInTheDocument();
});
});
describe("bulk Jira action", () => {
it("should summarize group-only selections", async () => {
// Given
@@ -2,7 +2,7 @@
import { Row, RowSelectionState } from "@tanstack/react-table";
import { useRouter, useSearchParams } from "next/navigation";
import { Suspense, useRef, useState } from "react";
import { Suspense, useEffect, useRef, useState } from "react";
import { resolveFindingIdsByVisibleGroupResources } from "@/actions/findings/findings-by-resource";
import { CustomCheckboxMutedFindings } from "@/components/filters/custom-checkbox-muted-findings";
@@ -78,6 +78,7 @@ interface FindingsGroupTableProps {
metadata?: MetaDataProps;
resolvedFilters: Record<string, string>;
hasHistoricalData: boolean;
expandedCheckId?: string;
}
export function FindingsGroupTable({
@@ -85,6 +86,7 @@ export function FindingsGroupTable({
metadata,
resolvedFilters,
hasHistoricalData,
expandedCheckId: requestedExpandedCheckId,
}: FindingsGroupTableProps) {
const router = useRouter();
const searchParams = useSearchParams();
@@ -105,6 +107,29 @@ export function FindingsGroupTable({
const filters = resolvedFilters;
const groupedJiraDispatchEnabled = isGroupedJiraDispatchEnabled();
useEffect(() => {
if (!requestedExpandedCheckId) return;
const requestedGroup = safeData.find(
(group) => group.checkId === requestedExpandedCheckId,
);
if (!requestedGroup || !canDrillDownFindingGroup(requestedGroup)) {
setExpandedCheckId(null);
setExpandedGroup(null);
setResourceSearchInput("");
setResourceSearch("");
setResourceSelection([]);
return;
}
setExpandedCheckId(requestedExpandedCheckId);
setExpandedGroup(requestedGroup);
setResourceSearchInput("");
setResourceSearch("");
setResourceSelection([]);
}, [requestedExpandedCheckId, safeData]);
// Exclude expanded group from group-level mutes when it has resource selections.
const selectedCheckIds = Object.keys(rowSelection)
.filter((key) => rowSelection[key])