Skip to content

Commit

Permalink
feat: move VLAN inline forms to side panel (#5404)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jay-Topher authored Apr 15, 2024
1 parent 6e5cd2f commit 6b17292
Show file tree
Hide file tree
Showing 11 changed files with 197 additions and 165 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ it("correctly initialises data if the VLAN has DHCP from rack controllers", asyn
// Wait for Formik validateOnMount to run.
await waitFor(() => {
expect(
screen.getByRole("region", { name: "Configure DHCP" })
screen.getByRole("form", { name: "Configure DHCP" })
).toBeInTheDocument();
});

Expand Down Expand Up @@ -90,7 +90,7 @@ it("correctly initialises data if the VLAN has relayed DHCP", async () => {
// Wait for Formik validateOnMount to run.
await waitFor(() => {
expect(
screen.getByRole("region", { name: "Configure DHCP" })
screen.getByRole("form", { name: "Configure DHCP" })
).toBeInTheDocument();
});

Expand Down Expand Up @@ -127,7 +127,7 @@ it("shows an error if no rack controllers are connected to the VLAN", async () =
});

expect(
screen.getByRole("region", { name: "Configure DHCP" })
screen.getByRole("form", { name: "Configure DHCP" })
).toBeInTheDocument();

expect(
Expand Down
154 changes: 76 additions & 78 deletions src/app/subnets/views/VLANDetails/ConfigureDHCP/ConfigureDHCP.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { useCallback } from "react";

import { ExternalLink } from "@canonical/maas-react-components";
import { Card, Spinner } from "@canonical/react-components";
import { Spinner } from "@canonical/react-components";
import { useDispatch, useSelector } from "react-redux";
import * as Yup from "yup";

import ConfigureDHCPFields from "./ConfigureDHCPFields";
import DHCPReservedRanges from "./DHCPReservedRanges";

import FormikForm from "@/app/base/components/FormikForm";
import TitledSection from "@/app/base/components/TitledSection";
import docsUrls from "@/app/base/docsUrls";
import { useFetchActions, useCycled } from "@/app/base/hooks";
import { controllerActions } from "@/app/store/controller";
Expand Down Expand Up @@ -158,83 +157,82 @@ const ConfigureDHCP = ({ closeForm, id }: Props): JSX.Element | null => {
});

return (
<Card>
<TitledSection className="u-no-padding" title="Configure DHCP">
{loading ? (
<span data-testid="loading-data">
<Spinner text="Loading..." />
</span>
) : (
<FormikForm<ConfigureDHCPValues>
allowUnchanged
buttonsHelp={
<ExternalLink to={docsUrls.dhcp}>About DHCP</ExternalLink>
}
cleanup={cleanup}
errors={configureDHCPError}
initialValues={{
dhcpType: isId(vlan.relay_vlan)
? DHCPType.RELAY
: DHCPType.CONTROLLERS,
enableDHCP: true,
endIP: "",
gatewayIP: "",
primaryRack: vlan.primary_rack || "",
relayVLAN: vlan.relay_vlan || "",
secondaryRack: vlan.secondary_rack || "",
startIP: "",
subnet: "",
}}
onCancel={closeForm}
onSaveAnalytics={{
action: "Configure DHCP",
category: "VLAN details",
label: "Configure DHCP form",
}}
onSubmit={(values) => {
resetConfiguredDHCP();
dispatch(cleanup());
const { enableDHCP, primaryRack, relayVLAN, secondaryRack } =
values;
const params: ConfigureDHCPParams = {
controllers: [],
id: vlan.id,
relay_vlan: null,
};
if (enableDHCP) {
if (primaryRack) {
params.controllers.push(primaryRack);
}
if (secondaryRack) {
params.controllers.push(secondaryRack);
}
if (isId(relayVLAN)) {
params.relay_vlan = Number(relayVLAN);
}
if (isId(values.subnet)) {
params.extra = {
end: values.endIP,
gateway: values.gatewayIP,
start: values.startIP,
subnet: Number(values.subnet),
};
}
<>
{loading ? (
<span data-testid="loading-data">
<Spinner text="Loading..." />
</span>
) : (
<FormikForm<ConfigureDHCPValues>
allowUnchanged
aria-label="Configure DHCP"
buttonsHelp={
<ExternalLink to={docsUrls.dhcp}>About DHCP</ExternalLink>
}
cleanup={cleanup}
errors={configureDHCPError}
initialValues={{
dhcpType: isId(vlan.relay_vlan)
? DHCPType.RELAY
: DHCPType.CONTROLLERS,
enableDHCP: true,
endIP: "",
gatewayIP: "",
primaryRack: vlan.primary_rack || "",
relayVLAN: vlan.relay_vlan || "",
secondaryRack: vlan.secondary_rack || "",
startIP: "",
subnet: "",
}}
onCancel={closeForm}
onSaveAnalytics={{
action: "Configure DHCP",
category: "VLAN details",
label: "Configure DHCP form",
}}
onSubmit={(values) => {
resetConfiguredDHCP();
dispatch(cleanup());
const { enableDHCP, primaryRack, relayVLAN, secondaryRack } =
values;
const params: ConfigureDHCPParams = {
controllers: [],
id: vlan.id,
relay_vlan: null,
};
if (enableDHCP) {
if (primaryRack) {
params.controllers.push(primaryRack);
}
if (secondaryRack) {
params.controllers.push(secondaryRack);
}
dispatch(vlanActions.configureDHCP(params));
}}
onSuccess={() => closeForm()}
saved={saved}
saving={configuringDHCP}
submitLabel="Configure DHCP"
validateOnMount
validationSchema={Schema}
>
<ConfigureDHCPFields vlan={vlan} />
<DHCPReservedRanges id={vlan.id} />
</FormikForm>
)}
</TitledSection>
</Card>
if (isId(relayVLAN)) {
params.relay_vlan = Number(relayVLAN);
}
if (isId(values.subnet)) {
params.extra = {
end: values.endIP,
gateway: values.gatewayIP,
start: values.startIP,
subnet: Number(values.subnet),
};
}
}
dispatch(vlanActions.configureDHCP(params));
}}
onSuccess={() => closeForm()}
saved={saved}
saving={configuringDHCP}
submitLabel="Configure DHCP"
validateOnMount
validationSchema={Schema}
>
<ConfigureDHCPFields vlan={vlan} />
<DHCPReservedRanges id={vlan.id} />
</FormikForm>
)}
</>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const ConfigureDHCPFields = ({ vlan }: Props): JSX.Element => {

return (
<Row>
<Col size={6}>
<Col size={12}>
<FormikField
label="MAAS provides DHCP"
name="enableDHCP"
Expand Down
16 changes: 8 additions & 8 deletions src/app/subnets/views/VLANDetails/DHCPStatus/DHCPStatus.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ it("shows a spinner if data is loading", () => {
render(
<Provider store={store}>
<MemoryRouter>
<DHCPStatus id={1} openForm={vi.fn()} />
<DHCPStatus id={1} />
</MemoryRouter>
</Provider>
);
Expand All @@ -38,7 +38,7 @@ it(`shows a warning and disables Configure DHCP button if there are no subnets
render(
<Provider store={store}>
<MemoryRouter>
<DHCPStatus id={vlan.id} openForm={vi.fn()} />
<DHCPStatus id={vlan.id} />
</MemoryRouter>
</Provider>
);
Expand Down Expand Up @@ -66,7 +66,7 @@ it("does not show a warning if there are subnets attached to the VLAN", () => {
render(
<Provider store={store}>
<MemoryRouter>
<DHCPStatus id={vlan.id} openForm={vi.fn()} />
<DHCPStatus id={vlan.id} />
</MemoryRouter>
</Provider>
);
Expand All @@ -92,7 +92,7 @@ it("renders correctly when a VLAN does not have DHCP enabled", () => {
render(
<Provider store={store}>
<MemoryRouter>
<DHCPStatus id={vlan.id} openForm={vi.fn()} />
<DHCPStatus id={vlan.id} />
</MemoryRouter>
</Provider>
);
Expand All @@ -116,7 +116,7 @@ it("renders correctly when a VLAN has external DHCP", () => {
render(
<Provider store={store}>
<MemoryRouter>
<DHCPStatus id={vlan.id} openForm={vi.fn()} />
<DHCPStatus id={vlan.id} />
</MemoryRouter>
</Provider>
);
Expand Down Expand Up @@ -148,7 +148,7 @@ it("renders correctly when a VLAN has relayed DHCP", () => {
render(
<Provider store={store}>
<MemoryRouter>
<DHCPStatus id={vlan.id} openForm={vi.fn()} />
<DHCPStatus id={vlan.id} />
</MemoryRouter>
</Provider>
);
Expand Down Expand Up @@ -178,7 +178,7 @@ it("renders correctly when a VLAN has MAAS-configured DHCP without high availabi
render(
<Provider store={store}>
<MemoryRouter>
<DHCPStatus id={vlan.id} openForm={vi.fn()} />
<DHCPStatus id={vlan.id} />
</MemoryRouter>
</Provider>
);
Expand Down Expand Up @@ -225,7 +225,7 @@ it("renders correctly when a VLAN has MAAS-configured DHCP with high availabilit
render(
<Provider store={store}>
<MemoryRouter>
<DHCPStatus id={vlan.id} openForm={vi.fn()} />
<DHCPStatus id={vlan.id} />
</MemoryRouter>
</Provider>
);
Expand Down
13 changes: 10 additions & 3 deletions src/app/subnets/views/VLANDetails/DHCPStatus/DHCPStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import Definition from "@/app/base/components/Definition";
import TitledSection from "@/app/base/components/TitledSection";
import docsUrls from "@/app/base/docsUrls";
import { useFetchActions } from "@/app/base/hooks";
import { SidePanelViews, useSidePanel } from "@/app/base/side-panel-context";
import urls from "@/app/base/urls";
import { fabricActions } from "@/app/store/fabric";
import fabricSelectors from "@/app/store/fabric/selectors";
Expand All @@ -29,7 +30,6 @@ import { isId } from "@/app/utils";

type Props = {
id: VLAN[VLANMeta.PK] | null;
openForm: () => void;
};

// Note this is not the same as the getDHCPStatus VLAN util as it uses slightly
Expand All @@ -54,7 +54,8 @@ const getDHCPStatus = (vlan: VLAN, vlans: VLAN[], fabrics: Fabric[]) => {
return "Disabled";
};

const DHCPStatus = ({ id, openForm }: Props): JSX.Element | null => {
const DHCPStatus = ({ id }: Props): JSX.Element | null => {
const { setSidePanelContent, setSidePanelSize } = useSidePanel();
const fabrics = useSelector(fabricSelectors.all);
const fabricsLoading = useSelector(fabricSelectors.loading);
const vlans = useSelector(vlanSelectors.all);
Expand Down Expand Up @@ -91,7 +92,13 @@ const DHCPStatus = ({ id, openForm }: Props): JSX.Element | null => {
return (
<TitledSection
buttons={
<Button disabled={!hasVLANSubnets} onClick={openForm}>
<Button
disabled={!hasVLANSubnets}
onClick={() => {
setSidePanelSize("large");
setSidePanelContent({ view: SidePanelViews.ConfigureDHCP });
}}
>
Configure DHCP
</Button>
}
Expand Down
4 changes: 2 additions & 2 deletions src/app/subnets/views/VLANDetails/EditVLAN/EditVLAN.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ const EditVLAN = ({ close, id, ...props }: Props): JSX.Element | null => {
{...props}
>
<Row>
<Col size={6}>
<Col size={12}>
<FormikField label="VID" name="vid" required type="text" />
<FormikField label="Name" name="name" type="text" />
<FormikField label="MTU" name="mtu" type="text" />
Expand All @@ -117,7 +117,7 @@ const EditVLAN = ({ close, id, ...props }: Props): JSX.Element | null => {
name="description"
/>
</Col>
<Col size={6}>
<Col size={12}>
<SpaceSelect
defaultOption={{ label: getSpaceDisplay(null), value: "" }}
name="space"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import type { SetSidePanelContent } from "@/app/base/side-panel-context";
import ConfigureDHCP from "../ConfigureDHCP";
import EditVLAN from "../EditVLAN";

import { type SetSidePanelContent } from "@/app/base/side-panel-context";
import type { Subnet, SubnetMeta } from "@/app/store/subnet/types";
import type { VLAN, VLANMeta } from "@/app/store/vlan/types";
import ReservedRangeDeleteForm from "@/app/subnets/components/ReservedRangeDeleteForm";
Expand Down Expand Up @@ -26,19 +29,30 @@ const VLANActionForms = ({
subnetId,
vlanId,
}: VLANActionFormProps) => {
const ActionForm = actionForms[activeForm];
const clearSidePanelContent = () => setSidePanelContent(null);

if (!ActionForm) {
return null;
}
switch (activeForm) {
case VLANActionTypes.ConfigureDHCP: {
return <ConfigureDHCP closeForm={clearSidePanelContent} id={vlanId} />;
}
case VLANActionTypes.EditVLAN:
return <EditVLAN close={clearSidePanelContent} id={vlanId} />;

return (
<ActionForm
setSidePanelContent={setSidePanelContent}
subnetId={subnetId}
vlanId={vlanId}
/>
);
default: {
const ActionForm = actionForms[activeForm];

if (!ActionForm) {
return null;
}
return (
<ActionForm
setSidePanelContent={setSidePanelContent}
subnetId={subnetId}
vlanId={vlanId}
/>
);
}
}
};

export default VLANActionForms;
Loading

0 comments on commit 6b17292

Please sign in to comment.