Skip to content

Commit

Permalink
Merge pull request #5248 from KKoukiou/webui-cleanup-code
Browse files Browse the repository at this point in the history
webui: clean up some code around AnacondaWizard component
  • Loading branch information
KKoukiou authored Oct 16, 2023
2 parents b86184e + ffee48d commit ae50381
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 131 deletions.
10 changes: 8 additions & 2 deletions ui/webui/src/components/AnacondaPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,19 @@
* You should have received a copy of the GNU Lesser General Public License
* along with This program; If not, see <http://www.gnu.org/licenses/>.
*/
import { Stack, Title } from "@patternfly/react-core";
import { Alert, Stack, Title } from "@patternfly/react-core";
import React from "react";

export const AnacondaPage = ({ title, children }) => {
export const AnacondaPage = ({ title, children, step, stepNotification }) => {
return (
<Stack hasGutter>
{title && <Title headingLevel="h2">{title}</Title>}
{stepNotification && stepNotification.step === step &&
<Alert
isInline
title={stepNotification.message}
variant="danger"
/>}
{children}
</Stack>
);
Expand Down
105 changes: 55 additions & 50 deletions ui/webui/src/components/AnacondaWizard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,14 @@ import {
WizardContextConsumer
} from "@patternfly/react-core/deprecated";

import { InstallationMethod } from "./storage/InstallationMethod.jsx";
import { AnacondaPage } from "./AnacondaPage.jsx";
import { InstallationMethod, getPageProps as getInstallationMethodProps } from "./storage/InstallationMethod.jsx";
import { getScenario, getDefaultScenario } from "./storage/InstallationScenario.jsx";
import { MountPointMapping } from "./storage/MountPointMapping.jsx";
import { DiskEncryption, getStorageEncryptionState } from "./storage/DiskEncryption.jsx";
import { InstallationLanguage } from "./localization/InstallationLanguage.jsx";
import { MountPointMapping, getPageProps as getMountPointMappingProps } from "./storage/MountPointMapping.jsx";
import { DiskEncryption, getStorageEncryptionState, getPageProps as getDiskEncryptionProps } from "./storage/DiskEncryption.jsx";
import { InstallationLanguage, getPageProps as getInstallationLanguageProps } from "./localization/InstallationLanguage.jsx";
import { InstallationProgress } from "./installation/InstallationProgress.jsx";
import { ReviewConfiguration, ReviewConfigurationConfirmModal } from "./review/ReviewConfiguration.jsx";
import { ReviewConfiguration, ReviewConfigurationConfirmModal, getPageProps as getReviewConfigurationProps } from "./review/ReviewConfiguration.jsx";
import { exitGui } from "../helpers/exit.js";
import { usePageLocation } from "hooks";
import {
Expand All @@ -53,14 +54,14 @@ import {
const _ = cockpit.gettext;
const N_ = cockpit.noop;

export const AnacondaWizard = ({ dispatch, isBootIso, osRelease, storageData, localizationData, onCritFail, onAddErrorNotification, title, conf }) => {
export const AnacondaWizard = ({ dispatch, isBootIso, osRelease, storageData, localizationData, onCritFail, title, conf }) => {
const [isFormDisabled, setIsFormDisabled] = useState(false);
const [isFormValid, setIsFormValid] = useState(false);
const [requiredMountPoints, setRequiredMountPoints] = useState();
const [reusePartitioning, setReusePartitioning] = useState(false);
const [stepNotification, setStepNotification] = useState();
const [isFormDisabled, setIsFormDisabled] = useState(false);
const [storageEncryption, setStorageEncryption] = useState(getStorageEncryptionState());
const [storageScenarioId, setStorageScenarioId] = useState(window.sessionStorage.getItem("storage-scenario-id") || getDefaultScenario().id);
const [reusePartitioning, setReusePartitioning] = useState(false);
const [requiredMountPoints, setRequiredMountPoints] = useState();

const availableDevices = useMemo(() => {
return Object.keys(storageData.devices);
Expand Down Expand Up @@ -94,35 +95,44 @@ export const AnacondaWizard = ({ dispatch, isBootIso, osRelease, storageData, lo
}
}, [localizationData]);
const stepsOrder = [
...(isBootIso
? [{
component: InstallationLanguage,
data: { dispatch, languages: localizationData.languages, language: localizationData.language, commonLocales: localizationData.commonLocales },
id: "installation-language",
label: _("Welcome"),
}]
: []),
{
component: InstallationLanguage,
data: { dispatch, languages: localizationData.languages, language: localizationData.language, commonLocales: localizationData.commonLocales },
...getInstallationLanguageProps({ isBootIso, osRelease })
},
{
component: InstallationMethod,
data: { deviceData: storageData.devices, diskSelection: storageData.diskSelection, dispatch },
id: "installation-method",
label: _("Installation method"),
data: {
deviceData: storageData.devices,
diskSelection: storageData.diskSelection,
dispatch,
storageScenarioId,
setStorageScenarioId: (scenarioId) => {
window.sessionStorage.setItem("storage-scenario-id", scenarioId);
setStorageScenarioId(scenarioId);
}
},
...getInstallationMethodProps({ isBootIso, osRelease })
},
{
id: "disk-configuration",
label: _("Disk configuration"),
steps: [{
component: MountPointMapping,
data: { deviceData: storageData.devices, diskSelection: storageData.diskSelection, partitioningData: storageData.partitioning, requiredMountPoints, dispatch, reusePartitioning, setReusePartitioning },
id: "mount-point-mapping",
label: _("Manual disk configuration"),
isHidden: storageScenarioId !== "mount-point-mapping"

data: {
deviceData: storageData.devices,
diskSelection: storageData.diskSelection,
dispatch,
partitioningData: storageData.partitioning,
requiredMountPoints,
reusePartitioning,
setReusePartitioning,
},
...getMountPointMappingProps({ storageScenarioId })
}, {
component: DiskEncryption,
id: "disk-encryption",
label: _("Disk encryption"),
isHidden: storageScenarioId === "mount-point-mapping"
data: { storageEncryption, setStorageEncryption },
...getDiskEncryptionProps({ storageScenarioId })
}]
},
{
Expand All @@ -133,10 +143,10 @@ export const AnacondaWizard = ({ dispatch, isBootIso, osRelease, storageData, lo
requests: storageData.partitioning ? storageData.partitioning.requests : null,
language,
localizationData,
osRelease
osRelease,
storageScenarioId,
},
id: "installation-review",
label: _("Review and install"),
...getReviewConfigurationProps()
},
{
component: InstallationProgress,
Expand Down Expand Up @@ -191,25 +201,20 @@ export const AnacondaWizard = ({ dispatch, isBootIso, osRelease, storageData, lo
step = ({
...step,
component: (
<s.component
idPrefix={s.id}
setIsFormValid={setIsFormValid}
onCritFail={onCritFail}
onAddErrorNotification={onAddErrorNotification}
stepNotification={stepNotification}
isFormDisabled={isFormDisabled}
setIsFormDisabled={setIsFormDisabled}
storageEncryption={storageEncryption}
setStorageEncryption={setStorageEncryption}
storageScenarioId={storageScenarioId}
isBootIso={isBootIso}
osRelease={osRelease}
setStorageScenarioId={(scenarioId) => {
window.sessionStorage.setItem("storage-scenario-id", scenarioId);
setStorageScenarioId(scenarioId);
}}
{...s.data}
/>
<AnacondaPage step={s.id} title={s.title} stepNotification={stepNotification}>
<s.component
idPrefix={s.id}
setIsFormValid={setIsFormValid}
onCritFail={onCritFail}
setStepNotification={ex => setStepNotification({ step: s.id, ...ex })}
stepNotification={stepNotification}
isFormDisabled={isFormDisabled}
setIsFormDisabled={setIsFormDisabled}
isBootIso={isBootIso}
osRelease={osRelease}
{...s.data}
/>
</AnacondaPage>
),
});
} else if (s.steps) {
Expand Down
37 changes: 0 additions & 37 deletions ui/webui/src/components/app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import cockpit from "cockpit";
import React, { useCallback, useEffect, useState } from "react";

import {
AlertGroup, AlertVariant, AlertActionCloseButton, Alert,
Page, PageGroup,
} from "@patternfly/react-core";

Expand Down Expand Up @@ -52,7 +51,6 @@ export const Application = () => {
const [beta, setBeta] = useState();
const [conf, setConf] = useState();
const [language, setLanguage] = useState();
const [notifications, setNotifications] = useState({});
const [osRelease, setOsRelease] = useState("");
const [state, dispatch] = useReducerWithThunk(reducer, initialState);
const [storeInitilized, setStoreInitialized] = useState(false);
Expand Down Expand Up @@ -105,17 +103,6 @@ export const Application = () => {
readOsRelease().then(osRelease => setOsRelease(osRelease));
}, [dispatch, onCritFail]);

const onAddNotification = (notificationProps) => {
setNotifications({
...notifications,
[notifications.length]: { index: notifications.length, ...notificationProps }
});
};

const onAddErrorNotification = ex => {
onAddNotification({ title: ex.name, message: ex.message, variant: "danger" });
};

// Postpone rendering anything until we read the dbus address and the default configuration
if (!criticalError && (!address || !conf || beta === undefined || !osRelease || !storeInitilized)) {
debug("Loading initial data...");
Expand All @@ -138,29 +125,6 @@ export const Application = () => {
<Page
data-debug={conf.Anaconda.debug}
>
{Object.keys(notifications).length > 0 &&
<AlertGroup isToast isLiveRegion>
{Object.keys(notifications).map(idx => {
const notification = notifications[idx];
const newNotifications = { ...notifications };
delete newNotifications[notification.index];

return (
<Alert
variant={AlertVariant[notification.variant]}
title={notification.title}
actionClose={
<AlertActionCloseButton
title={notifications.title}
onClose={() => setNotifications(newNotifications)}
/>
}
key={notification.index}>
{notification.message}
</Alert>
);
})}
</AlertGroup>}
<PageGroup stickyOnBreakpoint={{ default: "top" }}>
<AnacondaHeader
beta={beta}
Expand All @@ -174,7 +138,6 @@ export const Application = () => {
<AnacondaWizard
isBootIso={isBootIso}
onCritFail={onCritFail}
onAddErrorNotification={onAddErrorNotification}
title={title}
storageData={state.storage}
localizationData={state.localization}
Expand Down
34 changes: 19 additions & 15 deletions ui/webui/src/components/localization/InstallationLanguage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import {
Alert, MenuSearchInput,
} from "@patternfly/react-core";

import { read_os_release as readOsRelease } from "os-release.js";
import { AddressContext, LanguageContext } from "../Common.jsx";
import { setLocale } from "../../apis/boss.js";

Expand All @@ -46,7 +45,6 @@ import {
getLangCookie,
setLangCookie
} from "../../helpers/language.js";
import { AnacondaPage } from "../AnacondaPage.jsx";

import "./InstallationLanguage.scss";

Expand Down Expand Up @@ -78,7 +76,7 @@ class LanguageSelector extends React.Component {
}
setLocale({ locale: this.props.language });
} catch (e) {
this.props.onAddErrorNotification(e);
this.props.setStepNotification(e);
}
}

Expand Down Expand Up @@ -210,7 +208,10 @@ class LanguageSelector extends React.Component {
setLangCookie({ cockpitLang: convertToCockpitLang({ lang: getLocaleId(localeItem) }) });
setLanguage({ lang: getLocaleId(localeItem) })
.then(() => setLocale({ locale: getLocaleId(localeItem) }))
.catch(this.props.onAddErrorNotification);
.catch(ex => {
console.info({ ex });
this.props.setStepNotification(ex);
});
this.setState({ lang: item });
this.updateNativeName(localeItem);
fetch("po.js").then(response => response.text())
Expand Down Expand Up @@ -284,21 +285,15 @@ class LanguageSelector extends React.Component {
}
LanguageSelector.contextType = AddressContext;

export const InstallationLanguage = ({ idPrefix, languages, language, commonLocales, setIsFormValid, onAddErrorNotification }) => {
const [nativeName, setNativeName] = React.useState(false);
export const InstallationLanguage = ({ idPrefix, languages, language, commonLocales, setIsFormValid, setStepNotification }) => {
const [nativeName, setNativeName] = useState(false);
const { setLanguage } = React.useContext(LanguageContext);
const [distributionName, setDistributionName] = useState("");

useEffect(() => {
readOsRelease().then(osRelease => setDistributionName(osRelease.NAME));
}, []);

useEffect(() => {
setIsFormValid(language !== "");
}, [language, setIsFormValid]);

return (
<AnacondaPage title={cockpit.format(_("Welcome to $0"), distributionName)}>
<>
<Title
headingLevel="h3"
>
Expand All @@ -324,12 +319,21 @@ export const InstallationLanguage = ({ idPrefix, languages, language, commonLoca
commonLocales={commonLocales}
language={language}
setIsFormValid={setIsFormValid}
onAddErrorNotification={onAddErrorNotification}
setStepNotification={setStepNotification}
setNativeName={setNativeName}
reRenderApp={setLanguage}
/>
</FormGroup>
</Form>
</AnacondaPage>
</>
);
};

export const getPageProps = ({ isBootIso, osRelease }) => {
return ({
id: "installation-language",
label: _("Welcome"),
isHidden: !isBootIso,
title: cockpit.format(_("Welcome to $0"), osRelease.NAME),
});
};
14 changes: 10 additions & 4 deletions ui/webui/src/components/review/ReviewConfiguration.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ import {
} from "../../apis/storage.js";
import { checkDeviceInSubTree } from "../../helpers/storage.js";

import { AnacondaPage } from "../AnacondaPage.jsx";

import { getScenario } from "../storage/InstallationScenario.jsx";

import "./ReviewConfiguration.scss";
Expand Down Expand Up @@ -116,7 +114,7 @@ export const ReviewConfiguration = ({ deviceData, diskSelection, language, local
}, [setIsFormValid]);

return (
<AnacondaPage title={_("Review and install")}>
<>
<ReviewDescriptionList>
<DescriptionListGroup>
<DescriptionListTerm>
Expand Down Expand Up @@ -172,7 +170,7 @@ export const ReviewConfiguration = ({ deviceData, diskSelection, language, local
</DescriptionListDescription>
</DescriptionListGroup>
</ReviewDescriptionList>
</AnacondaPage>
</>
);
};

Expand Down Expand Up @@ -209,3 +207,11 @@ export const ReviewConfigurationConfirmModal = ({ idPrefix, onNext, setNextWaits
</Modal>
);
};

export const getPageProps = () => {
return ({
id: "installation-review",
label: _("Review and install"),
title: _("Review and install")
});
};
Loading

0 comments on commit ae50381

Please sign in to comment.