diff --git a/web/src/components/storage/BootSelection.tsx b/web/src/components/storage/BootSelection.tsx index e70788af68..c8d9356d5d 100644 --- a/web/src/components/storage/BootSelection.tsx +++ b/web/src/components/storage/BootSelection.tsx @@ -27,13 +27,11 @@ import { Card, CardBody, Form, FormGroup, Radio, Stack } from "@patternfly/react import { _ } from "~/i18n"; import { DevicesFormSelect } from "~/components/storage"; import { Page } from "~/components/core"; -import { Loading } from "~/components/layout"; import { deviceLabel } from "~/components/storage/utils"; import { sprintf } from "sprintf-js"; -import { useCancellablePromise } from "~/utils"; -import { useInstallerClient } from "~/context/installer"; import textStyles from "@patternfly/react-styles/css/utilities/Text/text"; import { StorageDevice } from "~/types/storage"; +import { useAvailableDevices, useProposalMutation, useProposalResult } from "~/queries/storage"; // FIXME: improve classNames // FIXME: improve and rename to BootSelectionDialog @@ -55,54 +53,40 @@ export default function BootSelectionDialog() { availableDevices?: StorageDevice[]; } - const { cancellablePromise } = useCancellablePromise(); - const { storage: client } = useInstallerClient(); const [state, setState] = useState({ load: false }); + const { settings } = useProposalResult(); + const availableDevices = useAvailableDevices(); + const updateProposal = useProposalMutation(); const navigate = useNavigate(); - // FIXME: Repeated code, see DeviceSelection. Use a context/hook or whatever - // approach to avoid duplication - const loadProposalResult = useCallback(async () => { - return await cancellablePromise(client.proposal.getResult()); - }, [client, cancellablePromise]); - - const loadAvailableDevices = useCallback(async () => { - return await cancellablePromise(client.proposal.getAvailableDevices()); - }, [client, cancellablePromise]); - useEffect(() => { if (state.load) return; - const load = async () => { - let selectedOption: string; - const { settings } = await loadProposalResult(); - const availableDevices: StorageDevice[] = await loadAvailableDevices(); - const { bootDevice, configureBoot, defaultBootDevice } = settings; - - if (!configureBoot) { - selectedOption = BOOT_DISABLED_ID; - } else if (configureBoot && bootDevice === "") { - selectedOption = BOOT_AUTO_ID; - } else { - selectedOption = BOOT_MANUAL_ID; - } - - const findDevice = (name: string) => availableDevices.find((d) => d.name === name); - - setState({ - load: true, - bootDevice: findDevice(bootDevice) || findDevice(defaultBootDevice) || availableDevices[0], - configureBoot, - defaultBootDevice: findDevice(defaultBootDevice), - availableDevices, - selectedOption, - }); - }; + let selectedOption: string; + const { bootDevice, configureBoot, defaultBootDevice } = settings; + + if (!configureBoot) { + selectedOption = BOOT_DISABLED_ID; + } else if (configureBoot && bootDevice === "") { + selectedOption = BOOT_AUTO_ID; + } else { + selectedOption = BOOT_MANUAL_ID; + } + + const findDevice = (name: string) => availableDevices.find((d) => d.name === name); + + setState({ + load: true, + bootDevice: findDevice(bootDevice) || findDevice(defaultBootDevice) || availableDevices[0], + configureBoot, + defaultBootDevice: findDevice(defaultBootDevice), + availableDevices, + selectedOption, + }); - load().catch(console.error); - }, [state, loadAvailableDevices, loadProposalResult]); + }, [availableDevices, settings]); - if (!state.load) return ; + if (!state.load) return; const onSubmit = async (e) => { e.preventDefault(); @@ -110,13 +94,12 @@ export default function BootSelectionDialog() { // const formData = new FormData(e.target); // const mode = formData.get("bootMode"); // const device = formData.get("bootDevice"); - const { settings } = await loadProposalResult(); const newSettings = { configureBoot: state.selectedOption !== BOOT_DISABLED_ID, bootDevice: state.selectedOption === BOOT_MANUAL_ID ? state.bootDevice.name : undefined, }; - await client.proposal.calculate({ ...settings, ...newSettings }); + await updateProposal.mutateAsync({ ...settings, ...newSettings }); navigate(".."); }; diff --git a/web/src/components/storage/SpacePolicySelection.tsx b/web/src/components/storage/SpacePolicySelection.tsx index 38e203a5f4..3d5a726155 100644 --- a/web/src/components/storage/SpacePolicySelection.tsx +++ b/web/src/components/storage/SpacePolicySelection.tsx @@ -21,18 +21,17 @@ // @ts-check -import React, { useCallback, useEffect, useState } from "react"; +import React, { useEffect, useState } from "react"; import { Card, CardBody, Form, Grid, GridItem, Radio, Stack } from "@patternfly/react-core"; import { useNavigate } from "react-router-dom"; -import { Loading } from "~/components/layout"; import { Page } from "~/components/core"; import { SpaceActionsTable } from "~/components/storage"; -import { _ } from "~/i18n"; import { SPACE_POLICIES, SpacePolicy } from "~/components/storage/utils"; -import { noop, useCancellablePromise } from "~/utils"; -import { useInstallerClient } from "~/context/installer"; +import { noop } from "~/utils"; +import { _ } from "~/i18n"; import textStyles from "@patternfly/react-styles/css/utilities/Text/text"; import { SpaceAction } from "~/types/storage"; +import { useProposalMutation, useProposalResult } from "~/queries/storage"; /** * Widget to allow user picking desired policy to make space. @@ -77,36 +76,27 @@ const SpacePolicyPicker = ({ currentPolicy, onChange = noop }: { currentPolicy: * Renders a page that allows the user to select the space policy and actions. */ export default function SpacePolicySelection() { - const [state, setState] = useState({ load: false, settings: {} }); + const { settings } = useProposalResult(); + const updateProposal = useProposalMutation(); + const [state, setState] = useState({ load: false }); const [policy, setPolicy] = useState(); const [actions, setActions] = useState([]); const [expandedDevices, setExpandedDevices] = useState([]); const [customUsed, setCustomUsed] = useState(false); const [devices, setDevices] = useState([]); - const { cancellablePromise } = useCancellablePromise(); - const { storage: client } = useInstallerClient(); const navigate = useNavigate(); - const loadProposalResult = useCallback(async () => { - return await cancellablePromise(client.proposal.getResult()); - }, [client, cancellablePromise]); - useEffect(() => { if (state.load) return; // FIXME: move to a state/reducer - const load = async () => { - const { settings } = await loadProposalResult(); - const policy = SPACE_POLICIES.find((p) => p.id === settings.spacePolicy); - setPolicy(policy); - setActions(settings.spaceActions); - setCustomUsed(policy.id === "custom"); - setDevices(settings.installationDevices); - setState({ load: true, settings }); - }; - - load().catch(console.error); - }, [state, loadProposalResult]); + const policy = SPACE_POLICIES.find((p) => p.id === settings.spacePolicy); + setPolicy(policy); + setActions(settings.spaceActions); + setCustomUsed(policy.id === "custom"); + setDevices(settings.installationDevices); + setState({ load: true }); + }, [state]); useEffect(() => { if (policy?.id === "custom") setExpandedDevices(devices); @@ -123,10 +113,10 @@ export default function SpacePolicySelection() { // Resets actions (i.e., sets everything to "keep") if the custom policy has not been used yet. useEffect(() => { - if (policy?.id !== "custom" && !customUsed) setActions([]); + if (policy && policy?.id !== "custom" && !customUsed) setActions([]); }, [policy, customUsed, setActions]); - if (!state.load) return ; + if (!state.load) return; // Generates the action value according to the policy. const deviceAction = (device) => { @@ -147,9 +137,9 @@ export default function SpacePolicySelection() { const onSubmit = (e) => { e.preventDefault(); - // @ts-ignore - client.proposal.calculate({ - ...state.settings, + + updateProposal.mutateAsync({ + ...settings, spacePolicy: policy.id, spaceActions: actions, });