fix: resolve widget deletion and layout persistence issues
- Add drag handles to widget title bars for precise drag control - Prevent delete button from triggering drag via event stopPropagation - Include statsConfig field in all GET/PUT API responses - Remove debug console logs from production code 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -524,6 +524,7 @@ router.put(
|
|||||||
? JSON.parse(updatedHost.tunnelConnections)
|
? JSON.parse(updatedHost.tunnelConnections)
|
||||||
: [],
|
: [],
|
||||||
enableFileManager: !!updatedHost.enableFileManager,
|
enableFileManager: !!updatedHost.enableFileManager,
|
||||||
|
statsConfig: updatedHost.statsConfig || undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
const resolvedHost = (await resolveHostCredentials(baseHost)) || baseHost;
|
const resolvedHost = (await resolveHostCredentials(baseHost)) || baseHost;
|
||||||
@@ -592,6 +593,7 @@ router.get("/db/host", authenticateJWT, async (req: Request, res: Response) => {
|
|||||||
? JSON.parse(row.tunnelConnections)
|
? JSON.parse(row.tunnelConnections)
|
||||||
: [],
|
: [],
|
||||||
enableFileManager: !!row.enableFileManager,
|
enableFileManager: !!row.enableFileManager,
|
||||||
|
statsConfig: row.statsConfig || undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
return (await resolveHostCredentials(baseHost)) || baseHost;
|
return (await resolveHostCredentials(baseHost)) || baseHost;
|
||||||
@@ -656,6 +658,7 @@ router.get(
|
|||||||
? JSON.parse(host.tunnelConnections)
|
? JSON.parse(host.tunnelConnections)
|
||||||
: [],
|
: [],
|
||||||
enableFileManager: !!host.enableFileManager,
|
enableFileManager: !!host.enableFileManager,
|
||||||
|
statsConfig: host.statsConfig || undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
res.json((await resolveHostCredentials(result)) || result);
|
res.json((await resolveHostCredentials(result)) || result);
|
||||||
|
|||||||
@@ -67,11 +67,7 @@ export function Server({
|
|||||||
const [hasUnsavedChanges, setHasUnsavedChanges] = React.useState(false);
|
const [hasUnsavedChanges, setHasUnsavedChanges] = React.useState(false);
|
||||||
|
|
||||||
const statsConfig = React.useMemo((): StatsConfig => {
|
const statsConfig = React.useMemo((): StatsConfig => {
|
||||||
console.log("[Load] Current host config:", currentHostConfig);
|
|
||||||
console.log("[Load] statsConfig field:", currentHostConfig?.statsConfig);
|
|
||||||
|
|
||||||
if (!currentHostConfig?.statsConfig) {
|
if (!currentHostConfig?.statsConfig) {
|
||||||
console.log("[Load] No statsConfig found, using default");
|
|
||||||
return DEFAULT_STATS_CONFIG;
|
return DEFAULT_STATS_CONFIG;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@@ -79,10 +75,9 @@ export function Server({
|
|||||||
typeof currentHostConfig.statsConfig === "string"
|
typeof currentHostConfig.statsConfig === "string"
|
||||||
? JSON.parse(currentHostConfig.statsConfig)
|
? JSON.parse(currentHostConfig.statsConfig)
|
||||||
: currentHostConfig.statsConfig;
|
: currentHostConfig.statsConfig;
|
||||||
console.log("[Load] Parsed statsConfig:", parsed);
|
|
||||||
return parsed?.widgets ? parsed : DEFAULT_STATS_CONFIG;
|
return parsed?.widgets ? parsed : DEFAULT_STATS_CONFIG;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("[Load] Failed to parse statsConfig:", error);
|
console.error("Failed to parse statsConfig:", error);
|
||||||
return DEFAULT_STATS_CONFIG;
|
return DEFAULT_STATS_CONFIG;
|
||||||
}
|
}
|
||||||
}, [currentHostConfig?.statsConfig]);
|
}, [currentHostConfig?.statsConfig]);
|
||||||
@@ -134,20 +129,18 @@ export function Server({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const newConfig: StatsConfig = { widgets };
|
const newConfig: StatsConfig = { widgets };
|
||||||
console.log("[Save] Saving layout:", newConfig);
|
|
||||||
const { updateSSHHost } = await import("@/ui/main-axios.ts");
|
const { updateSSHHost } = await import("@/ui/main-axios.ts");
|
||||||
|
|
||||||
const result = await updateSSHHost(currentHostConfig.id, {
|
await updateSSHHost(currentHostConfig.id, {
|
||||||
...currentHostConfig,
|
...currentHostConfig,
|
||||||
statsConfig: JSON.stringify(newConfig),
|
statsConfig: JSON.stringify(newConfig),
|
||||||
} as any);
|
} as any);
|
||||||
|
|
||||||
console.log("[Save] Server response:", result);
|
|
||||||
setHasUnsavedChanges(false);
|
setHasUnsavedChanges(false);
|
||||||
toast.success(t("serverStats.layoutSaved"));
|
toast.success(t("serverStats.layoutSaved"));
|
||||||
window.dispatchEvent(new Event("ssh-hosts:changed"));
|
window.dispatchEvent(new Event("ssh-hosts:changed"));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("[Save] Failed to save layout:", error);
|
console.error("Failed to save layout:", error);
|
||||||
toast.error(t("serverStats.failedToSaveLayout"));
|
toast.error(t("serverStats.failedToSaveLayout"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user