///////////////////////////////////////////////////////////// // // pgAdmin 4 - PostgreSQL Tools // // Copyright (C) 2013 - 2024, The pgAdmin Development Team // This software is released under the PostgreSQL Licence // ////////////////////////////////////////////////////////////// import React from 'react'; import { styled } from '@mui/material/styles'; import FastForwardIcon from '@mui/icons-material/FastForward'; import FastRewindIcon from '@mui/icons-material/FastRewind'; import ChevronRightIcon from '@mui/icons-material/ChevronRight'; import DoneIcon from '@mui/icons-material/Done'; import HelpIcon from '@mui/icons-material/HelpRounded'; import CheckIcon from '@mui/icons-material/Check'; import { DefaultButton, PrimaryButton, PgIconButton } from '../../../../static/js/components/Buttons'; import PropTypes from 'prop-types'; import { Box } from '@mui/material'; import gettext from 'sources/gettext'; import Loader from 'sources/components/Loader'; const StyledBox = styled(Box)(({theme}) => ({ height: '100%', display: 'flex', flexDirection: 'column', backgroundColor: theme.palette.background.default + ' !important', '& .Wizard-root': { display: 'flex', flexDirection: 'column', flexGrow: 1, minHeight: 0, '& .Wizard-body': { width: '100%', height: '100%', minHeight: 100, display: 'flex', flexWrap: 'wrap', '& .Wizard-rightPanel': { position: 'relative', display: 'flex', flexBasis: '75%', overflow: 'auto', height: '100%', minHeight: '100px', '& .Wizard-stepDefaultStyle': { width: '100%', height: '100%', padding: '8px', display: 'flex', flexDirection: 'column', }, '& .Wizard-hidden': { display: 'none', } }, '& .Wizard-active': { fontWeight: 600 }, '& .Wizard-leftPanel': { display: 'flex', flexBasis: '25%', flexDirection: 'column', alignItems: 'flex-start', borderRight: '1px solid', ...theme.mixins.panelBorder.right, '& .Wizard-active': { fontWeight: 600 }, '& .Wizard-stepLabel': { padding: '1em', paddingRight: 0, '& .Wizard-stepIndex': { padding: '0.5em 1em ', height: '2.5em', borderRadius: '2em', backgroundColor: theme.otherVars.stepBg, color: theme.otherVars.stepFg, display: 'inline-block', flex: 0.5, '& .Wizard-activeIndex': { backgroundColor: theme.otherVars.activeStepBg + ' !important', color: theme.otherVars.activeStepFg + ' !important' }, }, '& .Wizard-label': { display: 'inline-block', position: 'relative', paddingLeft: '0.5rem', flexBasis: '70%' }, '& .Wizard-labelArrow': { display: 'inline-block', position: 'relative', flexBasis: '30%' }, '& .Wizard-labelDone': { display: 'inline-block', position: 'relative', flexBasis: '30%', color: theme.otherVars.activeStepBg + ' !important', padding: '4px' }, }, }, }, }, '& .Wizard-footer': { borderTop: `1px solid ${theme.otherVars.inputBorderColor} !important`, padding: '0.5rem', display: 'flex', width: '100%', background: theme.otherVars.headerBg, zIndex: 999, '& .Wizard-actionBtn': { alignItems: 'flex-start', '& .Wizard-buttonMargin': { marginLeft: '0.5em' }, }, }, })); function Wizard({ stepList, onStepChange, onSave, className, ...props }) { const [activeStep, setActiveStep] = React.useState(0); const steps = stepList && stepList.length > 0 ? stepList : []; const [disableNext, setDisableNext] = React.useState(false); const handleNext = () => { // beforeNext should always return a promise if(props.beforeNext) { props.beforeNext(activeStep).then((skipCurrentStep=false)=>{ if (skipCurrentStep) { setActiveStep((prevActiveStep) => prevActiveStep + 2); } else { setActiveStep((prevActiveStep) => prevActiveStep + 1); } }).catch(()=>{/*This is intentional (SonarQube)*/}); } else { setActiveStep((prevActiveStep) => prevActiveStep + 1); } }; const handleBack = () => { // beforeBack should always return a promise if(props.beforeBack) { props.beforeBack(activeStep).then((skipCurrentStep=false)=>{ if (skipCurrentStep) { setActiveStep((prevActiveStep) => prevActiveStep - 1 < 0 ? prevActiveStep : prevActiveStep - 2); } else { setActiveStep((prevActiveStep) => prevActiveStep - 1 < 0 ? prevActiveStep : prevActiveStep - 1); } }).catch(()=>{/*This is intentional (SonarQube)*/}); } else { setActiveStep((prevActiveStep) => prevActiveStep - 1 < 0 ? prevActiveStep : prevActiveStep - 1); } }; React.useEffect(() => { if (onStepChange) { onStepChange({ currentStep: activeStep }); } }, [activeStep]); React.useEffect(() => { if (props.disableNextStep) { setDisableNext(props.disableNextStep(activeStep)); } }); return (
{steps.map((label, index) => ( {index + 1} {label} {index === activeStep ? : null} {index < activeStep ? : null} ))}
{ React.Children.map(props.children, (child) => { return (
{child}
); }) }
props.onHelp()} icon={} title="Help for this dialog." disabled={props.disableDialogHelp} /> }> {gettext('Back')} handleNext()} className='Wizard-buttonMargin' startIcon={} disabled={activeStep == steps.length - 1 || disableNext}> {gettext('Next')} } disabled={activeStep !== (steps.length - 1) } onClick={onSave}> {gettext('Finish')}
); } export default Wizard; Wizard.propTypes = { props: PropTypes.object, title: PropTypes.string, stepList: PropTypes.array, onSave: PropTypes.func, onHelp: PropTypes.func, onStepChange: PropTypes.func, className: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), disableNextStep: PropTypes.func, stepPanelCss: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), rootClass: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]), disableDialogHelp: PropTypes.bool, beforeNext: PropTypes.func, beforeBack: PropTypes.func, loaderText: PropTypes.string };