mirror of
https://github.com/kerberos-io/agent.git
synced 2026-08-23 15:08:32 +00:00
Refactor and update dependencies for improved performance and maintainability; enhance routing and authentication components
This commit is contained in:
@@ -2,44 +2,39 @@
|
||||
"name": "agent-ui",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.13.3",
|
||||
"@emotion/styled": "^11.13.0",
|
||||
"@giantmachines/redux-websocket": "^1.5.1",
|
||||
"@kerberos-io/ui": "^1.76.0",
|
||||
"@material-ui/core": "^4.12.4",
|
||||
"@material-ui/icons": "^4.11.3",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^11.2.7",
|
||||
"@testing-library/user-event": "^12.8.3",
|
||||
"axios": "^0.21.4",
|
||||
"classnames": "^2.3.1",
|
||||
"connected-react-router": "^6.9.3",
|
||||
"@mui/icons-material": "^6.1.6",
|
||||
"@mui/material": "^6.1.6",
|
||||
"@testing-library/jest-dom": "^6.6.3",
|
||||
"@testing-library/react": "^16.0.1",
|
||||
"@testing-library/user-event": "^14.5.2",
|
||||
"axios": "^1.7.7",
|
||||
"classnames": "^2.5.1",
|
||||
"eslint-config-prettier": "8.5.*",
|
||||
"eslint-plugin-prettier": "4.2.*",
|
||||
"eslint-watch": "^7.0.0",
|
||||
"history": "4.10.1",
|
||||
"i18next": "^21.9.1",
|
||||
"i18next-browser-languagedetector": "^6.1.5",
|
||||
"i18next-http-backend": "^1.4.1",
|
||||
"i18next-xhr-backend": "^3.2.2",
|
||||
"i18next": "^23.16.4",
|
||||
"i18next-browser-languagedetector": "^8.0.0",
|
||||
"i18next-http-backend": "^2.6.2",
|
||||
"md5": "^2.3.0",
|
||||
"prettier": "^2.7.1",
|
||||
"prettier": "^3.3.3",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^17.0.1",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-i18next": "^11.18.5",
|
||||
"react-redux": "^7.2.8",
|
||||
"react-router": "^5.2.0",
|
||||
"react-router-dom": "^5.3.3",
|
||||
"react-router-redux": "^4.0.8",
|
||||
"react-scripts": "5.*",
|
||||
"react-tooltip": "^4.2.21",
|
||||
"redux": "^4.2.0",
|
||||
"redux-devtools-extension": "^2.13.9",
|
||||
"redux-thunk": "^2.4.1",
|
||||
"rxjs": "^7.5.6",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-i18next": "^15.1.1",
|
||||
"react-redux": "^9.1.2",
|
||||
"react-router-dom": "^6.27.0",
|
||||
"react-scripts": "5.0.1",
|
||||
"react-tooltip": "^5.28.0",
|
||||
"redux": "^5.0.1",
|
||||
"redux-thunk": "^3.1.0",
|
||||
"rxjs": "^7.8.1",
|
||||
"typeface-roboto": "^1.1.13",
|
||||
"uuidv4": "2.0.0",
|
||||
"vott-ct": "^2.3.3",
|
||||
"web-vitals": "^0.2.4"
|
||||
"web-vitals": "^4.2.4"
|
||||
},
|
||||
"browser": {
|
||||
"crypto": false
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import uuid from 'uuidv4';
|
||||
import { Outlet } from 'react-router-dom';
|
||||
import {
|
||||
connect as connectWS,
|
||||
disconnect as disconnectWS,
|
||||
send,
|
||||
} from '@giantmachines/redux-websocket';
|
||||
|
||||
const genClientId = () =>
|
||||
typeof crypto !== 'undefined' && crypto.randomUUID
|
||||
? crypto.randomUUID()
|
||||
: `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
||||
import {
|
||||
Badge,
|
||||
Main,
|
||||
@@ -60,7 +65,7 @@ class App extends React.Component {
|
||||
const { connected: connectedPrev } = prevProps;
|
||||
if (connectedPrev === false && connected === true) {
|
||||
const message = {
|
||||
client_id: uuid(),
|
||||
client_id: genClientId(),
|
||||
message_type: 'hello',
|
||||
};
|
||||
dispatchSend(message);
|
||||
@@ -76,7 +81,7 @@ class App extends React.Component {
|
||||
this.subscription.unsubscribe();
|
||||
this.connectionSubscription.unsubscribe();
|
||||
const message = {
|
||||
client_id: uuid(),
|
||||
client_id: genClientId(),
|
||||
message_type: 'goodbye',
|
||||
};
|
||||
const { dispatchSend, dispatchDisconnect } = this.props;
|
||||
@@ -90,7 +95,7 @@ class App extends React.Component {
|
||||
|
||||
render() {
|
||||
const { t, connected } = this.props;
|
||||
const { children, username, dashboard, dispatchLogout } = this.props;
|
||||
const { username, dashboard, dispatchLogout } = this.props;
|
||||
const cloudOnline = this.getCurrentTimestamp() - dashboard.cloudOnline < 30;
|
||||
return (
|
||||
<>
|
||||
@@ -205,7 +210,9 @@ class App extends React.Component {
|
||||
</Link>
|
||||
)}
|
||||
|
||||
<MainBody>{children}</MainBody>
|
||||
<MainBody>
|
||||
<Outlet />
|
||||
</MainBody>
|
||||
</Main>
|
||||
</div>
|
||||
</>
|
||||
@@ -236,8 +243,6 @@ App.propTypes = {
|
||||
dispatchConnect: PropTypes.func.isRequired,
|
||||
dispatchDisconnect: PropTypes.func.isRequired,
|
||||
dispatchSend: PropTypes.func.isRequired,
|
||||
// eslint-disable-next-line react/forbid-prop-types
|
||||
children: PropTypes.array.isRequired,
|
||||
username: PropTypes.string.isRequired,
|
||||
connected: PropTypes.bool.isRequired,
|
||||
dashboard: PropTypes.object.isRequired,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { push } from 'react-router-redux';
|
||||
import { navigate } from '../navigation';
|
||||
import { doLogin, doCheckIfInstalled } from '../api/authentication';
|
||||
|
||||
export const login = (username, password) =>
|
||||
@@ -15,7 +15,7 @@ export const login = (username, password) =>
|
||||
token: data.token,
|
||||
expire: data.expire,
|
||||
});
|
||||
dispatch(push('/'));
|
||||
navigate('/');
|
||||
},
|
||||
(error) => {
|
||||
dispatch({
|
||||
@@ -60,6 +60,6 @@ export const logout = () => {
|
||||
dispatch({
|
||||
type: 'LOGOUT',
|
||||
});
|
||||
dispatch(push('/login'));
|
||||
navigate('/login');
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import React from 'react';
|
||||
import i18next from 'i18next';
|
||||
import Popover from '@material-ui/core/Popover';
|
||||
import List from '@material-ui/core/List';
|
||||
import ListItem from '@material-ui/core/ListItem';
|
||||
import ListSubheader from '@material-ui/core/ListSubheader';
|
||||
import Popover from '@mui/material/Popover';
|
||||
import List from '@mui/material/List';
|
||||
import ListItemButton from '@mui/material/ListItemButton';
|
||||
import ListSubheader from '@mui/material/ListSubheader';
|
||||
import { Icon } from '@kerberos-io/ui';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import './LanguageSelect.scss';
|
||||
@@ -69,8 +69,7 @@ const LanguageSelect = () => {
|
||||
<List>
|
||||
<ListSubheader>{t('navigation.choose_language')}</ListSubheader>
|
||||
{Object.keys(languageMap)?.map((item) => (
|
||||
<ListItem
|
||||
button
|
||||
<ListItemButton
|
||||
key={item}
|
||||
onClick={() => {
|
||||
i18next.changeLanguage(item);
|
||||
@@ -79,7 +78,7 @@ const LanguageSelect = () => {
|
||||
}}
|
||||
>
|
||||
{languageMap[item] ? languageMap[item].label : ''}
|
||||
</ListItem>
|
||||
</ListItemButton>
|
||||
))}
|
||||
<hr />
|
||||
<a
|
||||
@@ -87,9 +86,9 @@ const LanguageSelect = () => {
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<ListItem button key="contribute-language">
|
||||
<ListItemButton key="contribute-language">
|
||||
Contribute language
|
||||
</ListItem>
|
||||
</ListItemButton>
|
||||
</a>
|
||||
</List>
|
||||
</div>
|
||||
|
||||
@@ -1,47 +1,16 @@
|
||||
import React from 'react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import { push } from 'react-router-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { Navigate } from 'react-router-dom';
|
||||
|
||||
export default function RequireAuth(ComposedComponent) {
|
||||
class Auth extends React.Component {
|
||||
componentDidMount() {
|
||||
const { isAuthenticated, redirect } = this.props;
|
||||
if (!isAuthenticated) {
|
||||
redirect();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { isAuthenticated } = this.props;
|
||||
return (
|
||||
<div>
|
||||
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
|
||||
{isAuthenticated ? <ComposedComponent {...this.props} /> : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default function RequireAuth({ children }) {
|
||||
const isAuthenticated = useSelector((s) => s.authentication.loggedIn);
|
||||
if (!isAuthenticated) {
|
||||
return <Navigate to="/login" replace />;
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
isAuthenticated: state.authentication.loggedIn,
|
||||
isInstalled: state.authentication.installed,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) =>
|
||||
bindActionCreators(
|
||||
{
|
||||
redirect: () => push('/login'),
|
||||
},
|
||||
dispatch
|
||||
);
|
||||
|
||||
Auth.propTypes = {
|
||||
isAuthenticated: PropTypes.bool.isRequired,
|
||||
isInstalled: PropTypes.bool.isRequired,
|
||||
redirect: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
return connect(mapStateToProps, mapDispatchToProps)(Auth);
|
||||
return children;
|
||||
}
|
||||
|
||||
RequireAuth.propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
};
|
||||
|
||||
@@ -1,51 +1,20 @@
|
||||
import React from 'react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import { push } from 'react-router-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { Navigate } from 'react-router-dom';
|
||||
|
||||
export default function RequireGuest(ComposedComponent) {
|
||||
class Guest extends React.Component {
|
||||
componentDidMount() {
|
||||
const {
|
||||
isAuthenticated,
|
||||
isInstalled,
|
||||
redirectInstallation,
|
||||
redirectDashboard,
|
||||
} = this.props;
|
||||
if (!isInstalled) {
|
||||
redirectInstallation();
|
||||
} else if (isAuthenticated) {
|
||||
redirectDashboard();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { isAuthenticated } = this.props;
|
||||
return <div>{!isAuthenticated ? <ComposedComponent /> : null}</div>;
|
||||
}
|
||||
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 />;
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
isAuthenticated: state.authentication.loggedIn,
|
||||
isInstalled: state.authentication.installed,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) =>
|
||||
bindActionCreators(
|
||||
{
|
||||
redirectDashboard: () => push('/'),
|
||||
redirectInstallation: () => push('/install'),
|
||||
},
|
||||
dispatch
|
||||
);
|
||||
|
||||
Guest.propTypes = {
|
||||
isAuthenticated: PropTypes.bool.isRequired,
|
||||
isInstalled: PropTypes.bool.isRequired,
|
||||
redirectInstallation: PropTypes.func.isRequired,
|
||||
redirectDashboard: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
return connect(mapStateToProps, mapDispatchToProps)(Guest);
|
||||
if (isAuthenticated) {
|
||||
return <Navigate to="/" replace />;
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
RequireGuest.propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
};
|
||||
|
||||
@@ -1,49 +1,17 @@
|
||||
import React from 'react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import { push } from 'react-router-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { Navigate } from 'react-router-dom';
|
||||
|
||||
export default function RequireInstall(ComposedComponent) {
|
||||
class Install extends React.Component {
|
||||
componentDidMount() {
|
||||
const { isAuthenticated, isInstalled, redirectDashboard, redirectLogin } =
|
||||
this.props;
|
||||
if (isInstalled) {
|
||||
if (isAuthenticated) {
|
||||
redirectDashboard();
|
||||
} else if (!isAuthenticated) {
|
||||
redirectLogin();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { isInstalled } = this.props;
|
||||
return <div>{!isInstalled ? <ComposedComponent /> : null}</div>;
|
||||
}
|
||||
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 />;
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
isAuthenticated: state.authentication.loggedIn,
|
||||
isInstalled: state.authentication.installed,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) =>
|
||||
bindActionCreators(
|
||||
{
|
||||
redirectDashboard: () => push('/'),
|
||||
redirectLogin: () => push('/login'),
|
||||
},
|
||||
dispatch
|
||||
);
|
||||
|
||||
Install.propTypes = {
|
||||
isAuthenticated: PropTypes.bool.isRequired,
|
||||
isInstalled: PropTypes.bool.isRequired,
|
||||
redirectDashboard: PropTypes.func.isRequired,
|
||||
redirectLogin: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
return connect(mapStateToProps, mapDispatchToProps)(Install);
|
||||
return children;
|
||||
}
|
||||
|
||||
RequireInstall.propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import i18n from 'i18next';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
import Backend from 'i18next-xhr-backend';
|
||||
import Backend from 'i18next-http-backend';
|
||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||
|
||||
i18n
|
||||
@@ -14,7 +14,7 @@ i18n
|
||||
escapeValue: false,
|
||||
},
|
||||
load: 'languageOnly',
|
||||
whitelist: ['de', 'en', 'nl', 'fr', 'pl', 'es', 'pt', 'ja', 'ru', 'ro'],
|
||||
supportedLngs: ['de', 'en', 'nl', 'fr', 'pl', 'es', 'pt', 'ja', 'ru', 'ro'],
|
||||
});
|
||||
|
||||
export default i18n;
|
||||
|
||||
109
ui/src/index.jsx
109
ui/src/index.jsx
@@ -1,14 +1,16 @@
|
||||
import React, { Suspense } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Route, Switch } from 'react-router-dom';
|
||||
import { createStore, applyMiddleware } from 'redux';
|
||||
import { createBrowserHistory } from 'history';
|
||||
import { routerMiddleware, ConnectedRouter } from 'connected-react-router';
|
||||
import React, { Suspense, useEffect } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import {
|
||||
BrowserRouter,
|
||||
Routes,
|
||||
Route,
|
||||
Navigate,
|
||||
useNavigate,
|
||||
} from 'react-router-dom';
|
||||
import { createStore, applyMiddleware, compose } from 'redux';
|
||||
import { Provider } from 'react-redux';
|
||||
import reduxWebsocket from '@giantmachines/redux-websocket';
|
||||
import { composeWithDevTools } from 'redux-devtools-extension';
|
||||
import thunk from 'redux-thunk';
|
||||
import { Redirect } from 'react-router';
|
||||
import { thunk } from 'redux-thunk';
|
||||
import rootReducer from './reducers';
|
||||
import App from './App';
|
||||
import './index.scss';
|
||||
@@ -18,10 +20,9 @@ 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 './i18n';
|
||||
|
||||
const history = createBrowserHistory();
|
||||
|
||||
// We get the token from the store to initialise the store.
|
||||
// So we know if the user is still signed in.
|
||||
function getAuthState() {
|
||||
@@ -54,32 +55,76 @@ const reduxWebsocketMiddleware = reduxWebsocket({
|
||||
reconnectOnClose: true,
|
||||
});
|
||||
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
|
||||
|
||||
const store = createStore(
|
||||
rootReducer(history),
|
||||
rootReducer,
|
||||
{ ...getAuthState() },
|
||||
composeWithDevTools(
|
||||
applyMiddleware(thunk, reduxWebsocketMiddleware, routerMiddleware(history))
|
||||
)
|
||||
composeEnhancers(applyMiddleware(thunk, reduxWebsocketMiddleware))
|
||||
);
|
||||
|
||||
const Loader = () => <div>loading...</div>;
|
||||
|
||||
ReactDOM.render(
|
||||
// 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}>
|
||||
<ConnectedRouter history={history}>
|
||||
<Switch>
|
||||
<Route path="/login" component={RequireGuest(Login)} />
|
||||
<Suspense fallback={<Loader />}>
|
||||
<App>
|
||||
<Route exact path="/" component={RequireAuth(Dashboard)} />
|
||||
<Route exact path="/dashboard" component={RequireAuth(Dashboard)} />
|
||||
<Route exact path="/" render={() => <Redirect to="/dashboard" />} />
|
||||
<Route exact path="/media" component={RequireAuth(Media)} />
|
||||
<Route exact path="/settings" component={RequireAuth(Settings)} />
|
||||
</App>
|
||||
</Suspense>
|
||||
</Switch>
|
||||
</ConnectedRouter>
|
||||
</Provider>,
|
||||
document.getElementById('root')
|
||||
<BrowserRouter>
|
||||
<NavigationSetup />
|
||||
<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>
|
||||
}
|
||||
/>
|
||||
</Route>
|
||||
</Routes>
|
||||
</Suspense>
|
||||
</BrowserRouter>
|
||||
</Provider>
|
||||
);
|
||||
|
||||
16
ui/src/navigation.js
Normal file
16
ui/src/navigation.js
Normal file
@@ -0,0 +1,16 @@
|
||||
// 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).
|
||||
|
||||
let navigatorFn = null;
|
||||
|
||||
export const setNavigator = (fn) => {
|
||||
navigatorFn = fn;
|
||||
};
|
||||
|
||||
export const navigate = (path, options) => {
|
||||
if (navigatorFn) {
|
||||
navigatorFn(path, options);
|
||||
}
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Link, withRouter } from 'react-router-dom';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import { send } from '@giantmachines/redux-websocket';
|
||||
import { connect } from 'react-redux';
|
||||
@@ -24,7 +24,8 @@ import {
|
||||
ModalFooter,
|
||||
} from '@kerberos-io/ui';
|
||||
import './Dashboard.scss';
|
||||
import ReactTooltip from 'react-tooltip';
|
||||
import { Tooltip as ReactTooltip } from 'react-tooltip';
|
||||
import 'react-tooltip/dist/react-tooltip.css';
|
||||
import config from '../../config';
|
||||
import { getConfig } from '../../actions/agent';
|
||||
|
||||
@@ -617,7 +618,12 @@ class Dashboard extends React.Component {
|
||||
}
|
||||
>
|
||||
<Ellipse status="success" />{' '}
|
||||
<p data-tip="10m and 5s ago">{event.time}</p>
|
||||
<p
|
||||
data-tooltip-id="dashboard-tip"
|
||||
data-tooltip-content="10m and 5s ago"
|
||||
>
|
||||
{event.time}
|
||||
</p>
|
||||
</div>
|
||||
</>,
|
||||
<>
|
||||
@@ -716,7 +722,7 @@ class Dashboard extends React.Component {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ReactTooltip />
|
||||
<ReactTooltip id="dashboard-tip" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -746,5 +752,6 @@ Dashboard.propTypes = {
|
||||
};
|
||||
|
||||
export default withTranslation()(
|
||||
withRouter(connect(mapStateToProps, mapDispatchToProps)(Dashboard))
|
||||
connect(mapStateToProps, mapDispatchToProps)(Dashboard)
|
||||
)
|
||||
);
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
Icon,
|
||||
LandingLayout,
|
||||
} from '@kerberos-io/ui';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { connect } from 'react-redux';
|
||||
import { login, resetLogin } from '../../actions';
|
||||
import config from '../../config';
|
||||
@@ -166,4 +165,4 @@ Login.propTypes = {
|
||||
dispatchResetLogin: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Login));
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Login);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import classNames from 'classnames';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import { login } from '../../../../actions';
|
||||
import styles from './LoginForm.module.scss';
|
||||
@@ -103,6 +102,4 @@ LoginForm.propTypes = {
|
||||
dispatchLogin: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default withRouter(
|
||||
connect(mapStateToProps, mapDispatchToProps)(LoginForm)
|
||||
);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(LoginForm);
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
ModalBody,
|
||||
ModalFooter,
|
||||
} from '@kerberos-io/ui';
|
||||
import { Link, withRouter } from 'react-router-dom';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { connect } from 'react-redux';
|
||||
import { getEvents } from '../../actions/agent';
|
||||
import config from '../../config';
|
||||
@@ -351,5 +351,6 @@ Media.propTypes = {
|
||||
};
|
||||
|
||||
export default withTranslation()(
|
||||
withRouter(connect(mapStateToProps, mapDispatchToProps)(Media))
|
||||
connect(mapStateToProps, mapDispatchToProps)(Media)
|
||||
)
|
||||
);
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
Icon,
|
||||
Toggle,
|
||||
} from '@kerberos-io/ui';
|
||||
import { Link, withRouter } from 'react-router-dom';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { connect } from 'react-redux';
|
||||
import { interval } from 'rxjs';
|
||||
import { send } from '@giantmachines/redux-websocket';
|
||||
@@ -2825,5 +2825,6 @@ Settings.propTypes = {
|
||||
};
|
||||
|
||||
export default withTranslation()(
|
||||
withRouter(connect(mapStateToProps, mapDispatchToProps)(Settings))
|
||||
connect(mapStateToProps, mapDispatchToProps)(Settings)
|
||||
)
|
||||
);
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { combineReducers } from 'redux';
|
||||
import { connectRouter } from 'connected-react-router';
|
||||
import authentication from './authentication';
|
||||
import agent from './agent';
|
||||
import wss from './wss';
|
||||
|
||||
export default (history) =>
|
||||
combineReducers({
|
||||
authentication,
|
||||
agent,
|
||||
wss,
|
||||
router: connectRouter(history),
|
||||
});
|
||||
const rootReducer = combineReducers({
|
||||
authentication,
|
||||
agent,
|
||||
wss,
|
||||
});
|
||||
|
||||
export default rootReducer;
|
||||
|
||||
Reference in New Issue
Block a user