mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-11 19:26:56 +00:00
fix: dashboard cards and stacks list do not update on remote node switch
- HomeDashboard: both polling useEffects now depend on activeNode?.id so intervals restart and stale local-node data is cleared immediately on node switch; added res.ok guard before calling res.json() to prevent error objects being written into stats/systemStats state - EditorLayout: refreshStacks now guards res.ok before parsing the JSON body and iterates a typed fileList instead of the raw response value, preventing SyntaxError/TypeError when proxy returns a non-JSON response for an unreachable remote node
This commit is contained in:
@@ -123,12 +123,17 @@ export default function EditorLayout() {
|
||||
if (!background) setIsLoading(true);
|
||||
try {
|
||||
const res = await apiFetch('/stacks');
|
||||
const stacks = await res.json();
|
||||
setFiles(Array.isArray(stacks) ? stacks : []);
|
||||
if (!res.ok) {
|
||||
setFiles([]);
|
||||
return;
|
||||
}
|
||||
const data = await res.json();
|
||||
const fileList: string[] = Array.isArray(data) ? data : [];
|
||||
setFiles(fileList);
|
||||
|
||||
// Fetch status for each stack
|
||||
const statuses: StackStatus = {};
|
||||
for (const file of stacks) {
|
||||
for (const file of fileList) {
|
||||
try {
|
||||
const containersRes = await apiFetch(`/stacks/${file}/containers`);
|
||||
const containers = await containersRes.json();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useState, useEffect, useMemo } from 'react';
|
||||
import { useNodes } from '@/context/NodeContext';
|
||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from './ui/card';
|
||||
import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from 'recharts';
|
||||
import { ChartContainer, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart';
|
||||
@@ -53,6 +54,7 @@ const formatBytes = (bytes: number) => {
|
||||
};
|
||||
|
||||
export default function HomeDashboard() {
|
||||
const { activeNode } = useNodes();
|
||||
const [dockerRunInput, setDockerRunInput] = useState('');
|
||||
const [isConverting, setIsConverting] = useState(false);
|
||||
const [convertedYaml, setConvertedYaml] = useState('');
|
||||
@@ -62,11 +64,13 @@ export default function HomeDashboard() {
|
||||
const [systemStats, setSystemStats] = useState<SystemStats | null>(null);
|
||||
const [metrics, setMetrics] = useState<any[]>([]);
|
||||
|
||||
// Fetch stats from backend
|
||||
// Fetch container stats - re-runs when active node changes so stale data is cleared immediately
|
||||
useEffect(() => {
|
||||
setStats({ active: 0, exited: 0, total: 0, inactive: 0 });
|
||||
const fetchStats = async () => {
|
||||
try {
|
||||
const res = await apiFetch('/stats');
|
||||
if (!res.ok) return;
|
||||
const data = await res.json();
|
||||
setStats(data);
|
||||
} catch (error) {
|
||||
@@ -76,10 +80,12 @@ export default function HomeDashboard() {
|
||||
fetchStats();
|
||||
const interval = setInterval(fetchStats, 5000);
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
}, [activeNode?.id]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
// Fetch system stats from backend
|
||||
// Fetch system stats and historical metrics - re-runs when active node changes
|
||||
useEffect(() => {
|
||||
setSystemStats(null);
|
||||
setMetrics([]);
|
||||
const fetchSystemStats = async () => {
|
||||
try {
|
||||
const [sysRes, metricsRes] = await Promise.all([
|
||||
@@ -95,7 +101,7 @@ export default function HomeDashboard() {
|
||||
fetchSystemStats();
|
||||
const interval = setInterval(fetchSystemStats, 5000);
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
}, [activeNode?.id]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
const chartData = useMemo(() => {
|
||||
const buckets: Record<string, { time: string; timestamp: number; cpu: number; ram: number }> = {};
|
||||
|
||||
Reference in New Issue
Block a user