From c84d96b74766396ead48f04e791d94e63204e94a Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Mon, 18 Mar 2024 10:35:59 -0300 Subject: [PATCH] fix(site): display not found page when pagination page is invalid (#12611) --- .../components/PaginationWidget/utils.test.ts | 4 ++ site/src/components/PaginationWidget/utils.ts | 9 ++- .../WorkspacesPageView.stories.tsx | 9 +++ .../WorkspacesPage/WorkspacesPageView.tsx | 63 ++++++++++++++----- 4 files changed, 66 insertions(+), 19 deletions(-) diff --git a/site/src/components/PaginationWidget/utils.test.ts b/site/src/components/PaginationWidget/utils.test.ts index 12c53af85d..f53d1c37fc 100644 --- a/site/src/components/PaginationWidget/utils.test.ts +++ b/site/src/components/PaginationWidget/utils.test.ts @@ -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, () => { diff --git a/site/src/components/PaginationWidget/utils.ts b/site/src/components/PaginationWidget/utils.ts index cb1b7729af..57ce4e1ecb 100644 --- a/site/src/components/PaginationWidget/utils.ts +++ b/site/src/components/PaginationWidget/utils.ts @@ -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 = range(startPage, endPage); diff --git a/site/src/pages/WorkspacesPage/WorkspacesPageView.stories.tsx b/site/src/pages/WorkspacesPage/WorkspacesPageView.stories.tsx index 69578553cd..965dfe4b6b 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesPageView.stories.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesPageView.stories.tsx @@ -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, + }, +}; diff --git a/site/src/pages/WorkspacesPage/WorkspacesPageView.tsx b/site/src/pages/WorkspacesPage/WorkspacesPageView.tsx index 98a20004d1..4035202882 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesPageView.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesPageView.tsx @@ -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 ( ) : ( - + !invalidPageNumber && ( + + ) )} - + {invalidPageNumber ? ( + ({ + 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={ + + } + /> + ) : ( + + )} {count !== undefined && ( // Temporary styling stopgap before component is migrated to using