issue-31/add-ui-prefix-for-react-routes (#34)

* issue-31/add-ui-prefix-for-react-routes

* added route for /ui path (#40)

Co-authored-by: Roman Nedzvetskiy <roman@Romans-MacBook-Pro.local>

Co-authored-by: Roman Nedzvetskiy <gmcodemail@gmail.com>
Co-authored-by: Roman Nedzvetskiy <roman@Romans-MacBook-Pro.local>
This commit is contained in:
Azat Gataullin 2020-04-28 14:17:52 +03:00 committed by GitHub
parent b2465775e5
commit 5d0b783abb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 93 additions and 57 deletions

View file

@ -10,7 +10,7 @@ import reactor.core.publisher.Mono;
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());
}

View file

@ -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>
);

View file

@ -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;

View file

@ -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>
);

View file

@ -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;

View file

@ -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`;
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`;