Skip to content

Commit

Permalink
[UI] Wizard: listen for route changes and ask for confirmation (#455)
Browse files Browse the repository at this point in the history
* chore: update react-router-dom

* feat: listen to wizard exiting

* chore: rename callback

* fix: allow navigation after wizard

* chore: no need for formSubmitted validation

* chore: check dirty form for cancellation
  • Loading branch information
fabio-silva authored Jul 9, 2024
1 parent 1471f78 commit fd0b9e9
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 29 deletions.
2 changes: 1 addition & 1 deletion ui/apps/everest/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.47.0",
"react-router-dom": "^6.17.0",
"react-router-dom": "^6.24.0",
"semver": "^7.6.2",
"zod": "^3.22.4"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,14 @@ import {
Typography,
} from '@mui/material';
import { DialogTitle } from '@percona/ui-lib';
import { useNavigate } from 'react-router-dom';
import { Messages } from '../database-form.messages';
import { DatabaseFormCancelDialogProps } from './DatabaseFormCancelDialog.types';

const DatabaseFormCancelDialog = ({
open,
onClose,
onConfirm,
}: DatabaseFormCancelDialogProps) => {
const navigate = useNavigate();

const handleCancel = () => {
navigate('/databases');
};

return (
<Dialog open={open}>
<DialogTitle onClose={onClose}>{Messages.dialog.title}</DialogTitle>
Expand All @@ -45,7 +39,7 @@ const DatabaseFormCancelDialog = ({
<Button autoFocus variant="text" onClick={onClose}>
{Messages.dialog.reject}
</Button>
<Button variant="contained" onClick={handleCancel}>
<Button variant="contained" onClick={onConfirm}>
{Messages.dialog.accept}
</Button>
</DialogActions>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export type DatabaseFormCancelDialogProps = {
open: boolean;
onClose: () => void;
onConfirm: () => void;
};
38 changes: 29 additions & 9 deletions ui/apps/everest/src/pages/database-form/database-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// limitations under the License.

import { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom';
import { useLocation, useBlocker, useNavigate } from 'react-router-dom';
import { zodResolver } from '@hookform/resolvers/zod';
import { Stack, Step, StepLabel } from '@mui/material';
import { Stepper } from '@percona/ui-lib';
Expand All @@ -37,10 +37,10 @@ export const DatabasePage = () => {
const [activeStep, setActiveStep] = useState(0);
const [longestAchievedStep, setLongestAchievedStep] = useState(0);
const [formSubmitted, setFormSubmitted] = useState(false);
const [cancelModalOpen, setCancelModalOpen] = useState(false);
const { mutate: addDbCluster, isPending: isCreating } = useCreateDbCluster();
const { mutate: editDbCluster, isPending: isUpdating } = useUpdateDbCluster();
const { state } = useLocation();
const location = useLocation();
const navigate = useNavigate();
const { isDesktop } = useActiveBreakpoint();
const mode = useDatabasePageMode();
const {
Expand All @@ -66,6 +66,13 @@ export const DatabasePage = () => {
handleSubmit,
} = methods;

const blocker = useBlocker(
({ currentLocation, nextLocation }) =>
isDirty &&
!formSubmitted &&
currentLocation.pathname !== nextLocation.pathname
);

const formHasErrors = Object.values(errors).length > 0;

const onSubmit: SubmitHandler<DbWizardType> = (data) => {
Expand All @@ -75,10 +82,10 @@ export const DatabasePage = () => {
dbPayload: data,
...(mode === 'restoreFromBackup' && {
backupDataSource: {
dbClusterBackupName: state?.backupName,
...(state?.pointInTimeDate && {
dbClusterBackupName: location.state?.backupName,
...(location.state?.pointInTimeDate && {
pitr: {
date: state?.pointInTimeDate,
date: location.state?.pointInTimeDate,
type: 'date',
},
}),
Expand Down Expand Up @@ -139,6 +146,18 @@ export const DatabasePage = () => {
setActiveStep(order - 1);
};

const handleCloseCancellationModal = () => {
if (blocker.state === 'blocked') {
blocker.reset();
}
};

const proceedNavigation = () => {
if (blocker.state === 'blocked') {
blocker.proceed();
}
};

useEffect(() => {
// We disable the inputs on first step to make sure user doesn't change anything before all data is loaded
// When users change the inputs, it means all data was loaded and we should't change the defaults anymore at this point
Expand Down Expand Up @@ -173,7 +192,7 @@ export const DatabasePage = () => {
isSubmitting={isCreating || isUpdating}
hasErrors={formHasErrors}
onSubmit={handleSubmit(onSubmit)}
onCancel={() => setCancelModalOpen(true)}
onCancel={() => navigate('/databases')}
handleNextStep={handleNext}
handlePreviousStep={handleBack}
/>
Expand All @@ -186,8 +205,9 @@ export const DatabasePage = () => {
</FormProvider>
</Stack>
<DatabaseFormCancelDialog
open={cancelModalOpen}
onClose={() => setCancelModalOpen(false)}
open={blocker.state === 'blocked'}
onClose={handleCloseCancellationModal}
onConfirm={proceedNavigation}
/>
</>
);
Expand Down
22 changes: 11 additions & 11 deletions ui/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit fd0b9e9

Please sign in to comment.