/* * Copyright (C) 2022 Red Hat, Inc. * SPDX-License-Identifier: LGPL-2.1-or-later */ import cockpit from "cockpit"; import React, { useContext, useEffect, useMemo, useRef, useState } from "react"; import { Form } from "@patternfly/react-core/dist/esm/components/Form/index.js"; import { HelperText, HelperTextItem } from "@patternfly/react-core/dist/esm/components/HelperText/index.js"; import { useWizardContext, useWizardFooter } from "@patternfly/react-core/dist/esm/components/Wizard/index.js"; import { applyStorage, } from "../../../apis/storage_partitioning.js"; import { DialogsContext, PageContext, StorageContext, } from "../../../contexts/Common.jsx"; import { getNewPartitioning, useHomeReuseOptions, } from "../../../hooks/Storage.jsx"; import { AnacondaWizardFooter } from "../../AnacondaWizardFooter.jsx"; import { createStorageValidationNotification } from "../Common.jsx"; import { scenarios } from "../scenarios/index.js"; import { InstallationDestination } from "./InstallationDestination.jsx"; import { InstallationScenario } from "./InstallationScenario.jsx"; import { ReclaimSpaceModal } from "./ReclaimSpaceModal.jsx"; const _ = cockpit.gettext; const SCREEN_ID = "anaconda-screen-method"; export const InstallationMethod = ({ dispatch, idPrefix, isEfi, isFirstScreen, onCritFail, setShowStorage, }) => { const { setIsFormValid } = useContext(PageContext) ?? {}; const [isReclaimSpaceCheckboxChecked, setIsReclaimSpaceCheckboxChecked] = useState(); const [isDestinationValid, setIsDestinationValid] = useState(undefined); const [isScenarioValid, setIsScenarioValid] = useState(false); // Calculate overall form validity based on both children's validation states useEffect(() => { setIsFormValid(isDestinationValid && isScenarioValid); }, [isDestinationValid, isScenarioValid, setIsFormValid]); // Display custom footer const getFooter = useMemo(() => ( ), [isReclaimSpaceCheckboxChecked]); useWizardFooter(getFooter); return (
{ e.preventDefault(); return false }} > ); }; const CustomFooter = ({ isReclaimSpaceCheckboxChecked }) => { const { setIsFormDisabled, setStepNotification } = useContext(PageContext) ?? {}; const [isReclaimSpaceModalOpen, setIsReclaimSpaceModalOpen] = useState(false); const [isNextClicked, setIsNextClicked] = useState(false); const { goToNextStep } = useWizardContext(); const [newPartitioning, setNewPartitioning] = useState(-1); const [partitioningApplied, setPartitioningApplied] = useState(false); const nextRef = useRef(); const { partitioning, storageScenarioId } = useContext(StorageContext) ?? {}; const homeReuseOptions = useHomeReuseOptions(); /** Scenarios do not create or apply existing partitioning on this step. */ const SCENARIOS_WITHOUT_PARTITIONING_CREATION = ["mount-point-mapping", "use-configured-storage", "use-configured-storage-kickstart"]; useEffect(() => { if (nextRef.current !== true && newPartitioning === partitioning.path && isNextClicked) { nextRef.current = true; goToNextStep(); } }, [isNextClicked, goToNextStep, newPartitioning, partitioning.path]); const onNext = async () => { if (SCENARIOS_WITHOUT_PARTITIONING_CREATION.includes(storageScenarioId)) { setNewPartitioning(partitioning.path); setIsNextClicked(true); } else { const part = await getNewPartitioning({ currentPartitioning: partitioning, homeReuseOptions, method: "AUTOMATIC", storageScenarioId, }); setNewPartitioning(part); const scenarioSupportsReclaimSpace = scenarios.find(sc => sc.id === storageScenarioId)?.canReclaimSpace; const willShowReclaimSpaceModal = scenarioSupportsReclaimSpace && isReclaimSpaceCheckboxChecked; if (willShowReclaimSpaceModal) { setIsReclaimSpaceModalOpen(true); } else if (!["home-reuse"].includes(storageScenarioId)) { setIsNextClicked(true); } else { // If partitioning was already applied, proceed to next step if (partitioningApplied) { setPartitioningApplied(false); setStepNotification(); goToNextStep(); setIsFormDisabled(false); return; } setIsFormDisabled(true); const step = SCREEN_ID; try { const { validationReport } = await applyStorage({ partitioning: part }); const notification = createStorageValidationNotification(validationReport, step); setStepNotification(notification); setPartitioningApplied(notification?.variant === "warning"); if (!notification) { goToNextStep(); } } catch (ex) { setPartitioningApplied(false); setStepNotification({ message: ex.message || String(ex), step }); } finally { setIsFormDisabled(false); } } } }; const reclaimSpaceModal = ( setIsReclaimSpaceModalOpen(false)} /> ); const hasNewPartitioning = newPartitioning === undefined || newPartitioning !== partitioning.path; if (hasNewPartitioning && isReclaimSpaceModalOpen) { return; } return ( <> {isReclaimSpaceModalOpen ? reclaimSpaceModal : null} } onNext={onNext} /> ); }; const InstallationMethodFooterHelper = () => { const { isFormValid } = useContext(PageContext) ?? {}; if (isFormValid !== false) { return null; } return ( {_("To continue, select the devices to install to.")} ); };