From 9774989eeb6c33752c41c0243eb061ae54a6dbed Mon Sep 17 00:00:00 2001 From: "weakmap@gmail.com" Date: Tue, 2 Sep 2025 20:18:37 +0200 Subject: [PATCH] upgrade to react router 7 --- conf/config.json | 8 +- package.json | 16 +- ui/src/App.jsx | 68 +++-- ui/src/Index.jsx | 5 +- ui/src/components/menu/Menu.jsx | 13 +- .../permission/PermissionAwareRoute.jsx | 21 +- ui/src/views/jobs/Jobs.jsx | 10 +- ui/src/views/jobs/insights/JobInsight.jsx | 2 +- ui/src/views/jobs/mutation/JobMutation.jsx | 9 +- ui/src/views/login/Login.jsx | 6 +- ui/src/views/user/Users.jsx | 8 +- ui/src/views/user/mutation/UserMutator.jsx | 8 +- yarn.lock | 263 +++++++----------- 13 files changed, 180 insertions(+), 257 deletions(-) diff --git a/conf/config.json b/conf/config.json index b0003aa..3b48654 100755 --- a/conf/config.json +++ b/conf/config.json @@ -1,7 +1 @@ -{ - "interval": "60", - "port": 9998, - "workingHours": { "from": "", "to": "" }, - "demoMode": false, - "analyticsEnabled": null -} +{"interval":"60","port":9998,"workingHours":{"from":"","to":""},"demoMode":false,"analyticsEnabled":false} \ No newline at end of file diff --git a/package.json b/package.json index a6bda41..f64e84f 100755 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "Firefox ESR" ], "dependencies": { - "@douyinfe/semi-ui": "2.85.0", + "@douyinfe/semi-ui": "2.86.0", "@rematch/core": "2.2.0", "@rematch/loading": "2.1.2", "@sendgrid/mail": "8.1.5", @@ -75,22 +75,22 @@ "node-mailjet": "6.0.9", "p-throttle": "^8.0.0", "package-up": "^5.0.0", - "puppeteer": "^24.17.1", + "puppeteer": "^24.18.0", "puppeteer-extra": "^3.3.6", "puppeteer-extra-plugin-stealth": "^2.11.2", "query-string": "9.2.2", "react": "18.3.1", "react-dom": "18.3.1", "react-redux": "9.2.0", - "react-router": "5.2.1", - "react-router-dom": "5.3.0", + "react-router": "7.8.2", + "react-router-dom": "7.8.2", "redux": "5.0.1", "redux-thunk": "3.1.0", "restana": "5.1.0", "serve-static": "2.2.0", "slack": "11.0.2", "string-similarity": "^4.0.4", - "vite": "7.1.3", + "vite": "7.1.4", "x-var": "^2.1.0" }, "devDependencies": { @@ -102,12 +102,12 @@ "eslint": "9.34.0", "eslint-config-prettier": "10.1.8", "eslint-plugin-react": "7.37.5", - "esmock": "2.7.1", + "esmock": "2.7.2", "history": "5.3.0", "husky": "9.1.7", "less": "4.4.1", - "lint-staged": "16.1.5", - "mocha": "11.7.1", + "lint-staged": "16.1.6", + "mocha": "11.7.2", "nodemon": "^3.1.10", "prettier": "3.6.2", "redux-logger": "3.0.6" diff --git a/ui/src/App.jsx b/ui/src/App.jsx index 86485ac..919fd7b 100644 --- a/ui/src/App.jsx +++ b/ui/src/App.jsx @@ -7,14 +7,13 @@ import JobMutation from './views/jobs/mutation/JobMutation'; import UserMutator from './views/user/mutation/UserMutator'; import JobInsight from './views/jobs/insights/JobInsight.jsx'; import { useDispatch, useSelector } from 'react-redux'; -import { Switch, Redirect } from 'react-router-dom'; +import { Routes, Route, Navigate } from 'react-router-dom'; import Logout from './components/logout/Logout'; import Logo from './components/logo/Logo'; import Menu from './components/menu/Menu'; import Login from './views/login/Login'; import Users from './views/user/Users'; import Jobs from './views/jobs/Jobs'; -import { Route } from 'react-router'; import './App.less'; import TrackingModal from './components/tracking/TrackingModal.jsx'; @@ -49,10 +48,10 @@ export default function FredyApp() { const isAdmin = () => currentUser != null && currentUser.isAdmin; const login = () => ( - - - - + + } /> + } /> + ); return loading ? null : needsLogin() ? ( @@ -77,34 +76,49 @@ export default function FredyApp() { )} {settings.analyticsEnabled === null && !settings.demoMode && } - - - - - - - + } /> + } /> + } /> + } /> + } /> + + {/* Permission-aware routes */} + } - currentUser={currentUser} + element={ + + + + } /> - } - currentUser={currentUser} + element={ + + + + } /> - } currentUser={currentUser} /> - + + + } + /> + } - currentUser={currentUser} + element={ + + + + } /> - - + } /> + ); diff --git a/ui/src/Index.jsx b/ui/src/Index.jsx index d66dc47..1fe0883 100644 --- a/ui/src/Index.jsx +++ b/ui/src/Index.jsx @@ -2,7 +2,6 @@ import React from 'react'; import { reduxStore } from './services/rematch/store'; import { HashRouter } from 'react-router-dom'; -import { createHashHistory } from 'history'; import { Provider } from 'react-redux'; import { createRoot } from 'react-dom/client'; import en_US from '@douyinfe/semi-ui/lib/es/locale/source/en_US'; @@ -10,15 +9,13 @@ import { LocaleProvider } from '@douyinfe/semi-ui'; const container = document.getElementById('fredy'); const root = createRoot(container); -const history = createHashHistory(); - import App from './App'; import './Index.less'; root.render( - + diff --git a/ui/src/components/menu/Menu.jsx b/ui/src/components/menu/Menu.jsx index 4ba6e46..1f4cc74 100644 --- a/ui/src/components/menu/Menu.jsx +++ b/ui/src/components/menu/Menu.jsx @@ -1,8 +1,8 @@ import React from 'react'; -import { useHistory } from 'react-router-dom'; +import { useNavigate } from 'react-router-dom'; import { Tabs, TabPane } from '@douyinfe/semi-ui'; -import { useLocation } from 'react-router'; +import { useLocation } from 'react-router-dom'; import { IconUser, IconTerminal, IconSetting } from '@douyinfe/semi-icons'; import './Menu.less'; @@ -12,15 +12,10 @@ function parsePathName(name) { } const TopMenu = function TopMenu({ isAdmin }) { - const history = useHistory(); + const navigate = useNavigate(); const location = useLocation(); return ( - history.push(key)} - > + navigate(key)}> { - return currentUser != null && currentUser.isAdmin ? component : ; - }; - - return checkIfAdmin(component, path)} />; +export default function PermissionAwareRoute({ currentUser, children }) { + const isAdmin = currentUser != null && currentUser.isAdmin; + return isAdmin ? children : ; } diff --git a/ui/src/views/jobs/Jobs.jsx b/ui/src/views/jobs/Jobs.jsx index 1049d6c..fe7e927 100644 --- a/ui/src/views/jobs/Jobs.jsx +++ b/ui/src/views/jobs/Jobs.jsx @@ -3,7 +3,7 @@ import React from 'react'; import JobTable from '../../components/table/JobTable'; import { useSelector, useDispatch } from 'react-redux'; import { xhrDelete, xhrPut } from '../../services/xhr'; -import { useHistory } from 'react-router-dom'; +import { useNavigate } from 'react-router-dom'; import ProcessingTimes from './ProcessingTimes'; import { Button, Toast } from '@douyinfe/semi-ui'; import { IconPlusCircle } from '@douyinfe/semi-icons'; @@ -12,7 +12,7 @@ import './Jobs.less'; export default function Jobs() { const jobs = useSelector((state) => state.jobs.jobs); const processingTimes = useSelector((state) => state.jobs.processingTimes); - const history = useHistory(); + const navigate = useNavigate(); const dispatch = useDispatch(); const onJobRemoval = async (jobId) => { @@ -43,7 +43,7 @@ export default function Jobs() { type="primary" icon={} className="jobs__newButton" - onClick={() => history.push('/jobs/new')} + onClick={() => navigate('/jobs/new')} > New Job @@ -53,8 +53,8 @@ export default function Jobs() { jobs={jobs || []} onJobRemoval={onJobRemoval} onJobStatusChanged={onJobStatusChanged} - onJobInsight={(jobId) => history.push(`/jobs/insights/${jobId}`)} - onJobEdit={(jobId) => history.push(`/jobs/edit/${jobId}`)} + onJobInsight={(jobId) => navigate(`/jobs/insights/${jobId}`)} + onJobEdit={(jobId) => navigate(`/jobs/edit/${jobId}`)} /> ); diff --git a/ui/src/views/jobs/insights/JobInsight.jsx b/ui/src/views/jobs/insights/JobInsight.jsx index a727b65..5146423 100644 --- a/ui/src/views/jobs/insights/JobInsight.jsx +++ b/ui/src/views/jobs/insights/JobInsight.jsx @@ -3,7 +3,7 @@ import React from 'react'; import { roundToNext5Minute } from '../../../services/time/timeService'; import Headline from '../../../components/headline/Headline'; import { useDispatch, useSelector } from 'react-redux'; -import { useParams } from 'react-router'; +import { useParams } from 'react-router-dom'; import Linechart from './Linechart'; const JobInsight = function JobInsight() { diff --git a/ui/src/views/jobs/mutation/JobMutation.jsx b/ui/src/views/jobs/mutation/JobMutation.jsx index 644807c..d0172de 100644 --- a/ui/src/views/jobs/mutation/JobMutation.jsx +++ b/ui/src/views/jobs/mutation/JobMutation.jsx @@ -7,8 +7,7 @@ import ProviderMutator from './components/provider/ProviderMutator'; import Headline from '../../../components/headline/Headline'; import { useDispatch, useSelector } from 'react-redux'; import { xhrPost } from '../../../services/xhr'; -import { useHistory } from 'react-router-dom'; -import { useParams } from 'react-router'; +import { useNavigate, useParams } from 'react-router-dom'; import { Divider, Input, Switch, Button, TagInput, Toast } from '@douyinfe/semi-ui'; import './JobMutation.less'; import { SegmentPart } from '../../../components/segment/SegmentPart'; @@ -34,7 +33,7 @@ export default function JobMutator() { const [blacklist, setBlacklist] = useState(defaultBlacklist); const [notificationAdapterData, setNotificationAdapterData] = useState(defaultNotificationAdapter); const [enabled, setEnabled] = useState(defaultEnabled); - const history = useHistory(); + const navigate = useNavigate(); const dispatch = useDispatch(); const isSavingEnabled = () => { @@ -53,7 +52,7 @@ export default function JobMutator() { }); await dispatch.jobs.getJobs(); Toast.success('Job successfully saved...'); - history.push('/jobs'); + navigate('/jobs'); } catch (Exception) { console.error(Exception.json.message); Toast.error(Exception.json != null ? Exception.json.message : Exception); @@ -177,7 +176,7 @@ export default function JobMutator() { setEnabled(checked)} checked={enabled} /> - @@ -58,7 +58,7 @@ const Users = function Users() { { - history.push(`/users/edit/${userId}`); + navigate(`/users/edit/${userId}`); }} onUserRemoval={(userId) => { setUserIdToBeRemoved(userId); diff --git a/ui/src/views/user/mutation/UserMutator.jsx b/ui/src/views/user/mutation/UserMutator.jsx index 5912818..befd2ab 100644 --- a/ui/src/views/user/mutation/UserMutator.jsx +++ b/ui/src/views/user/mutation/UserMutator.jsx @@ -1,7 +1,7 @@ import React from 'react'; import { xhrGet, xhrPost } from '../../../services/xhr'; -import { useHistory, useParams } from 'react-router'; +import { useNavigate, useParams } from 'react-router-dom'; import { useDispatch } from 'react-redux'; import { Divider, Input, Switch, Button, Toast } from '@douyinfe/semi-ui'; import './UserMutator.less'; @@ -15,7 +15,7 @@ const UserMutator = function UserMutator() { const [password2, setPassword2] = React.useState(''); const [isAdmin, setIsAdmin] = React.useState(false); - const history = useHistory(); + const navigate = useNavigate(); const dispatch = useDispatch(); React.useEffect(() => { @@ -50,7 +50,7 @@ const UserMutator = function UserMutator() { }); await dispatch.user.getUsers(); Toast.success('User successfully saved...'); - history.push('/users'); + navigate('/users'); } catch (error) { console.error(error); Toast.error(error.json.message); @@ -98,7 +98,7 @@ const UserMutator = function UserMutator() { setIsAdmin(checked)} /> -