diff --git a/frontend/src/components/shared/FileGrid.tsx b/frontend/src/components/shared/FileGrid.tsx new file mode 100644 index 000000000..c1a5df58b --- /dev/null +++ b/frontend/src/components/shared/FileGrid.tsx @@ -0,0 +1,168 @@ +import React, { useState } from "react"; +import { Box, Flex, Group, Text, Button, TextInput, Select, Badge } from "@mantine/core"; +import { useTranslation } from "react-i18next"; +import SearchIcon from "@mui/icons-material/Search"; +import SortIcon from "@mui/icons-material/Sort"; +import FileCard from "../fileManagement/FileCard"; +import { FileWithUrl } from "../../types/file"; + +interface FileGridProps { + files: FileWithUrl[]; + onRemove?: (index: number) => void; + onDoubleClick?: (file: FileWithUrl) => void; + onView?: (file: FileWithUrl) => void; + onEdit?: (file: FileWithUrl) => void; + onSelect?: (fileId: string) => void; + selectedFiles?: string[]; + showSearch?: boolean; + showSort?: boolean; + maxDisplay?: number; // If set, shows only this many files with "Show All" option + onShowAll?: () => void; + showingAll?: boolean; +} + +type SortOption = 'date' | 'name' | 'size'; + +const FileGrid = ({ + files, + onRemove, + onDoubleClick, + onView, + onEdit, + onSelect, + selectedFiles = [], + showSearch = false, + showSort = false, + maxDisplay, + onShowAll, + showingAll = false +}: FileGridProps) => { + const { t } = useTranslation(); + const [searchTerm, setSearchTerm] = useState(""); + const [sortBy, setSortBy] = useState('date'); + + // Filter files based on search term + const filteredFiles = files.filter(file => + file.name.toLowerCase().includes(searchTerm.toLowerCase()) + ); + + // Sort files + const sortedFiles = [...filteredFiles].sort((a, b) => { + switch (sortBy) { + case 'date': + return (b.lastModified || 0) - (a.lastModified || 0); + case 'name': + return a.name.localeCompare(b.name); + case 'size': + return (b.size || 0) - (a.size || 0); + default: + return 0; + } + }); + + // Apply max display limit if specified + const displayFiles = maxDisplay && !showingAll + ? sortedFiles.slice(0, maxDisplay) + : sortedFiles; + + const hasMoreFiles = maxDisplay && !showingAll && sortedFiles.length > maxDisplay; + + return ( + + {/* Search and Sort Controls */} + {(showSearch || showSort) && ( + + {showSearch && ( + } + value={searchTerm} + onChange={(e) => setSearchTerm(e.currentTarget.value)} + style={{ flexGrow: 1, maxWidth: 300, minWidth: 200 }} + /> + )} + + {showSort && ( + )} - - {/* File Picker Modal */} - setShowFilePickerModal(false)} - storedFiles={sharedFiles} - onSelectFiles={handleStorageSelection} - /> + {/* Recent Files Section */} + {showRecentFiles && recentFiles.length > 0 && ( + + + + {t("fileUpload.recentFiles", "Recent Files")} + + setSelectedFiles([])} + onAddToUpload={handleSelectedRecentFiles} + /> + + setShowingAllRecent(true)} + showingAll={showingAllRecent} + showSearch={showingAllRecent} + showSort={showingAllRecent} + /> + + {showingAllRecent && ( +
+ +
+ )} +
+ )} + ); }; diff --git a/frontend/src/components/shared/MultiSelectControls.tsx b/frontend/src/components/shared/MultiSelectControls.tsx new file mode 100644 index 000000000..69fca71b2 --- /dev/null +++ b/frontend/src/components/shared/MultiSelectControls.tsx @@ -0,0 +1,76 @@ +import React from "react"; +import { Box, Group, Text, Button } from "@mantine/core"; +import { useTranslation } from "react-i18next"; + +interface MultiSelectControlsProps { + selectedCount: number; + onClearSelection: () => void; + onOpenInFileEditor?: () => void; + onOpenInPageEditor?: () => void; + onAddToUpload?: () => void; // New action for recent files +} + +const MultiSelectControls = ({ + selectedCount, + onClearSelection, + onOpenInFileEditor, + onOpenInPageEditor, + onAddToUpload +}: MultiSelectControlsProps) => { + const { t } = useTranslation(); + + if (selectedCount === 0) return null; + + return ( + + + + {selectedCount} {t("fileManager.filesSelected", "files selected")} + + + + + {onAddToUpload && ( + + )} + + {onOpenInFileEditor && ( + + )} + + {onOpenInPageEditor && ( + + )} + + + + ); +}; + +export default MultiSelectControls; \ No newline at end of file diff --git a/frontend/src/components/shared/TopControls.tsx b/frontend/src/components/shared/TopControls.tsx index 13c82103f..cab50337a 100644 --- a/frontend/src/components/shared/TopControls.tsx +++ b/frontend/src/components/shared/TopControls.tsx @@ -8,7 +8,6 @@ import LightModeIcon from '@mui/icons-material/LightMode'; import AutoAwesomeIcon from '@mui/icons-material/AutoAwesome'; import VisibilityIcon from "@mui/icons-material/Visibility"; import EditNoteIcon from "@mui/icons-material/EditNote"; -import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile"; import FolderIcon from "@mui/icons-material/Folder"; import { Group } from "@mantine/core"; @@ -29,14 +28,6 @@ const VIEW_OPTIONS = [ ), value: "pageEditor", }, - { - label: ( - - - - ), - value: "fileManager", - }, { label: ( diff --git a/frontend/src/pages/HomePage.tsx b/frontend/src/pages/HomePage.tsx index 515676bd8..1660b6544 100644 --- a/frontend/src/pages/HomePage.tsx +++ b/frontend/src/pages/HomePage.tsx @@ -13,7 +13,6 @@ import rainbowStyles from '../styles/rainbow.module.css'; import ToolPicker from "../components/tools/ToolPicker"; import TopControls from "../components/shared/TopControls"; -import FileManager from "../components/fileManagement/FileManager"; import FileEditor from "../components/pageEditor/FileEditor"; import PageEditor from "../components/pageEditor/PageEditor"; import PageEditorControls from "../components/pageEditor/PageEditorControls"; @@ -40,7 +39,7 @@ type ToolRegistry = { const baseToolRegistry = { split: { icon: , component: SplitPdfPanel, view: "viewer" }, compress: { icon: , component: CompressPdfPanel, view: "viewer" }, - merge: { icon: , component: MergePdfPanel, view: "fileManager" }, + merge: { icon: , component: MergePdfPanel, view: "pageEditor" }, }; export default function HomePage() { @@ -376,16 +375,7 @@ export default function HomePage() { /> {/* Main content area */} - {currentView === "fileManager" ? ( - - ) : (currentView != "fileManager") && !activeFiles[0] ? ( + {!activeFiles[0] ? ( { addToActiveFiles(file); }} - allowMultiple={false} + onFilesSelect={(files) => { + files.forEach(addToActiveFiles); + }} accept={["application/pdf"]} loading={false} + showRecentFiles={true} + maxRecentFiles={8} /> ) : currentView === "fileEditor" ? (