This is an automated email from the ASF dual-hosted git repository.

adoroszlai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new f9552d0bb58 HDDS-15148. Prevent 404 when toggling between Old/New UI 
on UI-exclusive routes (#10168)
f9552d0bb58 is described below

commit f9552d0bb5818f3a15b90ee58b06a45c3631ae11
Author: Chi-Hsuan Huang <[email protected]>
AuthorDate: Fri Jun 19 15:48:32 2026 +0800

    HDDS-15148. Prevent 404 when toggling between Old/New UI on UI-exclusive 
routes (#10168)
---
 .../webapps/recon/ozone-recon-web/src/app.tsx      | 65 ++++++++++++++++++----
 .../src/v2/constants/breadcrumbs.constants.tsx     |  1 +
 2 files changed, 54 insertions(+), 12 deletions(-)

diff --git 
a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/app.tsx
 
b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/app.tsx
index b3c8f764a62..7dd64c1ae8a 100644
--- 
a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/app.tsx
+++ 
b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/app.tsx
@@ -18,7 +18,7 @@
 
 import React, { Suspense } from 'react';
 
-import { Switch as AntDSwitch, Layout } from 'antd';
+import { Switch as AntDSwitch, Layout, message } from 'antd';
 import NavBar from './components/navBar/navBar';
 import NavBarV2 from '@/v2/components/navBar/navBar';
 import Breadcrumbs from './components/breadcrumbs/breadcrumbs';
@@ -26,6 +26,8 @@ import BreadcrumbsV2 from 
'@/v2/components/breadcrumbs/breadcrumbs';
 import { HashRouter as Router, Switch, Route, Redirect, useLocation } from 
'react-router-dom';
 import { routes } from '@/routes';
 import { routesV2 } from '@/v2/routes-v2';
+import { breadcrumbNameMap as breadcrumbNameMapV1 } from 
'@/constants/breadcrumbs.constants';
+import { breadcrumbNameMap as breadcrumbNameMapV2 } from 
'@/v2/constants/breadcrumbs.constants';
 import { MakeRouteWithSubRoutes } from '@/makeRouteWithSubRoutes';
 import classNames from 'classnames';
 
@@ -38,6 +40,18 @@ const {
   Header, Content, Footer
 } = Layout;
 
+const FALLBACK_PATH = '/Overview';
+const TOAST_DURATION_SECONDS = 4;
+type BreadcrumbNameMap = typeof breadcrumbNameMapV1;
+
+// Strict membership check that ignores parameterized/catch-all entries
+// (the v1 routes table ends with `/:NotFound`, which would otherwise match 
anything).
+const pathExistsIn = (path: string, table: ReadonlyArray<{ path: string }>): 
boolean =>
+  table.some((r) => !r.path.includes(':') && r.path === path);
+
+const getViewName = (path: string, preferredMap: BreadcrumbNameMap): string =>
+  preferredMap[path] ?? path;
+
 interface IAppState {
   collapsed: boolean;
   enableOldUI: boolean;
@@ -109,26 +123,53 @@ class App extends React.Component<Record<string, object>, 
IAppState> {
     this.setState({ collapsed });
   };
 
+  handleUIToggle = (enableOldUI: boolean) => {
+    const currentPath = window.location.hash.slice(1).split('?')[0] || 
FALLBACK_PATH;
+    const targetTable = enableOldUI ? routes : routesV2;
+    const sourceTable = enableOldUI ? routesV2 : routes;
+    const shouldRedirect = !pathExistsIn(currentPath, targetTable);
+    let redirectMessage: string | undefined;
+
+    if (shouldRedirect) {
+      window.location.hash = FALLBACK_PATH;
+      // Only explain the redirect when the user came from a real page in the 
source UI;
+      // a typo'd path otherwise produces a misleading "only available in..." 
message.
+      if (pathExistsIn(currentPath, sourceTable)) {
+        const sourceMap = enableOldUI ? breadcrumbNameMapV2 : 
breadcrumbNameMapV1;
+        const targetMap = enableOldUI ? breadcrumbNameMapV1 : 
breadcrumbNameMapV2;
+        const friendly = getViewName(currentPath, sourceMap);
+        const fallbackViewName = getViewName(FALLBACK_PATH, targetMap);
+        const sourceUiName = enableOldUI ? 'New UI' : 'Old UI';
+        redirectMessage =
+          `The '${friendly}' view is only available in the ${sourceUiName}. 
We've returned you to the ${fallbackViewName} dashboard.`;
+      }
+    }
+
+    this.setState({ enableOldUI }, () => {
+      // This is to persist the state of the UI between refreshes.
+      // While using session storage to store state is an anti-pattern, 
provided the size of the data stored in this case
+      // and the plan to deprecate UI v1 (old UI) in the future - this is the 
simplest approach/fix for persisting state.
+      sessionStorage.setItem('enableOldUI', JSON.stringify(enableOldUI));
+      if (redirectMessage) {
+        message.info(redirectMessage, TOAST_DURATION_SECONDS);
+      }
+    });
+  };
+
   render() {
     const { collapsed, enableOldUI } = this.state;
 
     return (
       <Router>
-        <AppLayout 
-          enableOldUI={enableOldUI} 
-          collapsed={collapsed} 
+        <AppLayout
+          enableOldUI={enableOldUI}
+          collapsed={collapsed}
           onCollapse={this.onCollapse}
-          onToggleUI={(checked: boolean) => {
-            this.setState({
-              enableOldUI: checked
-            }, () => {
-              sessionStorage.setItem('enableOldUI', JSON.stringify(checked));
-            });
-          }}
+          onToggleUI={this.handleUIToggle}
         />
       </Router>
     );
   }
 }
 
-export default App;
\ No newline at end of file
+export default App;
diff --git 
a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/constants/breadcrumbs.constants.tsx
 
b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/constants/breadcrumbs.constants.tsx
index 6f4f04d439a..7d867b482fc 100644
--- 
a/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/constants/breadcrumbs.constants.tsx
+++ 
b/hadoop-ozone/recon/src/main/resources/webapps/recon/ozone-recon-web/src/v2/constants/breadcrumbs.constants.tsx
@@ -31,5 +31,6 @@ export const breadcrumbNameMap: BreadcrumbNameMap = {
   '/NamespaceUsage': 'Namespace Usage',
   '/Heatmap': 'Heatmap',
   '/Om': 'OM DB Insights',
+  '/Capacity': 'Cluster Capacity',
   '/Assistant': 'Recon AI'
 };


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to