Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export function TestDetails({ testId, users }: CloudTestDetailsProps) {
// Format the test provider for display
const providerLabel = cloudTest.provider === "aws"
? "Amazon Web Services"
: cloudTest.provider === "AZURE"
: cloudTest.provider === "azure"
? "Microsoft Azure"
: "Google Cloud Platform";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,17 @@ export const getTests = authActionClient
},
})
.action(async ({ parsedInput, ctx }) => {
const { search, provider, status, page = 1, per_page = 10 } = parsedInput;
const { search, severity, status, page = 1, pageSize = 10 } = parsedInput;
const { user } = ctx;

console.log("--------------------------------");
console.log("search", search);
console.log("severity", severity);
console.log("status", status);
console.log("page", page);
console.log("pageSize", pageSize);
console.log("--------------------------------");

if (!user.organizationId) {
return {
success: false,
Expand All @@ -25,7 +33,7 @@ export const getTests = authActionClient
}

try {
const skip = (page - 1) * per_page;
const skip = (page - 1) * pageSize;

// Use the prisma client with correct model
const [integrationResults, total] = await Promise.all([
Expand All @@ -50,12 +58,8 @@ export const getTests = authActionClient
},
],
} : {}),
...(provider ? {
organizationIntegration: {
integration_id: provider,
},
} : {}),
...(status ? { label: status } : {}),
...(status ? { status: { equals: status, mode: "insensitive" } } : {}),
...(severity ? { label: { equals: severity, mode: "insensitive" } } : {}),
},
include: {
organizationIntegration: {
Expand All @@ -75,7 +79,7 @@ export const getTests = authActionClient
},
},
skip,
take: per_page,
take: pageSize,
orderBy: { completedAt: "desc" },
}),
db.organizationIntegrationResults.count({
Expand All @@ -99,12 +103,8 @@ export const getTests = authActionClient
},
],
} : {}),
...(provider ? {
organizationIntegration: {
integration_id: provider,
},
} : {}),
...(status ? { label: status } : {}),
...(status ? { status: { equals: status, mode: "insensitive" } } : {}),
...(severity ? { label: { equals: severity, mode: "insensitive" } } : {}),
},
}),
]);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,76 +1,43 @@
"use client";

import { DataTable } from "@/components/tables/tests/data-table";
import {
NoResults,
NoTests,
} from "@/components/tables/tests/empty-states";
import { FilterToolbar } from "@/components/tables/tests/filter-toolbar";
import { Loading } from "@/components/tables/tests/loading";
import { NoTests } from "./table/empty-states";
import { Loading } from "./table/loading";
import { useTests } from "../hooks/useTests";
import { useSearchParams } from "next/navigation";
import type { TestType } from "@/components/tables/tests/columns";
import { TestsListSkeleton } from "./TestsListSkeleton";
import { TestsTable } from "./table/TestsTable";
import { TestsTableProvider } from "../hooks/useTestsTableContext";

interface TestsListProps {
columnHeaders: {
severity: string;
result: string;
title: string;
provider: string;
createdAt: string;
assignedUser: string;
};
}

export function TestsList({ columnHeaders }: TestsListProps) {
const searchParams = useSearchParams();
const search = searchParams.get("search");
const provider = searchParams.get("provider");
const status = searchParams.get("status");
const per_page = Number(searchParams.get("per_page")) || 10;
const page = Number(searchParams.get("page")) || 1;

const { tests, total, isLoading, error } = useTests();
export function TestsList() {
const { tests, isLoading, error } = useTests('');

if (isLoading) {
return <TestsListSkeleton />;
return <Loading isEmpty={false} />;
}

if (error) {
return (
<div className="relative">
<FilterToolbar isEmpty={true} />
<NoResults hasFilters={false} />
<div className="space-y-4">
<h2 className="text-xl font-semibold">Tests</h2>
<div className="border p-4 rounded-md bg-red-50 text-red-800">
Error loading tests: {error.message}
</div>
</div>
);
}

const hasFilters = !!(search || provider || status);

if (tests.length === 0 && !hasFilters) {
if (tests.length === 0) {
return (
<div className="relative overflow-hidden">
<FilterToolbar isEmpty={true} />
<NoTests />
<Loading isEmpty />
</div>
);
}

return (
<div className="relative">
<FilterToolbar isEmpty={tests.length === 0} />
{tests.length > 0 ? (
<DataTable
columnHeaders={columnHeaders}
data={tests as TestType[]}
pageCount={Math.ceil(total / per_page)}
currentPage={page}
/>
) : (
<NoResults hasFilters={hasFilters} />
)}
</div>
<TestsTableProvider>
<div className="relative">
<TestsTable />
</div>
</TestsTableProvider>
);
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
"use client";

import { DataTable } from "@/components/ui/data-table";
import { useParams, useRouter } from "next/navigation";
import { getFilterCategories } from "./filterCategories";
import { getColumns } from "./columns";
import { useTestsTable } from "../../hooks/useTestsTableContext";
import { RefreshCcw } from "lucide-react";
import { refreshTestsAction } from "../../actions/refreshTests";
import { useAction } from "next-safe-action/hooks";
import { toast } from "sonner";
import { useI18n } from "@/locales/client";

export function TestsTable() {
const router = useRouter();
const { orgId } = useParams<{ orgId: string }>();
const t = useI18n();

const {
page,
setPage,
pageSize,
setPageSize,
tests,
total,
search,
setSearch,
status,
setStatus,
severity,
setSeverity,
hasActiveFilters,
clearFilters,
isLoading,
isSearching,
} = useTestsTable();

const refreshTests = useAction(refreshTestsAction, {
onSuccess: () => {
toast.success(t("tests.actions.refresh_success"));
window.location.reload();
},
onError: () => {
toast.error(t("tests.actions.refresh_error"));
},
});

const handleRowClick = (testId: string) => {
router.replace(`/${orgId}/tests/all/${testId}`);
};

const activeFilterCount = [status, severity].filter(Boolean).length;

const filterCategories = getFilterCategories({
status,
setStatus,
severity: severity,
setSeverity: setSeverity,
setPage,
});

// Calculate pagination values only when total is defined
const pagination =
total !== undefined
? {
page: Number(page),
pageSize: Number(pageSize),
totalCount: total,
totalPages: Math.ceil(total / Number(pageSize)),
hasNextPage: Number(page) * Number(pageSize) < total,
hasPreviousPage: Number(page) > 1,
}
: undefined;

return (
<DataTable
data={tests || []}
columns={getColumns(handleRowClick)}
onRowClick={(row) => handleRowClick(row.id)}
emptyMessage="No tests found."
isLoading={isLoading || isSearching}
pagination={pagination}
onPageChange={(page) => setPage(page.toString())}
onPageSizeChange={(pageSize) => setPageSize(pageSize.toString())}
search={{
value: search || "",
onChange: setSearch,
placeholder: "Search tests...",
}}
filters={{
categories: filterCategories,
hasActiveFilters,
onClearFilters: clearFilters,
activeFilterCount,
}}
ctaButton={{
label: "Refresh Tests",
onClick: () => refreshTests.execute(),
icon: <RefreshCcw className="h-4 w-4" />,
}}
/>
);
}
Loading