/*
* 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 (
);
};
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.")}
);
};