Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useState } from "react";

import DebounceSearchBox from "@/app/base/components/DebounceSearchBox";
import { MachineSelectTable } from "@/app/base/components/MachineSelectTable/MachineSelectTable";
import MachineListPagination from "@/app/machines/views/MachineList/MachineListTable/MachineListPagination";
import MachineListPagination from "@/app/machines/components/MachineListPagination";
import type { FetchFilters, Machine } from "@/app/store/machine/types";
import { FilterGroupKey } from "@/app/store/machine/types";
import { useFetchMachines } from "@/app/store/machine/utils/hooks";
Expand Down
2 changes: 1 addition & 1 deletion src/app/kvm/components/LXDVMsTable/LXDVMsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type { GetHostColumn, GetResources } from "./VMsTable/VMsTable";

import type { SetSearchFilter, SortDirection } from "@/app/base/types";
import type { KVMSetSidePanelContent } from "@/app/kvm/types";
import { DEFAULTS } from "@/app/machines/views/MachineList/MachineListTable/constants";
import { DEFAULTS } from "@/app/machines/views/MachinesList/constants";
import { machineActions } from "@/app/store/machine";
import type { FetchGroupKey } from "@/app/store/machine/types";
import { FilterGroupKey } from "@/app/store/machine/types";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Link } from "react-router";

import DoubleRow from "@/app/base/components/DoubleRow";
import urls from "@/app/base/urls";
import MachineCheckbox from "@/app/machines/views/MachineList/MachineListTable/MachineCheckbox";
import MachineCheckbox from "@/app/machines/components/MachineCheckbox";
import machineSelectors from "@/app/store/machine/selectors";
import type { Machine } from "@/app/store/machine/types";
import type { RootState } from "@/app/store/root/types";
Expand Down
2 changes: 1 addition & 1 deletion src/app/kvm/components/LXDVMsTable/VMsTable/VMsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import DoubleRow from "@/app/base/components/DoubleRow";
import Placeholder from "@/app/base/components/Placeholder";
import TableHeader from "@/app/base/components/TableHeader";
import { SortDirection } from "@/app/base/types";
import AllCheckbox from "@/app/machines/views/MachineList/MachineListTable/AllCheckbox";
import AllCheckbox from "@/app/machines/components/AllCheckbox";
import type { Machine } from "@/app/store/machine/types";
import { FilterGroupKey, FetchGroupKey } from "@/app/store/machine/types";
import { FilterMachines } from "@/app/store/machine/utils";
Expand Down
25 changes: 6 additions & 19 deletions src/app/kvm/components/VmResources/VmResources.test.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
import * as reduxToolkit from "@reduxjs/toolkit";
import configureStore from "redux-mock-store";

import VmResources, { Label } from "./VmResources";

import { Label as MachineListLabel } from "@/app/machines/views/MachineList/MachineListTable/MachineListTable";
import { machineActions } from "@/app/store/machine";
import * as query from "@/app/store/machine/utils/query";
import { PodType } from "@/app/store/pod/constants";
import type { RootState } from "@/app/store/root/types";
import * as factory from "@/testing/factories";
import {
userEvent,
screen,
renderWithBrowserRouter,
renderWithMockStore,
} from "@/testing/utils";
import { userEvent, screen, renderWithProviders } from "@/testing/utils";

vi.mock("@reduxjs/toolkit", async () => {
const actual: object = await vi.importActual("@reduxjs/toolkit");
Expand All @@ -24,7 +17,6 @@ vi.mock("@reduxjs/toolkit", async () => {
};
});
const callId = "mocked-nanoid";
const mockStore = configureStore<RootState>();

describe("VmResources", () => {
let state: RootState;
Expand Down Expand Up @@ -67,17 +59,16 @@ describe("VmResources", () => {
name: "Deployed",
}),
];
renderWithMockStore(<VmResources podId={1} />, { state });
renderWithProviders(<VmResources podId={1} />, { state });
expect(
screen.getByRole("button", { name: Label.ResourceVMs })
).toBeAriaDisabled();
});

it("can pass additional filters to the request", () => {
const store = mockStore(state);
renderWithMockStore(
const { store } = renderWithProviders(
<VmResources filters={{ id: ["abc123"] }} podId={1} />,
{ store }
{ state }
);
const expected = machineActions.fetch(callId);
const result = store
Expand All @@ -90,16 +81,12 @@ describe("VmResources", () => {
});

it("can display a list of VMs", async () => {
renderWithBrowserRouter(<VmResources podId={1} />, {
renderWithProviders(<VmResources podId={1} />, {
state,
});
await userEvent.click(
screen.getByRole("button", { name: Label.ResourceVMs })
);
expect(
screen.getByRole("grid", {
name: new RegExp(MachineListLabel.Machines, "i"),
})
).toBeInTheDocument();
expect(screen.getByRole("grid")).toBeInTheDocument();
});
});
110 changes: 66 additions & 44 deletions src/app/kvm/components/VmResources/VmResources.tsx
Original file line number Diff line number Diff line change
@@ -1,63 +1,80 @@
import type { ReactElement } from "react";
import { useState } from "react";

import type { ValueOf } from "@canonical/react-components";
import { GenericTable } from "@canonical/maas-react-components";
import { ContextualMenu } from "@canonical/react-components";
import type { SortingState } from "@tanstack/react-table";
import { useSelector } from "react-redux";

import type { SortDirection } from "@/app/base/types";
import MachineListTable from "@/app/machines/views/MachineList/MachineListTable";
import { DEFAULTS } from "@/app/machines/views/MachineList/MachineListTable/constants";
import type { FetchFilters, FetchGroupKey } from "@/app/store/machine/types";
import { FilterGroupKey } from "@/app/store/machine/types";
import usePagination from "@/app/base/hooks/usePagination/usePagination";
import type { Sort } from "@/app/base/types";
import { SortKeyMapping } from "@/app/machines/components/MachinesTable/MachinesTable";
import useMachinesTableColumns from "@/app/machines/components/MachinesTable/useMachinesTableColumns/useMachinesTableColumns";
import type { FetchFilters } from "@/app/store/machine/types";
import { FetchGroupKey, FilterGroupKey } from "@/app/store/machine/types";
import { useFetchedCount } from "@/app/store/machine/utils";
import { useFetchMachines } from "@/app/store/machine/utils/hooks";
import podSelectors from "@/app/store/pod/selectors";
import type { Pod } from "@/app/store/pod/types";
import type { RootState } from "@/app/store/root/types";

import "./_index.scss";

export enum Label {
ResourceVMs = "Resource VMs",
}

export type Props = {
export type VmResourcesProps = {
filters?: FetchFilters;
podId: Pod["id"];
};

export const VMS_PER_PAGE = 5;

const VmResources = ({ filters, podId }: Props): React.ReactElement => {
const VmResources = ({ filters, podId }: VmResourcesProps): ReactElement => {
const pod = useSelector((state: RootState) =>
podSelectors.getById(state, podId)
);
const [currentPage, setCurrentPage] = useState(1);
const [sortKey, setSortKey] = useState<FetchGroupKey | null>(
DEFAULTS.sortKey
);
const [sortDirection, setSortDirection] = useState<
ValueOf<typeof SortDirection>
>(DEFAULTS.sortDirection);
const [sorting, setSorting] = useState<SortingState>([
{ id: "hostname", desc: false },
]);
const sort: Sort<FetchGroupKey> = {
key: sorting.length ? SortKeyMapping[sorting[0].id] : null,
direction: sorting.length
? sorting[0].desc
? "descending"
: "ascending"
: "none",
};

const { page, size, handlePageSizeChange, setPage } =
usePagination(VMS_PER_PAGE);

const {
callId,
loading,
machineCount,
machines: vms,
groups,
totalPages,
} = useFetchMachines({
filters: {
...filters,
[FilterGroupKey.Pod]: pod ? [pod.name] : [],
},
sortDirection,
sortKey,
sortDirection: sort.direction,
sortKey: sort.key,
pagination: {
currentPage,
setCurrentPage,
currentPage: page,
setCurrentPage: setPage,
pageSize: VMS_PER_PAGE,
},
});

const count = useFetchedCount(machineCount, loading);
const columns = useMachinesTableColumns(FetchGroupKey.None, groups![0], {

Check failure on line 73 in src/app/kvm/components/VmResources/VmResources.tsx

View workflow job for this annotation

GitHub Actions / Lint

Expected 1 arguments, but got 3.
...filters,
[FilterGroupKey.Pod]: pod ? [pod.name] : [],
});

return (
<div className="vm-resources">
<div className="vm-resources__dropdown-container">
Expand All @@ -70,29 +87,34 @@
toggleLabel={`Total VMs: ${count ?? 0}`}
toggleProps={{ position: "left", "aria-label": Label.ResourceVMs }}
>
<MachineListTable
callId={callId}
currentPage={currentPage}
groups={groups}
hiddenColumns={[
"owner",
"pool",
"zone",
"fabric",
"disks",
"storage",
]}
machineCount={machineCount}
machines={vms}
machinesLoading={loading}
pageSize={VMS_PER_PAGE}
setCurrentPage={setCurrentPage}
setSortDirection={setSortDirection}
setSortKey={setSortKey}
showActions={false}
sortDirection={sortDirection}
sortKey={sortKey}
totalPages={totalPages}
<GenericTable
columns={columns.filter(
(column) =>
column.id &&
![
"group",
"owner",
"pool",
"zone",
"fabric",
"disks",
"storage",
].includes(column.id)
)}
data={vms}
isLoading={loading}
pagination={{
currentPage: page,
dataContext: "machines",
handlePageSizeChange: handlePageSizeChange,
isPending: false,
itemsPerPage: size,
setCurrentPage: setPage,
totalItems: machineCount ?? 0,
pageSizes: [VMS_PER_PAGE],
}}
setSorting={setSorting}
sorting={sorting}
/>
</ContextualMenu>
</div>
Expand Down
26 changes: 15 additions & 11 deletions src/app/kvm/components/VmResources/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,18 @@
100vw - #{(map.get($grid-gutter-widths, small) + $sph--large) * 2}
);

.fqdn-col,
.status-col {
width: 50%;
.fqdn,
.status {
width: 14rem;
}

.power-col,
.cores-col,
.ram-col {
.cpu {
text-align: right;
}

.power,
.cpu,
.ram {
display: none;
}

Expand All @@ -30,17 +34,17 @@
100vw - #{(map.get($grid-gutter-widths, default) + $sph--large) * 2}
);

.power-col {
.power {
display: table-cell;
width: 7rem;
width: 12rem;
}
}

@media only screen and (min-width: $breakpoint-small) {
width: 40rem;
width: 50rem;

.cores-col,
.ram-col {
.cpu,
.ram {
display: table-cell;
width: 5rem;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import SourceMachineDetails from "./SourceMachineDetails";
import DebounceSearchBox from "@/app/base/components/DebounceSearchBox";
import { MachineSelectTable } from "@/app/base/components/MachineSelectTable/MachineSelectTable";
import { useFetchActions } from "@/app/base/hooks";
import MachineListPagination from "@/app/machines/views/MachineList/MachineListTable/MachineListPagination";
import MachineListPagination from "@/app/machines/components/MachineListPagination";
import type { Machine, MachineDetails } from "@/app/store/machine/types";
import { FilterMachines } from "@/app/store/machine/utils";
import { useFetchMachines } from "@/app/store/machine/utils/hooks";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Meta } from "@storybook/react";

import MachineActionMenu from ".";
import MachineActionMenu from "./index";

const meta: Meta<typeof MachineActionMenu> = {
title: "Sections/Machine/MachineActionMenu",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import { Link } from "react-router";
import DebounceSearchBox from "@/app/base/components/DebounceSearchBox";
import GroupSelect from "@/app/base/components/GroupSelect";
import urls from "@/app/base/urls";
import HiddenColumnsSelect from "@/app/machines/components/MachineListControls/HiddenColumnsSelect";
import MachineActionMenu from "@/app/machines/components/MachineListControls/MachineActionMenu";
import MachinesFilterAccordion from "@/app/machines/components/MachineListControls/MachinesFilterAccordion";
import AddHardwareMenu from "@/app/machines/components/MachineListHeader/AddHardwareMenu";
import { groupOptions } from "@/app/machines/constants";
import type { MachineSetSidePanelContent } from "@/app/machines/types";
import HiddenColumnsSelect from "@/app/machines/views/MachineList/MachineListControls/HiddenColumnsSelect";
import MachineActionMenu from "@/app/machines/views/MachineList/MachineListControls/MachineActionMenu";
import MachinesFilterAccordion from "@/app/machines/views/MachineList/MachineListControls/MachinesFilterAccordion";
import AddHardwareMenu from "@/app/machines/views/MachineList/MachineListHeader/AddHardwareMenu";
import type { useResponsiveColumns } from "@/app/machines/views/MachineList/hooks";
import type { useResponsiveColumns } from "@/app/machines/views/MachinesList/hooks";
import { machineActions } from "@/app/store/machine";
import type { FetchGroupKey } from "@/app/store/machine/types";
import { useHasSelection } from "@/app/store/machine/utils/hooks";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { useCallback } from "react";

import { useDispatch } from "react-redux";

import type { useResponsiveColumns } from "../../views/MachinesList/hooks";
import MachineListControls from "../MachineListControls";
import type { useResponsiveColumns } from "../hooks";

import { usePoolCount } from "@/app/api/query/pools";
import type { SetSearchFilter } from "@/app/base/types";
Expand Down
Loading
Loading