From 8a2c1dd099151716b821e442013719ba0457f4bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?= Date: Thu, 12 Dec 2024 12:39:23 +0000 Subject: [PATCH] wip --- web/src/api/storage/types/config-model.ts | 20 +++++-- web/src/components/storage/BootSelection.tsx | 55 +++++++++++-------- .../components/storage/ConfigEditorMenu.tsx | 7 ++- web/src/components/storage/DriveEditor.tsx | 6 +- web/src/queries/storage/config-model.ts | 38 +++++++++++++ web/src/routes/paths.ts | 2 +- web/src/routes/storage.tsx | 2 +- 7 files changed, 100 insertions(+), 30 deletions(-) diff --git a/web/src/api/storage/types/config-model.ts b/web/src/api/storage/types/config-model.ts index 7951ae948b..ba00e219e7 100644 --- a/web/src/api/storage/types/config-model.ts +++ b/web/src/api/storage/types/config-model.ts @@ -1,9 +1,14 @@ +/* eslint-disable */ /** * This file was automatically generated by json-schema-to-typescript. * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, * and run json-schema-to-typescript to regenerate this file. */ +/** + * Alias used to reference a device. + */ +export type Alias = string; export type FilesystemType = | "bcachefs" | "btrfs" @@ -29,11 +34,20 @@ export type PartitionId = "linux" | "swap" | "lvm" | "raid" | "esp" | "prep" | " * Config model */ export interface Config { + boot?: Boot; drives?: Drive[]; } +export interface Boot { + configure: boolean; + device?: BootDevice; +} +export interface BootDevice { + default: boolean; + value?: Alias; +} export interface Drive { name: string; - alias?: string; + alias?: Alias; mountPath?: string; filesystem?: Filesystem; spacePolicy?: SpacePolicy; @@ -49,15 +63,13 @@ export interface Filesystem { } export interface Partition { name?: string; - alias?: string; + alias?: Alias; id?: PartitionId; mountPath?: string; filesystem?: Filesystem; size?: Size; delete?: boolean; - // TODO: ignore deleteIfNeeded?: boolean; - // TODO: ignore resize?: boolean; resizeIfNeeded?: boolean; } diff --git a/web/src/components/storage/BootSelection.tsx b/web/src/components/storage/BootSelection.tsx index 27fc49fa29..fb15867c0e 100644 --- a/web/src/components/storage/BootSelection.tsx +++ b/web/src/components/storage/BootSelection.tsx @@ -27,10 +27,11 @@ import { DevicesFormSelect } from "~/components/storage"; import { Page } from "~/components/core"; import { deviceLabel } from "~/components/storage/utils"; import { StorageDevice } from "~/types/storage"; -import { useAvailableDevices, useProposalMutation, useProposalResult } from "~/queries/storage"; +import { useAvailableDevices } from "~/queries/storage"; import textStyles from "@patternfly/react-styles/css/utilities/Text/text"; import { sprintf } from "sprintf-js"; import { _ } from "~/i18n"; +import { useBootDevice, useConfigModel } from "~/queries/storage"; // FIXME: improve classNames // FIXME: improve and rename to BootSelectionDialog @@ -39,50 +40,56 @@ const BOOT_AUTO_ID = "boot-auto"; const BOOT_MANUAL_ID = "boot-manual"; const BOOT_DISABLED_ID = "boot-disabled"; +type BootSelectionState = { + load: boolean; + selectedOption?: string; + configureBoot?: boolean; + bootDevice?: StorageDevice; + defaultBootDevice?: StorageDevice; + availableDevices?: StorageDevice[]; +}; + /** * Allows the user to select the boot configuration. */ export default function BootSelectionDialog() { - type BootSelectionState = { - load: boolean; - selectedOption?: string; - configureBoot?: boolean; - bootDevice?: StorageDevice; - defaultBootDevice?: StorageDevice; - availableDevices?: StorageDevice[]; - }; - const [state, setState] = useState({ load: false }); - const { settings } = useProposalResult(); + // const { settings } = useProposalResult(); const availableDevices = useAvailableDevices(); - const updateProposal = useProposalMutation(); + // const updateProposal = useProposalMutation(); const navigate = useNavigate(); + const configModel = useConfigModel(); + const bootDeviceModel = useBootDevice(); + + console.log(configModel); useEffect(() => { if (state.load) return; let selectedOption: string; - const { bootDevice, configureBoot, defaultBootDevice } = settings; + const bootModel = configModel?.boot; + const configureBoot = bootModel?.configure || false; + const defaultBootDevice = bootModel?.device?.default || false; if (!configureBoot) { selectedOption = BOOT_DISABLED_ID; - } else if (configureBoot && bootDevice === "") { + } else if (configureBoot && defaultBootDevice) { selectedOption = BOOT_AUTO_ID; } else { selectedOption = BOOT_MANUAL_ID; } - const findDevice = (name: string) => availableDevices.find((d) => d.name === name); + const bootDevice = availableDevices.find((d) => d.name === bootDeviceModel.name); setState({ load: true, - bootDevice: findDevice(bootDevice) || findDevice(defaultBootDevice) || availableDevices[0], + bootDevice: bootDevice || availableDevices[0], configureBoot, - defaultBootDevice: findDevice(defaultBootDevice), + defaultBootDevice: bootDevice, availableDevices, selectedOption, }); - }, [availableDevices, settings, state.load]); + }, [availableDevices, configModel, bootDeviceModel, state.load]); if (!state.load) return; @@ -92,12 +99,16 @@ export default function BootSelectionDialog() { // const formData = new FormData(e.target); // const mode = formData.get("bootMode"); // const device = formData.get("bootDevice"); - const newSettings = { - configureBoot: state.selectedOption !== BOOT_DISABLED_ID, - bootDevice: state.selectedOption === BOOT_MANUAL_ID ? state.bootDevice.name : undefined, + const bootModel = { + configure: state.selectedOption !== BOOT_DISABLED_ID, + device: { + default: state.selectedOption === BOOT_AUTO_ID, + device: state.bootDevice?.name, + }, }; - await updateProposal.mutateAsync({ ...settings, ...newSettings }); + // await updateProposal.mutateAsync({ ...settings, ...newSettings }); + console.log(bootModel); navigate(".."); }; diff --git a/web/src/components/storage/ConfigEditorMenu.tsx b/web/src/components/storage/ConfigEditorMenu.tsx index 4c9e95bd12..b8b5714f45 100644 --- a/web/src/components/storage/ConfigEditorMenu.tsx +++ b/web/src/components/storage/ConfigEditorMenu.tsx @@ -21,6 +21,7 @@ */ import React, { useState } from "react"; +import { useNavigate } from "react-router-dom"; import { _ } from "~/i18n"; import { useHref } from "react-router-dom"; import { @@ -31,8 +32,10 @@ import { DropdownItem, Divider, } from "@patternfly/react-core"; +import { STORAGE as PATHS } from "~/routes/paths"; export default function ConfigEditorMenu() { + const navigate = useNavigate(); const [isOpen, setIsOpen] = useState(false); const toggle = () => setIsOpen(!isOpen); @@ -58,7 +61,9 @@ export default function ConfigEditorMenu() { {_("Add LVM volume group")} {_("Add MD RAID")} - {_("Change boot options")} + navigate(PATHS.bootDevice)}> + {_("Change boot options")} + {_("Reinstall an existing system")} diff --git a/web/src/components/storage/DriveEditor.tsx b/web/src/components/storage/DriveEditor.tsx index 0c5d93e53f..10c8496dff 100644 --- a/web/src/components/storage/DriveEditor.tsx +++ b/web/src/components/storage/DriveEditor.tsx @@ -50,7 +50,7 @@ import { MenuToggle, } from "@patternfly/react-core"; -import { useChangeDrive, useSetSpacePolicy } from "~/queries/storage"; +import { useConfigModel, useChangeDrive, useSetSpacePolicy } from "~/queries/storage"; import { Drive } from "~/api/storage/types/config-model"; type DriveEditorProps = { drive: configModel.Drive; driveDevice: StorageDevice }; @@ -649,6 +649,10 @@ const PartitionsSelector = ({ drive }) => { }; export default function DriveEditor({ drive, driveDevice }: DriveEditorProps) { + const model = useConfigModel(); + + console.log("model: ", model); + return ( diff --git a/web/src/queries/storage/config-model.ts b/web/src/queries/storage/config-model.ts index 8327e7c875..44a38ea009 100644 --- a/web/src/queries/storage/config-model.ts +++ b/web/src/queries/storage/config-model.ts @@ -40,6 +40,10 @@ function changeDrive(model: configModel.Config, driveName: string, newDriveName: if (drive.spacePolicy === "custom") drive.spacePolicy = "keep"; } +function generateAlias(deviceName: string): string { + return `device-${deviceName.split("/").pop()}`; +} + function setSpacePolicy( model: configModel.Config, driveName: string, @@ -91,6 +95,21 @@ function setCustomSpacePolicy( }); } +function setBoot(model: configModel.Config, configure: boolean, driveName: string | undefined) { + model.boot ||= { configure }; + + if (driveName === undefined) { + model.boot.device = { default: true }; + return; + } + + const drive = findDrive(model, driveName); + if (drive === undefined) return; + + if (drive.alias === undefined) drive.alias = generateAlias(drive.name); + model.boot.device = { default: false, value: drive.alias }; +} + const configModelQuery = { queryKey: ["storage", "configModel"], queryFn: fetchConfigModel, @@ -107,6 +126,16 @@ export function useConfigModel(options?: QueryHookOptions): configModel.Config { return data; } +export function useBootDevice(): configModel.Drive { + const model = useConfigModel(); + const boot_device_alias = model.boot?.device?.value; + + if (boot_device_alias === undefined) return; + + const drives = model.drives || []; + return drives.find((d) => d.alias === boot_device_alias); +} + /** * Hook for setting a new config model. */ @@ -160,3 +189,12 @@ export function useSetCustomSpacePolicy() { applyModelAction(action); }; } + +export function useSetBoot() { + const applyModelAction = useApplyModelAction(); + + return (configure: boolean, deviceName: string | undefined) => { + const action: ModelActionF = (model) => setBoot(model, configure, deviceName); + applyModelAction(action); + }; +} diff --git a/web/src/routes/paths.ts b/web/src/routes/paths.ts index de6c97b825..395bc4d4b4 100644 --- a/web/src/routes/paths.ts +++ b/web/src/routes/paths.ts @@ -65,7 +65,7 @@ const SOFTWARE = { const STORAGE = { root: "/storage", targetDevice: "/storage/target-device", - bootingPartition: "/storage/booting-partition", + bootDevice: "/storage/boot-device", spacePolicy: "/storage/space-policy/:id", iscsi: "/storage/iscsi", dasd: "/storage/dasd", diff --git a/web/src/routes/storage.tsx b/web/src/routes/storage.tsx index 975c3b8d86..7a94b22553 100644 --- a/web/src/routes/storage.tsx +++ b/web/src/routes/storage.tsx @@ -47,7 +47,7 @@ const routes = (): Route => ({ element: , }, { - path: PATHS.bootingPartition, + path: PATHS.bootDevice, element: , }, {