diff --git a/web/src/components/overview/StorageSection.test.tsx b/web/src/components/overview/StorageSection.test.tsx
index f63f3d39fa..1ee9c1515e 100644
--- a/web/src/components/overview/StorageSection.test.tsx
+++ b/web/src/components/overview/StorageSection.test.tsx
@@ -25,6 +25,7 @@ import { screen } from "@testing-library/react";
import { plainRender } from "~/test-utils";
import { StorageSection } from "~/components/overview";
import * as ConfigModel from "~/api/storage/types/config-model";
+import { Issue } from "~/types/issues";
const sdaDrive: ConfigModel.Drive = {
name: "/dev/sda",
@@ -43,11 +44,22 @@ const mockDevices = [
{ name: "/dev/sdb", size: 697932185600 },
];
+const systemError: Issue = {
+ description: "System error",
+ kind: "storage",
+ details: "",
+ source: 1,
+ severity: 1,
+};
+
const mockUseConfigModelFn = jest.fn();
+const mockUseAvailableDevicesFn = jest.fn();
+const mockUseSystemErrorsFn = jest.fn();
jest.mock("~/queries/storage", () => ({
...jest.requireActual("~/queries/storage"),
useDevices: () => mockDevices,
+ useAvailableDevices: () => mockUseAvailableDevicesFn(),
}));
jest.mock("~/queries/storage/config-model", () => ({
@@ -55,6 +67,11 @@ jest.mock("~/queries/storage/config-model", () => ({
useConfigModel: () => mockUseConfigModelFn(),
}));
+jest.mock("~/queries/issues", () => ({
+ ...jest.requireActual("~/queries/issues"),
+ useSystemErrors: () => mockUseSystemErrorsFn(),
+}));
+
describe("when the configuration does not include any device", () => {
beforeEach(() => {
mockUseConfigModelFn.mockReturnValue({ drives: [] });
@@ -155,3 +172,65 @@ describe("when the configuration contains several drives", () => {
});
});
});
+
+describe("when there is no configuration model (unsupported features)", () => {
+ beforeEach(() => {
+ mockUseConfigModelFn.mockReturnValue(undefined);
+ });
+
+ describe("if the storage proposal succeeded", () => {
+ beforeEach(() => {
+ mockUseSystemErrorsFn.mockReturnValue([]);
+ });
+
+ describe("and there are no available disks", () => {
+ beforeEach(() => {
+ mockUseAvailableDevicesFn.mockReturnValue([]);
+ });
+
+ it("indicates that an unhandled configuration was used", async () => {
+ plainRender();
+ await screen.findByText(/advanced configuration/);
+ });
+ });
+
+ describe("and there are available disks", () => {
+ beforeEach(() => {
+ mockUseAvailableDevicesFn.mockReturnValue(mockDevices);
+ });
+
+ it("indicates that an unhandled configuration was used", async () => {
+ plainRender();
+ await screen.findByText(/advanced configuration/);
+ });
+ });
+ });
+
+ describe("if the storage proposal was not possible", () => {
+ beforeEach(() => {
+ mockUseSystemErrorsFn.mockReturnValue([systemError]);
+ });
+
+ describe("and there are no available disks", () => {
+ beforeEach(() => {
+ mockUseAvailableDevicesFn.mockReturnValue([]);
+ });
+
+ it("indicates that there are no available disks", async () => {
+ plainRender();
+ await screen.findByText(/no disks available/);
+ });
+ });
+
+ describe("and there are available disks", () => {
+ beforeEach(() => {
+ mockUseAvailableDevicesFn.mockReturnValue(mockDevices);
+ });
+
+ it("indicates that an unhandled configuration was used", async () => {
+ plainRender();
+ await screen.findByText(/advanced configuration/);
+ });
+ });
+ });
+});
diff --git a/web/src/components/overview/StorageSection.tsx b/web/src/components/overview/StorageSection.tsx
index 5df7520496..b3c8eb5246 100644
--- a/web/src/components/overview/StorageSection.tsx
+++ b/web/src/components/overview/StorageSection.tsx
@@ -23,8 +23,9 @@
import React from "react";
import { Content } from "@patternfly/react-core";
import { deviceLabel } from "~/components/storage/utils";
-import { useDevices } from "~/queries/storage";
+import { useDevices, useAvailableDevices } from "~/queries/storage";
import { useConfigModel } from "~/queries/storage/config-model";
+import { useSystemErrors } from "~/queries/issues";
import { StorageDevice } from "~/types/storage";
import * as ConfigModel from "~/api/storage/types/config-model";
import { _ } from "~/i18n";
@@ -78,26 +79,40 @@ const MultipleDisksSummary = ({ drives }: { drives: ConfigModel.Drive[] }): stri
return options[drives[0].spacePolicy];
};
+const ModelSummary = ({ model }: { model: ConfigModel.Config }): React.ReactNode => {
+ const devices = useDevices("system", { suspense: true });
+ const drives = model?.drives || [];
+ const existDevice = (name: string) => devices.some((d) => d.name === name);
+ const noDrive = drives.length === 0 || drives.some((d) => !existDevice(d.name));
+
+ if (noDrive) return ;
+ if (drives.length > 1) return ;
+ return ;
+};
+
+const NoModelSummary = (): React.ReactNode => {
+ const availableDevices = useAvailableDevices();
+ const systemErrors = useSystemErrors("storage");
+ const hasDisks = !!availableDevices.length;
+ const hasResult = !systemErrors.length;
+
+ if (!hasResult && !hasDisks) return _("There are no disks available for the installation.");
+ return _("Install using an advanced configuration.");
+};
+
/**
* Text explaining the storage 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 configModel = useConfigModel();
- const devices = useDevices("system", { suspense: true });
- const drives = configModel?.drives || [];
- const existDevice = (name: string) => devices.some((d) => d.name === name);
- const noDrive = drives.length === 0 || drives.some((d) => !existDevice(d.name));
return (
{_("Storage")}
- {noDrive && }
- {drives.length === 1 && }
- {drives.length > 1 && }
+
+ {configModel && }
+ {!configModel && }
+
);
}