Skip to content

Commit c84d96b

Browse files
fix(site): display not found page when pagination page is invalid (#12611)
1 parent b121f40 commit c84d96b

File tree

4 files changed

+66
-19
lines changed

4 files changed

+66
-19
lines changed

site/src/components/PaginationWidget/utils.test.ts

+4
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ describe(buildPagedList.name, () => {
5353
expect(uniqueCount).toEqual(result.length);
5454
}
5555
});
56+
57+
it("works for invalid active page number", () => {
58+
expect(buildPagedList(2, 4)).toEqual([1, 2]);
59+
});
5660
});
5761

5862
describe(getOffset.name, () => {

site/src/components/PaginationWidget/utils.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,14 @@ export const buildPagedList = (
3333
return range(1, numPages);
3434
}
3535

36+
const isInvalidActivePage = activePage > numPages || activePage < 1;
3637
const pageBeforeLast = numPages - 1;
37-
const startPage = Math.max(activePage - PAGE_NEIGHBORS, 2);
38-
const endPage = Math.min(activePage + PAGE_NEIGHBORS, pageBeforeLast);
38+
const startPage = isInvalidActivePage
39+
? 1 + PAGE_NEIGHBORS
40+
: Math.max(activePage - PAGE_NEIGHBORS, 2);
41+
const endPage = isInvalidActivePage
42+
? numPages - PAGE_NEIGHBORS
43+
: Math.min(activePage + PAGE_NEIGHBORS, pageBeforeLast);
3944

4045
let pages: ReturnType<typeof buildPagedList> = range(startPage, endPage);
4146

site/src/pages/WorkspacesPage/WorkspacesPageView.stories.tsx

+9
Original file line numberDiff line numberDiff line change
@@ -270,3 +270,12 @@ export const Error: Story = {
270270
error: mockApiError({ message: "Something went wrong" }),
271271
},
272272
};
273+
274+
export const InvalidPageNumber: Story = {
275+
args: {
276+
workspaces: [],
277+
count: 200,
278+
limit: 25,
279+
page: 1000,
280+
},
281+
};

site/src/pages/WorkspacesPage/WorkspacesPageView.tsx

+46-17
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ import KeyboardArrowDownOutlined from "@mui/icons-material/KeyboardArrowDownOutl
44
import PlayArrowOutlined from "@mui/icons-material/PlayArrowOutlined";
55
import StopOutlined from "@mui/icons-material/StopOutlined";
66
import LoadingButton from "@mui/lab/LoadingButton";
7+
import Button from "@mui/material/Button";
78
import Divider from "@mui/material/Divider";
89
import type { ComponentProps } from "react";
910
import type { UseQueryResult } from "react-query";
1011
import { hasError, isApiValidationError } from "api/errors";
1112
import type { Template, Workspace } from "api/typesGenerated";
1213
import { ErrorAlert } from "components/Alert/ErrorAlert";
14+
import { EmptyState } from "components/EmptyState/EmptyState";
1315
import { Margins } from "components/Margins/Margins";
1416
import {
1517
MoreMenu,
@@ -85,6 +87,11 @@ export const WorkspacesPageView = ({
8587
canCreateTemplate,
8688
canChangeVersions,
8789
}: WorkspacesPageViewProps) => {
90+
// Let's say the user has 5 workspaces, but tried to hit page 100, which does
91+
// not exist. In this case, the page is not valid and we want to show a better
92+
// error message.
93+
const invalidPageNumber = page !== 1 && workspaces?.length === 0;
94+
8895
return (
8996
<Margins>
9097
<PageHeader
@@ -168,26 +175,48 @@ export const WorkspacesPageView = ({
168175
</MoreMenu>
169176
</>
170177
) : (
171-
<PaginationHeader
172-
paginationUnitLabel="workspaces"
173-
limit={limit}
174-
totalRecords={count}
175-
currentOffsetStart={(page - 1) * limit + 1}
176-
css={{ paddingBottom: "0" }}
177-
/>
178+
!invalidPageNumber && (
179+
<PaginationHeader
180+
paginationUnitLabel="workspaces"
181+
limit={limit}
182+
totalRecords={count}
183+
currentOffsetStart={(page - 1) * limit + 1}
184+
css={{ paddingBottom: "0" }}
185+
/>
186+
)
178187
)}
179188
</TableToolbar>
180189

181-
<WorkspacesTable
182-
canCreateTemplate={canCreateTemplate}
183-
workspaces={workspaces}
184-
isUsingFilter={filterProps.filter.used}
185-
onUpdateWorkspace={onUpdateWorkspace}
186-
checkedWorkspaces={checkedWorkspaces}
187-
onCheckChange={onCheckChange}
188-
canCheckWorkspaces={canCheckWorkspaces}
189-
templates={templates}
190-
/>
190+
{invalidPageNumber ? (
191+
<EmptyState
192+
css={(theme) => ({
193+
border: `1px solid ${theme.palette.divider}`,
194+
borderRadius: theme.shape.borderRadius,
195+
})}
196+
message="Page not found"
197+
description="The page you are trying to access does not exist."
198+
cta={
199+
<Button
200+
onClick={() => {
201+
onPageChange(1);
202+
}}
203+
>
204+
Back to the first page
205+
</Button>
206+
}
207+
/>
208+
) : (
209+
<WorkspacesTable
210+
canCreateTemplate={canCreateTemplate}
211+
workspaces={workspaces}
212+
isUsingFilter={filterProps.filter.used}
213+
onUpdateWorkspace={onUpdateWorkspace}
214+
checkedWorkspaces={checkedWorkspaces}
215+
onCheckChange={onCheckChange}
216+
canCheckWorkspaces={canCheckWorkspaces}
217+
templates={templates}
218+
/>
219+
)}
191220

192221
{count !== undefined && (
193222
// Temporary styling stopgap before component is migrated to using

0 commit comments

Comments
 (0)