feat: enhance server stats widgets and fix TypeScript/ESLint errors #394

Merged
ZacharyZcR merged 50 commits from feature-server-stats-customization into dev-1.8.0 2025-10-10 03:48:34 +00:00
4 changed files with 27 additions and 74 deletions
Showing only changes of commit 720b7b5972 - Show all commits
@@ -9,21 +9,7 @@ import {
AccordionItem, AccordionItem,
AccordionTrigger, AccordionTrigger,
} from "@/components/ui/accordion"; } from "@/components/ui/accordion";
import { import { Sheet, SheetContent } from "@/components/ui/sheet";
Sheet,
SheetContent,
SheetDescription,
SheetFooter,
SheetHeader,
SheetTitle,
} from "@/components/ui/sheet";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { import {
Tooltip, Tooltip,
TooltipContent, TooltipContent,
@@ -37,7 +23,6 @@ import {
Edit, Edit,
Trash2, Trash2,
Shield, Shield,
Pin,
Tag, Tag,
Info, Info,
FolderMinus, FolderMinus,
@@ -75,9 +60,7 @@ export function CredentialsManager({
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const [searchQuery, setSearchQuery] = useState(""); const [searchQuery, setSearchQuery] = useState("");
const [showViewer, setShowViewer] = useState(false); const [showViewer, setShowViewer] = useState(false);
const [viewingCredential, setViewingCredential] = useState<Credential | null>( const [viewingCredential] = useState<Credential | null>(null);
null,
);
const [draggedCredential, setDraggedCredential] = useState<Credential | null>( const [draggedCredential, setDraggedCredential] = useState<Credential | null>(
null, null,
); );
@@ -153,7 +136,7 @@ export function CredentialsManager({
const data = await getCredentials(); const data = await getCredentials();
setCredentials(data); setCredentials(data);
setError(null); setError(null);
} catch (err) { } catch {
setError(t("credentials.failedToFetchCredentials")); setError(t("credentials.failedToFetchCredentials"));
} finally { } finally {
setLoading(false); setLoading(false);
@@ -256,7 +239,7 @@ export function CredentialsManager({
); );
await fetchCredentials(); await fetchCredentials();
window.dispatchEvent(new CustomEvent("credentials:changed")); window.dispatchEvent(new CustomEvent("credentials:changed"));
} catch (err) { } catch {
toast.error(t("credentials.failedToRemoveFromFolder")); toast.error(t("credentials.failedToRemoveFromFolder"));
} finally { } finally {
setOperationLoading(false); setOperationLoading(false);
@@ -285,7 +268,7 @@ export function CredentialsManager({
window.dispatchEvent(new CustomEvent("credentials:changed")); window.dispatchEvent(new CustomEvent("credentials:changed"));
setEditingFolder(null); setEditingFolder(null);
setEditingFolderName(""); setEditingFolderName("");
} catch (err) { } catch {
toast.error(t("credentials.failedToRenameFolder")); toast.error(t("credentials.failedToRenameFolder"));
} finally { } finally {
setOperationLoading(false); setOperationLoading(false);
@@ -359,7 +342,7 @@ export function CredentialsManager({
); );
await fetchCredentials(); await fetchCredentials();
window.dispatchEvent(new CustomEvent("credentials:changed")); window.dispatchEvent(new CustomEvent("credentials:changed"));
} catch (err) { } catch {
toast.error(t("credentials.failedToMoveToFolder")); toast.error(t("credentials.failedToMoveToFolder"));
} finally { } finally {
setOperationLoading(false); setOperationLoading(false);
@@ -23,8 +23,6 @@ import {
Search, Search,
Grid3X3, Grid3X3,
List, List,
Eye,
Settings,
} from "lucide-react"; } from "lucide-react";
import { TerminalWindow } from "./components/TerminalWindow"; import { TerminalWindow } from "./components/TerminalWindow";
import type { SSHHost, FileItem } from "../../../types/index.js"; import type { SSHHost, FileItem } from "../../../types/index.js";
@@ -87,9 +85,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
const { t } = useTranslation(); const { t } = useTranslation();
const { confirmWithToast } = useConfirmation(); const { confirmWithToast } = useConfirmation();
const [currentHost, setCurrentHost] = useState<SSHHost | null>( const [currentHost] = useState<SSHHost | null>(initialHost || null);
initialHost || null,
);
const [currentPath, setCurrentPath] = useState( const [currentPath, setCurrentPath] = useState(
initialHost?.defaultPath || "/", initialHost?.defaultPath || "/",
); );
@@ -145,10 +141,9 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
const [createIntent, setCreateIntent] = useState<CreateIntent | null>(null); const [createIntent, setCreateIntent] = useState<CreateIntent | null>(null);
const [editingFile, setEditingFile] = useState<FileItem | null>(null); const [editingFile, setEditingFile] = useState<FileItem | null>(null);
const { selectedFiles, selectFile, selectAll, clearSelection, setSelection } = const { selectedFiles, clearSelection, setSelection } = useFileSelection();
useFileSelection();
const { isDragging, dragHandlers } = useDragAndDrop({ const { dragHandlers } = useDragAndDrop({
onFilesDropped: handleFilesDropped, onFilesDropped: handleFilesDropped,
onError: (error) => toast.error(error), onError: (error) => toast.error(error),
maxFileSize: 5120, maxFileSize: 5120,
@@ -784,7 +779,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
} }
}; };
async function handleFileOpen(file: FileItem, editMode: boolean = false) { async function handleFileOpen(file: FileItem) {
if (file.type === "directory") { if (file.type === "directory") {
setCurrentPath(file.path); setCurrentPath(file.path);
} else if (file.type === "link") { } else if (file.type === "link") {
@@ -834,14 +829,6 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
} }
} }
function handleFileEdit(file: FileItem) {
handleFileOpen(file, true);
}
function handleFileView(file: FileItem) {
handleFileOpen(file, false);
}
function handleContextMenu(event: React.MouseEvent, file?: FileItem) { function handleContextMenu(event: React.MouseEvent, file?: FileItem) {
event.preventDefault(); event.preventDefault();
@@ -1351,18 +1338,16 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
} }
if (successCount > 0) { if (successCount > 0) {
const movedFiles = draggedFiles const movedFiles = draggedFiles.slice(0, successCount).map((file) => {
.slice(0, successCount) const targetPath = targetFolder.path.endsWith("/")
.map((file, index) => { ? `${targetFolder.path}${file.name}`
const targetPath = targetFolder.path.endsWith("/") : `${targetFolder.path}/${file.name}`;
? `${targetFolder.path}${file.name}` return {
: `${targetFolder.path}/${file.name}`; originalPath: file.path,
return { targetPath: targetPath,
originalPath: file.path, targetName: file.name,
targetPath: targetPath, };
targetName: file.name, });
};
});
const undoAction: UndoAction = { const undoAction: UndoAction = {
type: "cut", type: "cut",
+4 -11
View File
@@ -80,8 +80,8 @@ export const Terminal = forwardRef<TerminalHandle, SSHTerminalProps>(
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
const [isConnected, setIsConnected] = useState(false); const [isConnected, setIsConnected] = useState(false);
const [isConnecting, setIsConnecting] = useState(false); const [isConnecting, setIsConnecting] = useState(false);
const [connectionError, setConnectionError] = useState<string | null>(null); const [, setConnectionError] = useState<string | null>(null);
const [isAuthenticated, setIsAuthenticated] = useState(false); const [, setIsAuthenticated] = useState(false);
const [totpRequired, setTotpRequired] = useState(false); const [totpRequired, setTotpRequired] = useState(false);
const [totpPrompt, setTotpPrompt] = useState<string>(""); const [totpPrompt, setTotpPrompt] = useState<string>("");
const isVisibleRef = useRef<boolean>(false); const isVisibleRef = useRef<boolean>(false);
@@ -227,13 +227,6 @@ export const Terminal = forwardRef<TerminalHandle, SSHTerminalProps>(
[terminal], [terminal],
); );
function handleWindowResize() {
if (!isVisibleRef.current) return;
fitAddonRef.current?.fit();
if (terminal) scheduleNotify(terminal.cols, terminal.rows);
hardRefresh();
}
function getUseRightClickCopyPaste() { function getUseRightClickCopyPaste() {
return getCookie("rightClickCopyPaste") === "true"; return getCookie("rightClickCopyPaste") === "true";
} }
@@ -490,7 +483,7 @@ export const Terminal = forwardRef<TerminalHandle, SSHTerminalProps>(
setTotpRequired(true); setTotpRequired(true);
setTotpPrompt(msg.prompt || "Verification code:"); setTotpPrompt(msg.prompt || "Verification code:");
} }
} catch (error) { } catch {
toast.error(t("terminal.messageParseError")); toast.error(t("terminal.messageParseError"));
} }
}); });
@@ -526,7 +519,7 @@ export const Terminal = forwardRef<TerminalHandle, SSHTerminalProps>(
} }
}); });
ws.addEventListener("error", (event) => { ws.addEventListener("error", () => {
setIsConnected(false); setIsConnected(false);
isConnectingRef.current = false; isConnectingRef.current = false;
setConnectionError(t("terminal.websocketError")); setConnectionError(t("terminal.websocketError"));
+3 -11
View File
@@ -12,7 +12,6 @@ import { Unicode11Addon } from "@xterm/addon-unicode11";
import { WebLinksAddon } from "@xterm/addon-web-links"; import { WebLinksAddon } from "@xterm/addon-web-links";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { isElectron, getCookie } from "@/ui/main-axios.ts"; import { isElectron, getCookie } from "@/ui/main-axios.ts";
import { toast } from "sonner";
interface HostConfig { interface HostConfig {
id?: number; id?: number;
@@ -52,9 +51,9 @@ export const Terminal = forwardRef<TerminalHandle, SSHTerminalProps>(
const wasDisconnectedBySSH = useRef(false); const wasDisconnectedBySSH = useRef(false);
const pingIntervalRef = useRef<NodeJS.Timeout | null>(null); const pingIntervalRef = useRef<NodeJS.Timeout | null>(null);
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
const [isConnected, setIsConnected] = useState(false); const [, setIsConnected] = useState(false);
const [isConnecting, setIsConnecting] = useState(false); const [, setIsConnecting] = useState(false);
const [connectionError, setConnectionError] = useState<string | null>(null); const [, setConnectionError] = useState<string | null>(null);
const [isAuthenticated, setIsAuthenticated] = useState(false); const [isAuthenticated, setIsAuthenticated] = useState(false);
const isVisibleRef = useRef<boolean>(false); const isVisibleRef = useRef<boolean>(false);
const isConnectingRef = useRef(false); const isConnectingRef = useRef(false);
@@ -160,13 +159,6 @@ export const Terminal = forwardRef<TerminalHandle, SSHTerminalProps>(
[terminal], [terminal],
); );
function handleWindowResize() {
if (!isVisibleRef.current) return;
fitAddonRef.current?.fit();
if (terminal) scheduleNotify(terminal.cols, terminal.rows);
hardRefresh();
}
function setupWebSocketListeners( function setupWebSocketListeners(
ws: WebSocket, ws: WebSocket,
cols: number, cols: number,