diff --git a/src/Routes/RouteConstant.tsx b/src/Routes/RouteConstant.tsx
new file mode 100644
index 00000000..cd65fb01
--- /dev/null
+++ b/src/Routes/RouteConstant.tsx
@@ -0,0 +1,5 @@
+export const ROUTES = {
+ HOME: '/',
+ WIZARD: '/wizard',
+};
+
\ No newline at end of file
diff --git a/src/renderer/components/Dialogs/WarningDialog.tsx b/src/renderer/components/Dialogs/WarningDialog.tsx
new file mode 100644
index 00000000..49a6d7ea
--- /dev/null
+++ b/src/renderer/components/Dialogs/WarningDialog.tsx
@@ -0,0 +1,43 @@
+/*
+ * This program and the accompanying materials are made available under the terms of the
+ * Eclipse Public License v2.0 which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v20.html
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Copyright Contributors to the Zowe Project.
+ */
+import { Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, FormControl, TextField } from '@mui/material';
+import { useState } from 'react';
+
+const WarningDialog = ({onWarningDialogSubmit}: {onWarningDialogSubmit: any}) => {
+
+ const [isDialogVisible, setIsDialogVisible] = useState(true);
+
+ const handleClose = () => {
+ setIsDialogVisible(false);
+ onWarningDialogSubmit(false);
+ }
+
+ const handleSubmit = () => {
+ setIsDialogVisible(false);
+ onWarningDialogSubmit(true);
+ }
+
+ return (
+
+
+
+ )
+}
+
+export default WarningDialog;
\ No newline at end of file
diff --git a/src/renderer/components/Home.tsx b/src/renderer/components/Home.tsx
index 1499e9ca..0fe4644f 100644
--- a/src/renderer/components/Home.tsx
+++ b/src/renderer/components/Home.tsx
@@ -10,7 +10,7 @@
import '../global.css';
import { useEffect, useState } from "react";
-import { Link } from 'react-router-dom';
+import { Link, useNavigate } from 'react-router-dom';
import { Box, Card, CardContent, CardMedia, Typography, Button } from '@mui/material';
import flatten, { unflatten } from 'flat';
import { IResponse, IIpcConnectionArgs } from '../../types/interfaces';
@@ -22,25 +22,22 @@ import { Tooltip } from '@mui/material';
import installationImg from '../assets/installation.png'
import installationDryImg from '../assets/installation-dry-run.png'
import eventDispatcher from "../../services/eventDispatcher";
-import { selectConnectionStatus} from './stages/progress/progressSlice';
+import { selectConnectionStatus, setConnectionStatus} from './stages/progress/progressSlice';
import HorizontalLinearStepper from './common/Stepper';
import Wizard from './configuration-wizard/Wizard'
-import { ActiveState } from '../../types/stateInterfaces';
+import { ActiveState, InstallationArgs } from '../../types/stateInterfaces';
import { getInstallationArguments, getPreviousInstallation } from './stages/progress/StageProgressStatus';
import { DEF_NO_OUTPUT, FALLBACK_SCHEMA, FALLBACK_YAML } from './common/Utils';
-import { selectInstallationArgs, setInstallationArgs, installationSlice } from './stages/installation/installationSlice';
+import { selectInstallationArgs, setInstallationArgs, installationSlice, setIsNewInstallation, selectIsNewInstallation } from './stages/installation/installationSlice';
import PasswordDialog from './common/passwordDialog';
+import WarningDialog from './Dialogs/WarningDialog';
+import HomeCardComponent from './HomeCardComponent';
+import { ICard } from '../../types/interfaces';
+import { ROUTES } from '../../Routes/RouteConstant';
// REVIEW: Get rid of routing
-interface ICard {
- id: string,
- name: string,
- description: string,
- link: string,
- media: any,
-}
-
+// Cards Data
const cards: Array = [
{
id: "install",
@@ -58,79 +55,39 @@ const cards: Array = [
}
]
+// Constants
const prevInstallationKey = "prev_installation";
const lastActiveState: ActiveState = {
activeStepIndex: 0,
isSubStep: false,
activeSubStepIndex: 0,
};
+const defaultTooltip: string = "Resume";
+
+// Helper Functions
+const getNewInstallationArgs = (id: string, currentArgs: InstallationArgs) => {
+ return id === "install"
+ ? { ...currentArgs, dryRunMode: false }
+ : { ...currentArgs, dryRunMode: true };
+};
const Home = () => {
const dispatch = useAppDispatch();
+ const navigate = useNavigate();
const connectionStatus = useAppSelector(selectConnectionStatus);
- const [showWizard, setShowWizard] = useState(false);
- const [showLoginDialog, setShowLogin] = useState(false);
- const [localYaml, setLocalYaml] = useState(useAppSelector(selectYaml));
- const [schema, setLocalSchema] = useState(useAppSelector(selectSchema));
- const installationArgs = useAppSelector(selectInstallationArgs);
-
- const { activeStepIndex, isSubStep, activeSubStepIndex, lastActiveDate } = getPreviousInstallation();
-
- const [isNewInstallation, setIsNewInstallation] = useState(false);
-
+ const schema = useAppSelector(selectSchema);
const stages: any = [];
- const defaultTooltip: string = "Resume";
const resumeTooltip = connectionStatus ? defaultTooltip : `Validate Credentials & ${defaultTooltip}`;
+ const isNewInstallation = useAppSelector(selectIsNewInstallation);
+ const { lastActiveDate } = getPreviousInstallation();
+
+ const [showWizard, setShowWizard] = useState(false);
+ const [localYaml, setLocalYaml] = useState(useAppSelector(selectYaml));
const [showPasswordDialog, setShowPasswordDialog] = useState(false);
- const [updatedConnection, setUpdatedConnection] = useState(false);
- const [isResume, setIsResume] = useState(useAppSelector(selectResumeProgress));
-
- const makeCard = (card: ICard) => {
- const {id, name, description, link, media} = card;
-
- const handleClick = () => {
- let newInstallationArgs = installationSlice.getInitialState().installationArgs;
- if (id === "install") {
- newInstallationArgs = {...newInstallationArgs, dryRunMode: false};
- } else if (id === "dry run") {
- newInstallationArgs = {...newInstallationArgs, dryRunMode: true};
- }
- dispatch(setYaml(FALLBACK_YAML));
- dispatch(setInstallationArgs(newInstallationArgs));
- window.electron.ipcRenderer.setConfigByKeyNoValidate("installationArgs", newInstallationArgs);
- setLocalYaml(FALLBACK_YAML);
- window.electron.ipcRenderer.setConfig(FALLBACK_YAML);
- // TODO: Ideally, reset connectionArgs too
- // but this introduces bug with "self certificate chain" it's the checkbox, it looks checked but
- // it acts like it's not unless you touch it
- // dispatch(setConnectionArgs(connectionSlice.getInitialState().connectionArgs));
- setIsResume(false);
- };
-
- return (
-
-
-
-
-
-
-
- {name}
-
-
- {description}
-
-
-
-
-
-
- )
- }
+ const [newInstallationClicked, setNewInstallationClick] = useState(false);
+ const [previousInstallation, setPreviousInstallation] = useState(false);
+ const [defaultYaml, setDefaultYaml] = useState(FALLBACK_YAML);
useEffect(() => {
eventDispatcher.on('saveAndCloseEvent', () => setShowWizard(false));
@@ -142,8 +99,9 @@ const Home = () => {
window.electron.ipcRenderer.getConfig().then((res: IResponse) => {
if (res.status) {
dispatch(setYaml(res.details));
+ setDefaultYaml(res.details);
} else {
- dispatch(setYaml(FALLBACK_YAML));
+ dispatch(setYaml(defaultYaml));
}
})
}
@@ -176,14 +134,10 @@ const Home = () => {
}
});
- window.electron.ipcRenderer.setStandardOutput(DEF_NO_OUTPUT).then((res: any) => {
- })
-
window.electron.ipcRenderer.findPreviousInstallations().then((res: IResponse) => {
const connectionStore = res.details;
if (connectionStore["connection-type"] === 'ftp') {
const jobStatement = connectionStore['ftp-details'].jobStatement.trim() || useAppSelector(selectInitJobStatement);
- // console.log(JSON.stringify(connectionStore['ftp-details'],null,2));
const connectionArgs: IIpcConnectionArgs = {
...connectionStore["ftp-details"],
password: "",
@@ -200,13 +154,14 @@ const Home = () => {
if (!lastInstallation) {
const flattenedData = flatten(lastActiveState);
localStorage.setItem(prevInstallationKey, JSON.stringify(flattenedData));
- setIsNewInstallation(true);
+ dispatch(setIsNewInstallation(true));
+ setPreviousInstallation(false);
} else {
const data: ActiveState = unflatten(JSON.parse(lastInstallation));
- setIsNewInstallation(!(data && data.lastActiveDate));
+ dispatch(setIsNewInstallation(!(data && data.lastActiveDate)));
+ setPreviousInstallation(!!(data && data.lastActiveDate));
}
-
});
return () => {
eventDispatcher.off('saveAndCloseEvent', () => setShowWizard(true));
@@ -216,33 +171,93 @@ const Home = () => {
const resumeProgress = () => {
setShowWizard(true);
dispatch(setResumeProgress(true));
-
+ dispatch(setIsNewInstallation(false));
+
if(connectionStatus) {
setShowPasswordDialog(true);
- setUpdatedConnection(false);
}
}
const confirmConnection = (status: boolean) => {
- setUpdatedConnection(status);
+ setShowPasswordDialog(!status);
setShowWizard(status);
}
+ const handleNewInstallation = (newInstallationArgs: InstallationArgs) => {
+ dispatch(setYaml(defaultYaml));
+ dispatch(setInstallationArgs(newInstallationArgs));
+
+ window.electron.ipcRenderer.setConfigByKeyNoValidate("installationArgs", newInstallationArgs);
+ window.electron.ipcRenderer.setConfig(defaultYaml);
+
+ setLocalYaml(defaultYaml);
+
+ // TODO: Ideally, reset connectionArgs too
+ // but this introduces bug with "self certificate chain" it's the checkbox, it looks checked but
+ // it acts like it's not unless you touch it
+ // dispatch(setConnectionArgs(connectionSlice.getInitialState().connectionArgs));
+ }
+
+ const handleCardClick = (id: string) => {
+
+ const initialInstallationArgs = installationSlice.getInitialState().installationArgs;
+ const newInstallationArgs = getNewInstallationArgs(id, initialInstallationArgs);
+
+ if (id === "install") {
+ setNewInstallationClick(true);
+ if(previousInstallation) {
+ return;
+ }
+ dispatch(setIsNewInstallation(true));
+ dispatch(setConnectionStatus(false));
+ dispatch(setResumeProgress(false));
+ }
+ handleNewInstallation(newInstallationArgs);
+ };
+
+ const confirmNewInstallation = (status: boolean) => {
+ dispatch(setIsNewInstallation(status))
+ setNewInstallationClick(false);
+ setPreviousInstallation(!status);
+
+ if(status) {
+ dispatch(setConnectionStatus(false));
+ dispatch(setResumeProgress(false));
+ handleNewInstallation({ ...installationSlice.getInitialState().installationArgs, dryRunMode: false });
+ navigate(ROUTES.WIZARD);
+ }
+ }
+
return (
<>
+ { previousInstallation && newInstallationClicked &&
+
+ }
+
{!showWizard &&
-
+ {stages.length > 0 && }
{!connectionStatus &&
}
- {cards.map(card => makeCard(card))}
+ {cards.map(card => (
+
+ ))}
- {!isNewInstallation &&
+ {previousInstallation &&
@@ -268,8 +283,7 @@ const Home = () => {
{showWizard &&
<>
{showPasswordDialog &&
}
- {(showPasswordDialog && updatedConnection) &&
}
- {!showPasswordDialog && }
+ {!showPasswordDialog && }
>
}
>
diff --git a/src/renderer/components/HomeCardComponent.tsx b/src/renderer/components/HomeCardComponent.tsx
new file mode 100644
index 00000000..22355aff
--- /dev/null
+++ b/src/renderer/components/HomeCardComponent.tsx
@@ -0,0 +1,27 @@
+import { Box, Card, CardContent, CardMedia, Typography, Tooltip, Button } from '@mui/material';
+import { Link } from 'react-router-dom';
+
+const HomeCardComponent = ({ id, name, description, link, media, previousInstallation, handleCardClick }:{id: string, name: string, description: string, link: string, media: any, previousInstallation: boolean, handleCardClick: any}) => {
+
+ return (
+
+ handleCardClick(id)}>
+
+
+
+
+
+ {name}
+
+
+ {description}
+
+
+
+
+
+
+ );
+};
+
+export default HomeCardComponent;
diff --git a/src/renderer/components/common/Stepper.tsx b/src/renderer/components/common/Stepper.tsx
index 0b345870..e938f03b 100644
--- a/src/renderer/components/common/Stepper.tsx
+++ b/src/renderer/components/common/Stepper.tsx
@@ -9,7 +9,6 @@
*/
import React, { useState, useEffect } from 'react';
-import { useSelector } from 'react-redux';
import Box from '@mui/material/Box';
import Stepper from '@mui/material/Stepper';
import Step from '@mui/material/Step';
@@ -29,27 +28,25 @@ import Warning from '@mui/icons-material/Warning';
import CheckCircle from '@mui/icons-material/CheckCircle';
import { TYPE_YAML, TYPE_OUTPUT, TYPE_JCL, INIT_STAGE_LABEL, REVIEW_INSTALL_STAGE_LABEL, UNPAX_STAGE_LABEL } from '../common/Utils';
import { getProgress, getCompleteProgress, mapAndSetSkipStatus, mapAndGetSkipStatus } from '../stages/progress/StageProgressStatus';
-
import '../../styles/Stepper.css';
import { StepIcon } from '@mui/material';
import { getStageDetails } from '../../../services/StageDetails';
import { IResponse } from '../../../types/interfaces';
import { selectConnectionArgs, setPassword } from '../stages/connection/connectionSlice';
-import { selectInstallationArgs } from '../stages/installation/installationSlice';
+import { selectInstallationArgs, selectIsNewInstallation } from '../stages/installation/installationSlice';
// TODO: define props, stages, stage interfaces
// TODO: One rule in the store to enable/disable button
export default function HorizontalLinearStepper({stages, initialization}:{stages: any, initialization?:boolean}) {
- const connectionStatus = useSelector(selectConnectionStatus);
+ const connectionStatus = useAppSelector(selectConnectionStatus);
- const INIT_STAGE_ID = getStageDetails(INIT_STAGE_LABEL).id;
- const REVIEW_STAGE_ID = getStageDetails(REVIEW_INSTALL_STAGE_LABEL).id;
+ const isNewInstallation = useAppSelector(selectIsNewInstallation);
const completeProgress = getCompleteProgress();
-
+
const stageProgressStatus = [
- useSelector(selectConnectionStatus),
+ useAppSelector(selectConnectionStatus),
completeProgress.planningStatus,
completeProgress.installationTypeStatus,
completeProgress.downloadUnpaxStatus,
@@ -66,15 +63,11 @@ export default function HorizontalLinearStepper({stages, initialization}:{stages
completeProgress.certificateStatus,
completeProgress.launchConfigStatus
])
-
-
- const [activeStep, setActiveStep] = initialization ? useState(0) : useState(useAppSelector(selectActiveStepIndex));
- const [activeSubStep, setActiveSubStep] = initialization ? useState(0) : useState(useAppSelector(selectActiveSubStepIndex));
- const [nextText, setNextText] = useState("Continue");
+ const [activeStep, setActiveStep] = isNewInstallation ? useState(0) : useState(useAppSelector(selectActiveStepIndex));
+ const [activeSubStep, setActiveSubStep] = isNewInstallation ? useState(0) : useState(useAppSelector(selectActiveSubStepIndex));
const [contentType, setContentType] = useState('output');
const [editorVisible, setEditorVisible] = useState(false);
- const [editorContent, setEditorContent] = useState('');
const installationArgs = useAppSelector(selectInstallationArgs);
const connectionArgs = useAppSelector(selectConnectionArgs);
const dispatch = useAppDispatch();
@@ -108,14 +101,6 @@ export default function HorizontalLinearStepper({stages, initialization}:{stages
setEditorVisible(!editorVisible);
};
- const getContinueText = () => {
- return 'Continue to next step';//'+stages[activeStep+1].label;
- };
-
- const getSkipText = () => {
- return 'Skip step';//+stages[activeStep+1].label;
- };
-
const handleYAML = () => {
toggleEditorVisibility(TYPE_YAML);
}
@@ -168,14 +153,12 @@ export default function HorizontalLinearStepper({stages, initialization}:{stages
return;
}
setActiveStep((prevActiveStep) => prevActiveStep + 1);
- setNextText(getContinueText());
}
};
const handleBack = () => {
alertEmitter.emit('hideAlert');
stages[activeStep].subStages && activeSubStep > 0 ? setActiveSubStep((prevActiveSubStep) => prevActiveSubStep - 1) : setActiveStep((prevActiveStep) => prevActiveStep - 1);
- setNextText(getContinueText());
};
const handleReset = () => {
@@ -183,11 +166,6 @@ export default function HorizontalLinearStepper({stages, initialization}:{stages
setActiveStep(0);
};
- const handlePreview = (test_jcl: any) => {
- toggleEditorVisibility(TYPE_JCL);
- setEditorContent(test_jcl);
- };
-
const handleStepperClick = (newActiveStep: number, isSubStep: boolean, subStepIndex?: number) => {
if(!connectionStatus) {
return;
@@ -239,9 +217,6 @@ export default function HorizontalLinearStepper({stages, initialization}:{stages
alertEmitter.emit('hideAlert');
eventDispatcher.emit('saveAndCloseEvent');
dispatch(setPassword(''));
- // TODO: This is a workaround for same session + Save & Close + new install not resetting the Wizard properly.
- // Fixed by reloading page. This is not ideal and should be investigated
- window.location.reload();
}
const isNextStepEnabled = useAppSelector(selectNextStepEnabled);
diff --git a/src/renderer/components/stages/Planning.tsx b/src/renderer/components/stages/Planning.tsx
index 6280545f..e9fceadf 100644
--- a/src/renderer/components/stages/Planning.tsx
+++ b/src/renderer/components/stages/Planning.tsx
@@ -21,7 +21,7 @@ import { setYaml, setNextStepEnabled, setLoading, selectYaml } from '../configur
import { selectConnectionArgs, setConnectionArgs, setJobStatementVal } from './connection/connectionSlice';
import { setPlanningStatus, selectPlanningStatus } from './progress/progressSlice';
import { setZoweVersion, setInstallationArgs, selectInstallationArgs, selectZoweVersion } from './installation/installationSlice';
-import { setJobStatement, setJobStatementValid, setJobStatementValidMsg, setLocationValidationDetails, setIsLocationValid, selectJobStatementValidMsg, selectLocValidationDetails } from "./PlanningSlice";
+import { setJobStatement, setJobStatementValid, setJobStatementValidMsg, setLocationValidationDetails, setIsLocationValid, selectJobStatementValidMsg, selectLocValidationDetails, selectJobStatement } from "./PlanningSlice";
import { useAppDispatch, useAppSelector } from '../../hooks';
import { IResponse } from '../../../types/interfaces';
import { alertEmitter } from "../Header";
@@ -63,8 +63,7 @@ const Planning = () => {
const [jobHeaderSaved, setJobHeaderSaved] = useState(false);
const [isJobStatementUpdated, setIsJobStatementUpdated] = useState(false);
- // const [jobStatementValue, setJobStatementValue] = useState(useAppSelector(selectJobStatement));
- const [jobStatementValue, setJobStatementValue] = useState(getPlanningStageStatus()?.jobStatement);
+ const [jobStatementValue, setJobStatementValue] = useState(useAppSelector(selectJobStatement));
const [locationsValidated, setLocationsValidated] = useState(getPlanningStageStatus()?.isLocationValid || false);
const [isLocationsUpdated, setIsLocationsUpdated] = useState(false);
diff --git a/src/renderer/components/stages/PlanningSlice.tsx b/src/renderer/components/stages/PlanningSlice.tsx
index 82357bd5..765b5ebb 100644
--- a/src/renderer/components/stages/PlanningSlice.tsx
+++ b/src/renderer/components/stages/PlanningSlice.tsx
@@ -11,6 +11,7 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { RootState } from '../../store';
import { setPlanningStageStatus, getPlanningStageStatus } from './progress/StageProgressStatus';
+import { DEF_JOB_STATEMENT } from '../common/Utils';
export interface jobValidation {
jobStatement: string;
@@ -24,7 +25,7 @@ export interface locationValidation {
}
const initialState: jobValidation = {
- jobStatement: getPlanningStageStatus()?.jobStatement || '',
+ jobStatement: getPlanningStageStatus()?.jobStatement || DEF_JOB_STATEMENT,
isJobStatementValid: getPlanningStageStatus()?.isJobStatementValid || false,
jobStatementValidMsg: ''
}
diff --git a/src/renderer/components/stages/ReviewInstallation.tsx b/src/renderer/components/stages/ReviewInstallation.tsx
index 340ec70a..e2611626 100644
--- a/src/renderer/components/stages/ReviewInstallation.tsx
+++ b/src/renderer/components/stages/ReviewInstallation.tsx
@@ -9,7 +9,6 @@
*/
import React, {useEffect, useState} from "react";
-import { useSelector } from 'react-redux';
import {Box, Button, Typography, Tooltip} from '@mui/material';
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
import WarningIcon from '@mui/icons-material/Warning';
@@ -48,7 +47,7 @@ const ReviewInstallation = () => {
const completeProgress = getCompleteProgress();
const stageProgressStatus = [
- useSelector(selectConnectionStatus),
+ useAppSelector(selectConnectionStatus),
completeProgress.planningStatus,
completeProgress.installationTypeStatus,
completeProgress.initializationStatus,
diff --git a/src/renderer/components/stages/connection/Connection.tsx b/src/renderer/components/stages/connection/Connection.tsx
index f1d7dbd6..b4d875e5 100644
--- a/src/renderer/components/stages/connection/Connection.tsx
+++ b/src/renderer/components/stages/connection/Connection.tsx
@@ -33,10 +33,10 @@ import { setConnectionStatus, selectConnectionStatus} from '../progress/progres
import { Container } from "@mui/material";
import { alertEmitter } from "../../Header";
import { getStageDetails, initStageSkipStatus } from "../../../../services/StageDetails";
-import { initializeProgress, getActiveStage, } from "../progress/StageProgressStatus";
+import { initializeProgress, getActiveStage, resetProgress } from "../progress/StageProgressStatus";
import eventDispatcher from "../../../../services/eventDispatcher";
import { setLocationValidationDetails } from "../PlanningSlice";
-import { selectInstallationArgs } from "../installation/installationSlice";
+import { selectInstallationArgs, selectIsNewInstallation } from "../installation/installationSlice";
const Connection = () => {
@@ -125,6 +125,7 @@ const FTPConnectionForm = () => {
const [isFtpConnection, setIsFtpConnection] = useState(useAppSelector(selectConnectionSecure));
const [isAllCertificatesAccepted, setIsAllCertificatesAccepted] = useState(useAppSelector(selectAcceptAllCertificates));
+ const [isNewInstallation, setIsNewInstallation] = useState(useAppSelector(selectIsNewInstallation));
const [formProcessed, toggleFormProcessed] = React.useState(false);
const [validationDetails, setValidationDetails] = React.useState('');
@@ -132,6 +133,12 @@ const FTPConnectionForm = () => {
const installationArgs = useAppSelector(selectInstallationArgs);
+ useEffect(() => {
+ if(isNewInstallation) {
+ resetProgress(connectionArgs.host, connectionArgs.user);
+ }
+ }, []);
+
const handleFormChange = (ftpConnection?:boolean, acceptCerts?:boolean) => {
dispatch(setConnectionStatus(false));
dispatch(setNextStepEnabled(false));
diff --git a/src/renderer/components/stages/installation/installationSlice.ts b/src/renderer/components/stages/installation/installationSlice.ts
index 872c74b7..4bcd01e8 100644
--- a/src/renderer/components/stages/installation/installationSlice.ts
+++ b/src/renderer/components/stages/installation/installationSlice.ts
@@ -17,6 +17,7 @@ interface InstallationState {
installationArgs: InstallationArgs;
zoweVersion: string;
licenseAgreement: boolean;
+ isNewInstallation?: boolean;
}
const initialState: InstallationState = {
@@ -42,6 +43,7 @@ const initialState: InstallationState = {
},
zoweVersion: '',
licenseAgreement: getInstallationTypeStatus()?.licenseAgreement || false,
+ isNewInstallation: false,
};
export const installationSlice = createSlice({
@@ -67,14 +69,18 @@ export const installationSlice = createSlice({
state.licenseAgreement = action.payload;
setInstallationTypeStatus('licenseAgreement', action.payload)
},
+ setIsNewInstallation: (state, action: PayloadAction) => {
+ state.isNewInstallation = action.payload;
+ }
}
});
-export const { setInstallationArgs, setZoweVersion, setInstallationType, setLicenseAgreement, setUserUploadedPaxPath} = installationSlice.actions;
+export const { setInstallationArgs, setZoweVersion, setInstallationType, setLicenseAgreement, setUserUploadedPaxPath, setIsNewInstallation} = installationSlice.actions;
export const selectInstallationArgs = (state: RootState) => state.installation.installationArgs;
export const selectZoweVersion = (state: RootState) => state.installation.zoweVersion;
export const selectInstallationType = (state: RootState) => state.installation.installationArgs.installationType;
export const selectLicenseAgreement = (state: RootState) => state.installation.licenseAgreement;
+export const selectIsNewInstallation = (state: RootState) => state.installation.isNewInstallation;
export default installationSlice.reducer;
diff --git a/src/renderer/components/stages/progress/StageProgressStatus.ts b/src/renderer/components/stages/progress/StageProgressStatus.ts
index 592460c4..bd8c4716 100644
--- a/src/renderer/components/stages/progress/StageProgressStatus.ts
+++ b/src/renderer/components/stages/progress/StageProgressStatus.ts
@@ -10,126 +10,23 @@
import { flatten, unflatten } from 'flat';
import { ProgressState, PlanningState, InstallationType, ActiveState, DatasetInstallationState, InitSubStepsState, CertInitSubStepsState, PlanningValidationDetails, SkipState, InstallationArgs, DownloadUnpaxState} from '../../../../types/stateInterfaces';
+import { initProgressStatus, initInstallationTypeStatus, initDownloadUnpaxStatus, initActiveStatus, initPlanningStageStatus, initDatasetInstallationStatus, initApfAuthStatus, initSecurityInitStatus, initStcsInitStatus, initCertificateInitStatus, initVsamInitStatus, initPlanningValidationDetailsStatus, initStepSkipStatus, initInstallationArgsStatus } from './progressConst';
import { stages } from '../../configuration-wizard/Wizard';
-const installationTypeStatus: InstallationType = {
- installationType: 'download',
- licenseAgreement: false,
- userUploadedPaxPath: '',
-}
-
-export const downloadUnpaxStatus: DownloadUnpaxState = {
- uploadYaml: false,
- download: false,
- upload: false,
- unpax: false,
- getExampleYaml: false,
- getSchemas: false,
-}
-
-const progressStatus: ProgressState = {
- connectionStatus: false,
- planningStatus: false,
- installationTypeStatus: false,
- downloadUnpaxStatus: false,
- initializationStatus: false,
- datasetInstallationStatus: false,
- networkingStatus: false,
- apfAuthStatus: false,
- securityStatus: false,
- stcsStatus: false,
- certificateStatus: false,
- vsamStatus: false,
- launchConfigStatus: false,
- reviewStatus: false,
-}
-
-const activeStatus: ActiveState = {
- activeStepIndex: 0,
- isSubStep: false,
- activeSubStepIndex: 0,
-};
-
-const planningStageStatus: PlanningState = {
- jobStatement: '',
- isJobStatementValid: false,
- isLocationValid: false,
-}
-
-export const datasetInstallationStatus: DatasetInstallationState = {
- uploadYaml: false,
- install: false,
- initMVS: false
-}
-
-const apfAuthStatus: InitSubStepsState = {
- writeYaml: false,
- uploadYaml: false,
- success: false
-}
-
-const securityInitStatus: InitSubStepsState = {
- writeYaml: false,
- uploadYaml: false,
- success: false
-}
-
-const stcsInitStatus: InitSubStepsState = {
- writeYaml: false,
- uploadYaml: false,
- success: false
-}
-
-const certificateInitStatus: CertInitSubStepsState = {
- writeYaml: false,
- uploadYaml: false,
- zweInitCertificate: false
-}
-
-const vsamInitStatus: InitSubStepsState = {
- writeYaml: false,
- uploadYaml: false,
- success: false
-}
-
-const planningValidationDetailsStatus: PlanningValidationDetails = {
- javaVersion: '',
- nodeVersion: '',
- spaceAvailableMb: '',
- error: ''
-}
-
-const stepSkipStatus: SkipState = {
- downloadUnpax: false,
- datasetInstallation: false,
- networking: false,
- apfAuth: false,
- security: false,
- certificate: false,
- vsam: false,
- launchConfig: false
-}
-
-const installationArgsStatus: InstallationArgs = {
- installationDir: '',
- workspaceDir: '',
- logDir:'',
- extensionDir:'',
- installationType: 'download',
- userUploadedPaxPath: '',
- downloadDir: '',
- javaHome: '',
- nodeHome: '',
- setupConfig: {},
- jobName: 'ZWE1SV',
- jobPrefix: 'ZWE1',
- rbacProfile: '1',
- cookieId: '1',
- zosmfHost: '',
- zosmfPort: '443',
- zosmfApplId: 'IZUDFLT',
- dryRunMode:false
-}
+let installationTypeStatus: InstallationType;
+export let downloadUnpaxStatus: DownloadUnpaxState;
+let progressStatus: ProgressState;
+let activeStatus: ActiveState;
+let planningStageStatus: PlanningState;
+export let datasetInstallationStatus: DatasetInstallationState;
+let apfAuthStatus: InitSubStepsState;
+let securityInitStatus: InitSubStepsState;
+let stcsInitStatus: InitSubStepsState;
+let certificateInitStatus: CertInitSubStepsState;
+let vsamInitStatus: InitSubStepsState;
+let planningValidationDetailsStatus: PlanningValidationDetails;
+let stepSkipStatus: SkipState;
+let installationArgsStatus: InstallationArgs;
let progressStateKey = 'stage_progress';
let activeStateKey = 'active_state';
@@ -147,9 +44,14 @@ let prevInstallationKey = `prev_installation`;
let skipStateKey = `skip_state`;
let installationArgsKey = `intallation_args`;
-let skipKeysArray: (keyof SkipState)[] = Object.keys(stepSkipStatus) as (keyof SkipState)[];
+let skipKeysArray: (keyof SkipState)[];
const setKeys = (id: string) => {
+
+ if (progressStateKey.endsWith(`_${id}`)) {
+ return;
+ }
+
progressStateKey = `${progressStateKey}_${id}`;
activeStateKey = `${activeStateKey}_${id}`;
planningStateKey = `${planningStateKey}_${id}`;
@@ -166,10 +68,46 @@ const setKeys = (id: string) => {
installationArgsKey = `${installationArgsKey}_${id}`;
}
+const setProgressObjects = () => {
+ installationTypeStatus = { ...initInstallationTypeStatus };
+ downloadUnpaxStatus = { ...initDownloadUnpaxStatus };
+ progressStatus = { ...initProgressStatus };
+ activeStatus = { ...initActiveStatus };
+ planningStageStatus = { ...initPlanningStageStatus };
+ datasetInstallationStatus = { ...initDatasetInstallationStatus };
+ apfAuthStatus = { ...initApfAuthStatus };
+ securityInitStatus = { ...initSecurityInitStatus };
+ stcsInitStatus = { ...initStcsInitStatus };
+ certificateInitStatus = { ...initCertificateInitStatus };
+ vsamInitStatus = { ...initVsamInitStatus };
+ planningValidationDetailsStatus = { ...initPlanningValidationDetailsStatus };
+ stepSkipStatus = { ...initStepSkipStatus };
+ installationArgsStatus = { ...initInstallationArgsStatus };
+
+ skipKeysArray = Object.keys(stepSkipStatus) as (keyof SkipState)[];
+
+}
+
+export const resetProgress = (host: string, user: string,) => {
+ if(host && user) {
+ const id = `${host}_${user}`;
+ setKeys(id);
+ }
+
+ const keysArray = [progressStateKey, activeStateKey, planningStateKey, installationTypeKey, downloadUnpaxKey, datasetInstallationKey, apfAuthKey, securityKey, stcsKey, certificateKey, vsamKey, planningValidationDetailsKey, prevInstallationKey, skipStateKey, installationArgsKey];
+ keysArray.forEach(key => {
+ if(localStorage.getItem(key) !== null) {
+ localStorage.removeItem(key);
+ }
+ })
+}
+
export const initializeProgress = (host: string, user: string, isResume: boolean) => {
const id = `${host}_${user}`;
setKeys(id);
+ setProgressObjects();
+
const progress = localStorage.getItem(progressStateKey);
if(!progress || !isResume) {
const flattenedData = flatten(progressStatus);
@@ -440,6 +378,9 @@ export const getDownloadUnpaxState = (): DownloadUnpaxState => {
};
export const setPlanningStageStatus = (key: K, newValue: PlanningState[K]): void => {
+ if(!planningStageStatus) {
+ return;
+ }
const planningData = localStorage.getItem(planningStateKey);
if (planningData) {
const flattenedData = JSON.parse(planningData);
@@ -462,6 +403,9 @@ export const getPlanningStageStatus = (): PlanningState => {
}
export const setInstallationArguments = (newInstallationArgs: InstallationArgs): void => {
+ if(!installationArgsStatus) {
+ return;
+ }
Object.assign(installationArgsStatus, newInstallationArgs);
const flattenedData = flatten(installationArgsStatus);
localStorage.setItem(installationArgsKey, JSON.stringify(flattenedData));
@@ -496,6 +440,9 @@ export const getProgress = (key: keyof ProgressState): boolean => {
const unFlattenedData = unflatten(flattenedData) as ProgressState;
return unFlattenedData[key];
} else {
+ if(!progressStatus) {
+ return false;
+ }
return progressStatus[key];
}
}
@@ -506,6 +453,9 @@ export const getCompleteProgress = () : ProgressState => {
const flattenedData = JSON.parse(progress);
return unflatten(flattenedData);
} else {
+ if(!progressStatus) {
+ return initProgressStatus;
+ }
return progressStatus;
}
}
@@ -552,7 +502,7 @@ export const getPreviousInstallation = () : ActiveState => {
const flattenedData = JSON.parse(activeStage);
return unflatten(flattenedData);
} else {
- return activeStatus;
+ return initActiveStatus;
}
}
diff --git a/src/renderer/components/stages/progress/progressConst.ts b/src/renderer/components/stages/progress/progressConst.ts
new file mode 100644
index 00000000..5c3de832
--- /dev/null
+++ b/src/renderer/components/stages/progress/progressConst.ts
@@ -0,0 +1,131 @@
+/*
+ * This program and the accompanying materials are made available under the terms of the
+ * Eclipse Public License v2.0 which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v20.html
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Copyright Contributors to the Zowe Project.
+ */
+
+import { ProgressState, PlanningState, InstallationType, ActiveState, DatasetInstallationState, InitSubStepsState, CertInitSubStepsState, PlanningValidationDetails, SkipState, InstallationArgs, DownloadUnpaxState } from "../../../../types/stateInterfaces";
+
+export const initProgressStatus: ProgressState = {
+ connectionStatus: false,
+ planningStatus: false,
+ installationTypeStatus: false,
+ downloadUnpaxStatus: false,
+ initializationStatus: false,
+ datasetInstallationStatus: false,
+ networkingStatus: false,
+ apfAuthStatus: false,
+ securityStatus: false,
+ stcsStatus: false,
+ certificateStatus: false,
+ vsamStatus: false,
+ launchConfigStatus: false,
+ reviewStatus: false,
+}
+
+export const initInstallationTypeStatus: InstallationType = {
+ installationType: 'download',
+ licenseAgreement: false,
+ userUploadedPaxPath: '',
+}
+
+export const initDownloadUnpaxStatus: DownloadUnpaxState = {
+ uploadYaml: false,
+ download: false,
+ upload: false,
+ unpax: false,
+ getExampleYaml: false,
+ getSchemas: false,
+}
+
+export const initActiveStatus: ActiveState = {
+ activeStepIndex: 0,
+ isSubStep: false,
+ activeSubStepIndex: 0,
+}
+
+export const initPlanningStageStatus: PlanningState = {
+ jobStatement: '',
+ isJobStatementValid: false,
+ isLocationValid: false,
+}
+
+export const initDatasetInstallationStatus: DatasetInstallationState = {
+ uploadYaml: false,
+ install: false,
+ initMVS: false
+}
+
+export const initApfAuthStatus: InitSubStepsState = {
+ writeYaml: false,
+ uploadYaml: false,
+ success: false
+}
+
+export const initSecurityInitStatus: InitSubStepsState = {
+ writeYaml: false,
+ uploadYaml: false,
+ success: false
+}
+
+export const initStcsInitStatus: InitSubStepsState = {
+ writeYaml: false,
+ uploadYaml: false,
+ success: false
+}
+
+export const initCertificateInitStatus: CertInitSubStepsState = {
+ writeYaml: false,
+ uploadYaml: false,
+ zweInitCertificate: false
+}
+
+export const initVsamInitStatus: InitSubStepsState = {
+ writeYaml: false,
+ uploadYaml: false,
+ success: false
+}
+
+export const initPlanningValidationDetailsStatus: PlanningValidationDetails = {
+ javaVersion: '',
+ nodeVersion: '',
+ spaceAvailableMb: '',
+ error: ''
+}
+
+export const initStepSkipStatus: SkipState = {
+ downloadUnpax: false,
+ datasetInstallation: false,
+ networking: false,
+ apfAuth: false,
+ security: false,
+ certificate: false,
+ vsam: false,
+ launchConfig: false
+}
+
+export const initInstallationArgsStatus: InstallationArgs = {
+ installationDir: '',
+ workspaceDir: '',
+ logDir:'',
+ extensionDir:'',
+ installationType: 'download',
+ userUploadedPaxPath: '',
+ downloadDir: '',
+ javaHome: '',
+ nodeHome: '',
+ setupConfig: {},
+ jobName: 'ZWE1SV',
+ jobPrefix: 'ZWE1',
+ rbacProfile: '1',
+ cookieId: '1',
+ zosmfHost: '',
+ zosmfPort: '443',
+ zosmfApplId: 'IZUDFLT',
+ dryRunMode:false
+}
+
\ No newline at end of file
diff --git a/src/renderer/index.tsx b/src/renderer/index.tsx
index b8584af3..8f680680 100644
--- a/src/renderer/index.tsx
+++ b/src/renderer/index.tsx
@@ -19,6 +19,7 @@ import Wizard from './components/configuration-wizard/Wizard';
import Header from './components/Header';
import theme from './theme';
import { ThemeProvider } from '@mui/material/styles';
+import { ROUTES } from '../Routes/RouteConstant';
// TODO: Support of Zowe Configuration and Saved Installation actions.
// - Add and use state saving
@@ -34,9 +35,9 @@ function App() {
- }>
+ }>
} />
- }/>
+ }/>
} />
diff --git a/src/types/interfaces.ts b/src/types/interfaces.ts
index e7eecbae..0c84163a 100644
--- a/src/types/interfaces.ts
+++ b/src/types/interfaces.ts
@@ -45,3 +45,11 @@ export interface IResponse {
errorMsg?: string;
}
+export interface ICard {
+ id: string,
+ name: string,
+ description: string,
+ link: string,
+ media: any,
+}
+