Skip to content

Commit

Permalink
fully implement pagination
Browse files Browse the repository at this point in the history
  • Loading branch information
kantord committed Jan 17, 2025
1 parent ea7f374 commit 277cf72
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 29 deletions.
19 changes: 17 additions & 2 deletions src/components/AlertsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import { useCallback } from "react";
import { useSearchParams } from "react-router-dom";
import { useFilteredAlerts } from "@/hooks/useAlertsData";

const PAGE_SIZE = 15;

const wrapObjectOutput = (input: AlertConversation["trigger_string"]) => {
const data = getMaliciousPackage(input);
if (data === null) return "N/A";
Expand Down Expand Up @@ -77,8 +79,21 @@ export function AlertsTable() {
const [searchParams, setSearchParams] = useSearchParams();
const { data: filteredAlerts = [] } = useFilteredAlerts();

const pageStart = page * PAGE_SIZE;
const pageEnd = page * PAGE_SIZE + PAGE_SIZE - 1;

const dataView = filteredAlerts.slice(pageStart, pageEnd);

const hasPreviousPage = page > 0;
const hasNextPage = true;
const hasNextPage = pageEnd + 1 < filteredAlerts.length;

console.log({
pageStart,
pageEnd,
hasPreviousPage,
hasNextPage,
length: filteredAlerts.length,
});

const handleToggleFilter = useCallback(
(isChecked: boolean) => {
Expand Down Expand Up @@ -169,7 +184,7 @@ export function AlertsTable() {
</Row>
</TableHeader>
<TableBody>
{filteredAlerts
{dataView
.sort(
(a, b) =>
new Date(b.timestamp).getTime() -
Expand Down
34 changes: 16 additions & 18 deletions src/components/__tests__/Dashboard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ function mockManyAlerts() {
...mockedAlerts,
...mockedAlerts,
...mockedAlerts,
...mockedAlerts,
].map((alert) => ({ ...alert, alert_id: faker.string.uuid() })),
);
}),
Expand Down Expand Up @@ -332,34 +333,31 @@ describe("Dashboard", () => {

render(<Dashboard />);

expect(screen.getByRole("button", { name: /previous/i })).toBeDisabled();
expect(screen.getByRole("button", { name: /next/i })).toBeEnabled();
await waitFor(async () => {
await userEvent.click(screen.getByRole("button", { name: /next/i }));

await userEvent.click(screen.getByRole("button", { name: /next/i }));
expect(screen.getByRole("button", { name: /previous/i })).toBeEnabled();
expect(
within(screen.getByTestId("alerts-table")).getAllByRole("row").length,
).toBeLessThan(15);

Check failure on line 341 in src/components/__tests__/Dashboard.test.tsx

View workflow job for this annotation

GitHub Actions / Unit Tests / Vitest

src/components/__tests__/Dashboard.test.tsx > Dashboard > allows pagination

AssertionError: expected 15 to be less than 15 Ignored nodes: comments, script, style <html> <head /> <body> <span aria-hidden="true" id="recharts_measurement_span" style="position: absolute; top: -20000px; left: 0px; padding: 0px; margin: 0px; white-space: pre;" > 9 </span> <div> <div class="group/sidebar-wrapper flex min-h-svh w-full has-[[data-variant=inset]]:bg-gray-25" style="--sidebar-width: 16rem; --sidebar-width-icon: 3rem;" > <div class="flex-col" > <div class="grid 2xl:grid-cols-4 sm:grid-cols-2 grid-cols-1 items-stretch gap-4 w-full" > <section class="relative overflow-hidden rounded border border-gray-400 bg-base h-full flex flex-col" > <header class="flex items-center bg-gray-50 px-6 py-4" > <h3 class="font-title font-semibold text-primary mb-0 truncate text-xl flex justify-between items-center" slot="title" > <span class="block" > CodeGate Status </span> </h3> <button class="outline outline-0 outline-offset-2 outline-brand-700 forced-colors:outline-[Highlight] inline-flex shrink-0 cursor-pointer items-center justify-center gap-1 rounded-sm border px-4 py-2 text-center text-base font-medium [&_svg]:size-4 [&_svg]:shrink-0 border-transparent bg-transparent text-primary hover:bg-gray-100 pressed:bg-gray-200 disabled:bg-transparent disabled:text-disabled focus-within:&:has([data-focus-visible]):outline-2 invalid:!outline-red-700 focus-visible:outline-2 size-7 ml-auto -mr-2" data-rac="" id="react-aria-:r8a:" type="button" > <svg class="lucide lucide-refresh-ccw" fill="none" height="24" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" > <path d="M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" /> <path d="M3 3v5h5" /> <path d="M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16" /> <path d="M16 16h5v5" /> </svg> </button> </header> <div class="shrink grow px-6 py-4 h-max" > <span data-focus-scope-start="true" hidden="" /> <table aria-describedby="" aria-label="CodeGate status checks" class="group/table w-full border-separate border-spacing-0 h-max" data-rac="" id="react-aria-:r8c:" role="grid" tabindex="0" > <thead class="hidden" data-rac="" role="rowgroup" > <tr role="row" > <th class="subhead-bold cursor-default bg-gray-50 px-6 py-4 text-start font-semibold text-tertiary group-data-[compact]/table:first:pl-0 group-data-[compact]/table:last:pr-0 hover:cursor-pointer hover:text-secondary [&:focus-within]:z-20 [&:hover]:z-20" data-key="react-aria-1" data-rac="" id="re
});

await userEvent.click(screen.getByRole("button", { name: /next/i }));
expect(screen.getByRole("button", { name: /previous/i })).toBeEnabled();
// on the last page, we cannot go further
expect(screen.getByRole("button", { name: /next/i })).toBeDisabled();

await userEvent.click(screen.getByRole("button", { name: /previous/i }));
expect(screen.getByRole("button", { name: /previous/i })).toBeEnabled();

// back at the first page
await userEvent.click(screen.getByRole("button", { name: /previous/i }));
expect(screen.getByRole("button", { name: /previous/i })).toBeDisabled();
});

it("displays the correct rows when using pagination", async () => {
mockManyAlerts();

render(<Dashboard />);
expect(screen.getByRole("button", { name: /next/i })).toBeEnabled();

await waitFor(async () => {
await userEvent.click(screen.getByRole("button", { name: /next/i }));
await userEvent.click(screen.getByRole("button", { name: /previous/i }));

// once we reach the first page, we cannot paginate backwards anymore
expect(screen.getByRole("button", { name: /previous/i })).toBeDisabled();
expect(screen.getByRole("button", { name: /next/i })).toBeEnabled();

expect(
within(screen.getByTestId("alerts-table")).getAllByRole("row").length,
).toBeLessThan(15);
).toEqual(15);
});
});
});
14 changes: 5 additions & 9 deletions src/hooks/useAlertsData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,14 @@ export const useAlertsData = ({ ...args } = {}) => {
});
};

const PAGE_SIZE = 15;

export const useFilteredAlerts = () => {
const { isMaliciousFilterActive, search, page } = useAlertSearch();

const page_start = page * PAGE_SIZE;
const { isMaliciousFilterActive, search } = useAlertSearch();

return useAlertsData({
select: (
data: Exclude<ReturnType<typeof useAlertsData>["data"], undefined>,
) =>
data
) => {
return data
.filter((alert) => {
const maliciousPkg = getMaliciousPackage(alert.trigger_string);
const maliciousPkgName =
Expand Down Expand Up @@ -74,8 +70,8 @@ export const useFilteredAlerts = () => {
typeof alert.trigger_string === "object" &&
(alert.trigger_type as TriggerType) === "codegate-context-retriever"
);
})
.slice(page_start, page_start + PAGE_SIZE - 1),
});
},
});
};

Expand Down

0 comments on commit 277cf72

Please sign in to comment.