Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
0349c92
fix(Objects): maintain fixed column spacing regardless of row count
PaulJouvanceau Feb 10, 2026
39b7d9c
feat: Add key management enhancements to KeysSection
PaulJouvanceau Feb 12, 2026
6f7429e
feat(cluster): remove unfrozen count from nodes grid and harmonize ch…
PaulJouvanceau Feb 12, 2026
aeb8f8c
feat(heartbeat): Enhance heartbeat display and filtering with base ID…
PaulJouvanceau Feb 17, 2026
687f795
Replace storage-pools by pools on NavBar
PaulJouvanceau Feb 17, 2026
e543720
feat(cluster): Add pool chips to Pools grid similar to Networks grid
PaulJouvanceau Feb 17, 2026
78cd30a
refactor(WhoAmI): reorganize layout to optimize space and improve res…
PaulJouvanceau Feb 17, 2026
7134652
feat: Remove grey status dots from Namespaces grid
PaulJouvanceau Feb 17, 2026
b250384
feat: Add Kinds page and grid component with comprehensive test coverage
PaulJouvanceau Feb 17, 2026
7d8112f
test: complete rewrite of ClusterStatGrids test suite to ConfigSectio…
PaulJouvanceau Feb 17, 2026
586855a
Improve test coverage for KeysSection
PaulJouvanceau Feb 17, 2026
6b34ec3
Improve test coverage for Heartbeats
PaulJouvanceau Feb 19, 2026
dc33f20
feat: Implement responsive filter toggling and fix test suite
PaulJouvanceau Feb 19, 2026
2d005c8
Optimize ObjectDetails and test file for better coverage
PaulJouvanceau Feb 19, 2026
cd79ed9
refactor: Remove "showing X of Y" text from table components
PaulJouvanceau Feb 19, 2026
61ab3c9
fix(Objects): Replace text-based delete icons with Material-UI CloseI…
PaulJouvanceau Feb 19, 2026
cd87979
fix: make entire filter menu items clickable for multi-select filters
PaulJouvanceau Feb 19, 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
5 changes: 4 additions & 1 deletion src/components/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const ObjectDetails = lazy(() => import("./ObjectDetails"));
const ObjectInstanceView = lazy(() => import("./ObjectInstanceView"));
const ClusterOverview = lazy(() => import("./Cluster"));
const Namespaces = lazy(() => import("./Namespaces"));
const Kinds = lazy(() => import("./Kinds"));
const Heartbeats = lazy(() => import("./Heartbeats"));
const Pools = lazy(() => import("./Pools"));
const Network = lazy(() => import("./Network"));
Expand Down Expand Up @@ -350,9 +351,11 @@ const App = () => {
<Route path="/cluster"
element={<ProtectedRoute><ClusterOverview/></ProtectedRoute>}/>
<Route path="/namespaces" element={<ProtectedRoute><Namespaces/></ProtectedRoute>}/>
<Route path="/kinds"
element={<ProtectedRoute><Kinds/></ProtectedRoute>}/> {/* <-- AJOUT */}
<Route path="/heartbeats" element={<Heartbeats/>}/>
<Route path="/nodes" element={<ProtectedRoute><NodesTable/></ProtectedRoute>}/>
<Route path="/storage-pools" element={<ProtectedRoute><Pools/></ProtectedRoute>}/>
<Route path="/pools" element={<ProtectedRoute><Pools/></ProtectedRoute>}/>
<Route path="/network" element={<ProtectedRoute><Network/></ProtectedRoute>}/>
<Route path="/network/:networkName"
element={<ProtectedRoute><NetworkDetails/></ProtectedRoute>}/>
Expand Down
59 changes: 32 additions & 27 deletions src/components/Cluster.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,14 @@ import {
GridNamespaces,
GridHeartbeats,
GridPools,
GridNetworks
} from "./ClusterStatGrids.jsx";
GridNetworks,
GridKinds
} from "../components/ClusterStatGrids.jsx";
import {URL_POOL, URL_NETWORK} from "../config/apiPath.js";
import {startEventReception, DEFAULT_FILTERS} from "../eventSourceManager";
import EventLogger from "../components/EventLogger";
import {useNodeStats, useObjectStats, useHeartbeatStats} from "../hooks/useClusterData";

const CLUSTER_EVENT_TYPES = [
"NodeStatusUpdated",
"NodeMonitorUpdated",
"NodeStatsUpdated",
"DaemonHeartbeatUpdated",
"ObjectStatusUpdated",
"InstanceStatusUpdated",
"ObjectDeleted",
"InstanceMonitorUpdated",
"CONNECTION_OPENED",
"CONNECTION_ERROR",
"RECONNECTION_ATTEMPT",
"MAX_RECONNECTIONS_REACHED",
"CONNECTION_CLOSED"
];
import {useKindData} from "../hooks/useKindData";

const InitialLoader = memo(() => (
<Box sx={{
Expand All @@ -54,11 +40,13 @@ const ClusterOverview = () => {
const nodeStats = useNodeStats();
const objectStats = useObjectStats();
const heartbeatStats = useHeartbeatStats();
const {statusByKind, kinds} = useKindData();

const deferredNodeStats = useDeferredValue(nodeStats);
const deferredObjectStats = useDeferredValue(objectStats);
const deferredHeartbeatStats = useDeferredValue(heartbeatStats);

const [pools, setPools] = useState([]);
const [poolCount, setPoolCount] = useState(0);
const [networks, setNetworks] = useState([]);
const [isLoading, setIsLoading] = useState(true);
Expand All @@ -71,10 +59,11 @@ const ClusterOverview = () => {
navigate(globalState ? `/objects?globalState=${globalState}` : '/objects');
}, [navigate]);

const handleHeartbeatsClick = useCallback((status, state) => {
const handleHeartbeatsClick = useCallback((status, state, id) => {
const params = new URLSearchParams();
if (status) params.append('status', status);
if (state) params.append('state', state);
if (id) params.append('id', id);
navigate(`/heartbeats${params.toString() ? `?${params.toString()}` : ''}`);
}, [navigate]);

Expand Down Expand Up @@ -105,13 +94,15 @@ const ClusterOverview = () => {
const poolItems = poolsRes.data?.items || [];
const networkItems = networksRes.data?.items || [];

setPools(poolItems);
setPoolCount(poolItems.length);
setNetworks(networkItems);
setIsLoading(false);
} catch (error) {
if (!isMounted.current || error.name === 'AbortError') return;

logger.error('Failed to fetch cluster data:', error.message);
setPools([]);
setPoolCount(0);
setNetworks([]);
setIsLoading(false);
Expand All @@ -138,9 +129,8 @@ const ClusterOverview = () => {
const gridNodesProps = useMemo(() => ({
nodeCount: deferredNodeStats.count,
frozenCount: deferredNodeStats.frozen,
unfrozenCount: deferredNodeStats.unfrozen,
onClick: handleNavigate("/nodes")
}), [deferredNodeStats.count, deferredNodeStats.frozen, deferredNodeStats.unfrozen, handleNavigate]);
}), [deferredNodeStats.count, deferredNodeStats.frozen, handleNavigate]);

const gridObjectsProps = useMemo(() => ({
objectCount: deferredObjectStats.objectCount,
Expand All @@ -150,9 +140,8 @@ const ClusterOverview = () => {

const gridHeartbeatsProps = useMemo(() => ({
heartbeatCount: deferredHeartbeatStats.count,
beatingCount: deferredHeartbeatStats.beating,
nonBeatingCount: deferredHeartbeatStats.stale,
stateCount: deferredHeartbeatStats.stateCount,
runningCount: deferredHeartbeatStats.running,
perHeartbeatStats: deferredHeartbeatStats.perHeartbeatStats,
nodeCount: deferredNodeStats.count,
onClick: handleHeartbeatsClick
}), [deferredHeartbeatStats, deferredNodeStats.count, handleHeartbeatsClick]);
Expand All @@ -163,10 +152,24 @@ const ClusterOverview = () => {
onClick: (url) => navigate(url || "/namespaces")
}), [deferredObjectStats.namespaceCount, deferredObjectStats.namespaceSubtitle, navigate]);

const kindSubtitle = useMemo(() => {
return kinds.map(kind => ({
kind,
status: statusByKind[kind]
}));
}, [kinds, statusByKind]);

const gridKindsProps = useMemo(() => ({
kindCount: kinds.length,
kindSubtitle,
onClick: (url) => navigate(url || "/kinds")
}), [kinds.length, kindSubtitle, navigate]);

const gridPoolsProps = useMemo(() => ({
poolCount,
onClick: handleNavigate("/storage-pools")
}), [poolCount, handleNavigate]);
pools,
onClick: handleNavigate("/pools")
}), [poolCount, pools, handleNavigate]);

const gridNetworksProps = useMemo(() => ({
networks,
Expand Down Expand Up @@ -245,8 +248,10 @@ const ClusterOverview = () => {
</Box>
</Box>

<Box sx={{flex: 1}}>
{/* Colonne de droite : Namespaces et Kinds l'un en dessous de l'autre */}
<Box sx={{flex: 1, display: 'flex', flexDirection: 'column', gap: 3}}>
<GridNamespaces {...gridNamespacesProps} />
<GridKinds {...gridKindsProps} />
</Box>
</Box>
{/* <EventLogger eventTypes={CLUSTER_EVENT_TYPES} title="Cluster Events Logger" buttonLabel="Cluster Events"/> */}
Expand Down
Loading