* Copyright (C) 2023 Red Hat, Inc.
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
import { useCallback, useReducer } from "react";
export const storageInitialState = {
appliedPartitioning: null,
deviceTrees: {
"": {
actions: [],
devices: {},
mountPoints: {},
},
},
diskSelection: {
ignoredDisks: [],
selectedDisks: [],
usableDisks: []
},
luks: {
confirmPassphrase: "",
encrypted: false,
passphrase: "",
},
mountPoints: {},
partitioning: {},
storageScenarioId: null,
};
export const localizationInitialState = {
commonLocales: [],
compositorLayouts: [],
keyboardLayouts: [],
language: "",
languageKickstarted: false,
languages: {},
plannedVconsole: undefined,
plannedXlayouts: undefined,
userConfigured: false,
xlayouts: undefined,
};
export const bossInitialState = {
installationStatus: null,
pendingError: { message: "", type: "" },
};
export const networkInitialState = {
connected: null
};
export const runtimeInitialState = {
connected: null,
};
export const timezoneInitialState = {
allValidTimezones: {},
kickstarted: false,
timezone: "",
userConfigured: false,
};
export const miscInitialState = {
isFetching: false,
};
export const payloadInitialState = {
environments: [],
groups: [],
packagesKickstarted: false,
selection: null,
type: null,
};
export const usersInitialState = {
adminUserExists: false,
canModifyRootConfiguration: true,
canModifyUserConfiguration: true,
confirmPassword: "",
isRootEnabled: false,
isRootPasswordSet: false,
password: "",
rootConfirmPassword: "",
rootPassword: "",
users: [],
};
export const initialState = {
boss: bossInitialState,
localization: localizationInitialState,
misc: miscInitialState,
network: networkInitialState,
payload: payloadInitialState,
runtime: runtimeInitialState,
storage: storageInitialState,
timezone: timezoneInitialState,
users: usersInitialState,
};
export const useReducerWithThunk = (reducer, initialState) => {
const [state, dispatch] = useReducer(reducer, initialState);
function customDispatch (action) {
if (typeof action === "function") {
return action(customDispatch);
} else {
dispatch(action);
}
}
const stableDispatch = useCallback(customDispatch, [dispatch]);
return [state, stableDispatch];
};
export const reducer = (state, action) => {
return ({
boss: bossReducer(state.boss, action),
localization: localizationReducer(state.localization, action),
misc: miscReducer(state.misc, action),
network: networkReducer(state.network, action),
payload: payloadReducer(state.payload, action),
runtime: runtimeReducer(state.runtime, action),
storage: storageReducer(state.storage, action),
timezone: timezoneReducer(state.timezone, action),
users: usersReducer(state.users, action)
});
};
export const storageReducer = (state = storageInitialState, action) => {
if (action.type === "GET_DEVICES_DATA") {
return {
...state,
deviceTrees: {
...state.deviceTrees,
[state.appliedPartitioning ? state.partitioning.deviceTree.path : ""]: {
actions: action.payload.actions,
devices: action.payload.devices,
existingSystems: action.payload.existingSystems,
mountPoints: action.payload.mountPoints,
}
}
};
} else if (action.type === "GET_DISK_SELECTION") {
return { ...state, diskSelection: action.payload.diskSelection };
} else if (action.type === "GET_PARTITIONING_DATA") {
return {
...state,
partitioning: {
...state.partitioning,
...action.payload.partitioningData,
deviceTree: action.payload.deviceTree,
storageScenarioId: state.storageScenarioId
}
};
} else if (action.type === "SET_APPLIED_PARTITIONING") {
return { ...state, appliedPartitioning: action.payload.appliedPartitioning };
} else if (action.type === "SET_STORAGE_SCENARIO") {
return { ...state, storageScenarioId: action.payload.scenario };
} else if (action.type === "SET_LUKS_ENCRYPTION_DATA") {
const newLuksState = {
...state.luks,
...action.payload,
};
if (action.payload.encrypted === false) {
newLuksState.passphrase = "";
newLuksState.confirmPassphrase = "";
}
return {
...state,
luks: newLuksState,
};
} else {
return state;
}
};
export const localizationReducer = (state = localizationInitialState, action) => {
if (action.type === "GET_LANGUAGE_DATA") {
return { ...state, languages: { ...state.languages, ...action.payload.languageData } };
} else if (action.type === "GET_COMMON_LOCALES") {
return { ...state, commonLocales: action.payload.commonLocales };
} else if (action.type === "GET_LANGUAGE") {
return { ...state, language: action.payload.language };
} else if (action.type === "GET_KEYBOARD_LAYOUTS") {
return { ...state, keyboardLayouts: action.payload.keyboardLayouts };
} else if (action.type === "GET_PLANNED_KEYBOARD_CONFIGURATION") {
return {
...state,
plannedVconsole: action.payload.plannedVconsole,
plannedXlayouts: action.payload.plannedXlayouts,
xlayouts: action.payload.xlayouts,
};
} else if (action.type === "SET_LANGUAGE_KICKSTARTED") {
return { ...state, languageKickstarted: action.payload.languageKickstarted };
} else if (action.type === "SET_LANGUAGE_USER_CONFIGURED") {
return { ...state, userConfigured: true };
} else {
return state;
}
};
export const bossReducer = (state = bossInitialState, action) => {
if (action.type === "GET_INSTALLATION_STATUS") {
return { ...state, installationStatus: action.payload.status };
} else if (action.type === "GET_PENDING_ERROR") {
return { ...state, pendingError: { message: action.payload.message, type: action.payload.type } };
} else {
return state;
}
};
export const networkReducer = (state = networkInitialState, action) => {
if (action.type === "GET_NETWORK_CONNECTED") {
return { ...state, connected: action.payload.connected };
} else if (action.type === "GET_NETWORK_HOSTNAME") {
return { ...state, hostname: action.payload.hostname };
} else {
return state;
}
};
const miscReducer = (state = miscInitialState, action) => {
if (action.type === "SET_IS_FETCHING") {
return { ...state, isFetching: action.payload.isFetching };
} else {
return state;
}
};
export const runtimeReducer = (state = runtimeInitialState, action) => {
if (action.type === "GET_RUNTIME_PASSWORD_POLICIES") {
return { ...state, passwordPolicies: action.payload.passwordPolicies };
} else {
return state;
}
};
export const timezoneReducer = (state = timezoneInitialState, action) => {
if (action.type === "SET_TIMEZONE") {
const { kickstarted, timezone } = action.payload;
return {
...state,
...(kickstarted !== undefined && { kickstarted }),
...(timezone !== undefined && { timezone }),
};
} else if (action.type === "SET_TIMEZONE_USER_CONFIGURED") {
return { ...state, userConfigured: true };
} else if (action.type === "SET_ALL_VALID_TIMEZONES") {
return { ...state, allValidTimezones: action.payload.allValidTimezones };
} else {
return state;
}
};
export const payloadReducer = (state = payloadInitialState, action) => {
if (action.type === "SET_PAYLOAD_SELECTION") {
return {
...state,
selection: action.payload.selection,
...(action.payload.packagesKickstarted !== undefined
? { packagesKickstarted: action.payload.packagesKickstarted }
: {}),
};
} else if (action.type === "SET_PAYLOAD_ENVIRONMENTS") {
return { ...state, environments: action.payload.environments || [] };
} else if (action.type === "SET_PAYLOAD_TYPE") {
return { ...state, type: action.payload.type };
} else if (action.type === "SET_PAYLOAD_GROUPS") {
return { ...state, groups: action.payload.groups };
} else {
return state;
}
};
export const usersReducer = (state = usersInitialState, action) => {
if (action.type === "SET_USERS") {
const { firstUser, ...rest } = action.payload;
let next = { ...state, ...rest };
if (firstUser !== undefined) {
const existing = state.users ?? [];
const [currentFirst = {}, ...tail] = existing;
const updatedFirst = {
...currentFirst,
gecos: firstUser.gecos,
name: firstUser.name,
};
const updatedUsers = (firstUser.name || firstUser.gecos || tail.length > 0)
? [updatedFirst, ...tail]
: [];
next = {
...next,
users: updatedUsers,
};
if (firstUser.password !== undefined) {
next.password = firstUser.password;
}
if (firstUser.confirmPassword !== undefined) {
next.confirmPassword = firstUser.confirmPassword;
}
}
return next;
} else if (action.type === "SET_USER_CONFIGURATION_POLICY") {
return { ...state, ...action.payload };
} else {
return state;
}
};