mirror of
https://github.com/kerberos-io/agent.git
synced 2026-08-23 15:08:32 +00:00
Refactor routing components to use Redirect instead of Navigate; update react-router-dom version and implement history for navigation
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
"@testing-library/user-event": "^14.5.2",
|
||||
"axios": "^1.7.7",
|
||||
"classnames": "^2.5.1",
|
||||
"history": "^4.10.1",
|
||||
"eslint-config-prettier": "8.5.*",
|
||||
"eslint-plugin-prettier": "4.2.*",
|
||||
"eslint-watch": "^7.0.0",
|
||||
@@ -26,7 +27,7 @@
|
||||
"react-dom": "^19.0.0",
|
||||
"react-i18next": "^15.1.1",
|
||||
"react-redux": "^9.1.2",
|
||||
"react-router-dom": "^6.27.0",
|
||||
"react-router-dom": "^5.3.4",
|
||||
"react-scripts": "5.0.1",
|
||||
"react-tooltip": "^5.28.0",
|
||||
"redux": "^5.0.1",
|
||||
@@ -71,6 +72,8 @@
|
||||
},
|
||||
"resolutions": {
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
"react-dom": "^19.0.0",
|
||||
"react-router-dom": "^5.3.4",
|
||||
"react-router": "^5.3.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import { Outlet } from 'react-router-dom';
|
||||
import {
|
||||
connect as connectWS,
|
||||
disconnect as disconnectWS,
|
||||
@@ -94,7 +93,7 @@ class App extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { t, connected } = this.props;
|
||||
const { t, connected, children } = this.props;
|
||||
const { username, dashboard, dispatchLogout } = this.props;
|
||||
const cloudOnline = this.getCurrentTimestamp() - dashboard.cloudOnline < 30;
|
||||
return (
|
||||
@@ -211,7 +210,7 @@ class App extends React.Component {
|
||||
)}
|
||||
|
||||
<MainBody>
|
||||
<Outlet />
|
||||
{children}
|
||||
</MainBody>
|
||||
</Main>
|
||||
</div>
|
||||
@@ -247,6 +246,11 @@ App.propTypes = {
|
||||
connected: PropTypes.bool.isRequired,
|
||||
dashboard: PropTypes.object.isRequired,
|
||||
dispatchGetDashboardInformation: PropTypes.func.isRequired,
|
||||
children: PropTypes.node,
|
||||
};
|
||||
|
||||
App.defaultProps = {
|
||||
children: null,
|
||||
};
|
||||
|
||||
export default withTranslation()(
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { Navigate } from 'react-router-dom';
|
||||
import { Redirect } from 'react-router-dom';
|
||||
|
||||
export default function RequireAuth({ children }) {
|
||||
const isAuthenticated = useSelector((s) => s.authentication.loggedIn);
|
||||
if (!isAuthenticated) {
|
||||
return <Navigate to="/login" replace />;
|
||||
return <Redirect to="/login" />;
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { Navigate } from 'react-router-dom';
|
||||
import { Redirect } from 'react-router-dom';
|
||||
|
||||
export default function RequireGuest({ children }) {
|
||||
const isAuthenticated = useSelector((s) => s.authentication.loggedIn);
|
||||
const isInstalled = useSelector((s) => s.authentication.installed);
|
||||
if (!isInstalled) {
|
||||
return <Navigate to="/install" replace />;
|
||||
return <Redirect to="/install" />;
|
||||
}
|
||||
if (isAuthenticated) {
|
||||
return <Navigate to="/" replace />;
|
||||
return <Redirect to="/" />;
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { Navigate } from 'react-router-dom';
|
||||
import { Redirect } from 'react-router-dom';
|
||||
|
||||
export default function RequireInstall({ children }) {
|
||||
const isAuthenticated = useSelector((s) => s.authentication.loggedIn);
|
||||
const isInstalled = useSelector((s) => s.authentication.installed);
|
||||
if (isInstalled) {
|
||||
return <Navigate to={isAuthenticated ? '/' : '/login'} replace />;
|
||||
return <Redirect to={isAuthenticated ? '/' : '/login'} />;
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
4
ui/src/history.js
Normal file
4
ui/src/history.js
Normal file
@@ -0,0 +1,4 @@
|
||||
import { createBrowserHistory } from 'history';
|
||||
|
||||
const history = createBrowserHistory();
|
||||
export default history;
|
||||
@@ -1,12 +1,6 @@
|
||||
import React, { Suspense, useEffect } from 'react';
|
||||
import React, { Suspense } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import {
|
||||
BrowserRouter,
|
||||
Routes,
|
||||
Route,
|
||||
Navigate,
|
||||
useNavigate,
|
||||
} from 'react-router-dom';
|
||||
import { Router, Switch, Route, Redirect } from 'react-router-dom';
|
||||
import { createStore, applyMiddleware, compose } from 'redux';
|
||||
import { Provider } from 'react-redux';
|
||||
import reduxWebsocket from '@giantmachines/redux-websocket';
|
||||
@@ -20,7 +14,7 @@ import Media from './pages/Media/Media';
|
||||
import Settings from './pages/Settings/Settings';
|
||||
import RequireAuth from './containers/RequireAuth';
|
||||
import RequireGuest from './containers/RequireGuest';
|
||||
import { setNavigator } from './navigation';
|
||||
import history from './history';
|
||||
import './i18n';
|
||||
|
||||
// We get the token from the store to initialise the store.
|
||||
@@ -66,65 +60,45 @@ const store = createStore(
|
||||
|
||||
const Loader = () => <div>loading...</div>;
|
||||
|
||||
// Bridges React Router's navigate function into a module-scoped singleton
|
||||
// so Redux thunks (e.g. login/logout) can navigate without a hook.
|
||||
function NavigationSetup() {
|
||||
const nav = useNavigate();
|
||||
useEffect(() => {
|
||||
setNavigator(nav);
|
||||
}, [nav]);
|
||||
return null;
|
||||
}
|
||||
|
||||
const container = document.getElementById('root');
|
||||
const root = createRoot(container);
|
||||
|
||||
root.render(
|
||||
<Provider store={store}>
|
||||
<BrowserRouter>
|
||||
<NavigationSetup />
|
||||
<Router history={history}>
|
||||
<Suspense fallback={<Loader />}>
|
||||
<Routes>
|
||||
<Route
|
||||
path="/login"
|
||||
element={
|
||||
<RequireGuest>
|
||||
<Login />
|
||||
</RequireGuest>
|
||||
}
|
||||
/>
|
||||
<Route element={<App />}>
|
||||
<Route
|
||||
path="/"
|
||||
element={<Navigate to="/dashboard" replace />}
|
||||
/>
|
||||
<Route
|
||||
path="/dashboard"
|
||||
element={
|
||||
<RequireAuth>
|
||||
<Dashboard />
|
||||
</RequireAuth>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/media"
|
||||
element={
|
||||
<RequireAuth>
|
||||
<Media />
|
||||
</RequireAuth>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/settings"
|
||||
element={
|
||||
<RequireAuth>
|
||||
<Settings />
|
||||
</RequireAuth>
|
||||
}
|
||||
/>
|
||||
<Switch>
|
||||
<Route path="/login">
|
||||
<RequireGuest>
|
||||
<Login />
|
||||
</RequireGuest>
|
||||
</Route>
|
||||
</Routes>
|
||||
<Route>
|
||||
<App>
|
||||
<Switch>
|
||||
<Route exact path="/">
|
||||
<Redirect to="/dashboard" />
|
||||
</Route>
|
||||
<Route exact path="/dashboard">
|
||||
<RequireAuth>
|
||||
<Dashboard />
|
||||
</RequireAuth>
|
||||
</Route>
|
||||
<Route exact path="/media">
|
||||
<RequireAuth>
|
||||
<Media />
|
||||
</RequireAuth>
|
||||
</Route>
|
||||
<Route exact path="/settings">
|
||||
<RequireAuth>
|
||||
<Settings />
|
||||
</RequireAuth>
|
||||
</Route>
|
||||
</Switch>
|
||||
</App>
|
||||
</Route>
|
||||
</Switch>
|
||||
</Suspense>
|
||||
</BrowserRouter>
|
||||
</Router>
|
||||
</Provider>
|
||||
);
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
// Lightweight navigation singleton so non-React code (Redux thunks) can
|
||||
// trigger client-side navigation. The value is set from a component that
|
||||
// has access to React Router's `useNavigate` hook (see NavigationSetup in
|
||||
// index.jsx).
|
||||
// trigger client-side navigation. Backed by the shared `history` instance
|
||||
// passed to react-router's <Router>.
|
||||
import history from './history';
|
||||
|
||||
let navigatorFn = null;
|
||||
|
||||
export const setNavigator = (fn) => {
|
||||
navigatorFn = fn;
|
||||
export const setNavigator = () => {
|
||||
// Kept for API compatibility; no-op since history is module-scoped.
|
||||
};
|
||||
|
||||
export const navigate = (path, options) => {
|
||||
if (navigatorFn) {
|
||||
navigatorFn(path, options);
|
||||
}
|
||||
export const navigate = (path) => {
|
||||
history.push(path);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user