Skip to content

Reset pending changes on viewer page change #2070

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 29 additions & 14 deletions geonode_mapstore_client/client/js/epics/gnresource.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import uuid from "uuid";
import url from "url";
import get from 'lodash/get';
import isNil from 'lodash/isNil';

import {
getNewMapConfiguration,
getNewGeoStoryConfig,
Expand All @@ -33,12 +34,13 @@ import {
} from '@js/api/geonode/v2';
import { configureMap } from '@mapstore/framework/actions/config';
import { isMapInfoOpen } from '@mapstore/framework/selectors/mapInfo';
import { getSelectedLayer } from '@mapstore/framework/selectors/layers';
import { isLoggedIn, userSelector } from '@mapstore/framework/selectors/security';
import {
browseData,
selectNode,
showSettings
showSettings,
updateNode,
hideSettings
} from '@mapstore/framework/actions/layers';
import {
setSelectedResource,
Expand All @@ -64,7 +66,8 @@ import {
setMapViewerLinkedResource,
REQUEST_RESOURCE,
resourceLoading,
resourceError
resourceError,
setSelectedLayer
} from '@js/actions/gnresource';

import {
Expand Down Expand Up @@ -94,7 +97,8 @@ import {
canAddResource,
getResourceData,
getResourceId,
getResourceThumbnail
getResourceThumbnail,
getSelectedLayer
} from '@js/selectors/resource';
import { updateAdditionalLayer } from '@mapstore/framework/actions/additionallayers';
import { STYLE_OWNER_NAME } from '@mapstore/framework/utils/StyleEditorUtils';
Expand Down Expand Up @@ -425,15 +429,26 @@ const resourceTypes = {
};

// collect all the reset action needed before changing a viewer
const getResetActions = (isSameResource) => [
resetControls(),
...(!isSameResource ? [ resetResourceState() ] : []),
setControlProperty('rightOverlay', 'enabled', false),
setControlProperty(FIT_BOUNDS_CONTROL, 'geometry', null),
// reset style editor state to avoid persistence service configuration in between resource pages
initStyleService(),
resetStyleEditor()
];
const getResetActions = (state, isSameResource) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get action is used multiple times in this code so before was assuming isSameResource as for argument. Shouldn't we review also other places where getResetActions is used?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getResetActions is used in other scenarios that require a full reset—such as creating a new resource or handling an error—where the resource is not the same. The only case where the isSameResource argument is needed is when loading an existing resource

const initialResource = state?.gnresource?.initialResource;
const initialLayer = initialResource && initialResource.resource_type === ResourceTypes.DATASET && resourceToLayerConfig(initialResource);
return [
resetControls(),
...(!isSameResource
? [ resetResourceState() ]
: [
...(initialResource ? [setResource(initialResource)] : []),
...(initialLayer ? [setSelectedLayer(initialLayer), updateNode(initialLayer.layerId, 'layers', initialLayer)] : [])
]
),
setControlProperty('rightOverlay', 'enabled', false),
setControlProperty(FIT_BOUNDS_CONTROL, 'geometry', null),
// reset style editor state to avoid persistence service configuration in between resource pages
initStyleService(),
resetStyleEditor(),
hideSettings()
];
};

export const gnViewerRequestNewResourceConfig = (action$, store) =>
action$.ofType(REQUEST_NEW_RESOURCE_CONFIG)
Expand Down Expand Up @@ -502,7 +517,7 @@ export const gnViewerRequestResourceConfig = (action$, store) =>
const isSamePreviousResource = !resourceData?.['@ms-detail'] && resourceData?.pk === action.pk;
return Observable.concat(
Observable.of(
...getResetActions(isSamePreviousResource),
...getResetActions(state, isSamePreviousResource),
loadingResourceConfig(true),
setResourceType(action.resourceType),
setResourcePathParameters(action?.options?.params)
Expand Down
48 changes: 15 additions & 33 deletions geonode_mapstore_client/client/js/plugins/save/withPrompt.jsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,23 @@
import React, { useRef, useEffect } from 'react';
import React from 'react';
import PropTypes from 'prop-types';
import { getMessageById } from '@mapstore/framework/utils/LocaleUtils';
import { Prompt } from 'react-router-dom';

import PendingStatePrompt from '@mapstore/framework/plugins/ResourcesCatalog/containers/PendingStatePrompt';

export default (Component) => {
const PromptComponent = (props, {messages}) => {
const dirtyState = useRef();
dirtyState.current = props.dirtyState;
useEffect(() => {
function onBeforeUnload(event) {
if (dirtyState.current) {
(event || window.event).returnValue = null;
}
}
window.addEventListener('beforeunload', onBeforeUnload);
return () => {
window.removeEventListener('beforeunload', onBeforeUnload);
};
}, []);

const PromptComponent = (props) => {
return props.enabled
? <><Component {...props}/>
<Prompt
when={!!props.dirtyState}
message={(/* nextLocation, action */) => {
const confirmed = window.confirm(getMessageById(messages, 'gnviewer.prompPendingChanges')); // eslint-disable-line no-alert
// if confirm the path should be the next one
if (confirmed) {
return true;
}
window.history.back(); // to return back to previous path
// currently it's not possible to replace the pathname
// without side effect
// such as reloading of the page
return false;
}}
? <>
<Component {...props}/>
<PendingStatePrompt
show={props.show}
onCancel={props.onCancel}
onConfirm={props.onConfirm}
pendingState={!!props.dirtyState}
titleId="resourcesCatalog.detailsPendingChangesTitle"
descriptionId="resourcesCatalog.detailsPendingChangesDescription"
cancelId="resourcesCatalog.detailsPendingChangesCancel"
confirmId="resourcesCatalog.detailsPendingChangesConfirm"
variant="danger"
/>
</>
: null
Expand Down