diff --git a/web/src/components/overview/OverviewPage.tsx b/web/src/components/overview/OverviewPage.tsx
index 299f9081f6..f72e598b25 100644
--- a/web/src/components/overview/OverviewPage.tsx
+++ b/web/src/components/overview/OverviewPage.tsx
@@ -37,6 +37,7 @@ import {
import { Link } from "react-router-dom";
import { Page } from "~/components/core";
import L10nSection from "./L10nSection";
+import StorageSection from "./StorageSection";
import SoftwareSection from "./SoftwareSection";
import { _ } from "~/i18n";
import { useAllIssues } from "~/queries/issues";
@@ -100,6 +101,7 @@ const OverviewSection = () => (
>
+
diff --git a/web/src/components/overview/StorageSection.test.tsx b/web/src/components/overview/StorageSection.test.tsx
index 742ed461c5..bc85cd1fdd 100644
--- a/web/src/components/overview/StorageSection.test.tsx
+++ b/web/src/components/overview/StorageSection.test.tsx
@@ -24,27 +24,36 @@ import React from "react";
import { screen } from "@testing-library/react";
import { plainRender } from "~/test-utils";
import { StorageSection } from "~/components/overview";
+import * as ConfigModel from "~/storage/model/config";
-const mockAvailableDevices = [
+const mockDevices = [
{ name: "/dev/sda", size: 536870912000 },
{ name: "/dev/sdb", size: 697932185600 },
];
-const mockResultSettings = { target: "disk", targetDevice: "/dev/sda", spacePolicy: "delete" };
+const mockConfig = { devices: [] as ConfigModel.Device[] };
jest.mock("~/queries/storage", () => ({
...jest.requireActual("~/queries/storage"),
- useAvailableDevices: () => mockAvailableDevices,
- useProposalResult: () => ({
- settings: mockResultSettings,
- actions: [],
- }),
+ useDevices: () => mockDevices,
+ useConfigDevices: () => mockConfig.devices,
}));
-describe("when there is a proposal", () => {
+describe("when the configuration does not include any device", () => {
beforeEach(() => {
- mockResultSettings.target = "disk";
- mockResultSettings.spacePolicy = "delete";
+ mockConfig.devices = [];
+ });
+
+ it("indicates that a device is not selected", async () => {
+ plainRender();
+
+ await screen.findByText(/No device selected/);
+ });
+});
+
+describe("when the configuration contains one drive", () => {
+ beforeEach(() => {
+ mockConfig.devices = [{ name: "/dev/sda", spacePolicy: "delete" }];
});
it("renders the proposal summary", async () => {
@@ -57,9 +66,7 @@ describe("when there is a proposal", () => {
describe("and the space policy is set to 'resize'", () => {
beforeEach(() => {
- // const result = { settings: { spacePolicy: "resize", targetDevice: "/dev/sda" } };
- mockResultSettings.spacePolicy = "resize";
- mockResultSettings.targetDevice = "/dev/sda";
+ mockConfig.devices[0].spacePolicy = "resize";
});
it("indicates that partitions may be shrunk", async () => {
@@ -71,8 +78,7 @@ describe("when there is a proposal", () => {
describe("and the space policy is set to 'keep'", () => {
beforeEach(() => {
- mockResultSettings.spacePolicy = "keep";
- mockResultSettings.targetDevice = "/dev/sda";
+ mockConfig.devices[0].spacePolicy = "keep";
});
it("indicates that partitions will be kept", async () => {
@@ -82,9 +88,9 @@ describe("when there is a proposal", () => {
});
});
- describe("and there is no target device", () => {
+ describe("and the drive matches no disk", () => {
beforeEach(() => {
- mockResultSettings.targetDevice = "";
+ mockConfig.devices[0].name = null;
});
it("indicates that a device is not selected", async () => {
@@ -94,3 +100,19 @@ describe("when there is a proposal", () => {
});
});
});
+
+describe("when the configuration contains several drives", () => {
+ beforeEach(() => {
+ mockConfig.devices = [
+ { name: "/dev/sda", spacePolicy: "delete" },
+ { name: "/dev/sdb", spacePolicy: "delete" },
+ ];
+ });
+
+ it("renders the proposal summary", async () => {
+ plainRender();
+
+ await screen.findByText(/Install using several devices/);
+ await screen.findByText(/and deleting all its content/);
+ });
+});
diff --git a/web/src/components/overview/StorageSection.tsx b/web/src/components/overview/StorageSection.tsx
index 3e514a03ba..5dad33f41c 100644
--- a/web/src/components/overview/StorageSection.tsx
+++ b/web/src/components/overview/StorageSection.tsx
@@ -25,75 +25,8 @@ import { Text, TextContent, TextVariants } from "@patternfly/react-core";
import { deviceLabel } from "~/components/storage/utils";
import { Em } from "~/components/core";
import { _ } from "~/i18n";
-import { useAvailableDevices, useProposalResult } from "~/queries/storage";
-import { ProposalTarget } from "~/types/storage";
-
-/**
- * Build a translated summary string for installing on an LVM with multiple
- * physical partitions/disks
- * @param policy - Find space policy
- * @returns Translated description
- */
-const msgLvmMultipleDisks = (policy: string): string => {
- switch (policy) {
- case "resize":
- // TRANSLATORS: installing on an LVM with multiple physical partitions/disks
- return _(
- "Install in a new Logical Volume Manager (LVM) volume group shrinking existing partitions at the underlying devices as needed",
- );
- case "keep":
- // TRANSLATORS: installing on an LVM with multiple physical partitions/disks
- return _(
- "Install in a new Logical Volume Manager (LVM) volume group without modifying the partitions at the underlying devices",
- );
- case "delete":
- // TRANSLATORS: installing on an LVM with multiple physical partitions/disks
- return _(
- "Install in a new Logical Volume Manager (LVM) volume group deleting all the content of the underlying devices",
- );
- case "custom":
- // TRANSLATORS: installing on an LVM with multiple physical partitions/disks
- return _(
- "Install in a new Logical Volume Manager (LVM) volume group using a custom strategy to find the needed space at the underlying devices",
- );
- }
-};
-
-/**
- * Build a translated summary string for installing on an LVM with a single
- * physical partition/disk
- * @param policy - Find space policy
- * @returns Translated description with %s placeholder for the device
- * name
- */
-const msgLvmSingleDisk = (policy: string): string => {
- switch (policy) {
- case "resize":
- // TRANSLATORS: installing on an LVM with a single physical partition/disk,
- // %s will be replaced by a device name and its size (eg. "/dev/sda, 20 GiB")
- return _(
- "Install in a new Logical Volume Manager (LVM) volume group on %s shrinking existing partitions as needed",
- );
- case "keep":
- // TRANSLATORS: installing on an LVM with a single physical partition/disk,
- // %s will be replaced by a device name and its size (eg. "/dev/sda, 20 GiB")
- return _(
- "Install in a new Logical Volume Manager (LVM) volume group on %s without modifying existing partitions",
- );
- case "delete":
- // TRANSLATORS: installing on an LVM with a single physical partition/disk,
- // %s will be replaced by a device name and its size (eg. "/dev/sda, 20 GiB")
- return _(
- "Install in a new Logical Volume Manager (LVM) volume group on %s deleting all its content",
- );
- case "custom":
- // TRANSLATORS: installing on an LVM with a single physical partition/disk,
- // %s will be replaced by a device name and its size (eg. "/dev/sda, 20 GiB")
- return _(
- "Install in a new Logical Volume Manager (LVM) volume group on %s using a custom strategy to find the needed space",
- );
- }
-};
+import { useDevices, useConfigDevices } from "~/queries/storage";
+import * as ConfigModel from "~/storage/model/config";
const Content = ({ children }) => (
@@ -105,80 +38,74 @@ const Content = ({ children }) => (
/**
* 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
+ * TODO: The current implementation assumes there are only drives and no other kind of devices like
+ * LVM volume groups or MD raids. Support for more cases (like LVM installation) will be added as
+ * the rest of the interface is also adapted.
*/
export default function StorageSection() {
- const availableDevices = useAvailableDevices();
- const result = useProposalResult();
+ const drives = useConfigDevices();
+ const devices = useDevices("system", { suspense: true });
- if (result === undefined) return;
-
- const label = (deviceName) => {
- const device = availableDevices.find((d) => d.name === deviceName);
- return device ? deviceLabel(device) : deviceName;
+ const label = (drive) => {
+ const device = devices.find((d) => d.name === drive.name);
+ return device ? deviceLabel(device) : drive.name;
};
- if (result.settings.target === ProposalTarget.NEW_LVM_VG) {
- const pvDevices = result.settings.targetPVDevices;
-
- if (pvDevices.length > 1) {
- return (
-
- {msgLvmMultipleDisks(result.settings.spacePolicy)}
-
- );
- } else {
- const [msg1, msg2] = msgLvmSingleDisk(result.settings.spacePolicy).split("%s");
-
- return (
-
-
- {msg1}
- {label(pvDevices[0])}
- {msg2}
-
-
- );
- }
- }
-
- const targetDevice = result.settings.targetDevice;
- if (!targetDevice) return {_("No device selected yet")};
-
- const fullMsg = (policy: string): string => {
- switch (policy) {
+ const msgSingleDisk = (drive: ConfigModel.Device): string => {
+ switch (drive.spacePolicy) {
case "resize":
// TRANSLATORS: %s will be replaced by the device name and its size,
// example: "/dev/sda, 20 GiB"
- return _("Install using device %s shrinking existing partitions as needed");
+ return _("Install using device %s shrinking existing partitions as needed.");
case "keep":
// TRANSLATORS: %s will be replaced by the device name and its size,
// example: "/dev/sda, 20 GiB"
- return _("Install using device %s without modifying existing partitions");
+ return _("Install using device %s without modifying existing partitions.");
case "delete":
// TRANSLATORS: %s will be replaced by the device name and its size,
// example: "/dev/sda, 20 GiB"
- return _("Install using device %s and deleting all its content");
+ return _("Install using device %s and deleting all its content.");
}
// TRANSLATORS: %s will be replaced by the device name and its size,
// example: "/dev/sda, 20 GiB"
- return _("Install using device %s with a custom strategy to find the needed space");
+ return _("Install using device %s with a custom strategy to find the needed space.");
};
- const [msg1, msg2] = fullMsg(result.settings.spacePolicy).split("%s");
+ const msgMultipleDisks = (drives: ConfigModel.Device[]): string => {
+ if (drives.every((d) => d.spacePolicy === drives[0].spacePolicy)) {
+ switch (drives[0].spacePolicy) {
+ case "resize":
+ return _("Install using several devices shrinking existing partitions as needed.");
+ case "keep":
+ return _("Install using several devices without modifying existing partitions.");
+ case "delete":
+ return _("Install using several devices and deleting all its content.");
+ }
+ }
- return (
-
-
- {msg1}
- {label(targetDevice)}
- {msg2}
-
-
- );
+ return _("Install using several devices with a custom strategy to find the needed space.");
+ };
+
+ if (drives.length === 0) return {_("No device selected yet")};
+
+ if (drives.length > 1) {
+ return (
+
+ {msgMultipleDisks(drives)}
+
+ );
+ } else {
+ const [msg1, msg2] = msgSingleDisk(drives[0]).split("%s");
+
+ return (
+
+
+ {msg1}
+ {label(drives[0])}
+ {msg2}
+
+
+ );
+ }
}
diff --git a/web/src/components/overview/index.js b/web/src/components/overview/index.js
index a97896e9c6..6db707d5a2 100644
--- a/web/src/components/overview/index.js
+++ b/web/src/components/overview/index.js
@@ -22,4 +22,5 @@
export { default as OverviewPage } from "./OverviewPage";
export { default as L10nSection } from "./L10nSection";
+export { default as StorageSection } from "./StorageSection";
export { default as SoftwareSection } from "./SoftwareSection";