feat: Improve dashboard API, improve tab system, various other fixes

This commit is contained in:
LukeGus
2025-10-18 15:15:45 -05:00
parent a44e2be8a4
commit eda60ae3b6
14 changed files with 502 additions and 292 deletions

View File

@@ -78,7 +78,7 @@ export function Dashboard({
Array<{ id: number; name: string; cpu: number | null; ram: number | null }>
>([]);
const { addTab } = useTabs();
const { addTab, setCurrentTab, tabs: tabList } = useTabs();
let sidebarState: "expanded" | "collapsed" = "expanded";
try {
@@ -160,14 +160,27 @@ export function Dashboard({
const hosts = await getSSHHosts();
setTotalServers(hosts.length);
const tunnels = await getTunnelStatuses();
setTotalTunnels(Object.keys(tunnels).length);
// Count total tunnels across all hosts
let totalTunnelsCount = 0;
for (const host of hosts) {
if (host.tunnelConnections) {
try {
const tunnelConnections = JSON.parse(host.tunnelConnections);
if (Array.isArray(tunnelConnections)) {
totalTunnelsCount += tunnelConnections.length;
}
} catch {
// Ignore parse errors
}
}
}
setTotalTunnels(totalTunnelsCount);
const credentials = await getCredentials();
setTotalCredentials(credentials.length);
// Fetch recent activity
const activity = await getRecentActivity(10);
// Fetch recent activity (35 items)
const activity = await getRecentActivity(35);
setRecentActivity(activity);
// Fetch server stats for first 5 servers
@@ -237,6 +250,55 @@ export function Dashboard({
});
};
// Quick Actions handlers
const handleAddHost = () => {
const sshManagerTab = tabList.find((t) => t.type === "ssh_manager");
if (sshManagerTab) {
setCurrentTab(sshManagerTab.id);
} else {
const id = addTab({
type: "ssh_manager",
title: "Host Manager",
initialTab: "add_host",
});
setCurrentTab(id);
}
};
const handleAddCredential = () => {
const sshManagerTab = tabList.find((t) => t.type === "ssh_manager");
if (sshManagerTab) {
setCurrentTab(sshManagerTab.id);
} else {
const id = addTab({
type: "ssh_manager",
title: "Host Manager",
initialTab: "add_credential",
});
setCurrentTab(id);
}
};
const handleOpenAdminSettings = () => {
const adminTab = tabList.find((t) => t.type === "admin");
if (adminTab) {
setCurrentTab(adminTab.id);
} else {
const id = addTab({ type: "admin", title: "Admin Settings" });
setCurrentTab(id);
}
};
const handleOpenUserProfile = () => {
const userProfileTab = tabList.find((t) => t.type === "user_profile");
if (userProfileTab) {
setCurrentTab(userProfileTab.id);
} else {
const id = addTab({ type: "user_profile", title: "User Profile" });
setCurrentTab(id);
}
};
return (
<>
{!loggedIn ? (
@@ -486,7 +548,7 @@ export function Dashboard({
<Button
variant="outline"
className="border-2 !border-dark-border flex flex-col items-center justify-center h-auto p-3"
onClick={() => onSelectView("host-manager-add")}
onClick={handleAddHost}
>
<Server
className="shrink-0"
@@ -499,7 +561,7 @@ export function Dashboard({
<Button
variant="outline"
className="border-2 !border-dark-border flex flex-col items-center justify-center h-auto p-3"
onClick={() => onSelectView("host-manager-credentials")}
onClick={handleAddCredential}
>
<Key
className="shrink-0"
@@ -513,7 +575,7 @@ export function Dashboard({
<Button
variant="outline"
className="border-2 !border-dark-border flex flex-col items-center justify-center h-auto p-3"
onClick={() => onSelectView("admin-settings")}
onClick={handleOpenAdminSettings}
>
<Settings
className="shrink-0"
@@ -527,7 +589,7 @@ export function Dashboard({
<Button
variant="outline"
className="border-2 !border-dark-border flex flex-col items-center justify-center h-auto p-3"
onClick={() => onSelectView("user-profile")}
onClick={handleOpenUserProfile}
>
<User
className="shrink-0"

View File

@@ -47,6 +47,7 @@ import {
removeRecentFile,
addFolderShortcut,
getPinnedFiles,
logActivity,
} from "@/ui/main-axios.ts";
import type { SidebarItem } from "./FileManagerSidebar";
@@ -298,6 +299,15 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
setSshSessionId(sessionId);
// Log activity for recent connections
if (currentHost?.id) {
const hostName =
currentHost.name || `${currentHost.username}@${currentHost.ip}`;
logActivity("file_manager", currentHost.id, hostName).catch((err) => {
console.warn("Failed to log file manager activity:", err);
});
}
try {
const response = await listSSHFiles(sessionId, currentPath);
const files = Array.isArray(response)
@@ -1247,6 +1257,15 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
setSshSessionId(totpSessionId);
setTotpSessionId(null);
// Log activity for recent connections
if (currentHost?.id) {
const hostName =
currentHost.name || `${currentHost.username}@${currentHost.ip}`;
logActivity("file_manager", currentHost.id, hostName).catch((err) => {
console.warn("Failed to log file manager activity:", err);
});
}
try {
const response = await listSSHFiles(totpSessionId, currentPath);
const files = Array.isArray(response)

View File

@@ -16,9 +16,10 @@ import type { SSHHost, HostManagerProps } from "../../../types/index";
export function HostManager({
isTopbarOpen,
initialTab = "host_viewer",
}: HostManagerProps): React.ReactElement {
const { t } = useTranslation();
const [activeTab, setActiveTab] = useState("host_viewer");
const [activeTab, setActiveTab] = useState(initialTab);
const [editingHost, setEditingHost] = useState<SSHHost | null>(null);
const [editingCredential, setEditingCredential] = useState<{

View File

@@ -12,7 +12,7 @@ import { Unicode11Addon } from "@xterm/addon-unicode11";
import { WebLinksAddon } from "@xterm/addon-web-links";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
import { getCookie, isElectron } from "@/ui/main-axios.ts";
import { getCookie, isElectron, logActivity } from "@/ui/main-axios.ts";
import { TOTPDialog } from "@/ui/components/TOTPDialog";
interface HostConfig {
@@ -469,6 +469,15 @@ export const Terminal = forwardRef<TerminalHandle, SSHTerminalProps>(
}
reconnectAttempts.current = 0;
isReconnectingRef.current = false;
// Log activity for recent connections
if (hostConfig.id) {
const hostName =
hostConfig.name || `${hostConfig.username}@${hostConfig.ip}`;
logActivity("terminal", hostConfig.id, hostName).catch((err) => {
console.warn("Failed to log terminal activity:", err);
});
}
} else if (msg.type === "disconnected") {
wasDisconnectedBySSH.current = true;
setIsConnected(false);