FIx frontend old confige editor paths
This commit is contained in:
@@ -2,8 +2,6 @@ import React, {useState, useEffect} from "react"
|
|||||||
import {LeftSidebar} from "@/ui/Navigation/LeftSidebar.tsx"
|
import {LeftSidebar} from "@/ui/Navigation/LeftSidebar.tsx"
|
||||||
import {Homepage} from "@/ui/Homepage/Homepage.tsx"
|
import {Homepage} from "@/ui/Homepage/Homepage.tsx"
|
||||||
import {AppView} from "@/ui/Navigation/AppView.tsx"
|
import {AppView} from "@/ui/Navigation/AppView.tsx"
|
||||||
// import {SSHTunnel} from "@/ui/SSH/Tunnel/SSHTunnel.tsx"
|
|
||||||
// import {ConfigEditor} from "@/ui/SSH/Config Editor/ConfigEditor.tsx"
|
|
||||||
import {HostManager} from "@/ui/apps/Host Manager/HostManager.tsx"
|
import {HostManager} from "@/ui/apps/Host Manager/HostManager.tsx"
|
||||||
import {TabProvider, useTabs} from "@/ui/Navigation/Tabs/TabContext.tsx"
|
import {TabProvider, useTabs} from "@/ui/Navigation/Tabs/TabContext.tsx"
|
||||||
import axios from "axios"
|
import axios from "axios"
|
||||||
@@ -88,7 +86,7 @@ function AppContent() {
|
|||||||
|
|
||||||
// Determine what to show based on current tab
|
// Determine what to show based on current tab
|
||||||
const currentTabData = tabs.find(tab => tab.id === currentTab);
|
const currentTabData = tabs.find(tab => tab.id === currentTab);
|
||||||
const showTerminalView = currentTabData?.type === 'terminal' || currentTabData?.type === 'server' || currentTabData?.type === 'config';
|
const showTerminalView = currentTabData?.type === 'terminal' || currentTabData?.type === 'server' || currentTabData?.type === 'file_manager';
|
||||||
const showHome = currentTabData?.type === 'home';
|
const showHome = currentTabData?.type === 'home';
|
||||||
const showSshManager = currentTabData?.type === 'ssh_manager';
|
const showSshManager = currentTabData?.type === 'ssh_manager';
|
||||||
const showAdmin = currentTabData?.type === 'admin';
|
const showAdmin = currentTabData?.type === 'admin';
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ interface SSHHost {
|
|||||||
keyType?: string;
|
keyType?: string;
|
||||||
enableTerminal: boolean;
|
enableTerminal: boolean;
|
||||||
enableTunnel: boolean;
|
enableTunnel: boolean;
|
||||||
enableConfigEditor: boolean;
|
enableFileManager: boolean;
|
||||||
defaultPath: string;
|
defaultPath: string;
|
||||||
tunnelConnections: TunnelConnection[];
|
tunnelConnections: TunnelConnection[];
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export function AppView({ isTopbarOpen = true }: TerminalViewProps): React.React
|
|||||||
const {tabs, currentTab, allSplitScreenTab} = useTabs() as any;
|
const {tabs, currentTab, allSplitScreenTab} = useTabs() as any;
|
||||||
const { state: sidebarState } = useSidebar();
|
const { state: sidebarState } = useSidebar();
|
||||||
|
|
||||||
const terminalTabs = tabs.filter((tab: any) => tab.type === 'terminal' || tab.type === 'server' || tab.type === 'config');
|
const terminalTabs = tabs.filter((tab: any) => tab.type === 'terminal' || tab.type === 'server' || tab.type === 'file_manager');
|
||||||
|
|
||||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||||
const panelRefs = useRef<Record<string, HTMLDivElement | null>>({});
|
const panelRefs = useRef<Record<string, HTMLDivElement | null>>({});
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ interface SSHHost {
|
|||||||
keyType?: string;
|
keyType?: string;
|
||||||
enableTerminal: boolean;
|
enableTerminal: boolean;
|
||||||
enableTunnel: boolean;
|
enableTunnel: boolean;
|
||||||
enableConfigEditor: boolean;
|
enableFileManager: boolean;
|
||||||
defaultPath: string;
|
defaultPath: string;
|
||||||
tunnelConnections: any[];
|
tunnelConnections: any[];
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ interface SSHHost {
|
|||||||
keyType?: string;
|
keyType?: string;
|
||||||
enableTerminal: boolean;
|
enableTerminal: boolean;
|
||||||
enableTunnel: boolean;
|
enableTunnel: boolean;
|
||||||
enableConfigEditor: boolean;
|
enableFileManager: boolean;
|
||||||
defaultPath: string;
|
defaultPath: string;
|
||||||
tunnelConnections: any[];
|
tunnelConnections: any[];
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ interface SSHHost {
|
|||||||
keyType?: string;
|
keyType?: string;
|
||||||
enableTerminal: boolean;
|
enableTerminal: boolean;
|
||||||
enableTunnel: boolean;
|
enableTunnel: boolean;
|
||||||
enableConfigEditor: boolean;
|
enableFileManager: boolean;
|
||||||
defaultPath: string;
|
defaultPath: string;
|
||||||
tunnelConnections: any[];
|
tunnelConnections: any[];
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ export function Tab({tabType, title, isActive, onActivate, onClose, onSplit, can
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tabType === "terminal" || tabType === "server" || tabType === "config") {
|
if (tabType === "terminal" || tabType === "server" || tabType === "file_manager") {
|
||||||
const isServer = tabType === 'server';
|
const isServer = tabType === 'server';
|
||||||
const isConfig = tabType === 'config';
|
const isFileManager = tabType === 'file_manager';
|
||||||
return (
|
return (
|
||||||
<ButtonGroup>
|
<ButtonGroup>
|
||||||
<Button
|
<Button
|
||||||
@@ -42,8 +42,8 @@ export function Tab({tabType, title, isActive, onActivate, onClose, onSplit, can
|
|||||||
onClick={onActivate}
|
onClick={onActivate}
|
||||||
disabled={disableActivate}
|
disabled={disableActivate}
|
||||||
>
|
>
|
||||||
{isServer ? <ServerIcon className="mr-1 h-4 w-4"/> : isConfig ? <FolderIcon className="mr-1 h-4 w-4"/> : <TerminalIcon className="mr-1 h-4 w-4"/>}
|
{isServer ? <ServerIcon className="mr-1 h-4 w-4"/> : isFileManager ? <FolderIcon className="mr-1 h-4 w-4"/> : <TerminalIcon className="mr-1 h-4 w-4"/>}
|
||||||
{title || (isServer ? 'Server' : isConfig ? 'Config' : 'Terminal')}
|
{title || (isServer ? 'Server' : isFileManager ? 'file_manager' : 'Terminal')}
|
||||||
</Button>
|
</Button>
|
||||||
{canSplit && (
|
{canSplit && (
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { createContext, useContext, useState, useRef, type ReactNode } fr
|
|||||||
|
|
||||||
export interface Tab {
|
export interface Tab {
|
||||||
id: number;
|
id: number;
|
||||||
type: 'home' | 'terminal' | 'ssh_manager' | 'server' | 'admin' | 'config';
|
type: 'home' | 'terminal' | 'ssh_manager' | 'server' | 'admin' | 'file_manager';
|
||||||
title: string;
|
title: string;
|
||||||
hostConfig?: any;
|
hostConfig?: any;
|
||||||
terminalRef?: React.RefObject<any>;
|
terminalRef?: React.RefObject<any>;
|
||||||
@@ -42,7 +42,7 @@ export function TabProvider({ children }: TabProviderProps) {
|
|||||||
const nextTabId = useRef(2);
|
const nextTabId = useRef(2);
|
||||||
|
|
||||||
function computeUniqueTitle(tabType: Tab['type'], desiredTitle: string | undefined): string {
|
function computeUniqueTitle(tabType: Tab['type'], desiredTitle: string | undefined): string {
|
||||||
const defaultTitle = tabType === 'server' ? 'Server' : (tabType === 'config' ? 'Config' : 'Terminal');
|
const defaultTitle = tabType === 'server' ? 'Server' : (tabType === 'file_manager' ? 'File Manager' : 'Terminal');
|
||||||
const baseTitle = (desiredTitle || defaultTitle).trim();
|
const baseTitle = (desiredTitle || defaultTitle).trim();
|
||||||
// Extract base name without trailing " (n)"
|
// Extract base name without trailing " (n)"
|
||||||
const match = baseTitle.match(/^(.*) \((\d+)\)$/);
|
const match = baseTitle.match(/^(.*) \((\d+)\)$/);
|
||||||
@@ -72,7 +72,7 @@ export function TabProvider({ children }: TabProviderProps) {
|
|||||||
|
|
||||||
const addTab = (tabData: Omit<Tab, 'id'>): number => {
|
const addTab = (tabData: Omit<Tab, 'id'>): number => {
|
||||||
const id = nextTabId.current++;
|
const id = nextTabId.current++;
|
||||||
const needsUniqueTitle = tabData.type === 'terminal' || tabData.type === 'server' || tabData.type === 'config';
|
const needsUniqueTitle = tabData.type === 'terminal' || tabData.type === 'server' || tabData.type === 'file_manager';
|
||||||
const effectiveTitle = needsUniqueTitle ? computeUniqueTitle(tabData.type, tabData.title) : (tabData.title || '');
|
const effectiveTitle = needsUniqueTitle ? computeUniqueTitle(tabData.type, tabData.title) : (tabData.title || '');
|
||||||
const newTab: Tab = {
|
const newTab: Tab = {
|
||||||
...tabData,
|
...tabData,
|
||||||
|
|||||||
@@ -53,11 +53,11 @@ export function TopNavbar({isTopbarOpen, setIsTopbarOpen}: TopNavbarProps): Reac
|
|||||||
const isSplit = Array.isArray(allSplitScreenTab) && allSplitScreenTab.includes(tab.id);
|
const isSplit = Array.isArray(allSplitScreenTab) && allSplitScreenTab.includes(tab.id);
|
||||||
const isTerminal = tab.type === 'terminal';
|
const isTerminal = tab.type === 'terminal';
|
||||||
const isServer = tab.type === 'server';
|
const isServer = tab.type === 'server';
|
||||||
const isConfig = tab.type === 'config';
|
const isFileManager = tab.type === 'file_manager';
|
||||||
const isSshManager = tab.type === 'ssh_manager';
|
const isSshManager = tab.type === 'ssh_manager';
|
||||||
const isAdmin = tab.type === 'admin';
|
const isAdmin = tab.type === 'admin';
|
||||||
// Split availability
|
// Split availability
|
||||||
const isSplittable = isTerminal || isServer || isConfig;
|
const isSplittable = isTerminal || isServer || isFileManager;
|
||||||
// Disable split entirely when on Home or SSH Manager
|
// Disable split entirely when on Home or SSH Manager
|
||||||
const isSplitButtonDisabled = (isActive && !isSplitScreenActive) || ((allSplitScreenTab?.length || 0) >= 3 && !isSplit);
|
const isSplitButtonDisabled = (isActive && !isSplitScreenActive) || ((allSplitScreenTab?.length || 0) >= 3 && !isSplit);
|
||||||
const disableSplit = !isSplittable || isSplitButtonDisabled || isActive || currentTabIsHome || currentTabIsSshManager || currentTabIsAdmin;
|
const disableSplit = !isSplittable || isSplitButtonDisabled || isActive || currentTabIsHome || currentTabIsSshManager || currentTabIsAdmin;
|
||||||
@@ -70,10 +70,10 @@ export function TopNavbar({isTopbarOpen, setIsTopbarOpen}: TopNavbarProps): Reac
|
|||||||
title={tab.title}
|
title={tab.title}
|
||||||
isActive={isActive}
|
isActive={isActive}
|
||||||
onActivate={() => handleTabActivate(tab.id)}
|
onActivate={() => handleTabActivate(tab.id)}
|
||||||
onClose={isTerminal || isServer || isConfig || isSshManager || isAdmin ? () => handleTabClose(tab.id) : undefined}
|
onClose={isTerminal || isServer || isFileManager || isSshManager || isAdmin ? () => handleTabClose(tab.id) : undefined}
|
||||||
onSplit={isSplittable ? () => handleTabSplit(tab.id) : undefined}
|
onSplit={isSplittable ? () => handleTabSplit(tab.id) : undefined}
|
||||||
canSplit={isSplittable}
|
canSplit={isSplittable}
|
||||||
canClose={isTerminal || isServer || isConfig || isSshManager || isAdmin}
|
canClose={isTerminal || isServer || isFileManager || isSshManager || isAdmin}
|
||||||
disableActivate={disableActivate}
|
disableActivate={disableActivate}
|
||||||
disableSplit={disableSplit}
|
disableSplit={disableSplit}
|
||||||
disableClose={disableClose}
|
disableClose={disableClose}
|
||||||
|
|||||||
@@ -7,15 +7,15 @@ import {Button} from '@/components/ui/button.tsx';
|
|||||||
import {FIleManagerTopNavbar} from "@/ui/apps/File Manager/FIleManagerTopNavbar.tsx";
|
import {FIleManagerTopNavbar} from "@/ui/apps/File Manager/FIleManagerTopNavbar.tsx";
|
||||||
import {cn} from '@/lib/utils.ts';
|
import {cn} from '@/lib/utils.ts';
|
||||||
import {
|
import {
|
||||||
getConfigEditorRecent,
|
getFileManagerRecent,
|
||||||
getConfigEditorPinned,
|
getFileManagerPinned,
|
||||||
getConfigEditorShortcuts,
|
getFileManagerShortcuts,
|
||||||
addConfigEditorRecent,
|
addFileManagerRecent,
|
||||||
removeConfigEditorRecent,
|
removeFileManagerRecent,
|
||||||
addConfigEditorPinned,
|
addFileManagerPinned,
|
||||||
removeConfigEditorPinned,
|
removeFileManagerPinned,
|
||||||
addConfigEditorShortcut,
|
addFileManagerShortcut,
|
||||||
removeConfigEditorShortcut,
|
removeFileManagerShortcut,
|
||||||
readSSHFile,
|
readSSHFile,
|
||||||
writeSSHFile,
|
writeSSHFile,
|
||||||
getSSHStatus,
|
getSSHStatus,
|
||||||
@@ -52,14 +52,18 @@ interface SSHHost {
|
|||||||
keyType?: string;
|
keyType?: string;
|
||||||
enableTerminal: boolean;
|
enableTerminal: boolean;
|
||||||
enableTunnel: boolean;
|
enableTunnel: boolean;
|
||||||
enableConfigEditor: boolean;
|
enableFileManager: boolean;
|
||||||
defaultPath: string;
|
defaultPath: string;
|
||||||
tunnelConnections: any[];
|
tunnelConnections: any[];
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function FileManager({onSelectView, embedded = false, initialHost = null}: { onSelectView?: (view: string) => void, embedded?: boolean, initialHost?: SSHHost | null }): React.ReactElement {
|
export function FileManager({onSelectView, embedded = false, initialHost = null}: {
|
||||||
|
onSelectView?: (view: string) => void,
|
||||||
|
embedded?: boolean,
|
||||||
|
initialHost?: SSHHost | null
|
||||||
|
}): React.ReactElement {
|
||||||
const [tabs, setTabs] = useState<Tab[]>([]);
|
const [tabs, setTabs] = useState<Tab[]>([]);
|
||||||
const [activeTab, setActiveTab] = useState<string | number>('home');
|
const [activeTab, setActiveTab] = useState<string | number>('home');
|
||||||
const [recent, setRecent] = useState<any[]>([]);
|
const [recent, setRecent] = useState<any[]>([]);
|
||||||
@@ -118,9 +122,9 @@ export function FileManager({onSelectView, embedded = false, initialHost = null}
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const homeDataPromise = Promise.all([
|
const homeDataPromise = Promise.all([
|
||||||
getConfigEditorRecent(currentHost.id),
|
getFileManagerRecent(currentHost.id),
|
||||||
getConfigEditorPinned(currentHost.id),
|
getFileManagerPinned(currentHost.id),
|
||||||
getConfigEditorShortcuts(currentHost.id),
|
getFileManagerShortcuts(currentHost.id),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const timeoutPromise = new Promise((_, reject) =>
|
const timeoutPromise = new Promise((_, reject) =>
|
||||||
@@ -197,7 +201,7 @@ export function FileManager({onSelectView, embedded = false, initialHost = null}
|
|||||||
loading: false,
|
loading: false,
|
||||||
error: undefined
|
error: undefined
|
||||||
} : t));
|
} : t));
|
||||||
await addConfigEditorRecent({
|
await addFileManagerRecent({
|
||||||
name: file.name,
|
name: file.name,
|
||||||
path: file.path,
|
path: file.path,
|
||||||
isSSH: true,
|
isSSH: true,
|
||||||
@@ -215,7 +219,7 @@ export function FileManager({onSelectView, embedded = false, initialHost = null}
|
|||||||
|
|
||||||
const handleRemoveRecent = async (file: any) => {
|
const handleRemoveRecent = async (file: any) => {
|
||||||
try {
|
try {
|
||||||
await removeConfigEditorRecent({
|
await removeFileManagerRecent({
|
||||||
name: file.name,
|
name: file.name,
|
||||||
path: file.path,
|
path: file.path,
|
||||||
isSSH: true,
|
isSSH: true,
|
||||||
@@ -229,7 +233,7 @@ export function FileManager({onSelectView, embedded = false, initialHost = null}
|
|||||||
|
|
||||||
const handlePinFile = async (file: any) => {
|
const handlePinFile = async (file: any) => {
|
||||||
try {
|
try {
|
||||||
await addConfigEditorPinned({
|
await addFileManagerPinned({
|
||||||
name: file.name,
|
name: file.name,
|
||||||
path: file.path,
|
path: file.path,
|
||||||
isSSH: true,
|
isSSH: true,
|
||||||
@@ -246,7 +250,7 @@ export function FileManager({onSelectView, embedded = false, initialHost = null}
|
|||||||
|
|
||||||
const handleUnpinFile = async (file: any) => {
|
const handleUnpinFile = async (file: any) => {
|
||||||
try {
|
try {
|
||||||
await removeConfigEditorPinned({
|
await removeFileManagerPinned({
|
||||||
name: file.name,
|
name: file.name,
|
||||||
path: file.path,
|
path: file.path,
|
||||||
isSSH: true,
|
isSSH: true,
|
||||||
@@ -286,7 +290,7 @@ export function FileManager({onSelectView, embedded = false, initialHost = null}
|
|||||||
const handleAddShortcut = async (folderPath: string) => {
|
const handleAddShortcut = async (folderPath: string) => {
|
||||||
try {
|
try {
|
||||||
const name = folderPath.split('/').pop() || folderPath;
|
const name = folderPath.split('/').pop() || folderPath;
|
||||||
await addConfigEditorShortcut({
|
await addFileManagerShortcut({
|
||||||
name,
|
name,
|
||||||
path: folderPath,
|
path: folderPath,
|
||||||
isSSH: true,
|
isSSH: true,
|
||||||
@@ -300,7 +304,7 @@ export function FileManager({onSelectView, embedded = false, initialHost = null}
|
|||||||
|
|
||||||
const handleRemoveShortcut = async (shortcut: any) => {
|
const handleRemoveShortcut = async (shortcut: any) => {
|
||||||
try {
|
try {
|
||||||
await removeConfigEditorShortcut({
|
await removeFileManagerShortcut({
|
||||||
name: shortcut.name,
|
name: shortcut.name,
|
||||||
path: shortcut.path,
|
path: shortcut.path,
|
||||||
isSSH: true,
|
isSSH: true,
|
||||||
@@ -402,7 +406,7 @@ export function FileManager({onSelectView, embedded = false, initialHost = null}
|
|||||||
Promise.allSettled([
|
Promise.allSettled([
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
await addConfigEditorRecent({
|
await addFileManagerRecent({
|
||||||
name: tab.fileName,
|
name: tab.fileName,
|
||||||
path: tab.filePath,
|
path: tab.filePath,
|
||||||
isSSH: true,
|
isSSH: true,
|
||||||
@@ -445,14 +449,16 @@ export function FileManager({onSelectView, embedded = false, initialHost = null}
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Host is locked; no external host change from UI
|
// Host is locked; no external host change from UI
|
||||||
const handleHostChange = (_host: SSHHost | null) => {};
|
const handleHostChange = (_host: SSHHost | null) => {
|
||||||
|
};
|
||||||
|
|
||||||
if (!currentHost) {
|
if (!currentHost) {
|
||||||
return (
|
return (
|
||||||
<div style={{position: 'relative', width: '100%', height: '100%', overflow: 'hidden'}}>
|
<div style={{position: 'relative', width: '100%', height: '100%', overflow: 'hidden'}}>
|
||||||
<div style={{position: 'absolute', top: 0, left: 0, width: 256, height: '100%', zIndex: 20}}>
|
<div style={{position: 'absolute', top: 0, left: 0, width: 256, height: '100%', zIndex: 20}}>
|
||||||
<FileManagerLeftSidebar
|
<FileManagerLeftSidebar
|
||||||
onSelectView={onSelectView || (() => {})}
|
onSelectView={onSelectView || (() => {
|
||||||
|
})}
|
||||||
onOpenFile={handleOpenFile}
|
onOpenFile={handleOpenFile}
|
||||||
tabs={tabs}
|
tabs={tabs}
|
||||||
ref={sidebarRef}
|
ref={sidebarRef}
|
||||||
@@ -483,7 +489,8 @@ export function FileManager({onSelectView, embedded = false, initialHost = null}
|
|||||||
<div style={{position: 'relative', width: '100%', height: '100%', overflow: 'hidden'}}>
|
<div style={{position: 'relative', width: '100%', height: '100%', overflow: 'hidden'}}>
|
||||||
<div style={{position: 'absolute', top: 0, left: 0, width: 256, height: '100%', zIndex: 20}}>
|
<div style={{position: 'absolute', top: 0, left: 0, width: 256, height: '100%', zIndex: 20}}>
|
||||||
<FileManagerLeftSidebar
|
<FileManagerLeftSidebar
|
||||||
onSelectView={onSelectView || (() => {})}
|
onSelectView={onSelectView || (() => {
|
||||||
|
})}
|
||||||
onOpenFile={handleOpenFile}
|
onOpenFile={handleOpenFile}
|
||||||
tabs={tabs}
|
tabs={tabs}
|
||||||
ref={sidebarRef}
|
ref={sidebarRef}
|
||||||
|
|||||||
@@ -5,13 +5,13 @@ import {hyperLink} from '@uiw/codemirror-extensions-hyper-link';
|
|||||||
import {oneDark} from '@codemirror/theme-one-dark';
|
import {oneDark} from '@codemirror/theme-one-dark';
|
||||||
import {EditorView} from '@codemirror/view';
|
import {EditorView} from '@codemirror/view';
|
||||||
|
|
||||||
interface ConfigCodeEditorProps {
|
interface FileManagerCodeEditorProps {
|
||||||
content: string;
|
content: string;
|
||||||
fileName: string;
|
fileName: string;
|
||||||
onContentChange: (value: string) => void;
|
onContentChange: (value: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function FileManagerFileEditor({content, fileName, onContentChange}: ConfigCodeEditorProps) {
|
export function FileManagerFileEditor({content, fileName, onContentChange}: FileManagerCodeEditorProps) {
|
||||||
function getLanguageName(filename: string): string {
|
function getLanguageName(filename: string): string {
|
||||||
if (!filename || typeof filename !== 'string') {
|
if (!filename || typeof filename !== 'string') {
|
||||||
return 'text';
|
return 'text';
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ interface ShortcutItem {
|
|||||||
path: string;
|
path: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ConfigHomeViewProps {
|
interface FileManagerHomeViewProps {
|
||||||
recent: FileItem[];
|
recent: FileItem[];
|
||||||
pinned: FileItem[];
|
pinned: FileItem[];
|
||||||
shortcuts: ShortcutItem[];
|
shortcuts: ShortcutItem[];
|
||||||
@@ -42,7 +42,7 @@ export function FileManagerHomeView({
|
|||||||
onOpenShortcut,
|
onOpenShortcut,
|
||||||
onRemoveShortcut,
|
onRemoveShortcut,
|
||||||
onAddShortcut
|
onAddShortcut
|
||||||
}: ConfigHomeViewProps) {
|
}: FileManagerHomeViewProps) {
|
||||||
const [tab, setTab] = useState<'recent' | 'pinned' | 'shortcuts'>('recent');
|
const [tab, setTab] = useState<'recent' | 'pinned' | 'shortcuts'>('recent');
|
||||||
const [newShortcut, setNewShortcut] = useState('');
|
const [newShortcut, setNewShortcut] = useState('');
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ import {
|
|||||||
listSSHFiles,
|
listSSHFiles,
|
||||||
connectSSH,
|
connectSSH,
|
||||||
getSSHStatus,
|
getSSHStatus,
|
||||||
getConfigEditorPinned,
|
getFileManagerPinned,
|
||||||
addConfigEditorPinned,
|
addFileManagerPinned,
|
||||||
removeConfigEditorPinned
|
removeFileManagerPinned
|
||||||
} from '@/ui/main-axios.ts';
|
} from '@/ui/main-axios.ts';
|
||||||
|
|
||||||
interface SSHHost {
|
interface SSHHost {
|
||||||
@@ -30,14 +30,14 @@ interface SSHHost {
|
|||||||
keyType?: string;
|
keyType?: string;
|
||||||
enableTerminal: boolean;
|
enableTerminal: boolean;
|
||||||
enableTunnel: boolean;
|
enableTunnel: boolean;
|
||||||
enableConfigEditor: boolean;
|
enableFileManager: boolean;
|
||||||
defaultPath: string;
|
defaultPath: string;
|
||||||
tunnelConnections: any[];
|
tunnelConnections: any[];
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FileManagerLeftSidebar = forwardRef(function ConfigEditorSidebar(
|
const FileManagerLeftSidebar = forwardRef(function FileManagerSidebar(
|
||||||
{onSelectView, onOpenFile, tabs, host}: {
|
{onSelectView, onOpenFile, tabs, host}: {
|
||||||
onSelectView?: (view: string) => void;
|
onSelectView?: (view: string) => void;
|
||||||
onOpenFile: (file: any) => void;
|
onOpenFile: (file: any) => void;
|
||||||
@@ -146,7 +146,7 @@ const FileManagerLeftSidebar = forwardRef(function ConfigEditorSidebar(
|
|||||||
let pinnedFiles: any[] = [];
|
let pinnedFiles: any[] = [];
|
||||||
try {
|
try {
|
||||||
if (host) {
|
if (host) {
|
||||||
pinnedFiles = await getConfigEditorPinned(host.id);
|
pinnedFiles = await getFileManagerPinned(host.id);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
}
|
}
|
||||||
@@ -336,7 +336,7 @@ const FileManagerLeftSidebar = forwardRef(function ConfigEditorSidebar(
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
try {
|
try {
|
||||||
if (item.isPinned) {
|
if (item.isPinned) {
|
||||||
await removeConfigEditorPinned({
|
await removeFileManagerPinned({
|
||||||
name: item.name,
|
name: item.name,
|
||||||
path: item.path,
|
path: item.path,
|
||||||
hostId: host?.id,
|
hostId: host?.id,
|
||||||
@@ -347,7 +347,7 @@ const FileManagerLeftSidebar = forwardRef(function ConfigEditorSidebar(
|
|||||||
f.path === item.path ? { ...f, isPinned: false } : f
|
f.path === item.path ? { ...f, isPinned: false } : f
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
await addConfigEditorPinned({
|
await addFileManagerPinned({
|
||||||
name: item.name,
|
name: item.name,
|
||||||
path: item.path,
|
path: item.path,
|
||||||
hostId: host?.id,
|
hostId: host?.id,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ interface FileItem {
|
|||||||
isStarred?: boolean;
|
isStarred?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ConfigFileSidebarViewerProps {
|
interface FileManagerLeftSidebarVileViewerProps {
|
||||||
sshConnections: SSHConnection[];
|
sshConnections: SSHConnection[];
|
||||||
onAddSSH: () => void;
|
onAddSSH: () => void;
|
||||||
onConnectSSH: (conn: SSHConnection) => void;
|
onConnectSSH: (conn: SSHConnection) => void;
|
||||||
@@ -60,7 +60,7 @@ export function FileManagerLeftSidebarFileViewer({
|
|||||||
onSwitchToLocal,
|
onSwitchToLocal,
|
||||||
onSwitchToSSH,
|
onSwitchToSSH,
|
||||||
currentSSH,
|
currentSSH,
|
||||||
}: ConfigFileSidebarViewerProps) {
|
}: FileManagerLeftSidebarVileViewerProps) {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col h-full">
|
<div className="flex flex-col h-full">
|
||||||
{/* SSH Connections */}
|
{/* SSH Connections */}
|
||||||
|
|||||||
@@ -2,20 +2,20 @@ import React from 'react';
|
|||||||
import {Button} from '@/components/ui/button.tsx';
|
import {Button} from '@/components/ui/button.tsx';
|
||||||
import {X, Home} from 'lucide-react';
|
import {X, Home} from 'lucide-react';
|
||||||
|
|
||||||
interface ConfigTab {
|
interface FileManagerTab {
|
||||||
id: string | number;
|
id: string | number;
|
||||||
title: string;
|
title: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ConfigTabListProps {
|
interface FileManagerTabList {
|
||||||
tabs: ConfigTab[];
|
tabs: FileManagerTab[];
|
||||||
activeTab: string | number;
|
activeTab: string | number;
|
||||||
setActiveTab: (tab: string | number) => void;
|
setActiveTab: (tab: string | number) => void;
|
||||||
closeTab: (tab: string | number) => void;
|
closeTab: (tab: string | number) => void;
|
||||||
onHomeClick: () => void;
|
onHomeClick: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function FileManagerTabList({tabs, activeTab, setActiveTab, closeTab, onHomeClick}: ConfigTabListProps) {
|
export function FileManagerTabList({tabs, activeTab, setActiveTab, closeTab, onHomeClick}: FileManagerTabList) {
|
||||||
return (
|
return (
|
||||||
<div className="inline-flex items-center h-full px-[0.5rem] overflow-x-auto">
|
<div className="inline-flex items-center h-full px-[0.5rem] overflow-x-auto">
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {Separator} from "@/components/ui/separator.tsx";
|
|||||||
import {HostManagerHostEditor} from "@/ui/apps/Host Manager/HostManagerHostEditor.tsx";
|
import {HostManagerHostEditor} from "@/ui/apps/Host Manager/HostManagerHostEditor.tsx";
|
||||||
import {useSidebar} from "@/components/ui/sidebar.tsx";
|
import {useSidebar} from "@/components/ui/sidebar.tsx";
|
||||||
|
|
||||||
interface ConfigEditorProps {
|
interface HostManagerProps {
|
||||||
onSelectView: (view: string) => void;
|
onSelectView: (view: string) => void;
|
||||||
isTopbarOpen?: boolean;
|
isTopbarOpen?: boolean;
|
||||||
}
|
}
|
||||||
@@ -26,14 +26,14 @@ interface SSHHost {
|
|||||||
keyType?: string;
|
keyType?: string;
|
||||||
enableTerminal: boolean;
|
enableTerminal: boolean;
|
||||||
enableTunnel: boolean;
|
enableTunnel: boolean;
|
||||||
enableConfigEditor: boolean;
|
enableFileManager: boolean;
|
||||||
defaultPath: string;
|
defaultPath: string;
|
||||||
tunnelConnections: any[];
|
tunnelConnections: any[];
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function HostManager({onSelectView, isTopbarOpen}: ConfigEditorProps): React.ReactElement {
|
export function HostManager({onSelectView, isTopbarOpen}: HostManagerProps): React.ReactElement {
|
||||||
const [activeTab, setActiveTab] = useState("host_viewer");
|
const [activeTab, setActiveTab] = useState("host_viewer");
|
||||||
const [editingHost, setEditingHost] = useState<SSHHost | null>(null);
|
const [editingHost, setEditingHost] = useState<SSHHost | null>(null);
|
||||||
const {state: sidebarState} = useSidebar();
|
const {state: sidebarState} = useSidebar();
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ interface SSHHost {
|
|||||||
keyType?: string;
|
keyType?: string;
|
||||||
enableTerminal: boolean;
|
enableTerminal: boolean;
|
||||||
enableTunnel: boolean;
|
enableTunnel: boolean;
|
||||||
enableConfigEditor: boolean;
|
enableFileManager: boolean;
|
||||||
defaultPath: string;
|
defaultPath: string;
|
||||||
tunnelConnections: any[];
|
tunnelConnections: any[];
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
@@ -120,7 +120,7 @@ export function HostManagerHostEditor({editingHost, onFormSubmit}: SSHManagerHos
|
|||||||
retryInterval: z.coerce.number().min(1).max(3600).default(10),
|
retryInterval: z.coerce.number().min(1).max(3600).default(10),
|
||||||
autoStart: z.boolean().default(false),
|
autoStart: z.boolean().default(false),
|
||||||
})).default([]),
|
})).default([]),
|
||||||
enableConfigEditor: z.boolean().default(true),
|
enableFileManager: z.boolean().default(true),
|
||||||
defaultPath: z.string().optional(),
|
defaultPath: z.string().optional(),
|
||||||
}).superRefine((data, ctx) => {
|
}).superRefine((data, ctx) => {
|
||||||
if (data.authType === 'password') {
|
if (data.authType === 'password') {
|
||||||
@@ -178,7 +178,7 @@ export function HostManagerHostEditor({editingHost, onFormSubmit}: SSHManagerHos
|
|||||||
keyType: "auto",
|
keyType: "auto",
|
||||||
enableTerminal: editingHost?.enableTerminal !== false,
|
enableTerminal: editingHost?.enableTerminal !== false,
|
||||||
enableTunnel: editingHost?.enableTunnel !== false,
|
enableTunnel: editingHost?.enableTunnel !== false,
|
||||||
enableConfigEditor: editingHost?.enableConfigEditor !== false,
|
enableFileManager: editingHost?.enableFileManager !== false,
|
||||||
defaultPath: editingHost?.defaultPath || "/",
|
defaultPath: editingHost?.defaultPath || "/",
|
||||||
tunnelConnections: editingHost?.tunnelConnections || [],
|
tunnelConnections: editingHost?.tunnelConnections || [],
|
||||||
}
|
}
|
||||||
@@ -205,7 +205,7 @@ export function HostManagerHostEditor({editingHost, onFormSubmit}: SSHManagerHos
|
|||||||
keyType: (editingHost.keyType as any) || "auto",
|
keyType: (editingHost.keyType as any) || "auto",
|
||||||
enableTerminal: editingHost.enableTerminal !== false,
|
enableTerminal: editingHost.enableTerminal !== false,
|
||||||
enableTunnel: editingHost.enableTunnel !== false,
|
enableTunnel: editingHost.enableTunnel !== false,
|
||||||
enableConfigEditor: editingHost.enableConfigEditor !== false,
|
enableFileManager: editingHost.enableFileManager !== false,
|
||||||
defaultPath: editingHost.defaultPath || "/",
|
defaultPath: editingHost.defaultPath || "/",
|
||||||
tunnelConnections: editingHost.tunnelConnections || [],
|
tunnelConnections: editingHost.tunnelConnections || [],
|
||||||
});
|
});
|
||||||
@@ -227,7 +227,7 @@ export function HostManagerHostEditor({editingHost, onFormSubmit}: SSHManagerHos
|
|||||||
keyType: "auto",
|
keyType: "auto",
|
||||||
enableTerminal: true,
|
enableTerminal: true,
|
||||||
enableTunnel: true,
|
enableTunnel: true,
|
||||||
enableConfigEditor: true,
|
enableFileManager: true,
|
||||||
defaultPath: "/",
|
defaultPath: "/",
|
||||||
tunnelConnections: [],
|
tunnelConnections: [],
|
||||||
});
|
});
|
||||||
@@ -989,7 +989,7 @@ export function HostManagerHostEditor({editingHost, onFormSubmit}: SSHManagerHos
|
|||||||
<TabsContent value="file_manager">
|
<TabsContent value="file_manager">
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="enableConfigEditor"
|
name="enableFileManager"
|
||||||
render={({field}) => (
|
render={({field}) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>Enable File Manager</FormLabel>
|
<FormLabel>Enable File Manager</FormLabel>
|
||||||
@@ -1006,7 +1006,7 @@ export function HostManagerHostEditor({editingHost, onFormSubmit}: SSHManagerHos
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{form.watch('enableConfigEditor') && (
|
{form.watch('enableFileManager') && (
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ interface SSHHost {
|
|||||||
authType: string;
|
authType: string;
|
||||||
enableTerminal: boolean;
|
enableTerminal: boolean;
|
||||||
enableTunnel: boolean;
|
enableTunnel: boolean;
|
||||||
enableConfigEditor: boolean;
|
enableFileManager: boolean;
|
||||||
defaultPath: string;
|
defaultPath: string;
|
||||||
tunnelConnections: any[];
|
tunnelConnections: any[];
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
@@ -275,7 +275,7 @@ export function HostManagerHostViewer({onEditHost}: SSHManagerHostViewerProps) {
|
|||||||
pin: true,
|
pin: true,
|
||||||
enableTerminal: true,
|
enableTerminal: true,
|
||||||
enableTunnel: false,
|
enableTunnel: false,
|
||||||
enableConfigEditor: true,
|
enableFileManager: true,
|
||||||
defaultPath: "/var/www"
|
defaultPath: "/var/www"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -292,7 +292,7 @@ export function HostManagerHostViewer({onEditHost}: SSHManagerHostViewerProps) {
|
|||||||
pin: false,
|
pin: false,
|
||||||
enableTerminal: true,
|
enableTerminal: true,
|
||||||
enableTunnel: true,
|
enableTunnel: true,
|
||||||
enableConfigEditor: false,
|
enableFileManager: false,
|
||||||
tunnelConnections: [
|
tunnelConnections: [
|
||||||
{
|
{
|
||||||
sourcePort: 5432,
|
sourcePort: 5432,
|
||||||
@@ -347,7 +347,7 @@ OPTIONAL FIELDS:
|
|||||||
• pin: Pin to top (boolean)
|
• pin: Pin to top (boolean)
|
||||||
• enableTerminal: Show in Terminal tab (boolean, default: true)
|
• enableTerminal: Show in Terminal tab (boolean, default: true)
|
||||||
• enableTunnel: Show in Tunnel tab (boolean, default: true)
|
• enableTunnel: Show in Tunnel tab (boolean, default: true)
|
||||||
• enableConfigEditor: Show in Config Editor tab (boolean, default: true)
|
• enableFileManager: Show in File Manager tab (boolean, default: true)
|
||||||
• defaultPath: Default directory path (string)
|
• defaultPath: Default directory path (string)
|
||||||
|
|
||||||
TUNNEL CONFIGURATION:
|
TUNNEL CONFIGURATION:
|
||||||
@@ -374,7 +374,7 @@ EXAMPLE STRUCTURE:
|
|||||||
"pin": true,
|
"pin": true,
|
||||||
"enableTerminal": true,
|
"enableTerminal": true,
|
||||||
"enableTunnel": false,
|
"enableTunnel": false,
|
||||||
"enableConfigEditor": true,
|
"enableFileManager": true,
|
||||||
"defaultPath": "/var/www"
|
"defaultPath": "/var/www"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -500,8 +500,8 @@ EXAMPLE STRUCTURE:
|
|||||||
<button class="copy-btn" onclick="navigator.clipboard.writeText('enableTunnel')">Copy</button>
|
<button class="copy-btn" onclick="navigator.clipboard.writeText('enableTunnel')">Copy</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="field-item">
|
<div class="field-item">
|
||||||
<code>enableConfigEditor</code> - Show in Config Editor tab (boolean, default: true)
|
<code>enableFileManager</code> - Show in File Manager tab (boolean, default: true)
|
||||||
<button class="copy-btn" onclick="navigator.clipboard.writeText('enableConfigEditor')">Copy</button>
|
<button class="copy-btn" onclick="navigator.clipboard.writeText('enableFileManager')">Copy</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="field-item">
|
<div class="field-item">
|
||||||
<code>defaultPath</code> - Default directory path (string)
|
<code>defaultPath</code> - Default directory path (string)
|
||||||
@@ -558,7 +558,7 @@ EXAMPLE STRUCTURE:
|
|||||||
"pin": true,
|
"pin": true,
|
||||||
"enableTerminal": true,
|
"enableTerminal": true,
|
||||||
"enableTunnel": false,
|
"enableTunnel": false,
|
||||||
"enableConfigEditor": true,
|
"enableFileManager": true,
|
||||||
"defaultPath": "/var/www"
|
"defaultPath": "/var/www"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -709,10 +709,10 @@ EXAMPLE STRUCTURE:
|
|||||||
)}
|
)}
|
||||||
</Badge>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
{host.enableConfigEditor && (
|
{host.enableFileManager && (
|
||||||
<Badge variant="outline" className="text-xs px-1 py-0">
|
<Badge variant="outline" className="text-xs px-1 py-0">
|
||||||
<FileEdit className="h-2 w-2 mr-0.5"/>
|
<FileEdit className="h-2 w-2 mr-0.5"/>
|
||||||
Config
|
File Manager
|
||||||
</Badge>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ export function Server({ hostConfig, title, isVisible = true, isTopbarOpen = tru
|
|||||||
</Status>
|
</Status>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
{currentHostConfig?.enableConfigEditor && (
|
{currentHostConfig?.enableFileManager && (
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="font-semibold"
|
className="font-semibold"
|
||||||
@@ -155,7 +155,7 @@ export function Server({ hostConfig, title, isVisible = true, isTopbarOpen = tru
|
|||||||
? currentHostConfig.name.trim()
|
? currentHostConfig.name.trim()
|
||||||
: `${currentHostConfig.username}@${currentHostConfig.ip}`;
|
: `${currentHostConfig.username}@${currentHostConfig.ip}`;
|
||||||
addTab({
|
addTab({
|
||||||
type: 'config',
|
type: 'file_manager',
|
||||||
title: titleBase,
|
title: titleBase,
|
||||||
hostConfig: currentHostConfig,
|
hostConfig: currentHostConfig,
|
||||||
});
|
});
|
||||||
@@ -194,7 +194,7 @@ export function Server({ hostConfig, title, isVisible = true, isTopbarOpen = tru
|
|||||||
|
|
||||||
{/* Memory */}
|
{/* Memory */}
|
||||||
<div className="flex-1 min-w-0 px-2 py-2">
|
<div className="flex-1 min-w-0 px-2 py-2">
|
||||||
<h1 className="font-bold text-lg flex flex-row gap-2 mb-1">
|
<h1 className="font-bold xt-lg flex flex-row gap-2 mb-1">
|
||||||
<MemoryStick/>
|
<MemoryStick/>
|
||||||
{(() => {
|
{(() => {
|
||||||
const pct = metrics?.memory?.percent;
|
const pct = metrics?.memory?.percent;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ interface SSHHost {
|
|||||||
keyType?: string;
|
keyType?: string;
|
||||||
enableTerminal: boolean;
|
enableTerminal: boolean;
|
||||||
enableTunnel: boolean;
|
enableTunnel: boolean;
|
||||||
enableConfigEditor: boolean;
|
enableFileManager: boolean;
|
||||||
defaultPath: string;
|
defaultPath: string;
|
||||||
tunnelConnections: TunnelConnection[];
|
tunnelConnections: TunnelConnection[];
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ interface SSHHost {
|
|||||||
authType: string;
|
authType: string;
|
||||||
enableTerminal: boolean;
|
enableTerminal: boolean;
|
||||||
enableTunnel: boolean;
|
enableTunnel: boolean;
|
||||||
enableConfigEditor: boolean;
|
enableFileManager: boolean;
|
||||||
defaultPath: string;
|
defaultPath: string;
|
||||||
tunnelConnections: TunnelConnection[];
|
tunnelConnections: TunnelConnection[];
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ interface SSHHost {
|
|||||||
authType: string;
|
authType: string;
|
||||||
enableTerminal: boolean;
|
enableTerminal: boolean;
|
||||||
enableTunnel: boolean;
|
enableTunnel: boolean;
|
||||||
enableConfigEditor: boolean;
|
enableFileManager: boolean;
|
||||||
defaultPath: string;
|
defaultPath: string;
|
||||||
tunnelConnections: TunnelConnection[];
|
tunnelConnections: TunnelConnection[];
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ interface SSHHostData {
|
|||||||
keyType?: string;
|
keyType?: string;
|
||||||
enableTerminal?: boolean;
|
enableTerminal?: boolean;
|
||||||
enableTunnel?: boolean;
|
enableTunnel?: boolean;
|
||||||
enableConfigEditor?: boolean;
|
enableFileManager?: boolean;
|
||||||
defaultPath?: string;
|
defaultPath?: string;
|
||||||
tunnelConnections?: any[];
|
tunnelConnections?: any[];
|
||||||
}
|
}
|
||||||
@@ -36,7 +36,7 @@ interface SSHHost {
|
|||||||
keyType?: string;
|
keyType?: string;
|
||||||
enableTerminal: boolean;
|
enableTerminal: boolean;
|
||||||
enableTunnel: boolean;
|
enableTunnel: boolean;
|
||||||
enableConfigEditor: boolean;
|
enableFileManager: boolean;
|
||||||
defaultPath: string;
|
defaultPath: string;
|
||||||
tunnelConnections: any[];
|
tunnelConnections: any[];
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
@@ -80,7 +80,7 @@ interface TunnelStatus {
|
|||||||
retryExhausted?: boolean;
|
retryExhausted?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ConfigEditorFile {
|
interface FileManagerFile {
|
||||||
name: string;
|
name: string;
|
||||||
path: string;
|
path: string;
|
||||||
type?: 'file' | 'directory';
|
type?: 'file' | 'directory';
|
||||||
@@ -88,7 +88,7 @@ interface ConfigEditorFile {
|
|||||||
sshSessionId?: string;
|
sshSessionId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ConfigEditorShortcut {
|
interface FileManagerShortcut {
|
||||||
name: string;
|
name: string;
|
||||||
path: string;
|
path: string;
|
||||||
}
|
}
|
||||||
@@ -121,7 +121,7 @@ const tunnelApi = axios.create({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const configEditorApi = axios.create({
|
const fileManagerApi = axios.create({
|
||||||
baseURL: isLocalhost ? 'http://localhost:8084' : '',
|
baseURL: isLocalhost ? 'http://localhost:8084' : '',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@@ -165,7 +165,7 @@ tunnelApi.interceptors.request.use((config) => {
|
|||||||
return config;
|
return config;
|
||||||
});
|
});
|
||||||
|
|
||||||
configEditorApi.interceptors.request.use((config) => {
|
fileManagerApi.interceptors.request.use((config) => {
|
||||||
const token = getCookie('jwt');
|
const token = getCookie('jwt');
|
||||||
if (token) {
|
if (token) {
|
||||||
config.headers.Authorization = `Bearer ${token}`;
|
config.headers.Authorization = `Bearer ${token}`;
|
||||||
@@ -199,7 +199,7 @@ export async function createSSHHost(hostData: SSHHostData): Promise<SSHHost> {
|
|||||||
keyType: hostData.authType === 'key' ? hostData.keyType : '',
|
keyType: hostData.authType === 'key' ? hostData.keyType : '',
|
||||||
enableTerminal: hostData.enableTerminal !== false,
|
enableTerminal: hostData.enableTerminal !== false,
|
||||||
enableTunnel: hostData.enableTunnel !== false,
|
enableTunnel: hostData.enableTunnel !== false,
|
||||||
enableConfigEditor: hostData.enableConfigEditor !== false,
|
enableFileManager: hostData.enableFileManager !== false,
|
||||||
defaultPath: hostData.defaultPath || '/',
|
defaultPath: hostData.defaultPath || '/',
|
||||||
tunnelConnections: hostData.tunnelConnections || [],
|
tunnelConnections: hostData.tunnelConnections || [],
|
||||||
};
|
};
|
||||||
@@ -208,7 +208,7 @@ export async function createSSHHost(hostData: SSHHostData): Promise<SSHHost> {
|
|||||||
submitData.tunnelConnections = [];
|
submitData.tunnelConnections = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!submitData.enableConfigEditor) {
|
if (!submitData.enableFileManager) {
|
||||||
submitData.defaultPath = '';
|
submitData.defaultPath = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,7 +253,7 @@ export async function updateSSHHost(hostId: number, hostData: SSHHostData): Prom
|
|||||||
keyType: hostData.authType === 'key' ? hostData.keyType : '',
|
keyType: hostData.authType === 'key' ? hostData.keyType : '',
|
||||||
enableTerminal: hostData.enableTerminal !== false,
|
enableTerminal: hostData.enableTerminal !== false,
|
||||||
enableTunnel: hostData.enableTunnel !== false,
|
enableTunnel: hostData.enableTunnel !== false,
|
||||||
enableConfigEditor: hostData.enableConfigEditor !== false,
|
enableFileManager: hostData.enableFileManager !== false,
|
||||||
defaultPath: hostData.defaultPath || '/',
|
defaultPath: hostData.defaultPath || '/',
|
||||||
tunnelConnections: hostData.tunnelConnections || [],
|
tunnelConnections: hostData.tunnelConnections || [],
|
||||||
};
|
};
|
||||||
@@ -261,7 +261,7 @@ export async function updateSSHHost(hostId: number, hostData: SSHHostData): Prom
|
|||||||
if (!submitData.enableTunnel) {
|
if (!submitData.enableTunnel) {
|
||||||
submitData.tunnelConnections = [];
|
submitData.tunnelConnections = [];
|
||||||
}
|
}
|
||||||
if (!submitData.enableConfigEditor) {
|
if (!submitData.enableFileManager) {
|
||||||
submitData.defaultPath = '';
|
submitData.defaultPath = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,7 +362,7 @@ export async function cancelTunnel(tunnelName: string): Promise<any> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getConfigEditorRecent(hostId: number): Promise<ConfigEditorFile[]> {
|
export async function getFileManagerRecent(hostId: number): Promise<FileManagerFile[]> {
|
||||||
try {
|
try {
|
||||||
const response = await sshHostApi.get(`/ssh/file_manager/recent?hostId=${hostId}`);
|
const response = await sshHostApi.get(`/ssh/file_manager/recent?hostId=${hostId}`);
|
||||||
return response.data || [];
|
return response.data || [];
|
||||||
@@ -371,7 +371,7 @@ export async function getConfigEditorRecent(hostId: number): Promise<ConfigEdito
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function addConfigEditorRecent(file: {
|
export async function addFileManagerRecent(file: {
|
||||||
name: string;
|
name: string;
|
||||||
path: string;
|
path: string;
|
||||||
isSSH: boolean;
|
isSSH: boolean;
|
||||||
@@ -386,7 +386,7 @@ export async function addConfigEditorRecent(file: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function removeConfigEditorRecent(file: {
|
export async function removeFileManagerRecent(file: {
|
||||||
name: string;
|
name: string;
|
||||||
path: string;
|
path: string;
|
||||||
isSSH: boolean;
|
isSSH: boolean;
|
||||||
@@ -401,7 +401,7 @@ export async function removeConfigEditorRecent(file: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getConfigEditorPinned(hostId: number): Promise<ConfigEditorFile[]> {
|
export async function getFileManagerPinned(hostId: number): Promise<FileManagerFile[]> {
|
||||||
try {
|
try {
|
||||||
const response = await sshHostApi.get(`/ssh/file_manager/pinned?hostId=${hostId}`);
|
const response = await sshHostApi.get(`/ssh/file_manager/pinned?hostId=${hostId}`);
|
||||||
return response.data || [];
|
return response.data || [];
|
||||||
@@ -410,7 +410,7 @@ export async function getConfigEditorPinned(hostId: number): Promise<ConfigEdito
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function addConfigEditorPinned(file: {
|
export async function addFileManagerPinned(file: {
|
||||||
name: string;
|
name: string;
|
||||||
path: string;
|
path: string;
|
||||||
isSSH: boolean;
|
isSSH: boolean;
|
||||||
@@ -425,7 +425,7 @@ export async function addConfigEditorPinned(file: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function removeConfigEditorPinned(file: {
|
export async function removeFileManagerPinned(file: {
|
||||||
name: string;
|
name: string;
|
||||||
path: string;
|
path: string;
|
||||||
isSSH: boolean;
|
isSSH: boolean;
|
||||||
@@ -440,7 +440,7 @@ export async function removeConfigEditorPinned(file: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getConfigEditorShortcuts(hostId: number): Promise<ConfigEditorShortcut[]> {
|
export async function getFileManagerShortcuts(hostId: number): Promise<FileManagerShortcut[]> {
|
||||||
try {
|
try {
|
||||||
const response = await sshHostApi.get(`/ssh/file_manager/shortcuts?hostId=${hostId}`);
|
const response = await sshHostApi.get(`/ssh/file_manager/shortcuts?hostId=${hostId}`);
|
||||||
return response.data || [];
|
return response.data || [];
|
||||||
@@ -449,7 +449,7 @@ export async function getConfigEditorShortcuts(hostId: number): Promise<ConfigEd
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function addConfigEditorShortcut(shortcut: {
|
export async function addFileManagerShortcut(shortcut: {
|
||||||
name: string;
|
name: string;
|
||||||
path: string;
|
path: string;
|
||||||
isSSH: boolean;
|
isSSH: boolean;
|
||||||
@@ -464,7 +464,7 @@ export async function addConfigEditorShortcut(shortcut: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function removeConfigEditorShortcut(shortcut: {
|
export async function removeFileManagerShortcut(shortcut: {
|
||||||
name: string;
|
name: string;
|
||||||
path: string;
|
path: string;
|
||||||
isSSH: boolean;
|
isSSH: boolean;
|
||||||
@@ -488,7 +488,7 @@ export async function connectSSH(sessionId: string, config: {
|
|||||||
keyPassword?: string;
|
keyPassword?: string;
|
||||||
}): Promise<any> {
|
}): Promise<any> {
|
||||||
try {
|
try {
|
||||||
const response = await configEditorApi.post('/ssh/file_manager/ssh/connect', {
|
const response = await fileManagerApi.post('/ssh/file_manager/ssh/connect', {
|
||||||
sessionId,
|
sessionId,
|
||||||
...config
|
...config
|
||||||
});
|
});
|
||||||
@@ -500,7 +500,7 @@ export async function connectSSH(sessionId: string, config: {
|
|||||||
|
|
||||||
export async function disconnectSSH(sessionId: string): Promise<any> {
|
export async function disconnectSSH(sessionId: string): Promise<any> {
|
||||||
try {
|
try {
|
||||||
const response = await configEditorApi.post('/ssh/file_manager/ssh/disconnect', {sessionId});
|
const response = await fileManagerApi.post('/ssh/file_manager/ssh/disconnect', {sessionId});
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
@@ -509,7 +509,7 @@ export async function disconnectSSH(sessionId: string): Promise<any> {
|
|||||||
|
|
||||||
export async function getSSHStatus(sessionId: string): Promise<{ connected: boolean }> {
|
export async function getSSHStatus(sessionId: string): Promise<{ connected: boolean }> {
|
||||||
try {
|
try {
|
||||||
const response = await configEditorApi.get('/ssh/file_manager/ssh/status', {
|
const response = await fileManagerApi.get('/ssh/file_manager/ssh/status', {
|
||||||
params: {sessionId}
|
params: {sessionId}
|
||||||
});
|
});
|
||||||
return response.data;
|
return response.data;
|
||||||
@@ -520,7 +520,7 @@ export async function getSSHStatus(sessionId: string): Promise<{ connected: bool
|
|||||||
|
|
||||||
export async function listSSHFiles(sessionId: string, path: string): Promise<any[]> {
|
export async function listSSHFiles(sessionId: string, path: string): Promise<any[]> {
|
||||||
try {
|
try {
|
||||||
const response = await configEditorApi.get('/ssh/file_manager/ssh/listFiles', {
|
const response = await fileManagerApi.get('/ssh/file_manager/ssh/listFiles', {
|
||||||
params: {sessionId, path}
|
params: {sessionId, path}
|
||||||
});
|
});
|
||||||
return response.data || [];
|
return response.data || [];
|
||||||
@@ -531,7 +531,7 @@ export async function listSSHFiles(sessionId: string, path: string): Promise<any
|
|||||||
|
|
||||||
export async function readSSHFile(sessionId: string, path: string): Promise<{ content: string; path: string }> {
|
export async function readSSHFile(sessionId: string, path: string): Promise<{ content: string; path: string }> {
|
||||||
try {
|
try {
|
||||||
const response = await configEditorApi.get('/ssh/file_manager/ssh/readFile', {
|
const response = await fileManagerApi.get('/ssh/file_manager/ssh/readFile', {
|
||||||
params: {sessionId, path}
|
params: {sessionId, path}
|
||||||
});
|
});
|
||||||
return response.data;
|
return response.data;
|
||||||
@@ -542,7 +542,7 @@ export async function readSSHFile(sessionId: string, path: string): Promise<{ co
|
|||||||
|
|
||||||
export async function writeSSHFile(sessionId: string, path: string, content: string): Promise<any> {
|
export async function writeSSHFile(sessionId: string, path: string, content: string): Promise<any> {
|
||||||
try {
|
try {
|
||||||
const response = await configEditorApi.post('/ssh/file_manager/ssh/writeFile', {
|
const response = await fileManagerApi.post('/ssh/file_manager/ssh/writeFile', {
|
||||||
sessionId,
|
sessionId,
|
||||||
path,
|
path,
|
||||||
content
|
content
|
||||||
@@ -558,7 +558,7 @@ export async function writeSSHFile(sessionId: string, path: string, content: str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {sshHostApi, tunnelApi, configEditorApi};
|
export {sshHostApi, tunnelApi, fileManagerApi};
|
||||||
|
|
||||||
export async function getAllServerStatuses(): Promise<Record<number, ServerStatus>> {
|
export async function getAllServerStatuses(): Promise<Record<number, ServerStatus>> {
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user