Skip to content

Commit

Permalink
feat: maas-react-components pagination (#5311)
Browse files Browse the repository at this point in the history
  • Loading branch information
petermakowski committed Feb 8, 2024
1 parent 0aba297 commit 84d7777
Show file tree
Hide file tree
Showing 21 changed files with 233 additions and 243 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"build-storybook": "storybook build"
},
"dependencies": {
"@canonical/maas-react-components": "1.19.1",
"@canonical/maas-react-components": "1.21.0",
"@canonical/macaroon-bakery": "1.3.2",
"@canonical/react-components": "0.46.0",
"@reduxjs/toolkit": "1.9.3",
Expand Down
27 changes: 16 additions & 11 deletions src/app/base/components/ActionBar/ActionBar.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { ReactNode } from "react";

import { Pagination } from "@canonical/maas-react-components";
import type { SearchBoxProps } from "@canonical/react-components";

import ArrowPagination from "@/app/base/components/ArrowPagination";
import SearchBox from "@/app/base/components/SearchBox";

type Props = {
Expand Down Expand Up @@ -30,7 +30,7 @@ const ActionBar = ({
return (
<div className="action-bar" {...props}>
{actions && <div className="action-bar__actions">{actions}</div>}
<div className="action-bar__search">
<div className="action-bar__search u-flex--grow">
<SearchBox
className="u-no-margin--bottom"
externallyControlled
Expand All @@ -39,15 +39,20 @@ const ActionBar = ({
/>
</div>
<div className="action-bar__pagination">
<ArrowPagination
className="u-display--inline-block"
currentPage={currentPage}
itemCount={itemCount}
loading={loading}
pageSize={pageSize}
setCurrentPage={setCurrentPage}
showPageBounds
/>
<div className="u-flex--between u-flex--align-baseline u-flex--wrap">
<Pagination
aria-label="pagination"
currentPage={currentPage}
disabled={loading || itemCount === 0}
onInputBlur={() => {}}
onInputChange={(e) => {
setCurrentPage(Number(e.target.value));
}}
onNextClick={() => setCurrentPage(currentPage + 1)}
onPreviousClick={() => setCurrentPage(currentPage - 1)}
totalPages={Math.ceil(itemCount / pageSize)}
/>
</div>
</div>
</div>
);
Expand Down
1 change: 0 additions & 1 deletion src/app/base/components/ActionBar/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@

.action-bar__search {
margin: 0 $sph--large 0 0;
max-width: 50rem;
}
}
}
Expand Down
26 changes: 26 additions & 0 deletions src/app/base/components/ListDisplayCount/ListDisplayCount.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import ListDisplayCount from "./ListDisplayCount";

import { render, screen } from "@/testing/utils";

it("shows the true number of items on a page if it is under the maximum items per page limit.", () => {
render(
<ListDisplayCount count={135} currentPage={3} pageSize={50} type="tag" />
);

expect(screen.getByText("Showing 35 out of 135 tags")).toBeInTheDocument();
});

it("shows the maximum number of items per page if that limit is reached", () => {
render(
<ListDisplayCount
count={135}
currentPage={2}
pageSize={50}
type="machine"
/>
);

expect(
screen.getByText("Showing 50 out of 135 machines")
).toBeInTheDocument();
});
38 changes: 38 additions & 0 deletions src/app/base/components/ListDisplayCount/ListDisplayCount.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
export const getCurrentPageDisplayedCount = (
count: number | null,
pageSize: number,
currentPage: number
): number => {
if (!count) {
return 0;
}

const totalPages = Math.ceil(count / pageSize);

if (currentPage === totalPages) {
return pageSize - (totalPages * pageSize - count);
} else {
return pageSize;
}
};

export const ListDisplayCount = ({
count,
pageSize,
currentPage,
type = "item",
}: {
count: number;
pageSize: number;
currentPage: number;
type: string;
}): JSX.Element => {
return (
<strong className="machine-list--display-count">
Showing {getCurrentPageDisplayedCount(count, pageSize, currentPage)} out
of {count} {type}s
</strong>
);
};

export default ListDisplayCount;
5 changes: 5 additions & 0 deletions src/app/base/components/ListDisplayCount/_index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@mixin ListDisplayCount {
.list--display-count {
padding-bottom: $spv--small;
}
}
1 change: 1 addition & 0 deletions src/app/base/components/ListDisplayCount/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./ListDisplayCount";
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export type Props = {
isNotificationListHidden?: boolean;
} & HTMLProps<HTMLDivElement>;

export const MAIN_CONTENT_SECTION_ID = "main-content-section";

const MainContentSection = ({
children,
header,
Expand All @@ -23,7 +25,7 @@ const MainContentSection = ({
}: Props): JSX.Element => {
const { SIDEBAR, TOTAL } = COL_SIZES;
return (
<div {...props} id="main-content-section">
<div {...props} id={MAIN_CONTENT_SECTION_ID}>
<div>
{header ? (
<header aria-label="main content" className="row">
Expand Down
1 change: 1 addition & 0 deletions src/app/base/components/MainContentSection/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { default } from "./MainContentSection";
export * from "./MainContentSection";
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { Mock } from "vitest";
import EventLogs, { Label } from "./EventLogs";

import { Labels as ArrowPaginationLabels } from "@/app/base/components/ArrowPagination";
import { MAIN_CONTENT_SECTION_ID } from "@/app/base/components/MainContentSection";
import type { MachineDetails } from "@/app/store/machine/types";
import type { RootState } from "@/app/store/root/types";
import {
Expand All @@ -22,6 +23,7 @@ import {
screen,
within,
renderWithMockStore,
renderWithBrowserRouter,
} from "@/testing/utils";

const mockStore = configureStore();
Expand Down Expand Up @@ -314,11 +316,12 @@ describe("EventLogs", () => {
})
);
}
renderWithMockStore(<EventLogs node={machine} />, {
renderWithBrowserRouter(<EventLogs node={machine} />, {
state,
});
await userEvent.selectOptions(screen.getByRole("combobox"), "50");
expect(window.location.hash).toBe("");
await userEvent.click(screen.getByRole("link", { name: Label.BackToTop }));
expect(scrollToSpy).toHaveBeenCalled();
expect(window.location.hash).toBe(`#${MAIN_CONTENT_SECTION_ID}`);
});
});
94 changes: 40 additions & 54 deletions src/app/base/components/node/NodeLogs/EventLogs/EventLogs.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { useEffect, useState } from "react";

import { Col, Link, Row, Select, Spinner } from "@canonical/react-components";
import { Link, Select, Spinner } from "@canonical/react-components";
import { useDispatch, useSelector } from "react-redux";
import { useStorageState } from "react-storage-hooks";

import EventLogsTable from "./EventLogsTable";

import ArrowPagination from "@/app/base/components/ArrowPagination";
import { MAIN_CONTENT_SECTION_ID } from "@/app/base/components/MainContentSection/MainContentSection";
import SearchBox from "@/app/base/components/SearchBox";
import type { ControllerDetails } from "@/app/store/controller/types";
import { actions as eventActions } from "@/app/store/event";
Expand Down Expand Up @@ -142,68 +143,53 @@ const EventLogs = ({ node }: Props): JSX.Element => {

return (
<div aria-label={Label.Title}>
<Row className="u-nudge-down--small">
<Col size={6}>
<div className="u-flex">
<div className="u-flex--grow">
<SearchBox
onChange={setSearchText}
placeholder="Search event logs"
value={searchText}
/>
</Col>
<Col className="u-align--right" size={6}>
Show
<Select
className="u-auto-min-width"
defaultValue={pageSize.toString()}
name="page-size"
onChange={(evt: React.ChangeEvent<HTMLSelectElement>) => {
setPageSize(Number(evt.target.value));
}}
options={[
{
value: "25",
label: "25",
},
{
value: "50",
label: "50",
},
{
value: "100",
label: "100",
},
{
value: "200",
label: "200",
},
]}
wrapperClassName="u-display--inline-block u-nudge-right"
/>
<ArrowPagination
className="u-display--inline-block u-nudge-right"
currentPage={currentPage}
itemCount={unpaginatedEvents.length}
pageSize={pageSize}
setCurrentPage={setCurrentPage}
/>
</Col>
</Row>
</div>
<ArrowPagination
className="u-display--inline-block u-nudge-right"
currentPage={currentPage}
itemCount={unpaginatedEvents.length}
pageSize={pageSize}
setCurrentPage={setCurrentPage}
/>
<Select
defaultValue={pageSize.toString()}
name="page-size"
onChange={(evt: React.ChangeEvent<HTMLSelectElement>) => {
setPageSize(Number(evt.target.value));
}}
options={[
{
value: "25",
label: "25/page",
},
{
value: "50",
label: "50/page",
},
{
value: "100",
label: "100/page",
},
{
value: "200",
label: "200/page",
},
]}
wrapperClassName="u-display--inline-block u-nudge-right"
/>
</div>
<hr />
<EventLogsTable events={paginatedEvents} />
{loading && <Spinner text="Loading..." />}
{showBackToTop && (
<Link
data-testid="backToTop"
onClick={(evt: React.MouseEvent<HTMLAnchorElement>) => {
evt.preventDefault();
window.scrollTo({
top: 0,
left: 0,
behavior: "smooth",
});
}}
top
>
<Link data-testid="backToTop" href={`#${MAIN_CONTENT_SECTION_ID}`} top>
{Label.BackToTop}
</Link>
)}
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading

0 comments on commit 84d7777

Please sign in to comment.