Skip to content

Commit

Permalink
feat: Block navigation in visualization form
Browse files Browse the repository at this point in the history
  • Loading branch information
josebui committed Dec 7, 2023
1 parent 2e2b06d commit 6c814cd
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 17 deletions.
4 changes: 3 additions & 1 deletion src/localization/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,9 @@
"upload_link_form.description": "$t(sharedData.upload_description_label)",
"addSharedDataLink.terraso_api.invalid": "Invalid $t(sharedData.upload_{{field}}_label)",
"link_delete_tooltip": "Remove link “{{name}}”.",
"file_delete_tooltip": "Remove file “{{name}}”."
"file_delete_tooltip": "Remove file “{{name}}”.",
"visualization_unsaved_changes_title": "Leave Map?",
"visualization_unsaved_changes_message": "You have unsaved changes that will be lost if you leave the page. Finish map before you leave."
},
"common": {
"dialog_cancel_label": "Cancel",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -697,8 +697,16 @@ test.each([
])(
'VisualizationConfigForm: Create %s visualization',
async (caseDescription, testParams) => {
const preventDefault = jest.fn();
window.onbeforeunload = jest.fn(event => {
event.preventDefault = preventDefault;
});
const { map, events } = await setup(testParams);

// Navigation is not blocked in the first step
window.dispatchEvent(new Event('beforeunload'));
expect(preventDefault).toHaveBeenCalledTimes(0);

await testSelectDataFileStep(testParams);
await testStepper(testParams);
if (isDataSetFile(testParams.selectFile)) {
Expand All @@ -714,6 +722,10 @@ test.each([
testParams.expectedDataEntriesFetchInput
);

// Block navigation if there are unsaved changes
window.dispatchEvent(new Event('beforeunload'));
expect(preventDefault).toHaveBeenCalledTimes(1);

// Save
await act(async () =>
fireEvent.click(screen.getByRole('button', { name: 'Publish' }))
Expand All @@ -728,6 +740,10 @@ test.each([
expect(JSON.parse(saveCall[1].input.configuration)).toStrictEqual(
testParams.expectedConfiguration
);

// Navigation is not blocked after saving
window.dispatchEvent(new Event('beforeunload'));
expect(preventDefault).toHaveBeenCalledTimes(1);
},
30000
);
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
import React, { useState } from 'react';
import React, { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next';

import Stepper from 'common/components/Stepper';
import NavigationBlockedDialog from 'navigation/components/NavigationBlockedDialog';
import { useNavigationBlocker } from 'navigation/navigationContext';
import {
useVisualizationContext,
VisualizationContextProvider,
Expand Down Expand Up @@ -143,32 +145,59 @@ const Steps = props => {
};

const VisualizationConfigForm = props => {
const { t } = useTranslation();
const { onCompleteSuccess, onCancel } = props;
const [visualizationConfig, setVisualizationConfig] =
useState(INITIAL_CONFIG);
const [isDirty, setIsDirty] = useState(false);

const onReadFileFails = setActiveStepIndex => () => {
setActiveStepIndex(0);
};
const { isBlocked, unblock, cancel } = useNavigationBlocker(
isDirty,
t('sharedData.visualization_unsaved_changes_message')
);

const onReadFileFails = useCallback(
setActiveStepIndex => () => {
setActiveStepIndex(0);
},
[]
);

const onStepUpdate = update =>
const onStepUpdate = useCallback(update => {
setVisualizationConfig(current => ({
...current,
...update,
}));
setIsDirty(true);
}, []);

const onCompleteSuccessWrapper = useCallback(() => {
onCompleteSuccess(visualizationConfig);
setIsDirty(false);
}, [onCompleteSuccess, visualizationConfig]);

return (
<VisualizationContextProvider
visualizationConfig={visualizationConfig}
setVisualizationConfig={setVisualizationConfig}
>
<Steps
onReadFileFails={onReadFileFails}
onStepUpdate={onStepUpdate}
onCompleteSuccess={onCompleteSuccess}
onCancel={onCancel}
/>
</VisualizationContextProvider>
<>
{isBlocked && (
<NavigationBlockedDialog
title={t('sharedData.visualization_unsaved_changes_title')}
message={t('sharedData.visualization_unsaved_changes_message')}
onConfirm={unblock}
onCancel={cancel}
/>
)}
<VisualizationContextProvider
visualizationConfig={visualizationConfig}
setVisualizationConfig={setVisualizationConfig}
>
<Steps
onReadFileFails={onReadFileFails}
onStepUpdate={onStepUpdate}
onCompleteSuccess={onCompleteSuccessWrapper}
onCancel={onCancel}
/>
</VisualizationContextProvider>
</>
);
};

Expand Down

0 comments on commit 6c814cd

Please sign in to comment.