Skip to content

Commit

Permalink
feat(devices): use MainToolbar in DeviceListHeader MAASENG-2515 (#5254)
Browse files Browse the repository at this point in the history
  • Loading branch information
ndv99 authored Jan 5, 2024
1 parent bc054f4 commit 0701d50
Show file tree
Hide file tree
Showing 13 changed files with 91 additions and 101 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"build-storybook": "storybook build"
},
"dependencies": {
"@canonical/maas-react-components": "1.14.0",
"@canonical/maas-react-components": "1.15.0",
"@canonical/macaroon-bakery": "1.3.2",
"@canonical/react-components": "0.46.0",
"@reduxjs/toolkit": "1.9.3",
Expand Down
11 changes: 3 additions & 8 deletions src/app/devices/views/DeviceList/DeviceList.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ describe("DeviceList", () => {
route: "/devices?q=test+search",
state,
});
expect(screen.getByRole("searchbox", { name: "Search" })).toHaveValue(
"test search"
);
expect(screen.getByRole("searchbox")).toHaveValue("test search");
});

it("changes the URL when the search text changes", async () => {
Expand All @@ -42,11 +40,8 @@ describe("DeviceList", () => {
</>,
{ route: "/machines?q=test+search", state }
);
await userEvent.clear(screen.getByRole("searchbox", { name: "Search" }));
await userEvent.type(
screen.getByRole("searchbox", { name: "Search" }),
"hostname:foo"
);
await userEvent.clear(screen.getByRole("searchbox"));
await userEvent.type(screen.getByRole("searchbox"), "hostname:foo");

await waitFor(() => {
expect(search).toBe("?hostname=foo");
Expand Down
3 changes: 1 addition & 2 deletions src/app/devices/views/DeviceList/DeviceList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { useDispatch, useSelector } from "react-redux";
import { useLocation } from "react-router";
import { useNavigate } from "react-router-dom-v5-compat";

import DeviceListControls from "./DeviceListControls";
import DeviceListHeader from "./DeviceListHeader";
import DeviceListTable from "./DeviceListTable";

Expand Down Expand Up @@ -53,6 +52,7 @@ const DeviceList = (): JSX.Element => {
<PageContent
header={
<DeviceListHeader
searchFilter={searchFilter}
setSearchFilter={setSearchFilter}
setSidePanelContent={setSidePanelContent}
/>
Expand All @@ -68,7 +68,6 @@ const DeviceList = (): JSX.Element => {
}
sidePanelTitle={getSidePanelTitle("Devices", sidePanelContent)}
>
<DeviceListControls filter={searchFilter} setFilter={setSearchFilter} />
<DeviceListTable
devices={filteredDevices}
hasFilter={!!searchFilter}
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ describe("DeviceListHeader", () => {
state.device.loaded = false;
renderWithBrowserRouter(
<DeviceListHeader
searchFilter=""
setSearchFilter={jest.fn()}
setSidePanelContent={jest.fn()}
/>,
Expand All @@ -42,42 +43,66 @@ describe("DeviceListHeader", () => {
state.device.loaded = true;
renderWithBrowserRouter(
<DeviceListHeader
searchFilter=""
setSearchFilter={jest.fn()}
setSidePanelContent={jest.fn()}
/>,
{ state }
);
expect(screen.getByTestId("section-header-subtitle")).toHaveTextContent(
"2 devices available"
);
expect(screen.getByText("2 devices available")).toBeInTheDocument();
});

it("disables the add device button if any devices are selected", () => {
state.device.selected = ["abc123"];
renderWithBrowserRouter(
<DeviceListHeader
searchFilter=""
setSearchFilter={jest.fn()}
setSidePanelContent={jest.fn()}
/>,
{ state }
);
expect(screen.getByTestId("add-device-button")).toBeDisabled();
expect(screen.getByRole("button", { name: "Add device" })).toBeDisabled();
});

it("can open the add device form", async () => {
const setSidePanelContent = jest.fn();
renderWithBrowserRouter(
<MemoryRouter>
<DeviceListHeader
searchFilter=""
setSearchFilter={jest.fn()}
setSidePanelContent={setSidePanelContent}
/>
</MemoryRouter>,
{ state }
);
await userEvent.click(screen.getByTestId("add-device-button"));
await userEvent.click(screen.getByRole("button", { name: "Add device" }));
expect(setSidePanelContent).toHaveBeenCalledWith({
view: DeviceSidePanelViews.ADD_DEVICE,
});
});

it("changes the search text when the filters change", () => {
const { rerender } = renderWithBrowserRouter(
<DeviceListHeader
searchFilter=""
setSearchFilter={jest.fn()}
setSidePanelContent={jest.fn()}
/>,
{ state }
);

expect(screen.getByRole("searchbox")).toHaveValue("");

rerender(
<DeviceListHeader
searchFilter="free-text"
setSearchFilter={jest.fn()}
setSidePanelContent={jest.fn()}
/>
);

expect(screen.getByRole("searchbox")).toHaveValue("free-text");
});
});
Original file line number Diff line number Diff line change
@@ -1,30 +1,67 @@
import { Button } from "@canonical/react-components";
import { useEffect, useState } from "react";

import { MainToolbar } from "@canonical/maas-react-components";
import { Button, Col, Spinner } from "@canonical/react-components";
import { useSelector } from "react-redux";

import DeviceFilterAccordion from "./DeviceFilterAccordion";

import DebounceSearchBox from "app/base/components/DebounceSearchBox";
import ModelListSubtitle from "app/base/components/ModelListSubtitle";
import NodeActionMenu from "app/base/components/NodeActionMenu";
import SectionHeader from "app/base/components/SectionHeader";
import type { SetSearchFilter } from "app/base/types";
import { DeviceSidePanelViews } from "app/devices/constants";
import type { DeviceSetSidePanelContent } from "app/devices/types";
import deviceSelectors from "app/store/device/selectors";

type Props = {
searchFilter: string;
setSidePanelContent: DeviceSetSidePanelContent;
setSearchFilter: SetSearchFilter;
};

const DeviceListHeader = ({
searchFilter,
setSidePanelContent,
setSearchFilter,
}: Props): JSX.Element => {
const devices = useSelector(deviceSelectors.all);
const devicesLoaded = useSelector(deviceSelectors.loaded);
const selectedDevices = useSelector(deviceSelectors.selected);
const [searchText, setSearchText] = useState(searchFilter);

useEffect(() => {
// If the filters change then update the search input text.
setSearchText(searchFilter);
}, [searchFilter]);

return (
<SectionHeader
buttons={[
<MainToolbar>
<MainToolbar.Title data-testid="section-header-title">
Devices
</MainToolbar.Title>
{devicesLoaded ? (
<ModelListSubtitle
available={devices.length}
filterSelected={() => setSearchFilter("in:(Selected)")}
modelName="device"
selected={selectedDevices.length}
/>
) : (
<Spinner text="Loading" />
)}
<MainToolbar.Controls>
<Col size={3}>
<DeviceFilterAccordion
searchText={searchText}
setSearchText={setSearchFilter}
/>
</Col>
<DebounceSearchBox
onDebounced={(debouncedText) => setSearchFilter(debouncedText)}
searchText={searchText}
setSearchText={setSearchText}
/>
<Button
data-testid="add-device-button"
disabled={selectedDevices.length > 0}
Expand All @@ -33,7 +70,7 @@ const DeviceListHeader = ({
}
>
Add device
</Button>,
</Button>
<NodeActionMenu
filterActions
hasSelection={selectedDevices.length > 0}
Expand All @@ -48,19 +85,9 @@ const DeviceListHeader = ({
}
}}
showCount
/>,
]}
subtitle={
<ModelListSubtitle
available={devices.length}
filterSelected={() => setSearchFilter("in:(Selected)")}
modelName="device"
selected={selectedDevices.length}
/>
}
subtitleLoading={!devicesLoaded}
title="Devices"
/>
</MainToolbar.Controls>
</MainToolbar>
);
};

Expand Down
8 changes: 8 additions & 0 deletions src/scss/_vanilla-overrides.scss
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,11 @@
.p-tooltip__message {
z-index: $side-navigation-z-index + 1;
}

// 05-01-2024 Nick: Using MainToolbar without ContentSection means no padding at top of page.
// Will be fixed once all main pages use MainToolbar and ContentSection is implemented
// https://warthogs.atlassian.net/browse/MAASENG-2440
// https://github.com/canonical/maas-ui/pull/5244
.main-toolbar {
padding-top: $spv--medium;
}
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2907,10 +2907,10 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==

"@canonical/maas-react-components@1.14.0":
version "1.14.0"
resolved "https://registry.yarnpkg.com/@canonical/maas-react-components/-/maas-react-components-1.14.0.tgz#3347a28cc968ed8a13a5e501ec6ebde11a0274c5"
integrity sha512-ApSpDchiCn8EJ597Er/yMeAzc4+iuphU0eXCmmZVcMFCSl2iQqJ6NncA1eCRPgBN7QQs++wqHJ5ry0VPHup0vA==
"@canonical/maas-react-components@1.15.0":
version "1.15.0"
resolved "https://registry.yarnpkg.com/@canonical/maas-react-components/-/maas-react-components-1.15.0.tgz#c14ec75eeb2bfe2757e45fb3bebf67689865e4df"
integrity sha512-0KQ0CXi6D2PURVUerRR/0CAitp3Qf7olUIJwXZnrePlLyas9zmnZ2HyVydlS/z5YptaHExqh/EQT9AGln/3T+A==

"@canonical/[email protected]":
version "1.3.2"
Expand Down

0 comments on commit 0701d50

Please sign in to comment.