Refactor pgroup handling and routing logic.
Enable synchronization of active pgroup across components using a callback mechanism. Improve handling of query parameters, props, and redirection to ensure accurate user context and state across pages like ResultsView and BeamtimeOverview. Update ProtectedRoute to support additional props.
This commit is contained in:
parent
a169a39edd
commit
26f8870d04
@ -66,10 +66,11 @@ const App: React.FC = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handlePgroupChange = (newPgroup: string) => {
|
const handlePgroupChange = (newPgroup: string) => {
|
||||||
setActivePgroup(newPgroup);
|
setActivePgroup(newPgroup); // Updates active pgroup state in App
|
||||||
console.log(`pgroup changed to: ${newPgroup}`);
|
console.log(`pgroup changed to: ${newPgroup}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Router>
|
<Router>
|
||||||
<ResponsiveAppBar
|
<ResponsiveAppBar
|
||||||
@ -85,9 +86,33 @@ const App: React.FC = () => {
|
|||||||
<Route path="/" element={<ProtectedRoute element={<HomePage />} />} />
|
<Route path="/" element={<ProtectedRoute element={<HomePage />} />} />
|
||||||
<Route path="/shipments" element={<ProtectedRoute element={<ShipmentView pgroups={pgroups} activePgroup={activePgroup} />} />} />
|
<Route path="/shipments" element={<ProtectedRoute element={<ShipmentView pgroups={pgroups} activePgroup={activePgroup} />} />} />
|
||||||
<Route path="/planning" element={<ProtectedRoute element={<PlanningView />} />} />
|
<Route path="/planning" element={<ProtectedRoute element={<PlanningView />} />} />
|
||||||
<Route path="/results/:beamtimeId" element={<ProtectedRoute element={<ResultsView pgroups={pgroups} activePgroup={activePgroup} />} />} />
|
<Route
|
||||||
<Route path="/beamtime-overview" element={<ProtectedRoute element={<BeamtimeOverview activePgroup={activePgroup} />} />} />
|
path="/results/:beamtimeId"
|
||||||
<Route path="/results" element={<ProtectedRoute element={<BeamtimeOverview activePgroup={activePgroup} />} />}/>
|
element={
|
||||||
|
<ProtectedRoute
|
||||||
|
element={
|
||||||
|
<ResultsView
|
||||||
|
onPgroupChange={handlePgroupChange}
|
||||||
|
currentPgroup={activePgroup}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="/beamtime-overview"
|
||||||
|
element={
|
||||||
|
<ProtectedRoute
|
||||||
|
element={
|
||||||
|
<BeamtimeOverview
|
||||||
|
activePgroup={activePgroup}
|
||||||
|
onPgroupChange={handlePgroupChange} // Pass this prop correctly
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Route path="/results" element={<ProtectedRoute element={<BeamtimeOverview activePgroup={activePgroup} onPgroupChange={handlePgroupChange} />} />}/>
|
||||||
{/* Optionally, add a 404 fallback route */}
|
{/* Optionally, add a 404 fallback route */}
|
||||||
<Route path="*" element={<div>Page not found</div>} />
|
<Route path="*" element={<div>Page not found</div>} />
|
||||||
|
|
||||||
|
@ -16,9 +16,10 @@ interface BeamtimeRecord {
|
|||||||
|
|
||||||
interface BeamtimeOverviewProps {
|
interface BeamtimeOverviewProps {
|
||||||
activePgroup: string;
|
activePgroup: string;
|
||||||
|
onPgroupChange: (pgroup: string) => void; // Add callback to update the selected pgroup
|
||||||
}
|
}
|
||||||
|
|
||||||
const BeamtimeOverview: React.FC<BeamtimeOverviewProps> = ({ activePgroup }) => {
|
const BeamtimeOverview: React.FC<BeamtimeOverviewProps> = ({ activePgroup, onPgroupChange }) => {
|
||||||
const [rows, setRows] = useState<BeamtimeRecord[]>([]);
|
const [rows, setRows] = useState<BeamtimeRecord[]>([]);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
@ -101,7 +102,7 @@ const BeamtimeOverview: React.FC<BeamtimeOverviewProps> = ({ activePgroup }) =>
|
|||||||
flex: 1,
|
flex: 1,
|
||||||
renderCell: (params) => (
|
renderCell: (params) => (
|
||||||
<button
|
<button
|
||||||
onClick={() => handleViewResults(params.row.id)}
|
onClick={() => handleViewResults(params.row.id, params.row.pgroups)}
|
||||||
style={{
|
style={{
|
||||||
padding: '6px 12px',
|
padding: '6px 12px',
|
||||||
backgroundColor: '#1976d2',
|
backgroundColor: '#1976d2',
|
||||||
@ -118,8 +119,15 @@ const BeamtimeOverview: React.FC<BeamtimeOverviewProps> = ({ activePgroup }) =>
|
|||||||
];
|
];
|
||||||
|
|
||||||
// Navigate to the ResultsView page for the selected beamtime
|
// Navigate to the ResultsView page for the selected beamtime
|
||||||
const handleViewResults = (beamtimeId: number) => {
|
const handleViewResults = (beamtimeId: number, pgroups: string) => {
|
||||||
navigate(`/results/${beamtimeId}?pgroup=${activePgroup}`);
|
const pgroupArray = pgroups.split(',').map((pgroup) => pgroup.trim());
|
||||||
|
const firstPgroup = pgroupArray[0] || ''; // Choose the first pgroup (or fallback to empty string)
|
||||||
|
|
||||||
|
// Ensure onPgroupChange is invoked correctly
|
||||||
|
onPgroupChange(firstPgroup);
|
||||||
|
|
||||||
|
// Navigate directly to the Results page with the correct pgroup in the query
|
||||||
|
navigate(`/results/${beamtimeId}?pgroup=${firstPgroup}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -3,16 +3,19 @@ import { Navigate } from 'react-router-dom';
|
|||||||
|
|
||||||
interface ProtectedRouteProps {
|
interface ProtectedRouteProps {
|
||||||
element: JSX.Element;
|
element: JSX.Element;
|
||||||
|
[key: string]: any; // Allow additional props
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProtectedRoute: React.FC<ProtectedRouteProps> = ({ element }) => {
|
const ProtectedRoute: React.FC<ProtectedRouteProps> = ({ element, ...rest }) => {
|
||||||
const isAuthenticated = () => {
|
const isAuthenticated = () => {
|
||||||
const token = localStorage.getItem('token');
|
const token = localStorage.getItem('token');
|
||||||
console.log("Is Authenticated: ", token !== null);
|
console.log("Is Authenticated: ", token !== null);
|
||||||
return token !== null;
|
return token !== null;
|
||||||
};
|
};
|
||||||
|
|
||||||
return isAuthenticated() ? element : <Navigate to="/login" />;
|
return isAuthenticated()
|
||||||
|
? React.cloneElement(element, { ...rest }) // Pass all additional props
|
||||||
|
: <Navigate to="/login" />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ProtectedRoute;
|
export default ProtectedRoute;
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { useNavigate, useLocation } from 'react-router-dom';
|
import { useNavigate, useLocation } from 'react-router-dom';
|
||||||
import AppBar from '@mui/material/AppBar';
|
import AppBar from '@mui/material/AppBar';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
@ -38,6 +38,12 @@ const ResponsiveAppBar: React.FC<ResponsiveAppBarProps> = ({
|
|||||||
const [anchorElNav, setAnchorElNav] = useState<null | HTMLElement>(null);
|
const [anchorElNav, setAnchorElNav] = useState<null | HTMLElement>(null);
|
||||||
const [anchorElUser, setAnchorElUser] = useState<null | HTMLElement>(null);
|
const [anchorElUser, setAnchorElUser] = useState<null | HTMLElement>(null);
|
||||||
const [selectedPgroup, setSelectedPgroup] = useState(currentPgroup);
|
const [selectedPgroup, setSelectedPgroup] = useState(currentPgroup);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setSelectedPgroup(currentPgroup); // Sync local state with the global activePgroup
|
||||||
|
}, [currentPgroup]);
|
||||||
|
|
||||||
|
|
||||||
console.log('Active Pgroup:', activePgroup);
|
console.log('Active Pgroup:', activePgroup);
|
||||||
const handlePgroupChange = (event: React.ChangeEvent<{ value: unknown }>) => {
|
const handlePgroupChange = (event: React.ChangeEvent<{ value: unknown }>) => {
|
||||||
const newPgroup = event.target.value as string;
|
const newPgroup = event.target.value as string;
|
||||||
|
@ -1,16 +1,39 @@
|
|||||||
import React from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { useParams, useSearchParams} from 'react-router-dom';
|
import { useParams, useSearchParams, useNavigate } from 'react-router-dom';
|
||||||
import SampleTracker from '../components/SampleTracker';
|
import SampleTracker from '../components/SampleTracker';
|
||||||
import ResultGrid from '../components/ResultGrid';
|
import ResultGrid from '../components/ResultGrid';
|
||||||
|
|
||||||
|
interface ResultsViewProps {
|
||||||
|
onPgroupChange?: (pgroup: string) => void; // Callback to notify about pgroup changes
|
||||||
|
currentPgroup: string; // Currently selected pgroup
|
||||||
|
}
|
||||||
|
|
||||||
interface ResultsViewProps {}
|
const ResultsView: React.FC<ResultsViewProps> = ({ onPgroupChange, currentPgroup }) => {
|
||||||
|
|
||||||
const ResultsView: React.FC<ResultsViewProps> = () => {
|
|
||||||
// Get the selected beamtime ID from the URL
|
|
||||||
const { beamtimeId } = useParams();
|
const { beamtimeId } = useParams();
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const activePgroup = searchParams.get("pgroup") ?? '';
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
// Get the active pgroup for the experiment from the query params.
|
||||||
|
const activePgroup = searchParams.get("pgroup") ?? ''; // Default to an empty string if missing
|
||||||
|
|
||||||
|
// Redirect if the selected pgroup does not match the beamtime's pgroup
|
||||||
|
useEffect(() => {
|
||||||
|
if (!currentPgroup || currentPgroup !== activePgroup) {
|
||||||
|
console.warn(
|
||||||
|
`Redirecting to BeamtimeOverview because selected pgroup (${currentPgroup || "undefined"}) does not match beamtime's pgroup (${activePgroup})`
|
||||||
|
);
|
||||||
|
navigate('/beamtime-overview'); // Redirect to BeamtimeOverview
|
||||||
|
}
|
||||||
|
}, [currentPgroup, activePgroup, navigate]);
|
||||||
|
|
||||||
|
// Notify parent about the selected pgroup (if needed)
|
||||||
|
useEffect(() => {
|
||||||
|
// Synchronize the pgroup when the component loads
|
||||||
|
if (onPgroupChange && activePgroup !== currentPgroup) {
|
||||||
|
onPgroupChange(activePgroup); // Update the selected pgroup
|
||||||
|
}
|
||||||
|
}, [onPgroupChange, activePgroup, currentPgroup]);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@ -24,4 +47,4 @@ const ResultsView: React.FC<ResultsViewProps> = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ResultsView;
|
export default ResultsView;
|
Loading…
x
Reference in New Issue
Block a user