Initial UI commit for 1.3

This commit is contained in:
LukeGus
2025-08-14 01:24:05 -05:00
parent 96864dbeb4
commit 81d1db09e4
33 changed files with 196 additions and 272 deletions

2
.env
View File

@@ -1 +1 @@
VERSION=1.1.1
VERSION=1.3

View File

@@ -1,14 +1,64 @@
import React from "react"
import React, { useState, useEffect } from "react"
import { Sidebar } from "@/ui/Navigation/Sidebar.tsx"
import { Homepage } from "@/ui/Homepage/Homepage.tsx"
import { Terminal } from "@/ui/SSH/Terminal/Terminal.tsx"
import { SSHTunnel } from "@/ui/SSH/Tunnel/SSHTunnel.tsx"
import { ConfigEditor } from "@/ui/SSH/Config Editor/ConfigEditor.tsx"
import { SSHManager } from "@/ui/SSH/Manager/SSHManager.tsx"
import axios from "axios"
import {Homepage} from "@/apps/Homepage/Homepage.tsx"
import {Terminal} from "@/apps/SSH/Terminal/Terminal.tsx"
import {SSHTunnel} from "@/apps/SSH/Tunnel/SSHTunnel.tsx";
import {ConfigEditor} from "@/apps/SSH/Config Editor/ConfigEditor.tsx";
import {SSHManager} from "@/apps/SSH/Manager/SSHManager.tsx"
const apiBase = import.meta.env.DEV ? "http://localhost:8081/users" : "/users";
const API = axios.create({ baseURL: apiBase });
function getCookie(name: string) {
return document.cookie.split('; ').reduce((r, v) => {
const parts = v.split('=');
return parts[0] === name ? decodeURIComponent(parts[1]) : r;
}, "");
}
function App() {
const [view, setView] = React.useState<string>("homepage")
const [mountedViews, setMountedViews] = React.useState<Set<string>>(new Set(["homepage"]))
const [isAuthenticated, setIsAuthenticated] = useState(false)
const [username, setUsername] = useState<string | null>(null)
const [isAdmin, setIsAdmin] = useState(false)
const [authLoading, setAuthLoading] = useState(true)
useEffect(() => {
const checkAuth = () => {
const jwt = getCookie("jwt");
if (jwt) {
setAuthLoading(true);
API.get("/me", {headers: {Authorization: `Bearer ${jwt}`}})
.then((meRes) => {
setIsAuthenticated(true);
setIsAdmin(!!meRes.data.is_admin);
setUsername(meRes.data.username || null);
})
.catch((err) => {
setIsAuthenticated(false);
setIsAdmin(false);
setUsername(null);
// Clear invalid JWT
document.cookie = 'jwt=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
})
.finally(() => setAuthLoading(false));
} else {
setIsAuthenticated(false);
setIsAdmin(false);
setUsername(null);
setAuthLoading(false);
}
}
checkAuth()
const handleStorageChange = () => checkAuth()
window.addEventListener('storage', handleStorageChange)
return () => window.removeEventListener('storage', handleStorageChange)
}, [])
const handleSelectView = (nextView: string) => {
setMountedViews((prev) => {
@@ -21,8 +71,12 @@ function App() {
}
return (
<div className="flex min-h-svh w-full">
<main className="flex-1 w-full">
<Sidebar
onSelectView={handleSelectView}
disabled={!isAuthenticated || authLoading}
isAdmin={isAdmin}
username={username}
>
{mountedViews.has("homepage") && (
<div style={{display: view === "homepage" ? "block" : "none"}}>
<Homepage onSelectView={handleSelectView} />
@@ -48,8 +102,7 @@ function App() {
<ConfigEditor onSelectView={handleSelectView} />
</div>
)}
</main>
</div>
</Sidebar>
)
}

View File

@@ -1,59 +0,0 @@
import React from 'react';
import {
CornerDownLeft
} from "lucide-react"
import {
Button
} from "@/components/ui/button.tsx"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuItem, SidebarProvider,
} from "@/components/ui/sidebar.tsx"
import {
Separator,
} from "@/components/ui/separator.tsx"
interface SidebarProps {
onSelectView: (view: string) => void;
}
export function SSHManagerSidebar({onSelectView}: SidebarProps): React.ReactElement {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel className="text-lg font-bold text-white flex items-center gap-2">
Termix / SSH Manager
</SidebarGroupLabel>
<Separator className="p-0.25 mt-1 mb-1"/>
<SidebarGroupContent className="flex flex-col flex-grow">
<SidebarMenu>
{/* Sidebar Items */}
<SidebarMenuItem key={"Homepage"}>
<Button className="w-full mt-2 mb-2 h-8" onClick={() => onSelectView("homepage")}
variant="outline">
<CornerDownLeft/>
Return
</Button>
<Separator className="p-0.25 mt-1 mb-1"/>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}

View File

@@ -1,18 +0,0 @@
import React from "react";
import {TemplateSidebar} from "@/apps/Template/TemplateSidebar.tsx";
interface ConfigEditorProps {
onSelectView: (view: string) => void;
}
export function Template({onSelectView}: ConfigEditorProps): React.ReactElement {
return (
<div>
<TemplateSidebar
onSelectView={onSelectView}
/>
Template
</div>
)
}

View File

@@ -1,58 +0,0 @@
import React from 'react';
import {
CornerDownLeft
} from "lucide-react"
import {
Button
} from "@/components/ui/button.tsx"
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuItem, SidebarProvider,
} from "@/components/ui/sidebar.tsx"
import {
Separator,
} from "@/components/ui/separator.tsx"
interface SidebarProps {
onSelectView: (view: string) => void;
}
export function TemplateSidebar({onSelectView}: SidebarProps): React.ReactElement {
return (
<SidebarProvider>
<Sidebar>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel className="text-lg font-bold text-white flex items-center gap-2">
Termix / Template
</SidebarGroupLabel>
<Separator className="p-0.25 mt-1 mb-1"/>
<SidebarGroupContent className="flex flex-col flex-grow">
<SidebarMenu>
<SidebarMenuItem key={"Homepage"}>
<Button className="w-full mt-2 mb-2 h-8" onClick={() => onSelectView("homepage")}
variant="outline">
<CornerDownLeft/>
Return
</Button>
<Separator className="p-0.25 mt-1 mb-1"/>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
</SidebarProvider>
)
}

View File

@@ -234,7 +234,7 @@ function Sidebar({
// Adjust the padding for floating and inset variants.
variant === "floating" || variant === "inset"
? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]"
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l",
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon)",
className
)}
{...props}
@@ -242,7 +242,7 @@ function Sidebar({
<div
data-sidebar="sidebar"
data-slot="sidebar-inner"
className="bg-sidebar group-data-[variant=floating]:border-sidebar-border flex h-full w-full flex-col group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow-sm"
className="bg-sidebar flex h-full w-full flex-col group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow-sm"
>
{children}
</div>

View File

@@ -1,9 +1,8 @@
import {HomepageSidebar} from "@/apps/Homepage/HomepageSidebar.tsx";
import React, {useEffect, useState} from "react";
import {HomepageAuth} from "@/apps/Homepage/HomepageAuth.tsx";
import {HomepageAuth} from "@/ui/Homepage/HomepageAuth.tsx";
import axios from "axios";
import {HomepageUpdateLog} from "@/apps/Homepage/HompageUpdateLog.tsx";
import {AlertManager} from "@/apps/Homepage/AlertManager.tsx";
import {HomepageUpdateLog} from "@/ui/Homepage/HompageUpdateLog.tsx";
import {HomepageAlertManager} from "@/ui/Homepage/HomepageAlertManager.tsx";
interface HomepageProps {
onSelectView: (view: string) => void;
@@ -70,12 +69,6 @@ export function Homepage({onSelectView}: HomepageProps): React.ReactElement {
}, []);
return (
<HomepageSidebar
onSelectView={onSelectView}
disabled={!loggedIn || authLoading}
isAdmin={isAdmin}
username={loggedIn ? username : null}
>
<div className="w-full min-h-svh grid place-items-center">
<div className="flex flex-row items-center justify-center gap-8">
<HomepageAuth
@@ -93,12 +86,10 @@ export function Homepage({onSelectView}: HomepageProps): React.ReactElement {
/>
</div>
{/* Alert Manager - replaces the old welcome card */}
<AlertManager
<HomepageAlertManager
userId={userId}
loggedIn={loggedIn}
/>
</div>
</HomepageSidebar>
);
}

View File

@@ -1,7 +1,7 @@
import React from "react";
import {Card, CardContent, CardFooter, CardHeader, CardTitle} from "@/components/ui/card";
import {Button} from "@/components/ui/button";
import {Badge} from "@/components/ui/badge";
import {Card, CardContent, CardFooter, CardHeader, CardTitle} from "@/components/ui/card.tsx";
import {Button} from "@/components/ui/button.tsx";
import {Badge} from "@/components/ui/badge.tsx";
import {X, ExternalLink, AlertTriangle, Info, CheckCircle, AlertCircle} from "lucide-react";
interface TermixAlert {
@@ -63,7 +63,7 @@ const getTypeBadgeVariant = (type?: string) => {
}
};
export function AlertCard({alert, onDismiss, onClose}: AlertCardProps): React.ReactElement {
export function HomepageAlertCard({alert, onDismiss, onClose}: AlertCardProps): React.ReactElement {
if (!alert) {
return null;
}

View File

@@ -1,6 +1,6 @@
import React, {useEffect, useState} from "react";
import {AlertCard} from "./AlertCard";
import {Button} from "@/components/ui/button";
import {HomepageAlertCard} from "./HomepageAlertCard.tsx";
import {Button} from "@/components/ui/button.tsx";
import axios from "axios";
interface TermixAlert {
@@ -25,7 +25,7 @@ const API = axios.create({
baseURL: apiBase,
});
export function AlertManager({userId, loggedIn}: AlertManagerProps): React.ReactElement {
export function HomepageAlertManager({userId, loggedIn}: AlertManagerProps): React.ReactElement {
const [alerts, setAlerts] = useState<TermixAlert[]>([]);
const [currentAlertIndex, setCurrentAlertIndex] = useState(0);
const [loading, setLoading] = useState(false);
@@ -154,14 +154,12 @@ export function AlertManager({userId, loggedIn}: AlertManagerProps): React.React
return (
<div className="fixed inset-0 flex items-center justify-center bg-background/80 backdrop-blur-sm z-10">
<div className="relative w-full max-w-2xl mx-4">
{/* Current Alert */}
<AlertCard
<HomepageAlertCard
alert={currentAlert}
onDismiss={handleDismissAlert}
onClose={handleCloseCurrentAlert}
/>
{/* Navigation Controls */}
{hasMultipleAlerts && (
<div className="absolute -bottom-16 left-1/2 transform -translate-x-1/2 flex items-center gap-2">
<Button
@@ -188,7 +186,6 @@ export function AlertManager({userId, loggedIn}: AlertManagerProps): React.React
</div>
)}
{/* Error Display */}
{error && (
<div className="absolute -bottom-20 left-1/2 transform -translate-x-1/2">
<div className="bg-destructive text-destructive-foreground px-3 py-1 rounded text-sm">

View File

@@ -1,10 +1,9 @@
import React, {useState, useEffect} from "react";
import {cn} from "@/lib/utils";
import {Button} from "@/components/ui/button";
import {Input} from "@/components/ui/input";
import {Label} from "@/components/ui/label";
import {Alert, AlertTitle, AlertDescription} from "@/components/ui/alert";
import {Separator} from "@/components/ui/separator";
import {cn} from "@/lib/utils.ts";
import {Button} from "@/components/ui/button.tsx";
import {Input} from "@/components/ui/input.tsx";
import {Label} from "@/components/ui/label.tsx";
import {Alert, AlertTitle, AlertDescription} from "@/components/ui/alert.tsx";
import axios from "axios";
function setCookie(name: string, value: string, days = 7) {

View File

@@ -1,9 +1,9 @@
import React from 'react';
import React, {useState} from 'react';
import {
Computer,
Server,
File,
Hammer, ChevronUp, User2, HardDrive, Trash2, Users, Shield, Settings
Hammer, ChevronUp, User2, HardDrive, Trash2, Users, Shield, Settings, Menu, ChevronRight
} from "lucide-react";
import {
@@ -14,7 +14,7 @@ import {
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem, SidebarProvider, SidebarInset,
SidebarMenuItem, SidebarProvider, SidebarInset, SidebarHeader,
} from "@/components/ui/sidebar.tsx"
import {
@@ -74,7 +74,7 @@ const API = axios.create({
baseURL: apiBase,
});
export function HomepageSidebar({
export function Sidebar({
onSelectView,
getView,
disabled,
@@ -117,6 +117,8 @@ export function HomepageSidebar({
const [makeAdminError, setMakeAdminError] = React.useState<string | null>(null);
const [makeAdminSuccess, setMakeAdminSuccess] = React.useState<string | null>(null);
const [isSidebarOpen, setIsSidebarOpen] = useState<boolean>(true);
React.useEffect(() => {
if (adminSheetOpen) {
const jwt = getCookie("jwt");
@@ -341,14 +343,23 @@ export function HomepageSidebar({
return (
<div className="min-h-svh">
<SidebarProvider>
<Sidebar>
<SidebarProvider open={isSidebarOpen}>
<Sidebar variant="floating">
<SidebarHeader>
<SidebarGroupLabel className="text-lg font-bold text-white">
Termix
<Button
variant="outline"
onClick={() => setIsSidebarOpen(!isSidebarOpen)}
className="w-[28px] h-[28px] absolute right-5"
>
<Menu className="h-4 w-4"/>
</Button>
</SidebarGroupLabel>
</SidebarHeader>
<Separator className="p-0.25"/>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel className="text-lg font-bold text-white flex items-center gap-2">
Termix
</SidebarGroupLabel>
<Separator className="p-0.25 mt-1 mb-1"/>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem key={"SSH Manager"}>
@@ -893,6 +904,14 @@ export function HomepageSidebar({
{children}
</SidebarInset>
</SidebarProvider>
{!isSidebarOpen && (
<div
onClick={() => setIsSidebarOpen(true)}
className="absolute top-0 left-0 w-[10px] h-full bg-[#18181b] cursor-pointer z-20 flex items-center justify-center">
<ChevronRight size={10} />
</div>
)}
</div>
)
}

View File

@@ -1,10 +1,10 @@
import React, {useState, useEffect, useRef} from "react";
import {ConfigEditorSidebar} from "@/apps/SSH/Config Editor/ConfigEditorSidebar.tsx";
import {ConfigTabList} from "@/apps/SSH/Config Editor/ConfigTabList.tsx";
import {ConfigHomeView} from "@/apps/SSH/Config Editor/ConfigHomeView.tsx";
import {ConfigCodeEditor} from "@/apps/SSH/Config Editor/ConfigCodeEditor.tsx";
import {ConfigEditorSidebar} from "@/ui/SSH/Config Editor/ConfigEditorSidebar.tsx";
import {ConfigTabList} from "@/ui/SSH/Config Editor/ConfigTabList.tsx";
import {ConfigHomeView} from "@/ui/SSH/Config Editor/ConfigHomeView.tsx";
import {ConfigCodeEditor} from "@/ui/SSH/Config Editor/ConfigCodeEditor.tsx";
import {Button} from '@/components/ui/button.tsx';
import {ConfigTopbar} from "@/apps/SSH/Config Editor/ConfigTopbar.tsx";
import {ConfigTopbar} from "@/ui/SSH/Config Editor/ConfigTopbar.tsx";
import {cn} from '@/lib/utils.ts';
import {
getConfigEditorRecent,
@@ -20,7 +20,7 @@ import {
writeSSHFile,
getSSHStatus,
connectSSH
} from '@/apps/SSH/ssh-axios.ts';
} from '@/ui/SSH/ssh-axios.ts';
interface Tab {
id: string | number;

View File

@@ -22,7 +22,7 @@ import {
getConfigEditorPinned,
addConfigEditorPinned,
removeConfigEditorPinned
} from '@/apps/SSH/ssh-axios.ts';
} from '@/ui/SSH/ssh-axios.ts';
interface SSHHost {
id: number;

View File

@@ -1,9 +1,9 @@
import React, {useState} from "react";
import {SSHManagerSidebar} from "@/apps/SSH/Manager/SSHManagerSidebar.tsx";
import {SSHManagerHostViewer} from "@/apps/SSH/Manager/SSHManagerHostViewer.tsx"
import {SSHManagerHostViewer} from "@/ui/SSH/Manager/SSHManagerHostViewer.tsx"
import {Tabs, TabsContent, TabsList, TabsTrigger} from "@/components/ui/tabs.tsx";
import {Separator} from "@/components/ui/separator.tsx";
import {SSHManagerHostEditor} from "@/apps/SSH/Manager/SSHManagerHostEditor.tsx";
import {SSHManagerHostEditor} from "@/ui/SSH/Manager/SSHManagerHostEditor.tsx";
import {useSidebar} from "@/components/ui/sidebar.tsx";
interface ConfigEditorProps {
onSelectView: (view: string) => void;
@@ -35,6 +35,7 @@ interface SSHHost {
export function SSHManager({onSelectView}: ConfigEditorProps): React.ReactElement {
const [activeTab, setActiveTab] = useState("host_viewer");
const [editingHost, setEditingHost] = useState<SSHHost | null>(null);
const {state: sidebarState} = useSidebar();
const handleEditHost = (host: SSHHost) => {
setEditingHost(host);
@@ -55,29 +56,25 @@ export function SSHManager({onSelectView}: ConfigEditorProps): React.ReactElemen
return (
<div>
<SSHManagerSidebar
onSelectView={onSelectView}
/>
<div className="flex w-screen h-screen overflow-hidden">
<div className="w-[256px]"/>
<div className="flex w-full h-screen overflow-hidden">
<div
className="flex-1 bg-[#18181b] m-[35px] text-white p-4 rounded-md w-[1200px] border h-[calc(100vh-70px)] flex flex-col min-h-0">
className={`flex-1 bg-[#18181b] m-[8px] text-white p-4 pt-0 rounded-lg border border-[#303032] flex flex-col min-h-0 ${
sidebarState === 'collapsed' ? 'ml-6' : ''
}`}>
<Tabs value={activeTab} onValueChange={handleTabChange}
className="flex-1 flex flex-col h-full min-h-0">
<TabsList>
<TabsList className="mt-1.5">
<TabsTrigger value="host_viewer">Host Viewer</TabsTrigger>
<TabsTrigger value="add_host">
{editingHost ? "Edit Host" : "Add Host"}
</TabsTrigger>
</TabsList>
<TabsContent value="host_viewer" className="flex-1 flex flex-col h-full min-h-0">
<Separator className="p-0.25 mt-1 mb-1"/>
<Separator className="p-0.25 -mt-0.5 mb-1"/>
<SSHManagerHostViewer onEditHost={handleEditHost}/>
</TabsContent>
<TabsContent value="add_host" className="flex-1 flex flex-col h-full min-h-0">
<Separator className="p-0.25 mt-1 mb-1"/>
<Separator className="p-0.25 -mt-0.5 mb-1"/>
<div className="flex flex-col h-full min-h-0">
<SSHManagerHostEditor
editingHost={editingHost}

View File

@@ -19,7 +19,7 @@ import {Tabs, TabsContent, TabsList, TabsTrigger} from "@/components/ui/tabs.tsx
import React, {useEffect, useRef, useState} from "react";
import {Switch} from "@/components/ui/switch.tsx";
import {Alert, AlertDescription} from "@/components/ui/alert.tsx";
import {createSSHHost, updateSSHHost, getSSHHosts} from '@/apps/SSH/ssh-axios';
import {createSSHHost, updateSSHHost, getSSHHosts} from '@/ui/SSH/ssh-axios';
interface SSHHost {
id: number;
@@ -388,7 +388,7 @@ export function SSHManagerHostEditor({editingHost, onFormSubmit}: SSHManagerHost
<div className="flex-1 flex flex-col h-full min-h-0 w-full">
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col flex-1 min-h-0 h-full">
<ScrollArea className="flex-1 min-h-0 w-full my-1">
<ScrollArea className="flex-1 min-h-0 w-full my-1 pb-2">
<Tabs defaultValue="general" className="w-full">
<TabsList>
<TabsTrigger value="general">General</TabsTrigger>
@@ -396,7 +396,7 @@ export function SSHManagerHostEditor({editingHost, onFormSubmit}: SSHManagerHost
<TabsTrigger value="tunnel">Tunnel</TabsTrigger>
<TabsTrigger value="config_editor">Config Editor</TabsTrigger>
</TabsList>
<TabsContent value="general">
<TabsContent value="general" className="pt-2">
<FormLabel className="mb-3 font-bold">Connection Details</FormLabel>
<div className="grid grid-cols-12 gap-4">
<FormField
@@ -1025,9 +1025,18 @@ export function SSHManagerHostEditor({editingHost, onFormSubmit}: SSHManagerHost
</TabsContent>
</Tabs>
</ScrollArea>
<footer className="shrink-0 w-full">
<Separator className="p-0.25 mt-1 mb-3"/>
<Button type="submit" variant="outline">{editingHost ? "Update Host" : "Add Host"}</Button>
<footer className="shrink-0 w-full pb-0">
<Separator className="p-0.25"/>
<Button
className=""
type="submit"
variant="outline"
style={{
transform: 'translateY(8px)'
}}
>
{editingHost ? "Update Host" : "Add Host"}
</Button>
</footer>
</form>
</Form>

View File

@@ -6,7 +6,7 @@ import {ScrollArea} from "@/components/ui/scroll-area";
import {Input} from "@/components/ui/input";
import {Accordion, AccordionContent, AccordionItem, AccordionTrigger} from "@/components/ui/accordion";
import {Tooltip, TooltipContent, TooltipProvider, TooltipTrigger} from "@/components/ui/tooltip";
import {getSSHHosts, deleteSSHHost, bulkImportSSHHosts} from "@/apps/SSH/ssh-axios";
import {getSSHHosts, deleteSSHHost, bulkImportSSHHosts} from "@/ui/SSH/ssh-axios";
import {
Edit,
Trash2,

View File

@@ -1,7 +1,7 @@
import React, {useState, useRef, useEffect} from "react";
import {TerminalSidebar} from "@/apps/SSH/Terminal/TerminalSidebar.tsx";
import {TerminalSidebar} from "@/ui/SSH/Terminal/TerminalSidebar.tsx";
import {TerminalComponent} from "./TerminalComponent.tsx";
import {TerminalTopbar} from "@/apps/SSH/Terminal/TerminalTopbar.tsx";
import {TerminalTopbar} from "@/ui/SSH/Terminal/TerminalTopbar.tsx";
import {ResizablePanelGroup, ResizablePanel, ResizableHandle} from '@/components/ui/resizable.tsx';
import * as ResizablePrimitive from "react-resizable-panels";
import {ChevronDown, ChevronRight} from "lucide-react";

View File

@@ -37,7 +37,7 @@ import {
} from "@/components/ui/accordion.tsx";
import {ScrollArea} from "@/components/ui/scroll-area.tsx";
import {Input} from "@/components/ui/input.tsx";
import {getSSHHosts} from "@/apps/SSH/ssh-axios";
import {getSSHHosts} from "@/ui/SSH/ssh-axios";
import {Checkbox} from "@/components/ui/checkbox.tsx";
interface SSHHost {

View File

@@ -1,4 +1,4 @@
import {TerminalTabList} from "@/apps/SSH/Terminal/TerminalTabList.tsx";
import {TerminalTabList} from "@/ui/SSH/Terminal/TerminalTabList.tsx";
import React from "react";
import {ChevronUp} from "lucide-react";

View File

@@ -1,7 +1,7 @@
import React, {useState, useEffect, useCallback} from "react";
import {SSHTunnelSidebar} from "@/apps/SSH/Tunnel/SSHTunnelSidebar.tsx";
import {SSHTunnelViewer} from "@/apps/SSH/Tunnel/SSHTunnelViewer.tsx";
import {getSSHHosts, getTunnelStatuses, connectTunnel, disconnectTunnel, cancelTunnel} from "@/apps/SSH/ssh-axios";
import {SSHTunnelSidebar} from "@/ui/SSH/Tunnel/SSHTunnelSidebar.tsx";
import {SSHTunnelViewer} from "@/ui/SSH/Tunnel/SSHTunnelViewer.tsx";
import {getSSHHosts, getTunnelStatuses, connectTunnel, disconnectTunnel, cancelTunnel} from "@/ui/SSH/ssh-axios";
interface ConfigEditorProps {
onSelectView: (view: string) => void;

View File

@@ -6,16 +6,12 @@
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
/* Linting - Made extremely permissive */
"strict": false,
"noUnusedLocals": false,
"noUnusedParameters": false,
@@ -31,8 +27,6 @@
"allowUnreachableCode": true,
"noImplicitOverride": false,
"noEmitOnError": false,
/* shadcn */
"baseUrl": ".",
"paths": {
"@/*": [