Skip to content

Commit

Permalink
[web] Create a section for file systems
Browse files Browse the repository at this point in the history
And mount there the storage/ProposalVolumes component instead of doing
so in the settings section.

Note that, most probably, the code of ProposalFileSystemsSection and
ProposalVolumes could be merged in a single component.
  • Loading branch information
dgdavid committed Feb 21, 2024
1 parent e431192 commit 2491bf4
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 26 deletions.
80 changes: 80 additions & 0 deletions web/src/components/storage/ProposalFileSystemsSection.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright (c) [2024] SUSE LLC
*
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, contact SUSE LLC.
*
* To contact SUSE LLC about this file by physical or electronic mail, you may
* find current contact information at www.suse.com.
*/

import React from "react";
import { _ } from "~/i18n";
import { Section } from "~/components/core";
import { ProposalVolumes } from "~/components/storage";
import { noop } from "~/utils";

/**
* @typedef {import ("~/client/storage").ProposalManager.ProposalSettings} ProposalSettings
* @typedef {import ("~/client/storage").ProposalManager.Volume} Volume
*/

/**
* Section for editing the proposal file systems
* @component
*
* @callback onChangeFn
* @param {object} settings
*
* @param {object} props
* @param {ProposalSettings} props.settings
* @param {Volume[]} [props.volumeTemplates=[]]
* @param {boolean} [props.isLoading=false]
* @param {onChangeFn} [props.onChange=noop]
*
*/
export default function ProposalFileSystemsSection({
settings,
volumeTemplates = [],
isLoading = false,
onChange = noop
}) {
const { volumes = [] } = settings;

const changeVolumes = (volumes) => {
onChange({ volumes });
};

// Templates for already existing mount points are filtered out
const usefulTemplates = () => {
const mountPaths = volumes.map(v => v.mountPath);
return volumeTemplates.filter(t => (
t.mountPath.length > 0 && !mountPaths.includes(t.mountPath)
));
};

const encryption = settings.encryptionPassword !== undefined && settings.encryptionPassword.length > 0;

return (
<Section title={_("File systems")}>
<ProposalVolumes
volumes={volumes}
templates={usefulTemplates()}
options={{ lvm: settings.lvm, encryption }}
isLoading={isLoading && settings.volumes === undefined}
onChange={changeVolumes}
/>
</Section>
);
}
54 changes: 54 additions & 0 deletions web/src/components/storage/ProposalFileSystemsSection.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright (c) [2024] SUSE LLC
*
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, contact SUSE LLC.
*
* To contact SUSE LLC about this file by physical or electronic mail, you may
* find current contact information at www.suse.com.
*/

import React from "react";
import { screen, within } from "@testing-library/react";
import { plainRender } from "~/test-utils";
import { ProposalFileSystemsSection } from "~/components/storage";

const props = {
settings: {},
isLoading: false,
onChange: jest.fn()
};

describe("ProposalFileSystemsSection", () => {
it("renders a section holding file systems related stuff", () => {
plainRender(<ProposalFileSystemsSection {...props} />);
screen.getByRole("region", { name: "File systems" });
});

it("requests a volume change when onChange callback is triggered", async () => {
const { user } = plainRender(<ProposalFileSystemsSection {...props} />);
const button = screen.getByRole("button", { name: "Actions" });

await user.click(button);

const menu = screen.getByRole("menu");
const reset = within(menu).getByRole("menuitem", { name: /Reset/ });

await user.click(reset);

expect(props.onChange).toHaveBeenCalledWith(
expect.objectContaining({ volumes: expect.any(Array) })
);
});
});
17 changes: 7 additions & 10 deletions web/src/components/storage/ProposalPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {
ProposalSettingsSection,
ProposalSpacePolicySection,
ProposalDeviceSection,
ProposalFileSystemsSection
} from "~/components/storage";
import { IDLE } from "~/client/status";

Expand Down Expand Up @@ -200,15 +201,6 @@ export default function ProposalPage() {
};

const PageContent = () => {
// Templates for already existing mount points are filtered out
const usefulTemplates = () => {
const volumes = state.settings.volumes || [];
const mountPaths = volumes.map(v => v.mountPath);
return state.volumeTemplates.filter(t => (
t.mountPath.length > 0 && !mountPaths.includes(t.mountPath)
));
};

return (
<>
<Alert
Expand All @@ -224,12 +216,17 @@ export default function ProposalPage() {
/>
<ProposalSettingsSection
availableDevices={state.availableDevices}
volumeTemplates={usefulTemplates()}
encryptionMethods={state.encryptionMethods}
settings={state.settings}
onChange={changeSettings}
isLoading={state.loading}
/>
<ProposalFileSystemsSection
settings={state.settings}
volumeTemplates={state.volumeTemplates}
onChange={changeSettings}
isLoading={state.loading}
/>
<ProposalSpacePolicySection
settings={state.settings}
onChange={changeSettings}
Expand Down
17 changes: 1 addition & 16 deletions web/src/components/storage/ProposalSettingsSection.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {

import { _ } from "~/i18n";
import { If, PasswordAndConfirmationInput, Section, Popup } from "~/components/core";
import { DeviceList, DeviceSelector, ProposalVolumes } from "~/components/storage";
import { DeviceList, DeviceSelector } from "~/components/storage";
import { Icon } from "~/components/layout";
import { noop } from "~/utils";

Expand Down Expand Up @@ -423,9 +423,7 @@ const EncryptionField = ({
* @param {object} props
* @param {ProposalSettings} props.settings
* @param {StorageDevice[]} [props.availableDevices=[]]
* @param {Volume[]} [props.volumeTemplates=[]]
* @param {String[]} [props.encryptionMethods=[]]
* @param {boolean} [isLoading=false]
* @param {onChangeFn} [props.onChange=noop]
*
* @callback onChangeFn
Expand All @@ -434,9 +432,7 @@ const EncryptionField = ({
export default function ProposalSettingsSection({
settings,
availableDevices = [],
volumeTemplates = [],
encryptionMethods = [],
isLoading = false,
onChange = noop
}) {
const changeLVM = ({ lvm, vgDevices }) => {
Expand All @@ -451,10 +447,6 @@ export default function ProposalSettingsSection({
onChange({ encryptionPassword: password, encryptionMethod: method });
};

const changeVolumes = (volumes) => {
onChange({ volumes });
};

const encryption = settings.encryptionPassword !== undefined && settings.encryptionPassword.length > 0;

return (
Expand All @@ -475,13 +467,6 @@ export default function ProposalSettingsSection({
isLoading={settings.encryptionPassword === undefined}
onChange={changeEncryption}
/>
<ProposalVolumes
volumes={settings.volumes || []}
templates={volumeTemplates}
options={{ lvm: settings.lvm, encryption }}
isLoading={isLoading && settings.volumes === undefined}
onChange={changeVolumes}
/>
</Section>
</>
);
Expand Down
1 change: 1 addition & 0 deletions web/src/components/storage/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export { default as ProposalPageMenu } from "./ProposalPageMenu";
export { default as ProposalSettingsSection } from "./ProposalSettingsSection";
export { default as ProposalSpacePolicySection } from "./ProposalSpacePolicySection";
export { default as ProposalDeviceSection } from "./ProposalDeviceSection";
export { default as ProposalFileSystemsSection } from "./ProposalFileSystemsSection";
export { default as ProposalActionsSection } from "./ProposalActionsSection";
export { default as ProposalVolumes } from "./ProposalVolumes";
export { default as DASDPage } from "./DASDPage";
Expand Down

0 comments on commit 2491bf4

Please sign in to comment.