CoolFace
Apppublic

legends810/testingnew

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes
ImportFolderButton.tsx142 linesDownload Raw Back to chat
1import React, { useState } from 'react';2import type { Message } from 'ai';3import { toast } from 'react-toastify';4import { MAX_FILES, isBinaryFile, shouldIncludeFile } from '~/utils/fileUtils';5import { createChatFromFolder } from '~/utils/folderImport';6import { logStore } from '~/lib/stores/logs'; // Assuming logStore is imported from this location7import { Button } from '~/components/ui/Button';8import { classNames } from '~/utils/classNames';9 10interface ImportFolderButtonProps {11  className?: string;12  importChat?: (description: string, messages: Message[]) => Promise<void>;13}14 15export const ImportFolderButton: React.FC<ImportFolderButtonProps> = ({ className, importChat }) => {16  const [isLoading, setIsLoading] = useState(false);17 18  const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {19    const allFiles = Array.from(e.target.files || []);20 21    const filteredFiles = allFiles.filter((file) => {22      const path = file.webkitRelativePath.split('/').slice(1).join('/');23      const include = shouldIncludeFile(path);24 25      return include;26    });27 28    if (filteredFiles.length === 0) {29      const error = new Error('No valid files found');30      logStore.logError('File import failed - no valid files', error, { folderName: 'Unknown Folder' });31      toast.error('No files found in the selected folder');32 33      return;34    }35 36    if (filteredFiles.length > MAX_FILES) {37      const error = new Error(`Too many files: ${filteredFiles.length}`);38      logStore.logError('File import failed - too many files', error, {39        fileCount: filteredFiles.length,40        maxFiles: MAX_FILES,41      });42      toast.error(43        `This folder contains ${filteredFiles.length.toLocaleString()} files. This product is not yet optimized for very large projects. Please select a folder with fewer than ${MAX_FILES.toLocaleString()} files.`,44      );45 46      return;47    }48 49    const folderName = filteredFiles[0]?.webkitRelativePath.split('/')[0] || 'Unknown Folder';50    setIsLoading(true);51 52    const loadingToast = toast.loading(`Importing ${folderName}...`);53 54    try {55      const fileChecks = await Promise.all(56        filteredFiles.map(async (file) => ({57          file,58          isBinary: await isBinaryFile(file),59        })),60      );61 62      const textFiles = fileChecks.filter((f) => !f.isBinary).map((f) => f.file);63      const binaryFilePaths = fileChecks64        .filter((f) => f.isBinary)65        .map((f) => f.file.webkitRelativePath.split('/').slice(1).join('/'));66 67      if (textFiles.length === 0) {68        const error = new Error('No text files found');69        logStore.logError('File import failed - no text files', error, { folderName });70        toast.error('No text files found in the selected folder');71 72        return;73      }74 75      if (binaryFilePaths.length > 0) {76        logStore.logWarning(`Skipping binary files during import`, {77          folderName,78          binaryCount: binaryFilePaths.length,79        });80        toast.info(`Skipping ${binaryFilePaths.length} binary files`);81      }82 83      const messages = await createChatFromFolder(textFiles, binaryFilePaths, folderName);84 85      if (importChat) {86        await importChat(folderName, [...messages]);87      }88 89      logStore.logSystem('Folder imported successfully', {90        folderName,91        textFileCount: textFiles.length,92        binaryFileCount: binaryFilePaths.length,93      });94      toast.success('Folder imported successfully');95    } catch (error) {96      logStore.logError('Failed to import folder', error, { folderName });97      console.error('Failed to import folder:', error);98      toast.error('Failed to import folder');99    } finally {100      setIsLoading(false);101      toast.dismiss(loadingToast);102      e.target.value = ''; // Reset file input103    }104  };105 106  return (107    <>108      <input109        type="file"110        id="folder-import"111        className="hidden"112        webkitdirectory=""113        directory=""114        onChange={handleFileChange}115        {...({} as any)}116      />117      <Button118        onClick={() => {119          const input = document.getElementById('folder-import');120          input?.click();121        }}122        title="Import Folder"123        variant="outline"124        size="lg"125        className={classNames(126          'gap-2 bg-[#F5F5F5] dark:bg-[#252525]',127          'text-bolt-elements-textPrimary dark:text-white',128          'hover:bg-[#E5E5E5] dark:hover:bg-[#333333]',129          'border-[#E5E5E5] dark:border-[#333333]',130          'h-10 px-4 py-2 min-w-[120px] justify-center',131          'transition-all duration-200 ease-in-out',132          className,133        )}134        disabled={isLoading}135      >136        <span className="i-ph:upload-simple w-4 h-4" />137        {isLoading ? 'Importing...' : 'Import Folder'}138      </Button>139    </>140  );141};142