Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
f29b05f
feat(tests): add comprehensive test coverage for ConfigSection component
PaulJouvanceau Jan 20, 2026
777e981
feat(node-table): maintain consistent icon positioning in NodeRow
PaulJouvanceau Jan 20, 2026
aa28b74
Create jest file for ObjectInstanceView
PaulJouvanceau Jan 21, 2026
b8a35ce
feat(event-logger): replace bug icon with sensors icon for event stream
PaulJouvanceau Jan 22, 2026
a7c7e54
refactor(eventSourceManager): optimize flush delay and remove unused …
PaulJouvanceau Jan 27, 2026
00bc21c
refactor(Objects): Optimize performance with custom hooks and improve…
PaulJouvanceau Jan 28, 2026
b0a3d1e
Optimization: Prevent unnecessary re-renders in Objects and Cluster c…
PaulJouvanceau Jan 29, 2026
6fa449d
feat: optimize performance with Safari-specific improvements and effi…
PaulJouvanceau Jan 29, 2026
e4316f5
feat: refactor Cluster component and update tests for improved perfor…
PaulJouvanceau Feb 2, 2026
e4a3db0
Improve test coverage for StatCard component
PaulJouvanceau Feb 2, 2026
7a81b9f
Improve test coverage for eventSourceManager
PaulJouvanceau Feb 2, 2026
3f462ad
Improve test coverage for Cluster
PaulJouvanceau Feb 2, 2026
17c5b6e
Performance Optimization: Objects Table Virtualization and Infinite S…
PaulJouvanceau Feb 3, 2026
b08c706
feat: optimize Namespaces page performance with React optimization pa…
PaulJouvanceau Feb 3, 2026
95c7490
fix(cluster-ui): center frozen/unfrozen stats in Nodes grid card
PaulJouvanceau Feb 3, 2026
54bae72
feat: optimize Heartbeats page performance with React best practices
PaulJouvanceau Feb 4, 2026
f23d7f3
feat: make filter section responsive for mobile devices
PaulJouvanceau Feb 4, 2026
b20ab01
feat: make Heartbeats page responsive and improve mobile usability
PaulJouvanceau Feb 4, 2026
0f31a84
fix: remove focus event that caused immediate redirect on login form …
PaulJouvanceau Feb 5, 2026
ade0529
Remove event loggers
PaulJouvanceau Feb 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 25 additions & 14 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
"react-icons": "^5.5.0",
"react-router-dom": "^7.4.0",
"react-virtualized-auto-sizer": "^2.0.2",
"react-window": "^2.2.5",
"react-virtuoso": "^4.18.1",
"react-window": "^2.2.6",
"web-vitals": "^3.5.0",
"zustand": "^5.0.3"
},
Expand Down
49 changes: 35 additions & 14 deletions src/components/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import {useDarkMode} from "../context/DarkModeContext";
import {ThemeProvider, createTheme} from '@mui/material/styles';
import {prepareForNavigation} from "../eventSourceManager";

import {decodeToken as decodeTokenFromLogin} from "./Login.jsx";

// Lazy load components for code splitting
const NodesTable = lazy(() => import("./NodesTable"));
const Objects = lazy(() => import("./Objects"));
Expand Down Expand Up @@ -92,21 +94,22 @@ const isTokenValid = (token) => {
logger.debug("No token found in localStorage");
return false;
}
try {
const payload = JSON.parse(atob(token.split(".")[1]));
const now = Date.now() / 1000;
const expiration = payload.exp;
const isValid = expiration > now;
logger.debug(`Token validation: expires_at=${expiration}, now=${now}, valid=${isValid}`);
return isValid;
} catch (error) {
logger.error("Error while verifying token:", error);

const payload = decodeTokenFromLogin(token);
if (!payload || !payload.exp) {
return false;
}

const now = Date.now() / 1000;
const expiration = payload.exp;
const isValid = expiration > now;
logger.debug(`Token validation: expires_at=${expiration}, now=${now}, valid=${isValid}`);
return isValid;
};

// Component to handle OIDC initialization
const OidcInitializer = ({children}) => {
const location = useLocation();
const {userManager, recreateUserManager, isInitialized} = useOidc();
const authDispatch = useAuthDispatch();
const auth = useAuth();
Expand Down Expand Up @@ -218,6 +221,11 @@ const OidcInitializer = ({children}) => {
// Handle auth check on resume for OIDC
useEffect(() => {
const handleCheckAuthOnResume = () => {
const authPaths = ['/auth-choice', '/auth/login', '/auth-callback', '/silent-renew'];
if (authPaths.includes(location.pathname)) {
return;
}

try {
const authChoice = localStorage.getItem('authChoice');
const token = localStorage.getItem('authToken');
Expand Down Expand Up @@ -259,25 +267,37 @@ const OidcInitializer = ({children}) => {
};

const visibilityHandler = () => {
if (document.visibilityState === 'visible') handleCheckAuthOnResume();
if (document.visibilityState === 'visible') {
setTimeout(handleCheckAuthOnResume, 500);
}
};

const focusHandler = () => {
setTimeout(handleCheckAuthOnResume, 500);
};

document.addEventListener('visibilitychange', visibilityHandler);
window.addEventListener('focus', handleCheckAuthOnResume);
window.addEventListener('focus', focusHandler);

return () => {
document.removeEventListener('visibilitychange', visibilityHandler);
window.removeEventListener('focus', handleCheckAuthOnResume);
window.removeEventListener('focus', focusHandler);
};
}, [navigate, userManager, onUserRefreshed]);
}, [navigate, userManager, onUserRefreshed, location.pathname]);

return children;
};

const ProtectedRoute = ({children}) => {
const location = useLocation();
const token = localStorage.getItem("authToken");
const authChoice = localStorage.getItem('authChoice');

const authPaths = ['/auth-choice', '/auth/login', '/auth-callback', '/silent-renew'];
if (authPaths.includes(location.pathname)) {
return children;
}

// For OIDC, rely on UserManager to handle expiration
if (authChoice === 'openid') {
if (!token) {
Expand Down Expand Up @@ -327,7 +347,8 @@ const App = () => {
<Suspense fallback={<Loading/>}>
<Routes>
<Route path="/" element={<Navigate to="/cluster" replace/>}/>
<Route path="/cluster" element={<ProtectedRoute><ClusterOverview/></ProtectedRoute>}/>
<Route path="/cluster"
element={<ProtectedRoute><ClusterOverview/></ProtectedRoute>}/>
<Route path="/namespaces" element={<ProtectedRoute><Namespaces/></ProtectedRoute>}/>
<Route path="/heartbeats" element={<Heartbeats/>}/>
<Route path="/nodes" element={<ProtectedRoute><NodesTable/></ProtectedRoute>}/>
Expand Down
Loading