mirror of
https://github.com/lordmathis/lemma.git
synced 2025-11-05 23:44:22 +00:00
Implement file upload functionality in FileActions and FileTree components
This commit is contained in:
@@ -9,17 +9,18 @@ import {
|
||||
} from '@tabler/icons-react';
|
||||
import { useModalContext } from '../../contexts/ModalContext';
|
||||
import { useWorkspace } from '../../hooks/useWorkspace';
|
||||
import { useFileOperations } from '../../hooks/useFileOperations';
|
||||
|
||||
interface FileActionsProps {
|
||||
handlePullChanges: () => Promise<boolean>;
|
||||
selectedFile: string | null;
|
||||
onFileUpload?: (files: FileList) => Promise<void>;
|
||||
loadFileList: () => Promise<void>;
|
||||
}
|
||||
|
||||
const FileActions: React.FC<FileActionsProps> = ({
|
||||
handlePullChanges,
|
||||
selectedFile,
|
||||
onFileUpload,
|
||||
loadFileList,
|
||||
}) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const {
|
||||
@@ -28,6 +29,8 @@ const FileActions: React.FC<FileActionsProps> = ({
|
||||
setCommitMessageModalVisible,
|
||||
} = useModalContext();
|
||||
|
||||
const { handleUpload } = useFileOperations();
|
||||
|
||||
// Hidden file input for upload
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
@@ -43,10 +46,20 @@ const FileActions: React.FC<FileActionsProps> = ({
|
||||
event: React.ChangeEvent<HTMLInputElement>
|
||||
): void => {
|
||||
const files = event.target.files;
|
||||
if (files && files.length > 0 && onFileUpload) {
|
||||
onFileUpload(files).catch((error) => {
|
||||
console.error('Error uploading files:', error);
|
||||
});
|
||||
if (files && files.length > 0) {
|
||||
const uploadFiles = async () => {
|
||||
try {
|
||||
const success = await handleUpload(files);
|
||||
if (success) {
|
||||
await loadFileList();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error uploading files:', error);
|
||||
}
|
||||
};
|
||||
|
||||
void uploadFiles();
|
||||
|
||||
// Reset the input so the same file can be selected again
|
||||
event.target.value = '';
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
} from '@tabler/icons-react';
|
||||
import { Tooltip, Text, Box } from '@mantine/core';
|
||||
import useResizeObserver from '@react-hook/resize-observer';
|
||||
import { useFileOperations } from '../../hooks/useFileOperations';
|
||||
import type { FileNode } from '@/types/models';
|
||||
|
||||
interface Size {
|
||||
@@ -19,12 +20,7 @@ interface FileTreeProps {
|
||||
files: FileNode[];
|
||||
handleFileSelect: (filePath: string | null) => Promise<void>;
|
||||
showHiddenFiles: boolean;
|
||||
onFileMove?: (
|
||||
dragIds: string[],
|
||||
parentId: string | null,
|
||||
index: number
|
||||
) => Promise<void>;
|
||||
onFileUpload?: (files: FileList, targetPath?: string) => Promise<void>;
|
||||
loadFileList: () => Promise<void>;
|
||||
}
|
||||
|
||||
const useSize = (target: React.RefObject<HTMLElement>): Size | undefined => {
|
||||
@@ -111,11 +107,11 @@ const FileTree: React.FC<FileTreeProps> = ({
|
||||
files,
|
||||
handleFileSelect,
|
||||
showHiddenFiles,
|
||||
onFileMove,
|
||||
onFileUpload,
|
||||
loadFileList,
|
||||
}) => {
|
||||
const target = useRef<HTMLDivElement>(null);
|
||||
const size = useSize(target);
|
||||
const { handleMove, handleUpload } = useFileOperations();
|
||||
|
||||
// State for drag and drop overlay
|
||||
const [isDragOver, setIsDragOver] = useState(false);
|
||||
@@ -136,7 +132,7 @@ const FileTree: React.FC<FileTreeProps> = ({
|
||||
};
|
||||
|
||||
// Handle file movement within the tree
|
||||
const handleMove = useCallback(
|
||||
const handleTreeMove = useCallback(
|
||||
async ({
|
||||
dragIds,
|
||||
parentId,
|
||||
@@ -146,11 +142,16 @@ const FileTree: React.FC<FileTreeProps> = ({
|
||||
parentId: string | null;
|
||||
index: number;
|
||||
}) => {
|
||||
if (onFileMove) {
|
||||
await onFileMove(dragIds, parentId, index);
|
||||
try {
|
||||
const success = await handleMove(dragIds, parentId, index);
|
||||
if (success) {
|
||||
await loadFileList();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error moving files:', error);
|
||||
}
|
||||
},
|
||||
[onFileMove]
|
||||
[handleMove, loadFileList]
|
||||
);
|
||||
|
||||
// External file drag and drop handlers
|
||||
@@ -189,14 +190,22 @@ const FileTree: React.FC<FileTreeProps> = ({
|
||||
setIsDragOver(false);
|
||||
|
||||
const { files } = e.dataTransfer;
|
||||
if (files && files.length > 0 && onFileUpload) {
|
||||
// Handle the upload without awaiting to avoid the eslint warning
|
||||
onFileUpload(files).catch((error) => {
|
||||
console.error('Error uploading files:', error);
|
||||
});
|
||||
if (files && files.length > 0) {
|
||||
const uploadFiles = async () => {
|
||||
try {
|
||||
const success = await handleUpload(files);
|
||||
if (success) {
|
||||
await loadFileList();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error uploading files:', error);
|
||||
}
|
||||
};
|
||||
|
||||
void uploadFiles();
|
||||
}
|
||||
},
|
||||
[onFileUpload]
|
||||
[handleUpload, loadFileList]
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -247,7 +256,8 @@ const FileTree: React.FC<FileTreeProps> = ({
|
||||
height={size.height}
|
||||
indent={24}
|
||||
rowHeight={28}
|
||||
onMove={handleMove}
|
||||
// Enable drag and drop for moving files
|
||||
onMove={handleTreeMove}
|
||||
onActivate={(node) => {
|
||||
const fileNode = node.data;
|
||||
if (!node.isInternal) {
|
||||
|
||||
@@ -37,11 +37,16 @@ const Sidebar: React.FC<SidebarProps> = ({
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
>
|
||||
<FileActions handlePullChanges={handlePull} selectedFile={selectedFile} />
|
||||
<FileActions
|
||||
handlePullChanges={handlePull}
|
||||
selectedFile={selectedFile}
|
||||
loadFileList={loadFileList}
|
||||
/>
|
||||
<FileTree
|
||||
files={files}
|
||||
handleFileSelect={handleFileSelect}
|
||||
showHiddenFiles={currentWorkspace?.showHiddenFiles || false}
|
||||
loadFileList={loadFileList}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -9,6 +9,12 @@ interface UseFileOperationsResult {
|
||||
handleSave: (filePath: string, content: string) => Promise<boolean>;
|
||||
handleDelete: (filePath: string) => Promise<boolean>;
|
||||
handleCreate: (fileName: string, initialContent?: string) => Promise<boolean>;
|
||||
handleUpload: (files: FileList, targetPath?: string) => Promise<boolean>;
|
||||
handleMove: (
|
||||
dragIds: string[],
|
||||
parentId: string | null,
|
||||
index: number
|
||||
) => Promise<boolean>;
|
||||
}
|
||||
|
||||
export const useFileOperations = (): UseFileOperationsResult => {
|
||||
@@ -109,5 +115,83 @@ export const useFileOperations = (): UseFileOperationsResult => {
|
||||
[currentWorkspace, autoCommit]
|
||||
);
|
||||
|
||||
return { handleSave, handleDelete, handleCreate };
|
||||
// Add these to your hook implementation:
|
||||
const handleUpload = useCallback(
|
||||
async (files: FileList, targetPath?: string): Promise<boolean> => {
|
||||
if (!currentWorkspace) return false;
|
||||
|
||||
try {
|
||||
// TODO: Implement your file upload API call
|
||||
// Example:
|
||||
// const formData = new FormData();
|
||||
// Array.from(files).forEach((file, index) => {
|
||||
// formData.append(`file${index}`, file);
|
||||
// });
|
||||
// if (targetPath) {
|
||||
// formData.append('targetPath', targetPath);
|
||||
// }
|
||||
// await uploadFiles(currentWorkspace.name, formData);
|
||||
|
||||
notifications.show({
|
||||
title: 'Success',
|
||||
message: `Successfully uploaded ${files.length} file(s)`,
|
||||
color: 'green',
|
||||
});
|
||||
|
||||
// Auto-commit if enabled
|
||||
await autoCommit('multiple files', FileAction.Create);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error uploading files:', error);
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: 'Failed to upload files',
|
||||
color: 'red',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
},
|
||||
[currentWorkspace, autoCommit]
|
||||
);
|
||||
|
||||
const handleMove = useCallback(
|
||||
async (
|
||||
dragIds: string[],
|
||||
parentId: string | null,
|
||||
index: number
|
||||
): Promise<boolean> => {
|
||||
if (!currentWorkspace) return false;
|
||||
|
||||
try {
|
||||
// TODO: Implement your file move API call
|
||||
// Example:
|
||||
// await moveFiles(currentWorkspace.name, {
|
||||
// sourceIds: dragIds,
|
||||
// targetParentId: parentId,
|
||||
// targetIndex: index
|
||||
// });
|
||||
|
||||
notifications.show({
|
||||
title: 'Success',
|
||||
message: `Successfully moved ${dragIds.length} file(s)`,
|
||||
color: 'green',
|
||||
});
|
||||
|
||||
// Auto-commit if enabled
|
||||
await autoCommit('multiple files', FileAction.Update);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error moving files:', error);
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: 'Failed to move files',
|
||||
color: 'red',
|
||||
});
|
||||
return false;
|
||||
}
|
||||
},
|
||||
[currentWorkspace, autoCommit]
|
||||
);
|
||||
|
||||
return { handleSave, handleDelete, handleCreate, handleUpload, handleMove };
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user