Skip to content

Commit

Permalink
FIX Reinstate unsaved changes dialog
Browse files Browse the repository at this point in the history
This broke when upgrading to react-router 6.4 - they've added a new API
for it in 6.7
  • Loading branch information
GuySartorelli committed Feb 23, 2023
1 parent 94e64c5 commit d5014f1
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 55 deletions.
2 changes: 1 addition & 1 deletion client/dist/js/bundle.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion client/dist/js/vendor.js

Large diffs are not rendered by default.

63 changes: 29 additions & 34 deletions client/src/boot/BootRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import $ from 'jquery';
import React from 'react';
import { Provider as ReduxProvider } from 'react-redux';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import { createBrowserRouter, createRoutesFromElements, RouterProvider } from 'react-router-dom';
import Config from 'lib/Config';
import pageRouter from 'lib/Router';
import reactRouteRegister from 'lib/ReactRouteRegister';
Expand All @@ -15,8 +15,9 @@ import { ApolloProvider } from '@apollo/client';
import i18n from 'i18n';
import { isDirty } from 'redux-form';
import getFormState from 'lib/getFormState';
import { Routes, Route } from 'react-router';
import { Route } from 'react-router';
import { joinUrlPaths } from 'lib/urls';
import NavigationBlocker from '../components/NavigationBlocker/NavigationBlocker';

/**
* Bootstraps routes
Expand All @@ -35,8 +36,7 @@ class BootRoutes {
const base = Config.get('absoluteBaseUrl');
pageRouter.setAbsoluteBase(base);

this.handleBeforeRoute = this.handleBeforeRoute.bind(this);
this.handleBeforeUnload = this.handleBeforeUnload.bind(this);
this.shouldConfirmBeforeUnload = this.shouldConfirmBeforeUnload.bind(this);
}

setStore(store) {
Expand Down Expand Up @@ -109,18 +109,30 @@ class BootRoutes {
initReactRouter() {
reactRouteRegister.updateRootRoute({ component: App });
const rootRoute = reactRouteRegister.getRootRoute();
const routes = reactRouteRegister.getChildRoutes().map((route) => (
<Route key={route.path} path={route.path} element={<route.component />} />
));
const router = createBrowserRouter(
createRoutesFromElements(
<Route
path={rootRoute.path}
element={
<rootRoute.component>
<NavigationBlocker shouldBlockFn={this.shouldConfirmBeforeUnload} blockMessage={this.getUnsavedChangesMessage()} />
</rootRoute.component>
}
>
{reactRouteRegister.getChildRoutes().map(
(route) => (
<Route key={route.path} path={route.path} element={<route.component />} />
)
)}
</Route>
),
{ basename: joinUrlPaths(Config.get('baseUrl'), Config.get('adminUrl')) }
);

ReactDOM.createRoot(document.getElementsByClassName('cms-content')[0]).render(
<ApolloProvider client={this.client}>
<ReduxProvider store={this.store}>
<BrowserRouter basename={joinUrlPaths(Config.get('baseUrl'), Config.get('adminUrl'))}>
<Routes>
<Route path={rootRoute.path} element={<rootRoute.component />}>{routes}</Route>
</Routes>
</BrowserRouter>
<RouterProvider router={router} />
</ReduxProvider>
</ApolloProvider>
);
Expand All @@ -134,12 +146,7 @@ class BootRoutes {
const store = this.store;

pageRouter('*', (ctx, next) => {
const msg = i18n._t(
'Admin.CONFIRMUNSAVED',
`Are you sure you want to navigate away from this page?\n\n
WARNING: Your changes have not been saved.\n\n
Press OK to continue, or Cancel to stay on the current page.`
);
const msg = this.getUnsavedChangesMessage();
if (!this.shouldConfirmBeforeUnload() || window.confirm(msg)) {
// eslint-disable-next-line no-param-reassign
ctx.store = store;
Expand Down Expand Up @@ -218,22 +225,10 @@ class BootRoutes {
return changedForms.length > 0;
}

handleBeforeUnload(content, callback) {
if (this.shouldConfirmBeforeUnload()) {
return callback(confirm(i18n._t('Admin.CONFIRMUNSAVEDSHORT', 'WARNING: Your changes have not been saved.')));
}

return callback(true);
}

handleBeforeRoute(content, callback) {
if (this.shouldConfirmBeforeUnload()) {
return callback(confirm(i18n._t('Admin.CONFIRMUNSAVED', `Are you sure you want to navigate away
from this page?\n\nWARNING: Your changes have not been saved.\n\n
Press OK to continue, or Cancel to stay on the current page.`)));
}

return callback(true);
getUnsavedChangesMessage() {
return i18n._t('Admin.CONFIRMUNSAVED', `Are you sure you want to navigate away
from this page?\n\nWARNING: Your changes have not been saved.\n\n
Press OK to continue, or Cancel to stay on the current page.`);
}
}

Expand Down
28 changes: 28 additions & 0 deletions client/src/components/NavigationBlocker/NavigationBlocker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { useEffect } from 'react';
import PropTypes from 'prop-types';
import { unstable_useBlocker as useBlocker } from 'react-router-dom';

export default function NavigationBlocker({ shouldBlockFn, blockMessage }) {
const blocker = useBlocker(shouldBlockFn);
useEffect(() => {
if (blocker.state === 'blocked') {
// eslint-disable-next-line no-alert
const canUnload = confirm(blockMessage);
if (canUnload) {
blocker.proceed();
} else {
blocker.reset();
}
}
}, [blocker.state]);

// Don't actually render anything - this component exists purely to hold the blocker
// logic, which we put here to (hopefully) avoid rerendering the entire app when blocker
// state changes.
return null;
}

NavigationBlocker.propTypes = {
shouldBlockFn: PropTypes.func.isRequired,
blockMessage: PropTypes.string.isRequired,
};
4 changes: 2 additions & 2 deletions client/src/containers/App/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { Outlet } from 'react-router';
* Empty container for the moment, will eventually contain the CMS menu`
* and apply to document.body, rather than just one specific DOM element.
*/
const App = () => (
<div className="app"><Outlet /></div>
const App = ({ children }) => (
<div className="app">{children}<Outlet /></div>
);

export default provideInjector(App);
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@
"react-dom": "^18.2.0",
"react-load-script": "^0.0.6",
"react-redux": "^8.0.4",
"react-router": "^6.4.2",
"react-router-dom": "^6.4.2",
"react-router": "^6.7",
"react-router-dom": "^6.7",
"react-select": "^5.5.8",
"reactstrap": "^8.9.0",
"redux": "^4.2.0",
Expand Down
30 changes: 15 additions & 15 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1651,10 +1651,10 @@
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.6.tgz#cee20bd55e68a1720bdab363ecf0c821ded4cd45"
integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==

"@remix-run/router@1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.0.3.tgz#953b88c20ea00d0eddaffdc1b115c08474aa295d"
integrity sha512-ceuyTSs7PZ/tQqi19YZNBc5X7kj1f8p+4DIyrcIYFY9h+hd1OKm4RqtiWldR9eGEvIiJfsqwM4BsuCtRIuEw6Q==
"@remix-run/router@1.3.2":
version "1.3.2"
resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.3.2.tgz#58cd2bd25df2acc16c628e1b6f6150ea6c7455bc"
integrity sha512-t54ONhl/h75X94SWsHGQ4G/ZrCEguKSRQr7DrjTciJXW0YU1QhlwYeycvK5JgkzlxmvrK7wq1NB/PLtHxoiDcA==

"@sect/modernizr-loader@^1.0.3":
version "1.0.3"
Expand Down Expand Up @@ -7556,20 +7556,20 @@ react-redux@^8.0.4:
react-is "^18.0.0"
use-sync-external-store "^1.0.0"

react-router-dom@^6.4.2:
version "6.4.3"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.4.3.tgz#70093b5f65f85f1df9e5d4182eb7ff3a08299275"
integrity sha512-MiaYQU8CwVCaOfJdYvt84KQNjT78VF0TJrA17SIQgNHRvLnXDJO6qsFqq8F/zzB1BWZjCFIrQpu4QxcshitziQ==
react-router-dom@^6.7:
version "6.8.1"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.8.1.tgz#7e136b67d9866f55999e9a8482c7008e3c575ac9"
integrity sha512-67EXNfkQgf34P7+PSb6VlBuaacGhkKn3kpE51+P6zYSG2kiRoumXEL6e27zTa9+PGF2MNXbgIUHTVlleLbIcHQ==
dependencies:
"@remix-run/router" "1.0.3"
react-router "6.4.3"
"@remix-run/router" "1.3.2"
react-router "6.8.1"

react-router@6.4.3, react-router@^6.4.2:
version "6.4.3"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.4.3.tgz#9ed3ee4d6e95889e9b075a5d63e29acc7def0d49"
integrity sha512-BT6DoGn6aV1FVP5yfODMOiieakp3z46P1Fk0RNzJMACzE7C339sFuHebfvWtnB4pzBvXXkHP2vscJzWRuUjTtA==
react-router@6.8.1, react-router@^6.7:
version "6.8.1"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.8.1.tgz#e362caf93958a747c649be1b47cd505cf28ca63e"
integrity sha512-Jgi8BzAJQ8MkPt8ipXnR73rnD7EmZ0HFFb7jdQU24TynGW1Ooqin2KVDN9voSC+7xhqbbCd2cjGUepb6RObnyg==
dependencies:
"@remix-run/router" "1.0.3"
"@remix-run/router" "1.3.2"

react-select@^5.5.8:
version "5.7.0"
Expand Down

0 comments on commit d5014f1

Please sign in to comment.