Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
ee33064
Fix installation stage
joseivanlopez Dec 12, 2025
7924763
Move api-model methods
joseivanlopez Dec 12, 2025
ef9ee70
Move methods for finding devices from collection
joseivanlopez Dec 15, 2025
8bac429
Move boot methods
joseivanlopez Dec 15, 2025
7d7a95c
Extract partitionable logic
joseivanlopez Dec 15, 2025
a57e71e
Extract boot logic
joseivanlopez Dec 16, 2025
f603d43
Unify partitionable logic
joseivanlopez Dec 16, 2025
8868f6a
Move partition methods
joseivanlopez Dec 16, 2025
182cc1a
Unify partition logic
joseivanlopez Dec 16, 2025
f7b024b
Move volume group methods
joseivanlopez Dec 16, 2025
702d0a8
Move logical volume names
joseivanlopez Dec 16, 2025
448a14e
Move data and utils
joseivanlopez Dec 16, 2025
e4f2417
Move drive methods
joseivanlopez Dec 16, 2025
c60637e
Move md raid methods
joseivanlopez Dec 16, 2025
bbdbc7c
Move search methods
joseivanlopez Dec 16, 2025
18cd35c
Move space policy methods
joseivanlopez Dec 16, 2025
13f5053
Move filesystem methods
joseivanlopez Dec 16, 2025
993ffc8
Move device methods
joseivanlopez Dec 16, 2025
4bd60f0
Move devices manager
joseivanlopez Dec 16, 2025
f3c3e14
Move config model hooks
joseivanlopez Dec 16, 2025
0423543
Remove useModel hook
joseivanlopez Dec 16, 2025
d2a1ac4
Move model hooks
joseivanlopez Dec 16, 2025
89b77c5
Move boot hooks
joseivanlopez Dec 17, 2025
39b10d1
Move drive hooks
joseivanlopez Dec 17, 2025
33ec807
Move md raid hooks
joseivanlopez Dec 17, 2025
823d862
Move volume group hooks
joseivanlopez Dec 17, 2025
6afb7d4
Move logical volume hooks
joseivanlopez Dec 17, 2025
12d7e4e
Move partition hooks
joseivanlopez Dec 17, 2025
69913dd
Move filesystem hooks
joseivanlopez Dec 17, 2025
d45c699
Move space policy hooks
joseivanlopez Dec 17, 2025
c42ac00
Move old hooks
joseivanlopez Dec 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions web/src/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { Product } from "~/types/software";
import { PATHS } from "~/router";
import { PRODUCT } from "~/routes/paths";
import type { Config } from "~/api";
import type { Progress, State } from "~/model/status";
import type { Progress, Stage } from "~/model/status";
import App from "./App";
import { System } from "~/model/system/network";

Expand All @@ -51,7 +51,7 @@ const network: System = {
accessPoints: [],
};
const mockProgresses: jest.Mock<Progress[]> = jest.fn();
const mockState: jest.Mock<State> = jest.fn();
const mockState: jest.Mock<Stage> = jest.fn();
const mockSelectedProduct: jest.Mock<Config["product"]> = jest.fn();

jest.mock("~/hooks/api", () => ({
Expand All @@ -62,7 +62,7 @@ jest.mock("~/hooks/api", () => ({
}),

useStatus: (): ReturnType<typeof useStatus> => ({
state: mockState(),
stage: mockState(),
progresses: mockProgresses(),
}),

Expand Down
2 changes: 1 addition & 1 deletion web/src/components/overview/StorageSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import React from "react";
import { Content } from "@patternfly/react-core";
import { deviceLabel } from "~/components/storage/utils";
import { useAvailableDevices, useDevices, useIssues } from "~/hooks/model/system/storage";
import { useConfigModel } from "~/hooks/model/storage";
import { useConfigModel } from "~/hooks/model/storage/config-model";
import { _ } from "~/i18n";
import type { Storage } from "~/model/system";
import type { ConfigModel } from "~/model/storage/config-model";
Expand Down
6 changes: 3 additions & 3 deletions web/src/components/storage/BootSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import textStyles from "@patternfly/react-styles/css/utilities/Text/text";
import Link from "~/components/core/Link";
import Icon from "~/components/layout/Icon";
import { useAvailableDrives } from "~/hooks/model/system/storage";
import { useConfigModel } from "~/hooks/model/storage";
import { useConfigModel } from "~/hooks/model/storage/config-model";
import configModel from "~/model/storage/config-model";
import { STORAGE } from "~/routes/paths";
import { deviceLabel, formattedPath } from "~/components/storage/utils";
Expand Down Expand Up @@ -76,8 +76,8 @@ export default function BootSection() {
const config = useConfigModel();
const devices = useAvailableDrives();

const isDefaultBoot = configModel.hasDefaultBoot(config);
const bootDevice = configModel.bootDevice(config);
const isDefaultBoot = configModel.boot.isDefault(config);
const bootDevice = configModel.boot.findDevice(config);
const device = devices.find((d) => d.name === bootDevice?.name);

return (
Expand Down
24 changes: 11 additions & 13 deletions web/src/components/storage/BootSelection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,13 @@ import { DevicesFormSelect } from "~/components/storage";
import { Page, SubtleContent } from "~/components/core";
import { deviceLabel, formattedPath } from "~/components/storage/utils";
import { useCandidateDevices, useDevices } from "~/hooks/model/system/storage";
import { useModel } from "~/hooks/storage/model";
import { useConfigModel } from "~/hooks/model/storage";
import { isDrive } from "~/storage/device";
import {
useConfigModel,
useSetBootDevice,
useSetDefaultBootDevice,
useDisableBootConfig,
} from "~/hooks/storage/boot";
useDisableBoot,
} from "~/hooks/model/storage/config-model";
import { isDrive } from "~/model/storage/device";
import textStyles from "@patternfly/react-styles/css/utilities/Text/text";
import { sprintf } from "sprintf-js";
import { _ } from "~/i18n";
Expand Down Expand Up @@ -77,21 +76,20 @@ export default function BootSelection() {
const [state, setState] = useState<BootSelectionState>({ load: false });
const navigate = useNavigate();
const devices = useDevices();
const model = useModel();
const config = useConfigModel();
const allCandidateDevices = useCandidateDevices();
const setBootDevice = useSetBootDevice();
const setDefaultBootDevice = useSetDefaultBootDevice();
const disableBootConfig = useDisableBootConfig();
const disableBootConfig = useDisableBoot();

const candidateDevices = filteredCandidates(allCandidateDevices, model);
const candidateDevices = filteredCandidates(allCandidateDevices, config);

useEffect(() => {
if (state.load || !model) return;
if (state.load || !config) return;

const bootModel = config.boot;
const isDefaultBoot = configModel.hasDefaultBoot(config);
const bootDevice = configModel.bootDevice(config);
const isDefaultBoot = configModel.boot.isDefault(config);
const bootDevice = configModel.boot.findDevice(config);
let selectedOption: string;

if (!bootModel.configure) {
Expand All @@ -118,9 +116,9 @@ export default function BootSelection() {
candidateDevices: candidates,
selectedOption,
});
}, [devices, candidateDevices, model, state.load, config]);
}, [devices, candidateDevices, config, state.load]);

if (!state.load || !model) return;
if (!state.load || !config) return;

const onSubmit = async (e) => {
e.preventDefault();
Expand Down
10 changes: 5 additions & 5 deletions web/src/components/storage/ConfigEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import VolumeGroupEditor from "~/components/storage/VolumeGroupEditor";
import MdRaidEditor from "~/components/storage/MdRaidEditor";
import { useReset } from "~/hooks/model/config/storage";
import ConfigureDeviceMenu from "./ConfigureDeviceMenu";
import { useModel } from "~/hooks/storage/model";
import { useConfigModel } from "~/hooks/model/storage/config-model";
import { _ } from "~/i18n";

const NoDevicesConfiguredAlert = () => {
Expand Down Expand Up @@ -57,10 +57,10 @@ const NoDevicesConfiguredAlert = () => {
};

export default function ConfigEditor() {
const model = useModel();
const drives = model.drives;
const mdRaids = model.mdRaids;
const volumeGroups = model.volumeGroups;
const config = useConfigModel();
const drives = config.drives;
const mdRaids = config.mdRaids;
const volumeGroups = config.volumeGroups;

if (!drives.length && !mdRaids.length && !volumeGroups.length) {
return <NoDevicesConfiguredAlert />;
Expand Down
12 changes: 5 additions & 7 deletions web/src/components/storage/ConfigureDeviceMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,12 @@ import { useNavigate } from "react-router";
import MenuButton, { MenuButtonItem } from "~/components/core/MenuButton";
import { Divider, Flex, MenuItemProps } from "@patternfly/react-core";
import { useAvailableDevices } from "~/hooks/model/system/storage";
import { useModel } from "~/hooks/storage/model";
import { useAddDrive } from "~/hooks/storage/drive";
import { useAddReusedMdRaid } from "~/hooks/storage/md-raid";
import { useConfigModel, useAddDrive, useAddMdRaid } from "~/hooks/model/storage/config-model";
import { STORAGE as PATHS } from "~/routes/paths";
import { sprintf } from "sprintf-js";
import { _, n_ } from "~/i18n";
import DeviceSelectorModal from "./DeviceSelectorModal";
import { isDrive } from "~/storage/device";
import { isDrive } from "~/model/storage/device";
import { Icon } from "../layout";
import type { Storage } from "~/model/system";

Expand Down Expand Up @@ -126,12 +124,12 @@ export default function ConfigureDeviceMenu(): React.ReactNode {

const navigate = useNavigate();

const model = useModel();
const config = useConfigModel();
const addDrive = useAddDrive();
const addReusedMdRaid = useAddReusedMdRaid();
const addReusedMdRaid = useAddMdRaid();
const allDevices = useAvailableDevices();

const usedDevicesNames = model.drives.concat(model.mdRaids).map((d) => d.name);
const usedDevicesNames = config.drives.concat(config.mdRaids).map((d) => d.name);
const usedDevicesCount = usedDevicesNames.length;
const devices = allDevices.filter((d) => !usedDevicesNames.includes(d.name));
const withRaids = !!allDevices.filter((d) => !isDrive(d)).length;
Expand Down
4 changes: 2 additions & 2 deletions web/src/components/storage/DeviceEditorContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import UnusedMenu from "~/components/storage/UnusedMenu";
import FilesystemMenu from "~/components/storage/FilesystemMenu";
import PartitionsSection from "~/components/storage/PartitionsSection";
import SpacePolicyMenu from "~/components/storage/SpacePolicyMenu";
import { useConfigModel } from "~/hooks/model/storage";
import { useConfigModel } from "~/hooks/model/storage/config-model";
import configModel from "~/model/storage/config-model";

type DeviceEditorContentProps = {
Expand All @@ -39,7 +39,7 @@ export default function DeviceEditorContent({
}: DeviceEditorContentProps): React.ReactNode {
const config = useConfigModel();
const device = config[collection][index];
const isUsed = configModel.isUsedDevice(config, device.name);
const isUsed = configModel.partitionable.isUsed(config, device.name);

if (!isUsed) return <UnusedMenu collection={collection} index={index} />;

Expand Down
2 changes: 1 addition & 1 deletion web/src/components/storage/DeviceSelectorModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import {
import { deviceSize } from "~/components/storage/utils";
import { sortCollection } from "~/utils";
import { _ } from "~/i18n";
import { deviceSystems } from "~/storage/device";
import { deviceSystems } from "~/model/storage/device";
import type { Storage } from "~/model/system";

type DeviceSelectorProps = {
Expand Down
20 changes: 10 additions & 10 deletions web/src/components/storage/DriveEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,9 @@ import DriveHeader from "~/components/storage/DriveHeader";
import DeviceEditorContent from "~/components/storage/DeviceEditorContent";
import SearchedDeviceMenu from "~/components/storage/SearchedDeviceMenu";
import { CustomToggleProps } from "~/components/core/MenuButton";
import { useDeleteDrive } from "~/hooks/storage/drive";
import { Button, Flex, FlexItem } from "@patternfly/react-core";
import textStyles from "@patternfly/react-styles/css/utilities/Text/text";
import { useDrive } from "~/hooks/storage/model";
import { useDrive, useDeleteDrive } from "~/hooks/model/storage/config-model";
import { useDevice } from "~/hooks/model/system/storage";
import type { ConfigModel } from "~/model/storage/config-model";
import type { Storage as System } from "~/model/system";
Expand Down Expand Up @@ -69,23 +68,24 @@ const DriveDeviceMenuToggle = forwardRef(
);

type DriveDeviceMenuProps = {
drive: ConfigModel.Drive;
selected: System.Device;
index: number;
};

/**
* Internal component that renders generic actions available for a Drive device.
*/
const DriveDeviceMenu = ({ drive, selected }: DriveDeviceMenuProps) => {
const DriveDeviceMenu = ({ index }: DriveDeviceMenuProps) => {
const driveModel = useDrive(index);
const drive = useDevice(driveModel.name);
const deleteDrive = useDeleteDrive();
const deleteFn = (device: ConfigModel.Drive) => deleteDrive(device.name);
const deleteFn = () => deleteDrive(index);

return (
<SearchedDeviceMenu
modelDevice={drive}
selected={selected}
modelDevice={driveModel}
selected={drive}
deleteFn={deleteFn}
toggle={<DriveDeviceMenuToggle drive={drive} device={selected} />}
toggle={<DriveDeviceMenuToggle drive={driveModel} device={drive} />}
/>
);
};
Expand All @@ -107,7 +107,7 @@ export default function DriveEditor({ index }: DriveEditorProps) {
if (drive === undefined) return null;

return (
<ConfigEditorItem header={<DriveDeviceMenu drive={driveModel} selected={drive} />}>
<ConfigEditorItem header={<DriveDeviceMenu index={index} />}>
<DeviceEditorContent collection="drives" index={index} />
</ConfigEditorItem>
);
Expand Down
9 changes: 4 additions & 5 deletions web/src/components/storage/DriveHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@

import { sprintf } from "sprintf-js";
import { deviceLabel } from "./utils";
import { useConfigModel } from "~/hooks/model/storage";
import { useConfigModel } from "~/hooks/model/storage/config-model";
import configModel from "~/model/storage/config-model";
import partitionableModel from "~/model/storage/partitionable-model";
import { _ } from "~/i18n";
import type { ConfigModel } from "~/model/storage/config-model";
import type { Storage } from "~/model/system";
Expand All @@ -41,10 +40,10 @@ const Text = (drive: ConfigModel.Drive): string => {
return _("Format disk %s");
}

const isBoot = configModel.isBootDevice(config, drive.name);
const isBoot = configModel.boot.hasDevice(config, drive.name);
const hasPv = configModel.isTargetDevice(config, drive.name);
const isRoot = !!partitionableModel.findPartition(drive, "/");
const hasFs = !!partitionableModel.usedMountPaths(drive).length;
const isRoot = !!configModel.partitionable.findPartition(drive, "/");
const hasFs = !!configModel.partitionable.usedMountPaths(drive).length;

if (isRoot) {
if (hasPv) {
Expand Down
5 changes: 3 additions & 2 deletions web/src/components/storage/EncryptionSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { Content, Flex, Split, Stack } from "@patternfly/react-core";
import textStyles from "@patternfly/react-styles/css/utilities/Text/text";
import { Link } from "~/components/core";
import Icon from "~/components/layout/Icon";
import { useEncryption } from "~/queries/storage/config-model";
import { useConfigModel } from "~/hooks/model/storage/config-model";
import { STORAGE } from "~/routes/paths";
import { _ } from "~/i18n";
import PasswordCheck from "~/components/users/PasswordCheck";
Expand All @@ -39,7 +39,8 @@ function encryptionLabel(method?: ConfigModel.EncryptionMethod) {
}

export default function EncryptionSection() {
const { encryption } = useEncryption();
const configModel = useConfigModel();
const encryption = configModel?.encryption;
const method = encryption?.method;
const password = encryption?.password;

Expand Down
17 changes: 9 additions & 8 deletions web/src/components/storage/EncryptionSettingsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { ActionGroup, Alert, Checkbox, Content, Form } from "@patternfly/react-c
import { NestedContent, Page, PasswordAndConfirmationInput } from "~/components/core";
import PasswordCheck from "~/components/users/PasswordCheck";
import { useEncryptionMethods } from "~/hooks/model/system/storage";
import { useEncryption } from "~/queries/storage/config-model";
import { useConfigModel, useSetEncryption } from "~/hooks/model/storage/config-model";
import { isEmpty } from "radashi";
import { _ } from "~/i18n";
import type { ConfigModel } from "~/model/storage/config-model";
Expand All @@ -37,8 +37,9 @@ import type { ConfigModel } from "~/model/storage/config-model";
export default function EncryptionSettingsPage() {
const navigate = useNavigate();
const location = useLocation();
const { encryption: encryptionConfig, enable, disable } = useEncryption();
const methods = useEncryptionMethods();
const configModel = useConfigModel();
const setEncryption = useSetEncryption();

const [errors, setErrors] = useState([]);
const [isEnabled, setIsEnabled] = useState(false);
Expand All @@ -49,12 +50,12 @@ export default function EncryptionSettingsPage() {
const formId = "encryptionSettingsForm";

useEffect(() => {
if (encryptionConfig) {
if (configModel?.encryption) {
setIsEnabled(true);
setMethod(encryptionConfig.method);
setPassword(encryptionConfig.password || "");
setMethod(configModel.encryption.method);
setPassword(configModel.encryption.password || "");
}
}, [encryptionConfig]);
}, [configModel]);

const changePassword = (_, v: string) => setPassword(v);

Expand All @@ -81,7 +82,7 @@ export default function EncryptionSettingsPage() {
return;
}

const commit = () => (isEnabled ? enable(method, password) : disable());
const commit = () => (isEnabled ? setEncryption({ method, password }) : setEncryption(null));

commit();
navigate({ pathname: "..", search: location.search });
Expand Down Expand Up @@ -128,7 +129,7 @@ at the new file systems, including data, programs, and system files.",
<NestedContent margin="mxLg">
<PasswordAndConfirmationInput
inputRef={passwordRef}
initialValue={encryptionConfig?.password}
initialValue={configModel?.encryption?.password}
value={password}
onChange={changePassword}
isDisabled={!isEnabled}
Expand Down
4 changes: 2 additions & 2 deletions web/src/components/storage/FilesystemMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { generatePath, useNavigate } from "react-router";
import MenuButton, { CustomToggleProps } from "~/components/core/MenuButton";
import { STORAGE as PATHS } from "~/routes/paths";
import { filesystemType, formattedPath } from "~/components/storage/utils";
import { useDevice } from "~/hooks/storage/model";
import { usePartitionable } from "~/hooks/model/storage/config-model";
import { sprintf } from "sprintf-js";
import { _ } from "~/i18n";
import type { ConfigModel } from "~/model/storage/config-model";
Expand Down Expand Up @@ -91,7 +91,7 @@ export default function FilesystemMenu({
index,
}: FilesystemMenuProps): React.ReactNode {
const navigate = useNavigate();
const deviceModel = useDevice(collection, index);
const deviceModel = usePartitionable(collection, index);
const editFilesystemPath = generatePath(PATHS.formatDevice, { collection, index });

return (
Expand Down
Loading
Loading