[FIX] website: fix back/forth navigation from iframe to other routes
Before this commit, following this flow on enterprise: - Go to the webclient, on the homepage: '/web' - Click on the website - Click on the "contact us" menu - Click on the browser's back button => The back navigation happens in the iframe, it's normal - Click on the back button again => The url has changed for the webclient "homepage" one but the WebsitePreview is still displayed. This happens because the router service listens to the hashchange events to communicate the webclient which component to display. But with [1] it was decided to replace the regular webclient's router url from the WebsitePreview client action with the frontend's url. As a result, the 'hashchange' is never fired when navigating back from the client action to another webclient route. To fix that, the 'popstate' event is listened at the client action level. If the new url is a regular webclient's router one, an 'hashchange' event is triggered to continue the flow as if the browser's url was never changed. The same hook is used to revert back the original webclient route /web#action=website.website_preview... when leaving it, so that the router can replay it correctly when navigating back from another route. [1]: https://github.com/odoo/odoo/commit/31cc10b91dc7762e23b4bde9b945be0c4ce3fe3b task-2687506 Part-of: odoo/odoo#97408
This commit is contained in:
@@ -7,6 +7,7 @@ import { AceEditorAdapterComponent } from '../../components/ace_editor/ace_edito
|
||||
import { WebsiteEditorComponent } from '../../components/editor/editor';
|
||||
import { WebsiteTranslator } from '../../components/translator/translator';
|
||||
import {OptimizeSEODialog} from '@website/components/dialog/seo';
|
||||
import { routeToUrl } from "@web/core/browser/router_service";
|
||||
|
||||
const { Component, onWillStart, onMounted, onWillUnmount, useRef, useEffect, useState } = owl;
|
||||
|
||||
@@ -84,6 +85,25 @@ export class WebsitePreview extends Component {
|
||||
this.websiteService.websiteRootInstance = undefined;
|
||||
this.websiteService.pageDocument = null;
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// When reaching a "regular" url of the webclient's router, an
|
||||
// hashchange event should be dispatched to properly display the
|
||||
// content of the previous URL before reaching the client action,
|
||||
// which was lost after being replaced for the frontend's URL.
|
||||
const handleBackNavigation = () => {
|
||||
if (!window.location.pathname.startsWith('/@')) {
|
||||
window.dispatchEvent(new HashChangeEvent('hashchange', {
|
||||
newURL: window.location.href.toString()
|
||||
}));
|
||||
}
|
||||
};
|
||||
window.addEventListener('popstate', handleBackNavigation);
|
||||
return () => {
|
||||
history.pushState({}, null, this.backendUrl);
|
||||
window.removeEventListener('popstate', handleBackNavigation);
|
||||
};
|
||||
}, () => []);
|
||||
}
|
||||
|
||||
get websiteId() {
|
||||
@@ -192,6 +212,12 @@ export class WebsitePreview extends Component {
|
||||
* the iframe's url (it is clearer for the user).
|
||||
*/
|
||||
_replaceBrowserUrl() {
|
||||
// The original /web#action=... url is saved to be pushed on top of the
|
||||
// history when leaving the component, so that the webclient can
|
||||
// correctly find back and replay the client action.
|
||||
if (!this.backendUrl) {
|
||||
this.backendUrl = routeToUrl(this.router.current);
|
||||
}
|
||||
const currentUrl = new URL(this.iframe.el.contentDocument.location.href);
|
||||
currentUrl.pathname = `/@${currentUrl.pathname}`;
|
||||
this.currentTitle = this.iframe.el.contentDocument.title;
|
||||
|
||||
Reference in New Issue
Block a user