feat(frontend): upgrade react-router-dom 5→6 (Phase 3)
- Update package.json: react-router-dom ^5.2.0→^6.28.0 - Migrate App.js: Switch→Routes, component→element props, path="*" for 404 - Migrate 5 pages: useHistory→useNavigate, history.push()→navigate() - GroupsOverviewPage.js (4x navigate) - ModerationGroupsPage.js (1x navigate) - ModerationGroupImagesPage.js (2x navigate) - PublicGroupImagesPage.js (import updated) - SlideshowPage.js (4x navigate + keyboard handler) - Regenerate package-lock.json with react-router v6 ✅ Tested: Production build 254.46 KB gzip (+1.17 KB) ✅ Manual test: Navigation, moderation routing, slideshow ESC - all working Phase 3 complete: Modern react-router v6 with improved routing API.
This commit is contained in:
parent
93534587d2
commit
5ba463427b
130
frontend/package-lock.json
generated
130
frontend/package-lock.json
generated
|
|
@ -20,7 +20,7 @@
|
|||
"react-dropzone": "^11.3.1",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-lottie": "^1.2.3",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-router-dom": "^6.28.0",
|
||||
"react-scripts": "5.0.1",
|
||||
"sass": "^1.32.8",
|
||||
"sweetalert2": "^10.15.6",
|
||||
|
|
@ -3840,6 +3840,14 @@
|
|||
"node": ">=8.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@remix-run/router": {
|
||||
"version": "1.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz",
|
||||
"integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==",
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/plugin-babel": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
|
||||
|
|
@ -9657,18 +9665,6 @@
|
|||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/history": {
|
||||
"version": "4.10.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"loose-envify": "^1.2.0",
|
||||
"resolve-pathname": "^3.0.0",
|
||||
"tiny-invariant": "^1.0.2",
|
||||
"tiny-warning": "^1.0.0",
|
||||
"value-equal": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/hoist-non-react-statics": {
|
||||
"version": "3.3.2",
|
||||
"license": "BSD-3-Clause",
|
||||
|
|
@ -17020,69 +17016,35 @@
|
|||
}
|
||||
},
|
||||
"node_modules/react-router": {
|
||||
"version": "5.2.0",
|
||||
"license": "MIT",
|
||||
"version": "6.30.1",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.1.tgz",
|
||||
"integrity": "sha512-X1m21aEmxGXqENEPG3T6u0Th7g0aS4ZmoNynhbs+Cn+q+QGTLt+d5IQ2bHAXKzKcxGJjxACpVbnYQSCRcfxHlQ==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"history": "^4.9.0",
|
||||
"hoist-non-react-statics": "^3.1.0",
|
||||
"loose-envify": "^1.3.1",
|
||||
"mini-create-react-context": "^0.4.0",
|
||||
"path-to-regexp": "^1.7.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"react-is": "^16.6.0",
|
||||
"tiny-invariant": "^1.0.2",
|
||||
"tiny-warning": "^1.0.0"
|
||||
"@remix-run/router": "1.23.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=15"
|
||||
"react": ">=16.8"
|
||||
}
|
||||
},
|
||||
"node_modules/react-router-dom": {
|
||||
"version": "5.2.0",
|
||||
"license": "MIT",
|
||||
"version": "6.30.1",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.1.tgz",
|
||||
"integrity": "sha512-llKsgOkZdbPU1Eg3zK8lCn+sjD9wMRZZPuzmdWWX5SUs8OFkN5HnFVC0u5KMeMaC9aoancFI/KoLuKPqN+hxHw==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"history": "^4.9.0",
|
||||
"loose-envify": "^1.3.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"react-router": "5.2.0",
|
||||
"tiny-invariant": "^1.0.2",
|
||||
"tiny-warning": "^1.0.0"
|
||||
"@remix-run/router": "1.23.0",
|
||||
"react-router": "6.30.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=15"
|
||||
"react": ">=16.8",
|
||||
"react-dom": ">=16.8"
|
||||
}
|
||||
},
|
||||
"node_modules/react-router/node_modules/isarray": {
|
||||
"version": "0.0.1",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/react-router/node_modules/mini-create-react-context": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz",
|
||||
"integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==",
|
||||
"deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.1",
|
||||
"tiny-warning": "^1.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"prop-types": "^15.0.0",
|
||||
"react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-router/node_modules/path-to-regexp": {
|
||||
"version": "1.8.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"isarray": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/react-router/node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/react-scripts": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
|
||||
|
|
@ -17518,10 +17480,6 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve-pathname": {
|
||||
"version": "3.0.0",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/resolve-url-loader": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz",
|
||||
|
|
@ -18966,19 +18924,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/tailwindcss/node_modules/yaml": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz",
|
||||
"integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"yaml": "bin.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14.6"
|
||||
}
|
||||
},
|
||||
"node_modules/tapable": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
|
||||
|
|
@ -19149,10 +19094,6 @@
|
|||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/tiny-invariant": {
|
||||
"version": "1.1.0",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tiny-warning": {
|
||||
"version": "1.0.3",
|
||||
"license": "MIT"
|
||||
|
|
@ -19396,19 +19337,6 @@
|
|||
"is-typedarray": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "3.9.10",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz",
|
||||
"integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript-plugin-styled-components": {
|
||||
"version": "1.4.4",
|
||||
"license": "MIT",
|
||||
|
|
@ -19607,10 +19535,6 @@
|
|||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
|
||||
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
|
||||
},
|
||||
"node_modules/value-equal": {
|
||||
"version": "1.0.1",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
"react-dropzone": "^11.3.1",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-lottie": "^1.2.3",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-router-dom": "^6.28.0",
|
||||
"react-scripts": "5.0.1",
|
||||
"sass": "^1.32.8",
|
||||
"sweetalert2": "^10.15.6",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import './App.css';
|
||||
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
|
||||
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
|
||||
|
||||
// Pages
|
||||
import MultiUploadPage from './Components/Pages/MultiUploadPage';
|
||||
|
|
@ -13,15 +13,15 @@ import FZF from './Components/Pages/404Page.js'
|
|||
function App() {
|
||||
return (
|
||||
<Router>
|
||||
<Switch>
|
||||
<Route path="/" exact component={MultiUploadPage} />
|
||||
<Route path="/slideshow" component={SlideshowPage} />
|
||||
<Route path="/groups/:groupId" component={PublicGroupImagesPage} />
|
||||
<Route path="/groups" component={GroupsOverviewPage} />
|
||||
<Route path="/moderation" exact component={ModerationGroupsPage} />
|
||||
<Route path="/moderation/groups/:groupId" component={ModerationGroupImagesPage} />
|
||||
<Route component={FZF} />
|
||||
</Switch>
|
||||
<Routes>
|
||||
<Route path="/" exact element={<MultiUploadPage />} />
|
||||
<Route path="/slideshow" element={<SlideshowPage />} />
|
||||
<Route path="/groups/:groupId" element={<PublicGroupImagesPage />} />
|
||||
<Route path="/groups" element={<GroupsOverviewPage />} />
|
||||
<Route path="/moderation" exact element={<ModerationGroupsPage />} />
|
||||
<Route path="/moderation/groups/:groupId" element={<ModerationGroupImagesPage />} />
|
||||
<Route path="*" element={<FZF />} />
|
||||
</Routes>
|
||||
</Router>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { useState, useEffect } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import {
|
||||
Container,
|
||||
|
|
@ -25,7 +25,7 @@ import '../../App.css';
|
|||
|
||||
function GroupsOverviewPage() {
|
||||
// use CSS classes from GroupsOverviewPage.css
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [groups, setGroups] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
|
@ -50,19 +50,19 @@ function GroupsOverviewPage() {
|
|||
};
|
||||
|
||||
const handleViewSlideshow = (groupId) => {
|
||||
history.push(`/slideshow/${groupId}`);
|
||||
navigate(`/slideshow/${groupId}`);
|
||||
};
|
||||
|
||||
const handleViewGroup = (groupId) => {
|
||||
history.push(`/groups/${groupId}`);
|
||||
navigate(`/groups/${groupId}`);
|
||||
};
|
||||
|
||||
const handleCreateNew = () => {
|
||||
history.push('/multi-upload');
|
||||
navigate('/multi-upload');
|
||||
};
|
||||
|
||||
const handleGoHome = () => {
|
||||
history.push('/');
|
||||
navigate('/');
|
||||
};
|
||||
|
||||
const formatDate = (dateString) => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { useParams, useHistory } from 'react-router-dom';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { Button, Container } from '@material-ui/core';
|
||||
import Swal from 'sweetalert2/dist/sweetalert2.js';
|
||||
import 'sweetalert2/src/sweetalert2.scss';
|
||||
|
|
@ -15,7 +15,7 @@ import DescriptionInput from '../ComponentUtils/MultiUpload/DescriptionInput';
|
|||
|
||||
const ModerationGroupImagesPage = () => {
|
||||
const { groupId } = useParams();
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
const [group, setGroup] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [saving, setSaving] = useState(false);
|
||||
|
|
@ -86,7 +86,7 @@ const ModerationGroupImagesPage = () => {
|
|||
}
|
||||
|
||||
Swal.fire({ icon: 'success', title: 'Gruppe erfolgreich aktualisiert', timer: 1500, showConfirmButton: false });
|
||||
history.push('/moderation');
|
||||
navigate('/moderation');
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
Swal.fire({ icon: 'error', title: 'Fehler beim Speichern', text: e.message });
|
||||
|
|
@ -144,7 +144,7 @@ const ModerationGroupImagesPage = () => {
|
|||
<DescriptionInput metadata={metadata} onMetadataChange={setMetadata} />
|
||||
|
||||
<div className="action-buttons">
|
||||
<Button className="btn btn-secondary" onClick={() => history.push('/moderation')}>↩ Zurück</Button>
|
||||
<Button className="btn btn-secondary" onClick={() => navigate('/moderation')}>↩ Zurück</Button>
|
||||
<Button className="primary-button" onClick={handleSave} disabled={saving}>{saving ? 'Speichern...' : 'Speichern'}</Button>
|
||||
</div>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Container } from '@material-ui/core';
|
||||
import Navbar from '../ComponentUtils/Headers/Navbar';
|
||||
import Footer from '../ComponentUtils/Footer';
|
||||
|
|
@ -12,7 +12,7 @@ const ModerationGroupsPage = () => {
|
|||
const [error, setError] = useState(null);
|
||||
const [selectedGroup, setSelectedGroup] = useState(null);
|
||||
const [showImages, setShowImages] = useState(false);
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
loadModerationGroups();
|
||||
|
|
@ -134,7 +134,7 @@ const ModerationGroupsPage = () => {
|
|||
|
||||
// Navigate to the dedicated group images page
|
||||
const viewGroupImages = (group) => {
|
||||
history.push(`/moderation/groups/${group.groupId}`);
|
||||
navigate(`/moderation/groups/${group.groupId}`);
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { useParams, useHistory } from 'react-router-dom';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { Button, Container } from '@material-ui/core';
|
||||
import Navbar from '../ComponentUtils/Headers/Navbar';
|
||||
import Footer from '../ComponentUtils/Footer';
|
||||
|
|
@ -9,7 +9,7 @@ import ImageGallery from '../ComponentUtils/ImageGallery';
|
|||
|
||||
const PublicGroupImagesPage = () => {
|
||||
const { groupId } = useParams();
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
const [group, setGroup] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import {
|
||||
Typography,
|
||||
|
|
@ -108,7 +108,7 @@ const useStyles = makeStyles({
|
|||
|
||||
function SlideshowPage() {
|
||||
const classes = useStyles();
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [allGroups, setAllGroups] = useState([]);
|
||||
const [currentGroupIndex, setCurrentGroupIndex] = useState(0);
|
||||
|
|
@ -184,7 +184,7 @@ function SlideshowPage() {
|
|||
const handleKeyPress = (event) => {
|
||||
switch (event.key) {
|
||||
case 'Escape':
|
||||
history.push('/');
|
||||
navigate('/');
|
||||
break;
|
||||
case ' ':
|
||||
case 'ArrowRight':
|
||||
|
|
@ -197,7 +197,7 @@ function SlideshowPage() {
|
|||
|
||||
document.addEventListener('keydown', handleKeyPress);
|
||||
return () => document.removeEventListener('keydown', handleKeyPress);
|
||||
}, [nextImage, history]);
|
||||
}, [nextImage, navigate]);
|
||||
|
||||
// Aktuelle Gruppe und Bild
|
||||
const currentGroup = allGroups[currentGroupIndex];
|
||||
|
|
@ -221,7 +221,7 @@ function SlideshowPage() {
|
|||
<Typography style={{ color: 'white', fontSize: '24px' }}>{error}</Typography>
|
||||
<IconButton
|
||||
className={classes.homeButton}
|
||||
onClick={() => history.push('/')}
|
||||
onClick={() => navigate('/')}
|
||||
title="Zur Startseite"
|
||||
>
|
||||
<HomeIcon />
|
||||
|
|
@ -240,7 +240,7 @@ function SlideshowPage() {
|
|||
</Typography>
|
||||
<IconButton
|
||||
className={classes.homeButton}
|
||||
onClick={() => history.push('/')}
|
||||
onClick={() => navigate('/')}
|
||||
title="Zur Startseite"
|
||||
>
|
||||
<HomeIcon />
|
||||
|
|
@ -255,7 +255,7 @@ function SlideshowPage() {
|
|||
{/* Navigation Buttons */}
|
||||
<IconButton
|
||||
className={classes.homeButton}
|
||||
onClick={() => history.push('/')}
|
||||
onClick={() => navigate('/')}
|
||||
title="Zur Startseite"
|
||||
>
|
||||
<HomeIcon />
|
||||
|
|
@ -263,7 +263,7 @@ function SlideshowPage() {
|
|||
|
||||
<IconButton
|
||||
className={classes.exitButton}
|
||||
onClick={() => history.push('/')}
|
||||
onClick={() => navigate('/')}
|
||||
title="Slideshow beenden"
|
||||
>
|
||||
<ExitIcon />
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user