Skip to content

Commit

Permalink
fix: handle unsaved changes
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffreiffers committed Sep 5, 2023
1 parent 50d9feb commit bf60364
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 16 deletions.
26 changes: 14 additions & 12 deletions src/components/form-control/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { memo, useEffect, useState } from 'react';
import { useHistory, useParams } from 'react-router-dom';
import { useParams } from 'react-router-dom';
import { Variant } from '@fellesdatakatalog/button';

import { ConceptStatus, TimeFormat } from '../../types/enums';
Expand All @@ -15,15 +15,19 @@ import SC from './styled';

interface Props<V> {
isFormDirty: boolean;
createNewConceptRevisionAndNavigate: () => void;
onNewConceptRevision: () => void;
onPatch: () => void;
onDelete: () => void;
isInitialInValidForm: boolean;
lastPatchedResponse: any;
values: V;
}

const FormControl = <V,>({
isFormDirty,
createNewConceptRevisionAndNavigate,
onNewConceptRevision,
onPatch,
onDelete,
isInitialInValidForm,
lastPatchedResponse,
values
Expand Down Expand Up @@ -56,11 +60,9 @@ const FormControl = <V,>({
const toggleShowConfirmDelete = (): void =>
setShowConfirmDelete(!showConfirmDelete);

const { catalogId, conceptId } = useParams<{
catalogId: string;
const { conceptId } = useParams<{
conceptId: string;
}>();
const history = useHistory();
const dispatch = useAppDispatch();
const conceptForm = useAppSelector(state => state.conceptForm);
const { concept } = conceptForm;
Expand Down Expand Up @@ -103,23 +105,23 @@ const FormControl = <V,>({
)}.`;
};

const deleteConceptAndNavigate = async (): Promise<void> => {
const confirmDelete = async (): Promise<void> => {
await deleteConcept(conceptId);
history.push(`/${catalogId}`);
onDelete();
};

useEffect(() => {
if (patchCalled && !(isSaving || errorSaving)) {
history.go(0);
onPatch();
}
}, [isSaving, errorSaving, setPatchCalled]);
}, [isSaving, errorSaving, patchCalled, onPatch]);

return concept ? (
<>
<SC.FormControl $isSticky={isSticky}>
<SC.FormControlContent>
{isFormDirty && published && erSistPublisert && (
<SC.Button onClick={createNewConceptRevisionAndNavigate}>
<SC.Button onClick={onNewConceptRevision}>
<SC.StatusDraftIcon />
{localization.saveDraft}
</SC.Button>
Expand Down Expand Up @@ -245,7 +247,7 @@ const FormControl = <V,>({
<ConfirmDialog
title={localization.confirmDeleteTitle}
text={localization.confirmDeleteMessage}
onConfirm={deleteConceptAndNavigate}
onConfirm={confirmDelete}
onCancel={toggleShowConfirmDelete}
/>
)}
Expand Down
45 changes: 41 additions & 4 deletions src/pages/concept-registration-page/form-concept/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { schema as validationSchema } from './form-concept.schema';

import SC from './styled';
import { InternalInfo } from './internal-info';
import { getConfig } from '../../../config';

export type FormValues = Pick<
Concept,
Expand Down Expand Up @@ -92,6 +93,10 @@ export const FormConceptPure: FC<Props> = ({
begrepsRelasjon: begrepsRelasjonError
} = errors;
const [showUserPrompt, setShowUserPrompt] = useState<boolean>(true);
const [patchCalled, setPatchCalled] = useState<boolean>(false);
const [deleteCalled, setDeleteCalled] = useState<boolean>(false);

const config = getConfig();

const languageEntities = useAppSelector(state => state.languages.entities);

Expand Down Expand Up @@ -135,10 +140,38 @@ export const FormConceptPure: FC<Props> = ({
history.push(`/${catalogId}/${resourceId}`);
});

useEffect(() => {
const handler = event => {
event.preventDefault();
event.returnValue = '';
};
// if the form is NOT unchanged, then set the onbeforeunload
if (dirty && showUserPrompt && !(patchCalled || deleteCalled)) {
window.addEventListener('beforeunload', handler);
// clean it up, if the dirty state changes
return () => {
window.removeEventListener('beforeunload', handler);
};
}

if (patchCalled) {
history.go(0);
}
if (deleteCalled) {
history.push(
config.enableConceptCatalogFrontend
? `${config.conceptCatalogFrontendBaseUri}/${catalogId}`
: `/${catalogId}`
);
}
// since this is not dirty, don't do anything
return () => {};
}, [dirty, showUserPrompt, patchCalled, deleteCalled]);

return (
<SC.Page>
<Prompt
when={dirty && showUserPrompt}
when={dirty && showUserPrompt && !(patchCalled || deleteCalled)}
message={localization.unsavedPrompt}
/>
<Can
Expand All @@ -147,9 +180,13 @@ export const FormConceptPure: FC<Props> = ({
>
<FormControl<FormValues>
isFormDirty={dirty}
createNewConceptRevisionAndNavigate={
createNewConceptRevisionAndNavigate
}
onNewConceptRevision={createNewConceptRevisionAndNavigate}
onPatch={() => {
setPatchCalled(true);
}}
onDelete={() => {
setDeleteCalled(true);
}}
isInitialInValidForm={!isValid}
lastPatchedResponse={lastPatchedResponse}
values={values}
Expand Down

0 comments on commit bf60364

Please sign in to comment.