fix(site): display not found page when pagination page is invalid (#12611)

This commit is contained in:
Bruno Quaresma 2024-03-18 10:35:59 -03:00 committed by GitHub
parent b121f407f5
commit c84d96b747
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 66 additions and 19 deletions

View File

@ -53,6 +53,10 @@ describe(buildPagedList.name, () => {
expect(uniqueCount).toEqual(result.length);
}
});
it("works for invalid active page number", () => {
expect(buildPagedList(2, 4)).toEqual([1, 2]);
});
});
describe(getOffset.name, () => {

View File

@ -33,9 +33,14 @@ export const buildPagedList = (
return range(1, numPages);
}
const isInvalidActivePage = activePage > numPages || activePage < 1;
const pageBeforeLast = numPages - 1;
const startPage = Math.max(activePage - PAGE_NEIGHBORS, 2);
const endPage = Math.min(activePage + PAGE_NEIGHBORS, pageBeforeLast);
const startPage = isInvalidActivePage
? 1 + PAGE_NEIGHBORS
: Math.max(activePage - PAGE_NEIGHBORS, 2);
const endPage = isInvalidActivePage
? numPages - PAGE_NEIGHBORS
: Math.min(activePage + PAGE_NEIGHBORS, pageBeforeLast);
let pages: ReturnType<typeof buildPagedList> = range(startPage, endPage);

View File

@ -270,3 +270,12 @@ export const Error: Story = {
error: mockApiError({ message: "Something went wrong" }),
},
};
export const InvalidPageNumber: Story = {
args: {
workspaces: [],
count: 200,
limit: 25,
page: 1000,
},
};

View File

@ -4,12 +4,14 @@ import KeyboardArrowDownOutlined from "@mui/icons-material/KeyboardArrowDownOutl
import PlayArrowOutlined from "@mui/icons-material/PlayArrowOutlined";
import StopOutlined from "@mui/icons-material/StopOutlined";
import LoadingButton from "@mui/lab/LoadingButton";
import Button from "@mui/material/Button";
import Divider from "@mui/material/Divider";
import type { ComponentProps } from "react";
import type { UseQueryResult } from "react-query";
import { hasError, isApiValidationError } from "api/errors";
import type { Template, Workspace } from "api/typesGenerated";
import { ErrorAlert } from "components/Alert/ErrorAlert";
import { EmptyState } from "components/EmptyState/EmptyState";
import { Margins } from "components/Margins/Margins";
import {
MoreMenu,
@ -85,6 +87,11 @@ export const WorkspacesPageView = ({
canCreateTemplate,
canChangeVersions,
}: WorkspacesPageViewProps) => {
// Let's say the user has 5 workspaces, but tried to hit page 100, which does
// not exist. In this case, the page is not valid and we want to show a better
// error message.
const invalidPageNumber = page !== 1 && workspaces?.length === 0;
return (
<Margins>
<PageHeader
@ -168,26 +175,48 @@ export const WorkspacesPageView = ({
</MoreMenu>
</>
) : (
<PaginationHeader
paginationUnitLabel="workspaces"
limit={limit}
totalRecords={count}
currentOffsetStart={(page - 1) * limit + 1}
css={{ paddingBottom: "0" }}
/>
!invalidPageNumber && (
<PaginationHeader
paginationUnitLabel="workspaces"
limit={limit}
totalRecords={count}
currentOffsetStart={(page - 1) * limit + 1}
css={{ paddingBottom: "0" }}
/>
)
)}
</TableToolbar>
<WorkspacesTable
canCreateTemplate={canCreateTemplate}
workspaces={workspaces}
isUsingFilter={filterProps.filter.used}
onUpdateWorkspace={onUpdateWorkspace}
checkedWorkspaces={checkedWorkspaces}
onCheckChange={onCheckChange}
canCheckWorkspaces={canCheckWorkspaces}
templates={templates}
/>
{invalidPageNumber ? (
<EmptyState
css={(theme) => ({
border: `1px solid ${theme.palette.divider}`,
borderRadius: theme.shape.borderRadius,
})}
message="Page not found"
description="The page you are trying to access does not exist."
cta={
<Button
onClick={() => {
onPageChange(1);
}}
>
Back to the first page
</Button>
}
/>
) : (
<WorkspacesTable
canCreateTemplate={canCreateTemplate}
workspaces={workspaces}
isUsingFilter={filterProps.filter.used}
onUpdateWorkspace={onUpdateWorkspace}
checkedWorkspaces={checkedWorkspaces}
onCheckChange={onCheckChange}
canCheckWorkspaces={canCheckWorkspaces}
templates={templates}
/>
)}
{count !== undefined && (
// Temporary styling stopgap before component is migrated to using