Format code
This commit is contained in:
@@ -1,21 +1,21 @@
|
||||
import React, { useState, useRef } from 'react';
|
||||
import { Button } from '@/components/ui/button.tsx';
|
||||
import { Input } from '@/components/ui/input.tsx';
|
||||
import { Card } from '@/components/ui/card.tsx';
|
||||
import { Separator } from '@/components/ui/separator.tsx';
|
||||
import {
|
||||
Upload,
|
||||
FilePlus,
|
||||
FolderPlus,
|
||||
Trash2,
|
||||
Edit3,
|
||||
X,
|
||||
import React, {useState, useRef} from 'react';
|
||||
import {Button} from '@/components/ui/button.tsx';
|
||||
import {Input} from '@/components/ui/input.tsx';
|
||||
import {Card} from '@/components/ui/card.tsx';
|
||||
import {Separator} from '@/components/ui/separator.tsx';
|
||||
import {
|
||||
Upload,
|
||||
FilePlus,
|
||||
FolderPlus,
|
||||
Trash2,
|
||||
Edit3,
|
||||
X,
|
||||
Check,
|
||||
AlertCircle,
|
||||
FileText,
|
||||
Folder
|
||||
} from 'lucide-react';
|
||||
import { cn } from '@/lib/utils.ts';
|
||||
import {cn} from '@/lib/utils.ts';
|
||||
|
||||
interface FileManagerOperationsProps {
|
||||
currentPath: string;
|
||||
@@ -26,18 +26,18 @@ interface FileManagerOperationsProps {
|
||||
}
|
||||
|
||||
export function FileManagerOperations({
|
||||
currentPath,
|
||||
sshSessionId,
|
||||
onOperationComplete,
|
||||
onError,
|
||||
onSuccess
|
||||
}: FileManagerOperationsProps) {
|
||||
currentPath,
|
||||
sshSessionId,
|
||||
onOperationComplete,
|
||||
onError,
|
||||
onSuccess
|
||||
}: FileManagerOperationsProps) {
|
||||
const [showUpload, setShowUpload] = useState(false);
|
||||
const [showCreateFile, setShowCreateFile] = useState(false);
|
||||
const [showCreateFolder, setShowCreateFolder] = useState(false);
|
||||
const [showDelete, setShowDelete] = useState(false);
|
||||
const [showRename, setShowRename] = useState(false);
|
||||
|
||||
|
||||
const [uploadFile, setUploadFile] = useState<File | null>(null);
|
||||
const [newFileName, setNewFileName] = useState('');
|
||||
const [newFolderName, setNewFolderName] = useState('');
|
||||
@@ -46,18 +46,18 @@ export function FileManagerOperations({
|
||||
const [renamePath, setRenamePath] = useState('');
|
||||
const [renameIsDirectory, setRenameIsDirectory] = useState(false);
|
||||
const [newName, setNewName] = useState('');
|
||||
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const handleFileUpload = async () => {
|
||||
if (!uploadFile || !sshSessionId) return;
|
||||
|
||||
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const content = await uploadFile.text();
|
||||
const { uploadSSHFile } = await import('@/ui/main-axios.ts');
|
||||
|
||||
const {uploadSSHFile} = await import('@/ui/main-axios.ts');
|
||||
|
||||
await uploadSSHFile(sshSessionId, currentPath, uploadFile.name, content);
|
||||
onSuccess(`File "${uploadFile.name}" uploaded successfully`);
|
||||
setShowUpload(false);
|
||||
@@ -72,11 +72,11 @@ export function FileManagerOperations({
|
||||
|
||||
const handleCreateFile = async () => {
|
||||
if (!newFileName.trim() || !sshSessionId) return;
|
||||
|
||||
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const { createSSHFile } = await import('@/ui/main-axios.ts');
|
||||
|
||||
const {createSSHFile} = await import('@/ui/main-axios.ts');
|
||||
|
||||
await createSSHFile(sshSessionId, currentPath, newFileName.trim());
|
||||
onSuccess(`File "${newFileName.trim()}" created successfully`);
|
||||
setShowCreateFile(false);
|
||||
@@ -91,11 +91,11 @@ export function FileManagerOperations({
|
||||
|
||||
const handleCreateFolder = async () => {
|
||||
if (!newFolderName.trim() || !sshSessionId) return;
|
||||
|
||||
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const { createSSHFolder } = await import('@/ui/main-axios.ts');
|
||||
|
||||
const {createSSHFolder} = await import('@/ui/main-axios.ts');
|
||||
|
||||
await createSSHFolder(sshSessionId, currentPath, newFolderName.trim());
|
||||
onSuccess(`Folder "${newFolderName.trim()}" created successfully`);
|
||||
setShowCreateFolder(false);
|
||||
@@ -110,11 +110,11 @@ export function FileManagerOperations({
|
||||
|
||||
const handleDelete = async () => {
|
||||
if (!deletePath || !sshSessionId) return;
|
||||
|
||||
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const { deleteSSHItem } = await import('@/ui/main-axios.ts');
|
||||
|
||||
const {deleteSSHItem} = await import('@/ui/main-axios.ts');
|
||||
|
||||
await deleteSSHItem(sshSessionId, deletePath, deleteIsDirectory);
|
||||
onSuccess(`${deleteIsDirectory ? 'Folder' : 'File'} deleted successfully`);
|
||||
setShowDelete(false);
|
||||
@@ -130,11 +130,11 @@ export function FileManagerOperations({
|
||||
|
||||
const handleRename = async () => {
|
||||
if (!renamePath || !newName.trim() || !sshSessionId) return;
|
||||
|
||||
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const { renameSSHItem } = await import('@/ui/main-axios.ts');
|
||||
|
||||
const {renameSSHItem} = await import('@/ui/main-axios.ts');
|
||||
|
||||
await renameSSHItem(sshSessionId, renamePath, newName.trim());
|
||||
onSuccess(`${renameIsDirectory ? 'Folder' : 'File'} renamed successfully`);
|
||||
setShowRename(false);
|
||||
@@ -179,7 +179,7 @@ export function FileManagerOperations({
|
||||
if (!sshSessionId) {
|
||||
return (
|
||||
<div className="p-4 text-center">
|
||||
<AlertCircle className="w-8 h-8 text-muted-foreground mx-auto mb-2" />
|
||||
<AlertCircle className="w-8 h-8 text-muted-foreground mx-auto mb-2"/>
|
||||
<p className="text-sm text-muted-foreground">Connect to SSH to use file operations</p>
|
||||
</div>
|
||||
);
|
||||
@@ -187,7 +187,6 @@ export function FileManagerOperations({
|
||||
|
||||
return (
|
||||
<div className="p-4 space-y-4">
|
||||
{/* Operation Buttons */}
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
@@ -195,7 +194,7 @@ export function FileManagerOperations({
|
||||
onClick={() => setShowUpload(true)}
|
||||
className="h-10 bg-[#18181b] border-2 border-[#303032] hover:border-[#434345] hover:bg-[#2d2d30]"
|
||||
>
|
||||
<Upload className="w-4 h-4 mr-2" />
|
||||
<Upload className="w-4 h-4 mr-2"/>
|
||||
Upload File
|
||||
</Button>
|
||||
<Button
|
||||
@@ -204,7 +203,7 @@ export function FileManagerOperations({
|
||||
onClick={() => setShowCreateFile(true)}
|
||||
className="h-10 bg-[#18181b] border-2 border-[#303032] hover:border-[#434345] hover:bg-[#2d2d30]"
|
||||
>
|
||||
<FilePlus className="w-4 h-4 mr-2" />
|
||||
<FilePlus className="w-4 h-4 mr-2"/>
|
||||
New File
|
||||
</Button>
|
||||
<Button
|
||||
@@ -213,7 +212,7 @@ export function FileManagerOperations({
|
||||
onClick={() => setShowCreateFolder(true)}
|
||||
className="h-10 bg-[#18181b] border-2 border-[#303032] hover:border-[#434345] hover:bg-[#2d2d30]"
|
||||
>
|
||||
<FolderPlus className="w-4 h-4 mr-2" />
|
||||
<FolderPlus className="w-4 h-4 mr-2"/>
|
||||
New Folder
|
||||
</Button>
|
||||
<Button
|
||||
@@ -222,7 +221,7 @@ export function FileManagerOperations({
|
||||
onClick={() => setShowRename(true)}
|
||||
className="h-10 bg-[#18181b] border-2 border-[#303032] hover:border-[#434345] hover:bg-[#2d2d30]"
|
||||
>
|
||||
<Edit3 className="w-4 h-4 mr-2" />
|
||||
<Edit3 className="w-4 h-4 mr-2"/>
|
||||
Rename
|
||||
</Button>
|
||||
<Button
|
||||
@@ -231,29 +230,27 @@ export function FileManagerOperations({
|
||||
onClick={() => setShowDelete(true)}
|
||||
className="h-10 bg-[#18181b] border-2 border-[#303032] hover:border-[#434345] hover:bg-[#2d2d30] col-span-2"
|
||||
>
|
||||
<Trash2 className="w-4 h-4 mr-2" />
|
||||
<Trash2 className="w-4 h-4 mr-2"/>
|
||||
Delete Item
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Current Path Display */}
|
||||
<div className="bg-[#18181b] border-2 border-[#303032] rounded-lg p-3">
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
<Folder className="w-4 h-4 text-blue-400" />
|
||||
<Folder className="w-4 h-4 text-blue-400"/>
|
||||
<span className="text-muted-foreground">Current Path:</span>
|
||||
<span className="text-white font-mono truncate">{currentPath}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Separator className="p-0.25 bg-[#303032]" />
|
||||
<Separator className="p-0.25 bg-[#303032]"/>
|
||||
|
||||
{/* Upload File Modal */}
|
||||
{showUpload && (
|
||||
<Card className="bg-[#18181b] border-2 border-[#303032] p-4">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold text-white flex items-center gap-2">
|
||||
<Upload className="w-5 h-5" />
|
||||
<Upload className="w-5 h-5"/>
|
||||
Upload File
|
||||
</h3>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
@@ -266,15 +263,15 @@ export function FileManagerOperations({
|
||||
onClick={() => setShowUpload(false)}
|
||||
className="h-8 w-8 p-0"
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
<X className="w-4 h-4"/>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="border-2 border-dashed border-[#434345] rounded-lg p-6 text-center">
|
||||
{uploadFile ? (
|
||||
<div className="space-y-2">
|
||||
<FileText className="w-8 h-8 text-blue-400 mx-auto" />
|
||||
<FileText className="w-8 h-8 text-blue-400 mx-auto"/>
|
||||
<p className="text-white font-medium">{uploadFile.name}</p>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{(uploadFile.size / 1024).toFixed(2)} KB
|
||||
@@ -290,7 +287,7 @@ export function FileManagerOperations({
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-2">
|
||||
<Upload className="w-8 h-8 text-muted-foreground mx-auto" />
|
||||
<Upload className="w-8 h-8 text-muted-foreground mx-auto"/>
|
||||
<p className="text-white">Click to select a file</p>
|
||||
<Button
|
||||
variant="outline"
|
||||
@@ -302,7 +299,7 @@ export function FileManagerOperations({
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
<input
|
||||
ref={fileInputRef}
|
||||
type="file"
|
||||
@@ -310,7 +307,7 @@ export function FileManagerOperations({
|
||||
className="hidden"
|
||||
accept="*/*"
|
||||
/>
|
||||
|
||||
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
onClick={handleFileUpload}
|
||||
@@ -331,12 +328,11 @@ export function FileManagerOperations({
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* Create File Modal */}
|
||||
{showCreateFile && (
|
||||
<Card className="bg-[#18181b] border-2 border-[#303032] p-4">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="text-lg font-semibold text-white flex items-center gap-2">
|
||||
<FilePlus className="w-5 h-5" />
|
||||
<FilePlus className="w-5 h-5"/>
|
||||
Create New File
|
||||
</h3>
|
||||
<Button
|
||||
@@ -345,10 +341,10 @@ export function FileManagerOperations({
|
||||
onClick={() => setShowCreateFile(false)}
|
||||
className="h-8 w-8 p-0"
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
<X className="w-4 h-4"/>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className="text-sm font-medium text-white mb-2 block">
|
||||
@@ -362,7 +358,7 @@ export function FileManagerOperations({
|
||||
onKeyDown={(e) => e.key === 'Enter' && handleCreateFile()}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
onClick={handleCreateFile}
|
||||
@@ -383,12 +379,11 @@ export function FileManagerOperations({
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* Create Folder Modal */}
|
||||
{showCreateFolder && (
|
||||
<Card className="bg-[#18181b] border-2 border-[#303032] p-4">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="text-lg font-semibold text-white flex items-center gap-2">
|
||||
<FolderPlus className="w-5 h-5" />
|
||||
<FolderPlus className="w-5 h-5"/>
|
||||
Create New Folder
|
||||
</h3>
|
||||
<Button
|
||||
@@ -397,10 +392,10 @@ export function FileManagerOperations({
|
||||
onClick={() => setShowCreateFolder(false)}
|
||||
className="h-8 w-8 p-0"
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
<X className="w-4 h-4"/>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className="text-sm font-medium text-white mb-2 block">
|
||||
@@ -414,7 +409,7 @@ export function FileManagerOperations({
|
||||
onKeyDown={(e) => e.key === 'Enter' && handleCreateFolder()}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
onClick={handleCreateFolder}
|
||||
@@ -435,12 +430,11 @@ export function FileManagerOperations({
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* Delete Modal */}
|
||||
{showDelete && (
|
||||
<Card className="bg-[#18181b] border-2 border-[#303032] p-4">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="text-lg font-semibold text-white flex items-center gap-2">
|
||||
<Trash2 className="w-5 h-5 text-red-400" />
|
||||
<Trash2 className="w-5 h-5 text-red-400"/>
|
||||
Delete Item
|
||||
</h3>
|
||||
<Button
|
||||
@@ -449,18 +443,18 @@ export function FileManagerOperations({
|
||||
onClick={() => setShowDelete(false)}
|
||||
className="h-8 w-8 p-0"
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
<X className="w-4 h-4"/>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="bg-red-900/20 border border-red-500/30 rounded-lg p-3">
|
||||
<div className="flex items-center gap-2 text-red-300">
|
||||
<AlertCircle className="w-4 h-4" />
|
||||
<AlertCircle className="w-4 h-4"/>
|
||||
<span className="text-sm font-medium">Warning: This action cannot be undone</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div>
|
||||
<label className="text-sm font-medium text-white mb-2 block">
|
||||
Item Path
|
||||
@@ -472,7 +466,7 @@ export function FileManagerOperations({
|
||||
className="bg-[#23232a] border-2 border-[#434345] text-white"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
@@ -485,7 +479,7 @@ export function FileManagerOperations({
|
||||
This is a directory (will delete recursively)
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
onClick={handleDelete}
|
||||
@@ -507,12 +501,11 @@ export function FileManagerOperations({
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* Rename Modal */}
|
||||
{showRename && (
|
||||
<Card className="bg-[#18181b] border-2 border-[#303032] p-4">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="text-lg font-semibold text-white flex items-center gap-2">
|
||||
<Edit3 className="w-5 h-5" />
|
||||
<Edit3 className="w-5 h-5"/>
|
||||
Rename Item
|
||||
</h3>
|
||||
<Button
|
||||
@@ -521,10 +514,10 @@ export function FileManagerOperations({
|
||||
onClick={() => setShowRename(false)}
|
||||
className="h-8 w-8 p-0"
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
<X className="w-4 h-4"/>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className="text-sm font-medium text-white mb-2 block">
|
||||
@@ -537,7 +530,7 @@ export function FileManagerOperations({
|
||||
className="bg-[#23232a] border-2 border-[#434345] text-white"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
<div>
|
||||
<label className="text-sm font-medium text-white mb-2 block">
|
||||
New Name
|
||||
@@ -550,7 +543,7 @@ export function FileManagerOperations({
|
||||
onKeyDown={(e) => e.key === 'Enter' && handleRename()}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
@@ -563,7 +556,7 @@ export function FileManagerOperations({
|
||||
This is a directory
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
onClick={handleRename}
|
||||
|
||||
Reference in New Issue
Block a user