Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
joseivanlopez committed Apr 10, 2024
1 parent 68aade4 commit c701cce
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 46 deletions.
2 changes: 1 addition & 1 deletion web/src/client/mixins.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ const WithStatus = (superclass, object_path) => class extends superclass {
* Register a callback to run when the "CurrentInstallationPhase" changes
*
* @param {function} handler - callback function
* @return {function} function to disable the callback
* @return {() => void} function to disable the callback
*/
onStatusChange(handler) {
return this.client.onObjectChanged(object_path, STATUS_IFACE, (changes) => {
Expand Down
40 changes: 32 additions & 8 deletions web/src/client/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ const ZFCP_DISK_IFACE = "org.opensuse.Agama.Storage1.ZFCP.Disk";
* @property {boolean} delete
*
* @typedef {object} ProposalSettings
* @property {string} target
* @property {ProposalTarget} target
* @property {string} [targetDevice]
* @property {string[]} targetPVDevices
* @property {boolean} configureBoot
Expand All @@ -124,6 +124,8 @@ const ZFCP_DISK_IFACE = "org.opensuse.Agama.Storage1.ZFCP.Disk";
* @property {Volume[]} volumes
* @property {StorageDevice[]} installationDevices
*
* @typedef {keyof ProposalTargets} ProposalTarget
*
* @typedef {object} SpaceAction
* @property {string} device
* @property {string} action
Expand Down Expand Up @@ -152,11 +154,16 @@ const ZFCP_DISK_IFACE = "org.opensuse.Agama.Storage1.ZFCP.Disk";
* @property {string[]} sizeRelevantVolumes
*/

// const ProposalTargets = Object.freeze({
// DISK: "disk",
// NEW_LVM_VG: "newLvmVg",
// REUSED_LVM_VG: "reusedLvmVg"
// });
/**
* Enum for the possible proposal targets.
*
* @readonly
*/
const ProposalTargets = Object.freeze({
DISK: "disk",
NEW_LVM_VG: "newLvmVg",
REUSED_LVM_VG: "reusedLvmVg"
});

/**
* Enum for the possible volume targets.
Expand Down Expand Up @@ -485,6 +492,23 @@ class ProposalManager {
};
};

/**
* Builds the proposal target from a D-Bus value.
*
* @param {string} dbusTarget
* @returns {ProposalTarget}
*/
const buildTarget = (dbusTarget) => {
switch (dbusTarget) {
case "disk": return "DISK";
case "newLvmVg": return "NEW_LVM_VG";
case "reusedLvmVg": return "REUSED_LVM_VG";
default:
console.log(`Unknown proposal target "${dbusTarget}", using "disk".`);
return "DISK";
}
};

const buildTargetPVDevices = dbusTargetPVDevices => {
if (!dbusTargetPVDevices) return [];

Expand Down Expand Up @@ -518,7 +542,7 @@ class ProposalManager {

return {
settings: {
target: dbusSettings.Target.v,
target: buildTarget(dbusSettings.Target.v),
targetDevice: dbusSettings.TargetDevice?.v,
targetPVDevices: buildTargetPVDevices(dbusSettings.TargetPVDevices),
configureBoot: dbusSettings.ConfigureBoot.v,
Expand Down Expand Up @@ -590,7 +614,7 @@ class ProposalManager {
};

const dbusSettings = removeUndefinedCockpitProperties({
Target: { t: "s", v: target },
Target: { t: "s", v: ProposalTargets[target] },
TargetDevice: { t: "s", v: targetDevice },
TargetPVDevices: { t: "as", v: targetPVDevices },
ConfigureBoot: { t: "b", v: configureBoot },
Expand Down
4 changes: 2 additions & 2 deletions web/src/client/storage.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1535,7 +1535,7 @@ describe("#proposal", () => {
const { settings, actions } = await client.proposal.getResult();

expect(settings).toMatchObject({
target: "newLvmVg",
target: "NEW_LVM_VG",
targetPVDevices: ["/dev/sda", "/dev/sdb"],
configureBoot: true,
bootDevice: "/dev/sda",
Expand Down Expand Up @@ -1615,7 +1615,7 @@ describe("#proposal", () => {

it("calculates a proposal with the given settings", async () => {
await client.proposal.calculate({
target: "disk",
target: "DISK",
targetDevice: "/dev/vdc",
configureBoot: true,
bootDevice: "/dev/vdb",
Expand Down
29 changes: 22 additions & 7 deletions web/src/components/overview/StorageSection.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
* find current contact information at www.suse.com.
*/

// @ts-check

import React, { useReducer, useEffect } from "react";
import { Text } from "@patternfly/react-core";

Expand All @@ -30,25 +32,37 @@ import { Em, ProgressText, Section } from "~/components/core";
import { sprintf } from "sprintf-js";
import { _, n_ } from "~/i18n";

/**
* @typedef {import ("~/client/storage").ProposalResult} ProposalResult
* @typedef {import ("~/client/storage").StorageDevice} StorageDevice
*
* @typedef {object} Proposal
* @property {StorageDevice[]} availableDevices
* @property {ProposalResult} result
*/

/**
* Text explaining the storage proposal
*
* FIXME: this needs to be basically rewritten. See
* https://github.com/openSUSE/agama/discussions/778#discussioncomment-7715244
*
* @param {object} props
* @param {Proposal} props.proposal
*/
const ProposalSummary = ({ proposal }) => {
const { availableDevices = [], result = {} } = proposal;
const { availableDevices, result } = proposal;

const label = (deviceName) => {
const device = availableDevices.find(d => d.name === deviceName);
return device ? deviceLabel(device) : deviceName;
};

if (result.settings?.target === "newLvmVg") {
if (result.settings.target === "NEW_LVM_VG") {
// TRANSLATORS: Part of the message describing where the system will be installed.
// Do not translate 'abbr' and 'title', they are part of the HTML markup.
const vg = _("<abbr title='Logical Volume Manager'>LVM</abbr> volume group");
const pvDevices = result.settings?.targetPVDevices;
const pvDevices = result.settings.targetPVDevices;
const fullMsg = (policy, num_pvs) => {
switch (policy) {
case "resize":
Expand Down Expand Up @@ -86,7 +100,7 @@ const ProposalSummary = ({ proposal }) => {
}
};

const msg = sprintf(fullMsg(result.settings?.spacePolicy, pvDevices.length), vg, "%dev%");
const msg = sprintf(fullMsg(result.settings.spacePolicy, pvDevices.length), vg, "%dev%");

if (pvDevices.length > 1) {
return (<span dangerouslySetInnerHTML={{ __html: msg }} />);
Expand All @@ -103,7 +117,7 @@ const ProposalSummary = ({ proposal }) => {
}
}

const targetDevice = result.settings?.targetDevice;
const targetDevice = result.settings.targetDevice;
if (!targetDevice) return <Text>{_("No device selected yet")}</Text>;

const fullMsg = (policy) => {
Expand All @@ -127,7 +141,7 @@ const ProposalSummary = ({ proposal }) => {
return _("Install using device %s with a custom strategy to find the needed space");
};

const [msg1, msg2] = fullMsg(result.settings?.spacePolicy).split("%s");
const [msg1, msg2] = fullMsg(result.settings.spacePolicy).split("%s");

return (
<Text>
Expand Down Expand Up @@ -183,6 +197,7 @@ const reducer = (state, action) => {
export default function StorageSection({ showErrors = false }) {
const { storage: client } = useInstallerClient();
const { cancellablePromise } = useCancellablePromise();
/** @type {[object, (action: object) => void]} */
const [state, dispatch] = useReducer(reducer, initialState);

useEffect(() => {
Expand Down Expand Up @@ -258,7 +273,7 @@ export default function StorageSection({ showErrors = false }) {
}

return (
<ProposalSummary proposal={state.proposal || {}} />
<ProposalSummary proposal={state.proposal} />
);
};

Expand Down
2 changes: 2 additions & 0 deletions web/src/components/storage/BootSelectionDialog.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
* find current contact information at www.suse.com.
*/

// @ts-check

import React from "react";
import { screen, within } from "@testing-library/react";
import { plainRender } from "~/test-utils";
Expand Down
11 changes: 6 additions & 5 deletions web/src/components/storage/DeviceSelectionDialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { DeviceSelectorTable } from "~/components/storage";
import { noop } from "~/utils";

/**
* @typedef {import ("~/client/storage").ProposalTarget} ProposalTarget
* @typedef {import ("~/client/storage").ProposalSettings} ProposalSettings
* @typedef {import ("~/client/storage").StorageDevice} StorageDevice
*/
Expand All @@ -50,7 +51,7 @@ const Html = ({ children, ...props }) => (
* @component
*
* @param {object} props
* @param {string} props.target
* @param {ProposalTarget} props.target
* @param {StorageDevice|undefined} props.targetDevice
* @param {StorageDevice[]} props.targetPVDevices
* @param {StorageDevice[]} props.devices - The actions to perform in the system.
Expand Down Expand Up @@ -78,11 +79,11 @@ export default function DeviceSelectionDialog({
const [targetDevice, setTargetDevice] = useState(defaultTargetDevice);
const [targetPVDevices, setTargetPVDevices] = useState(defaultPVDevices);

const isTargetDisk = target === "disk";
const isTargetNewLvmVg = target === "newLvmVg";
const isTargetDisk = target === "DISK";
const isTargetNewLvmVg = target === "NEW_LVM_VG";

const selectTargetDisk = () => setTarget("disk");
const selectTargetNewLvmVG = () => setTarget("newLvmVg");
const selectTargetDisk = () => setTarget("DISK");
const selectTargetNewLvmVG = () => setTarget("NEW_LVM_VG");

const selectTargetDevice = (devices) => setTargetDevice(devices[0]);

Expand Down
16 changes: 9 additions & 7 deletions web/src/components/storage/DeviceSelectionDialog.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
* find current contact information at www.suse.com.
*/

// @ts-check

import React from "react";
import { screen, within } from "@testing-library/react";
import { plainRender } from "~/test-utils";
Expand Down Expand Up @@ -121,7 +123,7 @@ describe("DeviceSelectionDialog", () => {
beforeEach(() => {
props = {
isOpen: true,
target: "disk",
target: "DISK",
targetPVDevices: [],
devices: [sda, sdb, sdc],
onCancel: jest.fn(),
Expand All @@ -141,7 +143,7 @@ describe("DeviceSelectionDialog", () => {

describe("if the target is a disk", () => {
beforeEach(() => {
props.target = "disk";
props.target = "DISK";
props.targetDevice = sda;
});

Expand Down Expand Up @@ -188,7 +190,7 @@ describe("DeviceSelectionDialog", () => {

describe("if the target is a new LVM volume group", () => {
beforeEach(() => {
props.target = "newLvmVg";
props.target = "NEW_LVM_VG";
props.targetPVDevices = [sda, sdc];
});

Expand Down Expand Up @@ -244,7 +246,7 @@ describe("DeviceSelectionDialog", () => {

describe("if the option to select a disk as target device is selected", () => {
beforeEach(() => {
props.target = "newLvmVg";
props.target = "NEW_LVM_VG";
props.targetDevice = sda;
});

Expand All @@ -261,7 +263,7 @@ describe("DeviceSelectionDialog", () => {
await user.click(accept);

expect(props.onAccept).toHaveBeenCalledWith({
target: "disk",
target: "DISK",
targetDevice: sdb,
targetPVDevices: []
});
Expand All @@ -270,7 +272,7 @@ describe("DeviceSelectionDialog", () => {

describe("if the option to create a new LVM volume group is selected", () => {
beforeEach(() => {
props.target = "disk";
props.target = "DISK";
props.targetDevice = sdb;
});

Expand All @@ -288,7 +290,7 @@ describe("DeviceSelectionDialog", () => {
await user.click(accept);

expect(props.onAccept).toHaveBeenCalledWith({
target: "newLvmVg",
target: "NEW_LVM_VG",
targetDevice: sdb,
targetPVDevices: [sda, sdc]
});
Expand Down
15 changes: 8 additions & 7 deletions web/src/components/storage/ProposalDeviceSection.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { sprintf } from "sprintf-js";
import { compact, noop } from "~/utils";

/**
* @typedef {import ("~/client/storage").ProposalTarget} ProposalTarget
* @typedef {import ("~/client/storage").ProposalSettings} ProposalSettings
* @typedef {import ("~/client/storage").StorageDevice} StorageDevice
*/
Expand All @@ -43,15 +44,15 @@ import { compact, noop } from "~/utils";
* Renders a button that allows changing the target device for installation.
*
* @param {object} props
* @param {string} props.target
* @param {ProposalTarget} props.target
* @param {StorageDevice|undefined} props.targetDevice
* @param {StorageDevice[]} props.targetPVDevices
* @param {import("react").MouseEventHandler<HTMLButtonElement>} [props.onClick=noop]
*/
const TargetDeviceButton = ({ target, targetDevice, targetPVDevices, onClick = noop }) => {
const label = () => {
if (target === "disk" && targetDevice) return deviceLabel(targetDevice);
if (target === "newLvmVg" && targetPVDevices.length > 0) {
if (target === "DISK" && targetDevice) return deviceLabel(targetDevice);
if (target === "NEW_LVM_VG" && targetPVDevices.length > 0) {
if (targetPVDevices.length > 1) return _("new LVM volume group");

if (targetPVDevices.length === 1) {
Expand All @@ -75,15 +76,15 @@ const TargetDeviceButton = ({ target, targetDevice, targetPVDevices, onClick = n
* @component
*
* @param {object} props
* @param {string} props.target - Installation target ("disk", "newLvmVg", "reusedLvmVg").
* @param {StorageDevice|undefined} props.targetDevice - Target device (for target "disk").
* @param {StorageDevice[]} props.targetPVDevices - Target devices for the LVM volume group (target "newLvmVg").
* @param {ProposalTarget} props.target - Installation target
* @param {StorageDevice|undefined} props.targetDevice - Target device (for target "DISK").
* @param {StorageDevice[]} props.targetPVDevices - Target devices for the LVM volume group (target "NEW_LVM_VG").
* @param {StorageDevice[]} props.devices - Available devices for installation.
* @param {boolean} props.isLoading
* @param {(target: Target) => void} props.onChange
*
* @typedef {object} Target
* @property {string} target
* @property {ProposalTarget} target
* @property {StorageDevice|undefined} targetDevice
* @property {StorageDevice[]} targetPVDevices
*/
Expand Down
Loading

0 comments on commit c701cce

Please sign in to comment.