Repository: provectus/kafka-ui
Issue: Add ui prefix to react router path
Labels: scope/frontend


Issue comments:

Pull request review comments:

Patch that resolved the issue:
diff --git a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/rest/config/CustomWebFilter.java b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/rest/config/CustomWebFilter.java
index 370e89847f8..e117a43b6c1 100644
--- a/kafka-ui-api/src/main/java/com/provectus/kafka/ui/rest/config/CustomWebFilter.java
+++ b/kafka-ui-api/src/main/java/com/provectus/kafka/ui/rest/config/CustomWebFilter.java
@@ -10,7 +10,7 @@
 public class CustomWebFilter implements WebFilter {
     @Override
     public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
-        if (exchange.getRequest().getURI().getPath().equals("/")) {
+        if (exchange.getRequest().getURI().getPath().equals("/") || exchange.getRequest().getURI().getPath().startsWith("/ui")) {
             return chain.filter(exchange.mutate().request(exchange.getRequest().mutate().path("/index.html").build()).build());
         }
 
diff --git a/kafka-ui-react-app/src/components/App.tsx b/kafka-ui-react-app/src/components/App.tsx
index 46a5ff84191..7c53592906b 100644
--- a/kafka-ui-react-app/src/components/App.tsx
+++ b/kafka-ui-react-app/src/components/App.tsx
@@ -1,9 +1,5 @@
 import React from 'react';
-import {
-  Switch,
-  Route,
-  Redirect,
-} from 'react-router-dom';
+import { Switch, Route, Redirect } from 'react-router-dom';
 import './App.scss';
 import BrokersContainer from './Brokers/BrokersContainer';
 import TopicsContainer from './Topics/TopicsContainer';
@@ -21,13 +17,19 @@ const App: React.FC<AppProps> = ({
   isClusterListFetched,
   fetchClustersList,
 }) => {
-  React.useEffect(() => { fetchClustersList() }, [fetchClustersList]);
+  React.useEffect(() => {
+    fetchClustersList();
+  }, [fetchClustersList]);
 
   return (
     <div className="Layout">
-      <nav className="navbar is-fixed-top is-white Layout__header" role="navigation" aria-label="main navigation">
+      <nav
+        className="navbar is-fixed-top is-white Layout__header"
+        role="navigation"
+        aria-label="main navigation"
+      >
         <div className="navbar-brand">
-          <a className="navbar-item title is-5 is-marginless" href="/">
+          <a className="navbar-item title is-5 is-marginless" href="/ui">
             Kafka UI
           </a>
         </div>
@@ -36,17 +38,31 @@ const App: React.FC<AppProps> = ({
         <NavConatiner className="Layout__navbar" />
         {isClusterListFetched ? (
           <Switch>
-            <Route exact path="/" component={Dashboard} />
-            <Route exact path="/clusters" component={Dashboard} />
-            <Route path="/clusters/:clusterName/topics" component={TopicsContainer} />
-            <Route path="/clusters/:clusterName/brokers" component={BrokersContainer} />
-            <Route path="/clusters/:clusterName/consumer-groups" component={ConsumersGroupsContainer} />
-            <Redirect from="/clusters/:clusterName" to="/clusters/:clusterName/brokers" />
+            <Route
+              exact
+              path={['/', '/ui', '/ui/clusters']}
+              component={Dashboard}
+            />
+            <Route
+              path="/ui/clusters/:clusterName/brokers"
+              component={BrokersContainer}
+            />
+            <Route
+              path="/ui/clusters/:clusterName/topics"
+              component={TopicsContainer}
+            />
+            <Route
+              path="/ui/clusters/:clusterName/consumer-groups"
+              component={ConsumersGroupsContainer}
+            />
+            <Redirect
+              from="/ui/clusters/:clusterName"
+              to="/ui/clusters/:clusterName/brokers"
+            />
           </Switch>
         ) : (
           <PageLoader />
         )}
-
       </main>
     </div>
   );
diff --git a/kafka-ui-react-app/src/components/ConsumerGroups/ConsumerGroups.tsx b/kafka-ui-react-app/src/components/ConsumerGroups/ConsumerGroups.tsx
index 6286345e018..747cf998f2e 100644
--- a/kafka-ui-react-app/src/components/ConsumerGroups/ConsumerGroups.tsx
+++ b/kafka-ui-react-app/src/components/ConsumerGroups/ConsumerGroups.tsx
@@ -1,11 +1,8 @@
 import React from 'react';
 import { ClusterName } from 'redux/interfaces';
-import {
-  Switch,
-  Route,
-} from 'react-router-dom';
-import ListContainer from './List/ListContainer';
+import { Switch, Route } from 'react-router-dom';
 import PageLoader from 'components/common/PageLoader/PageLoader';
+import ListContainer from './List/ListContainer';
 
 interface Props {
   clusterName: ClusterName;
@@ -18,17 +15,23 @@ const ConsumerGroups: React.FC<Props> = ({
   isFetched,
   fetchConsumerGroupsList,
 }) => {
-  React.useEffect(() => { fetchConsumerGroupsList(clusterName); }, [fetchConsumerGroupsList, clusterName]);
+  React.useEffect(() => {
+    fetchConsumerGroupsList(clusterName);
+  }, [fetchConsumerGroupsList, clusterName]);
 
   if (isFetched) {
     return (
       <Switch>
-        <Route exact path="/clusters/:clusterName/consumer-groups" component={ListContainer} />
+        <Route
+          exact
+          path="/ui/clusters/:clusterName/consumer-groups"
+          component={ListContainer}
+        />
       </Switch>
     );
   }
 
-  return (<PageLoader />);
+  return <PageLoader />;
 };
 
 export default ConsumerGroups;
diff --git a/kafka-ui-react-app/src/components/Nav/Nav.tsx b/kafka-ui-react-app/src/components/Nav/Nav.tsx
index acd427bc6fa..a6c40087894 100644
--- a/kafka-ui-react-app/src/components/Nav/Nav.tsx
+++ b/kafka-ui-react-app/src/components/Nav/Nav.tsx
@@ -5,7 +5,7 @@ import cx from 'classnames';
 import ClusterMenu from './ClusterMenu';
 
 interface Props {
-  isClusterListFetched: boolean,
+  isClusterListFetched: boolean;
   clusters: Cluster[];
   className?: string;
 }
@@ -16,22 +16,21 @@ const Nav: React.FC<Props> = ({
   className,
 }) => (
   <aside className={cx('menu has-shadow has-background-white', className)}>
-    <p className="menu-label">
-      General
-    </p>
+    <p className="menu-label">General</p>
     <ul className="menu-list">
       <li>
-        <NavLink exact to="/" activeClassName="is-active" title="Dashboard">
+        <NavLink exact to="/ui" activeClassName="is-active" title="Dashboard">
           Dashboard
         </NavLink>
       </li>
     </ul>
-    <p className="menu-label">
-      Clusters
-    </p>
+    <p className="menu-label">Clusters</p>
     {!isClusterListFetched && <div className="loader" />}
 
-    {isClusterListFetched && clusters.map((cluster, index) => <ClusterMenu {...cluster} key={`cluster-list-item-key-${index}`}/>)}
+    {isClusterListFetched &&
+      clusters.map((cluster, index) => (
+        <ClusterMenu {...cluster} key={`cluster-list-item-key-${index}`} />
+      ))}
   </aside>
 );
 
diff --git a/kafka-ui-react-app/src/components/Topics/Topics.tsx b/kafka-ui-react-app/src/components/Topics/Topics.tsx
index ed1652c847c..b66a72d3d56 100644
--- a/kafka-ui-react-app/src/components/Topics/Topics.tsx
+++ b/kafka-ui-react-app/src/components/Topics/Topics.tsx
@@ -1,12 +1,9 @@
 import React from 'react';
 import { ClusterName } from 'redux/interfaces';
-import {
-  Switch,
-  Route,
-} from 'react-router-dom';
+import { Switch, Route } from 'react-router-dom';
+import PageLoader from 'components/common/PageLoader/PageLoader';
 import ListContainer from './List/ListContainer';
 import DetailsContainer from './Details/DetailsContainer';
-import PageLoader from 'components/common/PageLoader/PageLoader';
 import NewContainer from './New/NewContainer';
 
 interface Props {
@@ -21,19 +18,32 @@ const Topics: React.FC<Props> = ({
   isFetched,
   fetchTopicList,
 }) => {
-  React.useEffect(() => { fetchTopicList(clusterName); }, [fetchTopicList, clusterName]);
+  React.useEffect(() => {
+    fetchTopicList(clusterName);
+  }, [fetchTopicList, clusterName]);
 
   if (isFetched) {
     return (
       <Switch>
-        <Route exact path="/clusters/:clusterName/topics" component={ListContainer} />
-        <Route exact path="/clusters/:clusterName/topics/new" component={NewContainer} />
-        <Route path="/clusters/:clusterName/topics/:topicName" component={DetailsContainer} />
+        <Route
+          exact
+          path="/ui/clusters/:clusterName/topics"
+          component={ListContainer}
+        />
+        <Route
+          exact
+          path="/ui/clusters/:clusterName/topics/new"
+          component={NewContainer}
+        />
+        <Route
+          path="/ui/clusters/:clusterName/topics/:topicName"
+          component={DetailsContainer}
+        />
       </Switch>
     );
   }
 
-  return (<PageLoader />);
+  return <PageLoader />;
 };
 
 export default Topics;
diff --git a/kafka-ui-react-app/src/lib/paths.ts b/kafka-ui-react-app/src/lib/paths.ts
index c01592db0ed..78e5e0167c2 100644
--- a/kafka-ui-react-app/src/lib/paths.ts
+++ b/kafka-ui-react-app/src/lib/paths.ts
@@ -1,17 +1,25 @@
-import {
-  ClusterName,
-  TopicName,
-} from 'redux/interfaces';
+import { ClusterName, TopicName } from 'redux/interfaces';
 
-const clusterPath = (clusterName: ClusterName) => `/clusters/${clusterName}`;
+const clusterPath = (clusterName: ClusterName) => `/ui/clusters/${clusterName}`;
 
-export const clusterBrokersPath = (clusterName: ClusterName) => `${clusterPath(clusterName)}/brokers`;
+export const clusterBrokersPath = (clusterName: ClusterName) =>
+  `${clusterPath(clusterName)}/brokers`;
+export const clusterTopicsPath = (clusterName: ClusterName) =>
+  `${clusterPath(clusterName)}/topics`;
+export const clusterTopicNewPath = (clusterName: ClusterName) =>
+  `${clusterPath(clusterName)}/topics/new`;
+export const clusterConsumerGroupsPath = (clusterName: ClusterName) =>
+  `${clusterPath(clusterName)}/consumer-groups`;
 
-export const clusterTopicsPath = (clusterName: ClusterName) => `${clusterPath(clusterName)}/topics`;
-export const clusterTopicNewPath = (clusterName: ClusterName) => `${clusterPath(clusterName)}/topics/new`;
-
-export const clusterTopicPath = (clusterName: ClusterName, topicName: TopicName) => `${clusterTopicsPath(clusterName)}/${topicName}`;
-export const clusterTopicSettingsPath = (clusterName: ClusterName, topicName: TopicName) => `${clusterTopicsPath(clusterName)}/${topicName}/settings`;
-export const clusterTopicMessagesPath = (clusterName: ClusterName, topicName: TopicName) => `${clusterTopicsPath(clusterName)}/${topicName}/messages`;
-
-export const clusterConsumerGroupsPath = (clusterName: ClusterName) => `${clusterPath(clusterName)}/consumer-groups`;
\ No newline at end of file
+export const clusterTopicPath = (
+  clusterName: ClusterName,
+  topicName: TopicName
+) => `${clusterTopicsPath(clusterName)}/${topicName}`;
+export const clusterTopicSettingsPath = (
+  clusterName: ClusterName,
+  topicName: TopicName
+) => `${clusterTopicsPath(clusterName)}/${topicName}/settings`;
+export const clusterTopicMessagesPath = (
+  clusterName: ClusterName,
+  topicName: TopicName
+) => `${clusterTopicsPath(clusterName)}/${topicName}/messages`;


Test patch: