From 7cbdb0aea55b4d6e4c09b945df3d8bcf5927e371 Mon Sep 17 00:00:00 2001 From: Ida Dittrich Date: Fri, 8 Aug 2025 13:00:01 +0200 Subject: [PATCH] worked on Dateien page --- src/assets/styles/bg.jpg | Bin 0 -> 141426 bytes .../Connections/ConnectionEditModal.tsx | 2 +- .../Connections/ConnectionsErrorDisplay.tsx | 2 +- .../Connections/ConnectionsTable.tsx | 2 +- ...interfaces.ts => connectionsInterfaces.ts} | 0 .../{logic.tsx => connectionsLogic.tsx} | 2 +- src/components/Connections/index.ts | 4 +- src/components/Dateien/DateienAll.tsx | 144 -------- src/components/Dateien/DateienCreated.tsx | 139 ------- .../DateienSelector.module.css | 349 ------------------ .../DateienHinzufügen/DateienSelector.tsx | 312 ---------------- .../DateienUploadTool.module.css | 163 -------- .../DateienHinzufügen/DateienUploadTool.tsx | 127 ------- src/components/Dateien/DateienItem.module.css | 175 --------- src/components/Dateien/DateienItem.tsx | 199 ---------- .../Dateien/DateienLists.module.css | 102 ----- src/components/Dateien/DateienShared.tsx | 139 ------- .../Dateien/DateienTable.module.css | 249 +++++++++++++ src/components/Dateien/DateienTable.tsx | 80 ++++ .../Dateien/DateienUploadModal.module.css | 0 src/components/Dateien/DateienUploadModal.tsx | 0 src/components/Dateien/DateienUploads.tsx | 139 ------- src/components/Dateien/dateienInterfaces.ts | 90 +++++ src/components/Dateien/dateienLogic.tsx | 274 ++++++++++++++ src/components/Dateien/index.ts | 3 + .../FormGenerator/FormGenerator.module.css | 95 +++-- .../FormGenerator/FormGenerator.tsx | 107 ++++-- .../Sidebar/SidebarStyles/Sidebar.module.css | 6 +- .../Workflows/WorkflowsTable.module.css | 189 ++++++++++ src/components/Workflows/WorkflowsTable.tsx | 227 ++++++++++++ src/components/Workflows/index.ts | 1 + src/hooks/useFiles.ts | 51 ++- src/hooks/useWorkflows.ts | 41 +- src/locales/de.ts | 78 ++++ src/locales/en.ts | 78 ++++ src/locales/fr.ts | 78 ++++ src/pages/Home/Dateien.tsx | 220 +++++------ src/pages/Home/HomeStyles/Dateien.module.css | 46 +++ src/pages/Home/HomeStyles/Home.module.css | 3 +- .../Home/HomeStyles/Workflows.module.css | 12 +- src/pages/Home/Workflows.tsx | 9 +- 41 files changed, 1679 insertions(+), 2258 deletions(-) create mode 100644 src/assets/styles/bg.jpg rename src/components/Connections/{interfaces.ts => connectionsInterfaces.ts} (100%) rename src/components/Connections/{logic.tsx => connectionsLogic.tsx} (99%) delete mode 100644 src/components/Dateien/DateienAll.tsx delete mode 100644 src/components/Dateien/DateienCreated.tsx delete mode 100644 src/components/Dateien/DateienHinzufügen/DateienSelector.module.css delete mode 100644 src/components/Dateien/DateienHinzufügen/DateienSelector.tsx delete mode 100644 src/components/Dateien/DateienHinzufügen/DateienUploadTool.module.css delete mode 100644 src/components/Dateien/DateienHinzufügen/DateienUploadTool.tsx delete mode 100644 src/components/Dateien/DateienItem.module.css delete mode 100644 src/components/Dateien/DateienItem.tsx delete mode 100644 src/components/Dateien/DateienLists.module.css delete mode 100644 src/components/Dateien/DateienShared.tsx create mode 100644 src/components/Dateien/DateienTable.module.css create mode 100644 src/components/Dateien/DateienTable.tsx create mode 100644 src/components/Dateien/DateienUploadModal.module.css create mode 100644 src/components/Dateien/DateienUploadModal.tsx delete mode 100644 src/components/Dateien/DateienUploads.tsx create mode 100644 src/components/Dateien/dateienInterfaces.ts create mode 100644 src/components/Dateien/dateienLogic.tsx create mode 100644 src/components/Dateien/index.ts create mode 100644 src/components/Workflows/WorkflowsTable.module.css create mode 100644 src/components/Workflows/WorkflowsTable.tsx create mode 100644 src/components/Workflows/index.ts diff --git a/src/assets/styles/bg.jpg b/src/assets/styles/bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cea486964b9e95411041ec0684c724d8a0663af1 GIT binary patch literal 141426 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 void; - onOptimisticDelete?: (fileId: number) => void; -} - -const DateienAll: React.FC = ({ files, onFileDeleted, onOptimisticDelete }) => { - const { t } = useLanguage(); - const [sortField, setSortField] = useState('created_at'); - const [sortDirection, setSortDirection] = useState('desc'); - - // Handle sorting - const handleSort = (field: SortField) => { - if (field === sortField) { - setSortDirection(sortDirection === 'asc' ? 'desc' : 'asc'); - } else { - setSortField(field); - setSortDirection(field === 'created_at' ? 'desc' : 'asc'); - } - }; - - // Sort all files - const sortedFiles = [...files].sort((a, b) => { - let result = 0; - - switch (sortField) { - case 'file_name': - result = a.file_name.localeCompare(b.file_name); - break; - case 'action': - result = a.action.localeCompare(b.action); - break; - case 'size': - const sizeA = a.size ?? 0; - const sizeB = b.size ?? 0; - result = sizeA - sizeB; - break; - case 'created_at': - result = new Date(a.created_at).getTime() - new Date(b.created_at).getTime(); - break; - case 'source': - result = a.source?.localeCompare(b.source ?? '') ?? 0; - break; - } - - return sortDirection === 'asc' ? result : -result; - }); - - // Helper to render sort icon - const renderSortIcon = (field: SortField) => { - if (sortField !== field) return ; - return sortDirection === 'asc' ? - : - ; - }; - - if (sortedFiles.length === 0) { - return ( - -

{t('files.no_files', 'No files found.')}

-
- ); - } - - return ( - - {/* Table Headers */} -
-
handleSort('file_name')}> - {t('files.header.name', 'Name')} - {renderSortIcon('file_name')} -
-
handleSort('action')}> - {t('files.header.type', 'Type')} - {renderSortIcon('action')} -
-
handleSort('size')}> - {t('files.header.size', 'Size')} - {renderSortIcon('size')} -
-
handleSort('created_at')}> - {t('files.header.date', 'Date')} - {renderSortIcon('created_at')} -
-
- - {/* Files List */} - - - {sortedFiles.map((file: UserFile) => ( - - onOptimisticDelete(file.id) : undefined} - /> - - ))} - - -
- ); -}; - -export default DateienAll; diff --git a/src/components/Dateien/DateienCreated.tsx b/src/components/Dateien/DateienCreated.tsx deleted file mode 100644 index 4ba2c4c..0000000 --- a/src/components/Dateien/DateienCreated.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import React, { useState } from 'react'; -import { FaSort, FaSortUp, FaSortDown } from "react-icons/fa"; -import { motion, AnimatePresence } from "framer-motion"; -import DateienItem from './DateienItem'; -import { UserFile } from '../../hooks/useFiles'; -import { useLanguage } from '../../contexts/LanguageContext'; -import styles from './DateienLists.module.css'; - -// Sort types -type SortField = 'file_name' | 'action' | 'size' | 'created_at'; -type SortDirection = 'asc' | 'desc'; - -interface DateienCreatedProps { - files: UserFile[]; - onFileDeleted: () => void; - onOptimisticDelete?: (fileId: number) => void; -} - -const DateienCreated: React.FC = ({ files, onFileDeleted, onOptimisticDelete }) => { - const { t } = useLanguage(); - const [sortField, setSortField] = useState('created_at'); - const [sortDirection, setSortDirection] = useState('desc'); - - // Filter files for created (agent_created) - const createdFiles = files.filter(file => file.source === 'agent_created'); - - // Handle sorting - const handleSort = (field: SortField) => { - if (field === sortField) { - setSortDirection(sortDirection === 'asc' ? 'desc' : 'asc'); - } else { - setSortField(field); - setSortDirection(field === 'created_at' ? 'desc' : 'asc'); - } - }; - - // Sort files - const sortedFiles = [...createdFiles].sort((a, b) => { - let result = 0; - - switch (sortField) { - case 'file_name': - result = a.file_name.localeCompare(b.file_name); - break; - case 'action': - result = a.action.localeCompare(b.action); - break; - case 'size': - const sizeA = a.size ?? 0; - const sizeB = b.size ?? 0; - result = sizeA - sizeB; - break; - case 'created_at': - result = new Date(a.created_at).getTime() - new Date(b.created_at).getTime(); - break; - } - - return sortDirection === 'asc' ? result : -result; - }); - - // Helper to render sort icon - const renderSortIcon = (field: SortField) => { - if (sortField !== field) return ; - return sortDirection === 'asc' ? - : - ; - }; - - if (sortedFiles.length === 0) { - return ( - -

{t('files.no_ai_files', 'No AI-created files found.')}

-
- ); - } - - return ( - - {/* Table Headers */} -
-
handleSort('file_name')}> - {t('files.header.name', 'Name')} - {renderSortIcon('file_name')} -
-
handleSort('action')}> - {t('files.header.type', 'Type')} - {renderSortIcon('action')} -
-
handleSort('size')}> - {t('files.header.size', 'Size')} - {renderSortIcon('size')} -
-
handleSort('created_at')}> - {t('files.header.date', 'Date')} - {renderSortIcon('created_at')} -
-
- - {/* Files List with AI-created indicator */} - - - {sortedFiles.map((file: UserFile) => ( - - onOptimisticDelete(file.id) : undefined} - /> - - ))} - - -
- ); -}; - -export default DateienCreated; diff --git a/src/components/Dateien/DateienHinzufügen/DateienSelector.module.css b/src/components/Dateien/DateienHinzufügen/DateienSelector.module.css deleted file mode 100644 index 42c7497..0000000 --- a/src/components/Dateien/DateienHinzufügen/DateienSelector.module.css +++ /dev/null @@ -1,349 +0,0 @@ -.overlay { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: rgba(0, 0, 0, 0.7); - display: flex; - align-items: center; - justify-content: center; - z-index: 9999; - padding: 20px; -} - -.modal { - background: var(--color-bg); - border-radius: 12px; - box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); - max-width: 90vw; - max-height: 90vh; - width: 900px; - height: 700px; - display: flex; - flex-direction: column; - overflow: hidden; - font-family: var(--font-family); -} - -.header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 20px; - border-bottom: 1px solid var(--color-gray-disabled); - background-color: var(--color-surface); - flex-shrink: 0; -} - -.header h2 { - margin: 0; - font-size: 20px; - font-weight: 600; - color: var(--color-text); - font-family: var(--font-family); -} - -.closeButton { - display: flex; - align-items: center; - justify-content: center; - width: 32px; - height: 32px; - border: none; - border-radius: 8px; - background-color: transparent; - color: var(--color-gray); - cursor: pointer; - transition: all 0.2s ease; - font-size: 18px; -} - -.closeButton:hover { - background-color: var(--color-gray-disabled); - color: var(--color-text); -} - -.content { - flex: 1; - display: flex; - flex-direction: column; - overflow: hidden; -} - -.tabNavigation { - display: flex; - border-bottom: 1px solid var(--color-gray-disabled); - background-color: var(--color-surface); - padding: 0 20px; -} - -.tabButton { - padding: 12px 16px; - border: none; - background: none; - color: var(--color-gray); - font-size: 14px; - font-weight: 500; - cursor: pointer; - border-bottom: 2px solid transparent; - transition: all 0.2s ease; - white-space: nowrap; - font-family: var(--font-family); -} - -.tabButton:hover { - color: var(--color-text); -} - -.tabButton.active { - color: var(--color-secondary); - border-bottom-color: var(--color-secondary); -} - -.actionBar { - display: flex; - align-items: center; - justify-content: space-between; - padding: 16px 20px; - border-bottom: 1px solid var(--color-gray-disabled); - background-color: var(--color-bg); -} - -.selectionControls { - display: flex; - align-items: center; - gap: 16px; -} - -.selectAllButton { - display: flex; - align-items: center; - gap: 8px; - padding: 8px 12px; - border: 1px solid var(--color-gray-disabled); - border-radius: 6px; - background-color: var(--color-bg); - color: var(--color-text); - font-size: 14px; - cursor: pointer; - transition: all 0.2s ease; - font-family: var(--font-family); -} - -.selectAllButton:hover { - background-color: var(--color-surface); - border-color: var(--color-gray); -} - -.selectionCount { - font-size: 14px; - color: var(--color-gray); - font-weight: 500; - font-family: var(--font-family); -} - -.uploadButton { - display: flex; - align-items: center; - gap: 8px; - padding: 10px 16px; - border: none; - border-radius: 8px; - background-color: var(--color-secondary); - color: var(--color-bg); - font-size: 14px; - font-weight: 500; - cursor: pointer; - transition: background-color 0.2s ease; - font-family: var(--font-family); -} - -.uploadButton:hover { - background-color: var(--color-secondary-hover); -} - -.fileListContainer { - flex: 1; - overflow-y: auto; - padding: 20px; -} - -.loading, -.error, -.noFiles { - display: flex; - align-items: center; - justify-content: center; - height: 200px; - color: var(--color-gray); - font-size: 16px; - text-align: center; - font-family: var(--font-family); -} - -.error { - color: var(--color-red); -} - -.selectableFileList { - display: flex; - flex-direction: column; - gap: 8px; -} - -.selectableFileItem { - display: flex; - align-items: center; - gap: 12px; - padding: 12px; - border: 1px solid var(--color-gray-disabled); - border-radius: 8px; - background-color: var(--color-bg); - cursor: pointer; - transition: all 0.2s ease; -} - -.selectableFileItem:hover { - background-color: var(--color-surface); - border-color: var(--color-primary); -} - -.selectableFileItem.selected { - background-color: var(--color-primary-disabled); - border-color: var(--color-primary); -} - -.fileCheckbox { - display: flex; - align-items: center; - font-size: 18px; - color: var(--color-text); -} - -.checkedIcon { - color: var(--color-secondary); -} - -.uncheckedIcon { - color: var(--color-text); -} - -.fileIcon { - display: flex; - align-items: center; - font-size: 16px; - color: var(--color-text); -} - -.fileInfo { - flex: 1; - min-width: 0; -} - -.fileName { - font-weight: 500; - color: var(--color-text); - margin-bottom: 2px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.fileDetails { - font-size: 12px; - color: var(--color-text); -} - -.footer { - display: flex; - align-items: center; - justify-content: flex-end; - gap: 12px; - padding: 20px; - border-top: 1px solid var(--color-gray-disabled); - background-color: var(--color-bg); - flex-shrink: 0; -} - -.cancelButton { - padding: 10px 16px; - border: 1px solid var(--color-red); - border-radius: 8px; - background-color: var(--color-bg); - color: var(--color-text); - font-size: 14px; - font-weight: 500; - cursor: pointer; - transition: all 0.2s ease; -} - -.cancelButton:hover { - background-color: var(--color-red); - border-color: var(--color-red); -} - -.confirmButton { - padding: 10px 16px; - border: none; - border-radius: 8px; - background-color: var(--color-secondary); - color: var(--color-bg); - font-size: 14px; - font-weight: 500; - cursor: pointer; - transition: background-color 0.2s ease; -} - -.confirmButton:hover:not(:disabled) { - background-color: var(--color-secondary-hover); -} - -.confirmButton:disabled { - background-color: var(--color-secondary-disabled); - cursor: not-allowed; -} - -/* Responsive design */ -@media (max-width: 768px) { - .modal { - width: 95vw; - height: 85vh; - } - - .header h2 { - font-size: 18px; - } - - .tabNavigation { - padding: 0 12px; - overflow-x: auto; - } - - .tabButton { - padding: 10px 12px; - font-size: 13px; - } - - .actionBar { - flex-direction: column; - gap: 12px; - align-items: stretch; - } - - .selectionControls { - justify-content: space-between; - } - - .fileListContainer { - padding: 12px; - } - - .selectableFileItem { - padding: 10px; - } - - .footer { - padding: 16px; - } -} \ No newline at end of file diff --git a/src/components/Dateien/DateienHinzufügen/DateienSelector.tsx b/src/components/Dateien/DateienHinzufügen/DateienSelector.tsx deleted file mode 100644 index 6e85e50..0000000 --- a/src/components/Dateien/DateienHinzufügen/DateienSelector.tsx +++ /dev/null @@ -1,312 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import { motion, AnimatePresence } from 'framer-motion'; -import { IoClose, IoCheckbox, IoSquareOutline, IoCloudUploadOutline } from 'react-icons/io5'; -import { FaFile } from 'react-icons/fa'; -import { useUserFiles, UserFile, FileInfo } from '../../../hooks/useFiles'; -import DateienUploadTool from './DateienUploadTool'; -import DateienAll from '../DateienAll'; -import DateienUploads from '../DateienUploads'; -import DateienCreated from '../DateienCreated'; -import DateienShared from '../DateienShared'; -import { useLanguage } from '../../../contexts/LanguageContext'; -import styles from './DateienSelector.module.css'; - -type FileListType = 'all' | 'uploads' | 'created' | 'shared'; - -interface DateienSelectorProps { - isOpen: boolean; - onClose: () => void; - onFilesSelected: (files: FileInfo[]) => void; - allowMultiple?: boolean; -} - -const DateienSelector: React.FC = ({ - isOpen, - onClose, - onFilesSelected, - allowMultiple = true -}) => { - const { t } = useLanguage(); - const [selectedFiles, setSelectedFiles] = useState>(new Set()); - const [activeTab, setActiveTab] = useState('all'); - const [showUploadTool, setShowUploadTool] = useState(false); - const { files, loading, error, refetch } = useUserFiles(); - - // Filter files based on source - const getFilteredFiles = (files: UserFile[], type: FileListType): UserFile[] => { - switch (type) { - case 'uploads': - return files.filter(file => file.source === 'user_uploaded'); - case 'created': - return files.filter(file => file.source === 'agent_created'); - case 'shared': - return files.filter(file => file.source === 'shared_with_me'); - case 'all': - default: - return files; - } - }; - - const filteredFiles = getFilteredFiles(files, activeTab); - - // Reset selection when tab changes - useEffect(() => { - setSelectedFiles(new Set()); - }, [activeTab]); - - // Reset state when modal closes - useEffect(() => { - if (!isOpen) { - setSelectedFiles(new Set()); - setShowUploadTool(false); - } - }, [isOpen]); - - const handleFileSelect = (fileId: number) => { - if (allowMultiple) { - setSelectedFiles(prev => { - const newSet = new Set(prev); - if (newSet.has(fileId)) { - newSet.delete(fileId); - } else { - newSet.add(fileId); - } - return newSet; - }); - } else { - setSelectedFiles(new Set([fileId])); - } - }; - - const handleSelectAll = () => { - if (selectedFiles.size === filteredFiles.length) { - setSelectedFiles(new Set()); - } else { - setSelectedFiles(new Set(filteredFiles.map(file => file.id))); - } - }; - - const handleConfirmSelection = () => { - const selectedFileObjects: FileInfo[] = files - .filter(file => selectedFiles.has(file.id)) - .map(file => ({ - id: file.id, - name: file.file_name, - mimeType: deriveMimeTypeFromAction(file.action), - size: file.size, - creationDate: file.created_at, - source: file.source - })); - - onFilesSelected(selectedFileObjects); - onClose(); - }; - - // Helper function to derive MIME type from action (reverse mapping) - const deriveMimeTypeFromAction = (action: string): string => { - switch (action.toLowerCase()) { - case 'bild': - return 'image/jpeg'; // Default image type - case 'pdf': - return 'application/pdf'; - case 'dokument': - return 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'; - case 'tabelle': - return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'; - case 'text': - return 'text/plain'; - case 'video': - return 'video/mp4'; // Default video type - case 'audio': - return 'audio/mpeg'; // Default audio type - default: - return 'application/octet-stream'; // Default binary type - } - }; - - const handleFileUpload = (file: File) => { - // Refresh file list after upload - refetch(); - setShowUploadTool(false); - }; - - const renderFileListComponent = () => { - const commonProps = { - files: filteredFiles, - onFileDeleted: refetch - }; - - switch (activeTab) { - case 'uploads': - return ; - case 'created': - return ; - case 'shared': - return ; - case 'all': - default: - return ; - } - }; - - const getTabLabel = (type: FileListType) => { - const counts = { - all: files.length, - uploads: files.filter(f => f.source === 'user_uploaded').length, - created: files.filter(f => f.source === 'agent_created').length, - shared: files.filter(f => f.source === 'shared_with_me').length - }; - - const labels = { - all: t('files.selector.tab.all', 'All files'), - uploads: t('files.selector.tab.uploads', 'Uploaded'), - created: t('files.selector.tab.created', 'AI-created'), - shared: t('files.selector.tab.shared', 'Shared') - }; - - return `${labels[type]} (${counts[type]})`; - }; - - if (!isOpen) return null; - - if (showUploadTool) { - return ( - setShowUploadTool(false)} - onFileUpload={handleFileUpload} - /> - ); - } - - return ( -
- -
-

{t('files.selector.title', 'Select files')}

- -
- -
- {/* Tab Navigation */} -
- {(['all', 'uploads', 'created', 'shared'] as FileListType[]).map(tab => ( - - ))} -
- - {/* Action Bar */} -
-
- {allowMultiple && filteredFiles.length > 0 && ( - - )} - {selectedFiles.size > 0 && ( - - {selectedFiles.size} {selectedFiles.size === 1 ? t('files.selector.file_selected', 'File') : t('files.selector.files_selected', 'Files')} {t('files.selector.selected_suffix', 'selected')} - - )} -
- - -
- - {/* File List */} -
- {loading ? ( -
{t('files.selector.loading', 'Loading files...')}
- ) : error ? ( -
{t('files.selector.error_loading', 'Error loading files:')} {error}
- ) : filteredFiles.length === 0 ? ( -
{t('files.no_files', 'No files found.')}
- ) : ( -
- {filteredFiles.map(file => ( -
handleFileSelect(file.id)} - > -
- {selectedFiles.has(file.id) ? ( - - ) : ( - - )} -
-
- -
-
-
{file.file_name}
-
- {file.action} • {file.size ? `${Math.round(file.size / 1024)} KB` : t('files.unknown_size', 'Unknown Size')} -
-
-
- ))} -
- )} -
-
- - {/* Footer */} -
- - -
-
-
- ); -}; - -export default DateienSelector; \ No newline at end of file diff --git a/src/components/Dateien/DateienHinzufügen/DateienUploadTool.module.css b/src/components/Dateien/DateienHinzufügen/DateienUploadTool.module.css deleted file mode 100644 index 540573e..0000000 --- a/src/components/Dateien/DateienHinzufügen/DateienUploadTool.module.css +++ /dev/null @@ -1,163 +0,0 @@ -.overlay { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: rgba(0, 0, 0, 0.5); - display: flex; - justify-content: center; - align-items: center; - z-index: 1000; -} - -.h2 { - font-size: 24px; - font-weight: 600; - font-family: var(--font-family); - color: var(--color-text); -} - -.modal { - background: var(--color-bg); - padding: 35px 40px 30px 40px; - border-radius: 30px; - width: 90%; - max-width: 500px; - position: relative; - box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); - font-family: var(--font-family); -} - -.modalHeader { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 1rem; -} - -.modalHeader h2 { - margin: 0; - font-size: 1.5rem; - color: var(--color-text); - font-family: var(--font-family); -} - -.closeButton { - background: none; - border: none; - font-size: 1.5rem; - cursor: pointer; - color: var(--color-gray); - padding: 0.25rem; - display: flex; - align-items: center; - justify-content: center; -} - -.closeButton:hover { - color: var(--color-text); -} - -.closeButton:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -.uploadStatus { - padding: 1rem; - border-radius: 15px; - margin-bottom: 1rem; - text-align: center; - font-weight: 500; - font-family: var(--font-family); -} - -.uploadStatus.success { - background-color: var(--color-secondary-disabled); - color: var(--color-secondary); - border: 1px solid var(--color-secondary); -} - -.uploadStatus.error { - background-color: var(--color-red-disabled); - color: var(--color-red); - border: 1px solid var(--color-red); -} - -.dropzone { - border: 2px dashed var(--color-gray-disabled); - border-radius: 15px; - padding: 2rem; - text-align: center; - cursor: pointer; - margin: 1rem 0; - transition: all 0.3s ease; - background-color: var(--color-bg); -} - -.dropzone.active { - border-color: var(--color-secondary); - background-color: var(--color-secondary-disabled); -} - -.dropzone.uploading { - border-color: var(--color-secondary); - background-color: var(--color-secondary-disabled); - cursor: wait; -} - -.uploadIcon { - font-size: 3rem; - color: var(--color-gray); - margin-bottom: 1rem; -} - -.dropzoneText { - color: var(--color-gray); - font-family: var(--font-family); -} - -.dropzoneText p { - margin: 0.5rem 0; -} - -.browseButton { - background-color: var(--color-secondary); - color: var(--color-bg); - border: none; - padding: 0.5rem 1rem; - border-radius: 15px; - cursor: pointer; - font-family: var(--font-family); -} - -.browseButton:hover { - background-color: var(--color-secondary-hover); -} - -.browseButton:disabled { - background-color: var(--color-gray-disabled); - color: var(--color-gray); - cursor: not-allowed; -} - -.uploadButton { - background-color: var(--color-secondary); - color: var(--color-bg); - border: none; - padding: 0.5rem 1rem; - border-radius: 15px; - cursor: pointer; - font-family: var(--font-family); -} - -.uploadButton:hover { - background-color: var(--color-secondary-hover); -} - -.uploadButton:disabled { - background-color: var(--color-gray-disabled); - color: var(--color-gray); - cursor: not-allowed; -} \ No newline at end of file diff --git a/src/components/Dateien/DateienHinzufügen/DateienUploadTool.tsx b/src/components/Dateien/DateienHinzufügen/DateienUploadTool.tsx deleted file mode 100644 index 934d749..0000000 --- a/src/components/Dateien/DateienHinzufügen/DateienUploadTool.tsx +++ /dev/null @@ -1,127 +0,0 @@ -import React, { useCallback, useState } from 'react'; -import { useDropzone } from 'react-dropzone'; -import styles from './DateienUploadTool.module.css'; -import { IoCloudUploadOutline } from "react-icons/io5"; -import { IoClose } from "react-icons/io5"; -import { useFileOperations } from '../../../hooks/useFiles'; -import { useLanguage } from '../../../contexts/LanguageContext'; - -interface DateienUploadToolProps { - isOpen: boolean; - onClose: () => void; - onFileUpload: (file: File) => void; -} - -function DateienUploadTool({ isOpen, onClose, onFileUpload }: DateienUploadToolProps) { - const { t } = useLanguage(); - const [selectedFile, setSelectedFile] = useState(null); - const [isUploading, setIsUploading] = useState(false); - const [uploadStatus, setUploadStatus] = useState<{ success: boolean; message: string } | null>(null); - const { handleFileUpload, uploadError } = useFileOperations(); - - const onDrop = useCallback((acceptedFiles: File[]) => { - if (acceptedFiles.length > 0) { - setSelectedFile(acceptedFiles[0]); - // Clear previous upload status when selecting a new file - setUploadStatus(null); - } - }, []); - - const { getRootProps, getInputProps, isDragActive } = useDropzone({ - onDrop, - multiple: false - }); - - const handleUpload = async () => { - if (selectedFile) { - setIsUploading(true); - setUploadStatus(null); - - try { - const result = await handleFileUpload(selectedFile); - - if (result.success) { - setUploadStatus({ - success: true, - message: t('files.upload.success', 'File uploaded successfully!') - }); - onFileUpload(selectedFile); - setSelectedFile(null); - // Close modal after brief success message - setTimeout(() => { - onClose(); - }, 1500); - } else { - setUploadStatus({ - success: false, - message: uploadError || t('files.upload.error', 'An error occurred while uploading.') - }); - } - } catch (error) { - setUploadStatus({ - success: false, - message: t('files.upload.unexpected_error', 'An unexpected error occurred while uploading.') - }); - } finally { - setIsUploading(false); - } - } - }; - - if (!isOpen) return null; - - return ( -
-
-
-

{t('files.upload.title', 'Upload file')}

- -
- - {uploadStatus && ( -
- {uploadStatus.message} -
- )} - -
- - - {isDragActive ? ( -

{t('files.upload.drop_here', 'Drop file here...')}

- ) : isUploading ? ( -

{t('files.upload.uploading', 'Uploading...')}

- ) : ( -
-

{t('files.upload.drag_files', 'Drag files here')}

-

{t('files.upload.or', 'or')}

- -
- )} -
- - {selectedFile && !isUploading && !uploadStatus?.success && ( -
-

{t('files.upload.selected_file', 'Selected file:')} {selectedFile.name}

- -
- )} -
-
- ); -} - -export default DateienUploadTool; \ No newline at end of file diff --git a/src/components/Dateien/DateienItem.module.css b/src/components/Dateien/DateienItem.module.css deleted file mode 100644 index 607ed9e..0000000 --- a/src/components/Dateien/DateienItem.module.css +++ /dev/null @@ -1,175 +0,0 @@ -.fileItem { - display: flex; - align-items: center; - height: 60px; - padding: 0px 16px; - justify-content: space-between; - color: var(--color-text); - transition: background-color 0.2s ease; - font-family: var(--font-family); -} - -.fileItem:hover { - background-color: var(--color-surface); -} - -/* Column layout matching the header structure */ -.fileName { - display: flex; - align-items: center; - overflow: hidden; - font-weight: 500; - color: var(--color-text); - padding-left: 14px; /* Align with table header */ - font-family: var(--font-family); -} - -.fileName span { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - margin-left: 12px; -} - -.fileType { - font-size: 14px; - color: var(--color-gray); - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - display: flex; - flex-direction: column; - gap: 2px; - font-family: var(--font-family); -} - -.fileSource { - font-size: 12px; - color: var(--color-gray-hover); - font-weight: 400; - opacity: 0.8; - font-family: var(--font-family); -} - -.fileSize { - font-size: 14px; - color: var(--color-gray); - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - font-family: var(--font-family); -} - -.fileDateWithActions { - display: flex; - justify-content: space-between; - align-items: center; - width: 100%; -} - -.fileDate { - font-size: 14px; - color: var(--color-gray); - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - margin-right: 8px; - font-family: var(--font-family); -} - -.icon { - font-size: 18px; - color: var(--color-gray); - flex-shrink: 0; -} - -.actionButtons { - display: flex; - gap: 4px; - justify-content: flex-end; - margin-left: auto; -} - -.downloadButton, -.deleteButton, -.previewButton { - display: flex; - align-items: center; - justify-content: center; - gap: 4px; - padding: 6px; - border: none; - border-radius: 4px; - background-color: transparent; - color: var(--color-gray); - cursor: pointer; - transition: all 0.2s ease; - min-width: 32px; - font-family: var(--font-family); -} - -.downloadButton:hover:not(:disabled), -.deleteButton:hover:not(:disabled), -.previewButton:hover:not(:disabled) { - background-color: var(--color-surface); - color: var(--color-text); -} - -.deleteButton:hover:not(:disabled) { - color: var(--color-red); -} - -.previewButton:hover:not(:disabled) { - color: var(--color-secondary); -} - -.deleteButton.confirm { - background-color: var(--color-red-disabled); - color: var(--color-red); -} - -.deleteButton.confirm:hover:not(:disabled) { - background-color: var(--color-red-hover); -} - -.downloadButton:disabled, -.deleteButton:disabled, -.previewButton:disabled { - cursor: not-allowed; - opacity: 0.7; -} - -.actionIcon { - font-size: 16px; - flex-shrink: 0; -} - -.downloadButton.downloading, -.deleteButton.deleting { - background-color: var(--color-surface); -} - -.actionText { - font-size: 12px; - color: var(--color-gray); - animation: pulse 1.5s infinite; - white-space: nowrap; - font-family: var(--font-family); -} - -.deleteButton.confirm .actionText { - color: var(--color-red); - animation: none; -} - -@keyframes pulse { - 0% { - opacity: 0.6; - } - 50% { - opacity: 1; - } - 100% { - opacity: 0.6; - } -} diff --git a/src/components/Dateien/DateienItem.tsx b/src/components/Dateien/DateienItem.tsx deleted file mode 100644 index 36a9e25..0000000 --- a/src/components/Dateien/DateienItem.tsx +++ /dev/null @@ -1,199 +0,0 @@ -import { FaFile, FaDownload, FaTrash } from "react-icons/fa"; -import { MdOutlineRemoveRedEye } from "react-icons/md"; -import styles from "./DateienItem.module.css"; -import { useState } from "react"; -import { useFileOperations } from "../../hooks/useFiles"; -import FilePreviewPopup from "../Dashboard/DashboardChat/DashboardChatAreaFilePreview"; -import { Document } from "../Dashboard/DashboardChat/dashboardChatAreaTypes"; -import { useLanguage } from "../../contexts/LanguageContext"; - -type DateienItemProps = { - file: { - id: number; - file_name: string; - action: string; - created_at: string; - size?: number; - source?: string; // 'user_uploaded', 'agent_created', or 'shared_with_me' - }; - onDelete?: () => void; - onOptimisticDelete?: () => void; // New prop for immediate UI update -}; - -const DateienItem = ({ file, onDelete, onOptimisticDelete }: DateienItemProps) => { - const { t } = useLanguage(); - const { downloadingFiles, deletingFiles, handleFileDownload, handleFileDelete } = useFileOperations(); - const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); - const [previewDocument, setPreviewDocument] = useState(null); - const [isPreviewOpen, setIsPreviewOpen] = useState(false); - const isDownloading = downloadingFiles.has(file.id); - const isDeleting = deletingFiles.has(file.id); - - /** - * Formats a file size in bytes to a human-readable string (KB, MB, etc.) - */ - const formatFileSize = (bytes?: number): string => { - if (bytes === undefined || bytes === null) return t('files.unknown_size', 'Unknown Size'); - - if (bytes === 0) return '0 Bytes'; - - const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; - const i = Math.floor(Math.log(bytes) / Math.log(1024)); - - if (i === 0) return `${bytes} ${sizes[i]}`; - - return `${(bytes / Math.pow(1024, i)).toFixed(1)} ${sizes[i]}`; - }; - - /** - * Formats the file source for display - */ - const formatFileSource = (source?: string): string => { - switch (source) { - case 'user_uploaded': - return t('files.source.uploaded', 'Uploaded'); - case 'agent_created': - return t('files.source.ai_created', 'AI-created'); - case 'shared_with_me': - return t('files.source.shared', 'Shared'); - default: - return t('files.source.unknown', 'Unknown'); - } - }; - - // Format the date properly - const formatDate = (dateString: string) => { - try { - const date = new Date(dateString); - // Check if date is valid - if (isNaN(date.getTime())) { - return t('files.unknown_date', 'Unknown Date'); - } - - return date.toLocaleDateString('de-DE', { - day: '2-digit', - month: '2-digit', - year: 'numeric' - }); - } catch (e) { - console.error('Error formatting date:', e); - return t('files.unknown_date', 'Unknown Date'); - } - }; - - const handleDeleteClick = async () => { - if (showDeleteConfirm) { - const success = await handleFileDelete(file.id, onOptimisticDelete); - if (!success) { - // If deletion failed, refresh the file list to restore the file - if (onDelete) { - onDelete(); - } - } - setShowDeleteConfirm(false); - } else { - setShowDeleteConfirm(true); - } - }; - - const handleCancelDelete = () => { - setShowDeleteConfirm(false); - }; - - const handlePreview = () => { - // Split filename to get name and extension - const nameParts = file.file_name.split('.'); - const extension = nameParts.length > 1 ? nameParts.pop() : undefined; - const fileName = nameParts.join('.'); - - // Create a Document object compatible with FilePreviewPopup - const document: Document = { - id: String(file.id), - fileId: file.id, - name: fileName, - ext: extension, - size: file.size - }; - - setPreviewDocument(document); - setIsPreviewOpen(true); - }; - - const handleClosePreview = () => { - setIsPreviewOpen(false); - setPreviewDocument(null); - }; - - return ( - <> -
  • - {/* 1st column: Name with icon */} -
    - - {file.file_name} -
    - - {/* 2nd column: Type with source */} -
    -
    {file.action}
    -
    {formatFileSource(file.source)}
    -
    - - {/* 3rd column: Size */} -
    - {formatFileSize(file.size)} -
    - - {/* 4th column: Date and action buttons */} -
    - - {formatDate(file.created_at)} - - -
    - - - -
    -
    -
  • - - {/* File Preview Popup */} - {previewDocument && ( - - )} - - ); -}; - -export default DateienItem; - diff --git a/src/components/Dateien/DateienLists.module.css b/src/components/Dateien/DateienLists.module.css deleted file mode 100644 index b1cd95e..0000000 --- a/src/components/Dateien/DateienLists.module.css +++ /dev/null @@ -1,102 +0,0 @@ -/* No files message */ -.noFilesMessage { - display: flex; - justify-content: center; - align-items: center; - padding: 60px 20px; - color: var(--color-gray); - font-style: italic; - font-family: var(--font-family); -} - -/* Files table container */ -.filesTable { - width: 100%; - margin-top: 10px; - display: flex; - flex-direction: column; - flex: 1; - min-height: 0; - height: 100%; - overflow: hidden; -} - -/* Table header with exact grid positioning */ -.tableHeader { - display: grid; - grid-template-columns: 45% 15% 15% 25%; - align-items: center; - height: 40px; - padding: 0px 16px; - position: sticky; - top: 0; - z-index: 10; - background-color: var(--color-bg); - border-bottom: 1px solid var(--color-gray-disabled); - margin-bottom: 10px; - flex-shrink: 0; -} - -/* Header cells with exact positioning */ -.headerCell { - display: flex; - align-items: center; - font-weight: 500; - font-size: 14px; - color: var(--color-text); - cursor: pointer; - white-space: nowrap; - padding-left: 0; - transition: color 0.2s ease; - font-family: var(--font-family); -} - -.headerCell:hover { - color: var(--color-primary); -} - -/* Adjust first column for icon space */ -.headerCell:nth-child(1) { - padding-left: 30px; -} - -/* Simple sort icon styling */ -.sortIcon { - margin-left: 6px; - font-size: 14px; - color: var(--color-gray); - transition: color 0.2s ease; -} - -.headerCell:hover .sortIcon { - color: var(--color-primary); -} - -/* File list styling */ -.filesList { - list-style: none; - padding: 0; - margin: 0; - width: 100%; - overflow-y: auto; - flex: 1; - min-height: 0; -} - -/* Override the flex layout in DateienItem to force matching the header */ -.filesList li { - display: grid !important; - grid-template-columns: 45% 15% 15% 25%; - border-bottom: 1px solid var(--color-gray-disabled); - height: 60px; - padding: 0 16px; - align-items: center; - transition: background-color 0.2s ease; - position: relative; -} - -.filesList li:hover { - background-color: var(--color-surface); -} - - diff --git a/src/components/Dateien/DateienShared.tsx b/src/components/Dateien/DateienShared.tsx deleted file mode 100644 index b032660..0000000 --- a/src/components/Dateien/DateienShared.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import React, { useState } from 'react'; -import { FaSort, FaSortUp, FaSortDown } from "react-icons/fa"; -import { motion, AnimatePresence } from "framer-motion"; -import DateienItem from './DateienItem'; -import { UserFile } from '../../hooks/useFiles'; -import { useLanguage } from '../../contexts/LanguageContext'; -import styles from './DateienLists.module.css'; - -// Sort types -type SortField = 'file_name' | 'action' | 'size' | 'created_at'; -type SortDirection = 'asc' | 'desc'; - -interface DateienSharedProps { - files: UserFile[]; - onFileDeleted: () => void; - onOptimisticDelete?: (fileId: number) => void; -} - -const DateienShared: React.FC = ({ files, onFileDeleted, onOptimisticDelete }) => { - const { t } = useLanguage(); - const [sortField, setSortField] = useState('created_at'); - const [sortDirection, setSortDirection] = useState('desc'); - - // Filter files for shared (shared_with_me) - const sharedFiles = files.filter(file => file.source === 'shared_with_me'); - - // Handle sorting - const handleSort = (field: SortField) => { - if (field === sortField) { - setSortDirection(sortDirection === 'asc' ? 'desc' : 'asc'); - } else { - setSortField(field); - setSortDirection(field === 'created_at' ? 'desc' : 'asc'); - } - }; - - // Sort files - const sortedFiles = [...sharedFiles].sort((a, b) => { - let result = 0; - - switch (sortField) { - case 'file_name': - result = a.file_name.localeCompare(b.file_name); - break; - case 'action': - result = a.action.localeCompare(b.action); - break; - case 'size': - const sizeA = a.size ?? 0; - const sizeB = b.size ?? 0; - result = sizeA - sizeB; - break; - case 'created_at': - result = new Date(a.created_at).getTime() - new Date(b.created_at).getTime(); - break; - } - - return sortDirection === 'asc' ? result : -result; - }); - - // Helper to render sort icon - const renderSortIcon = (field: SortField) => { - if (sortField !== field) return ; - return sortDirection === 'asc' ? - : - ; - }; - - if (sortedFiles.length === 0) { - return ( - -

    {t('files.no_shared_files', 'No shared files found.')}

    -
    - ); - } - - return ( - - {/* Table Headers */} -
    -
    handleSort('file_name')}> - {t('files.header.name', 'Name')} - {renderSortIcon('file_name')} -
    -
    handleSort('action')}> - {t('files.header.type', 'Type')} - {renderSortIcon('action')} -
    -
    handleSort('size')}> - {t('files.header.size', 'Size')} - {renderSortIcon('size')} -
    -
    handleSort('created_at')}> - {t('files.header.date', 'Date')} - {renderSortIcon('created_at')} -
    -
    - - {/* Files List with shared indicator */} - - - {sortedFiles.map((file: UserFile) => ( - - onOptimisticDelete(file.id) : undefined} - /> - - ))} - - -
    - ); -}; - -export default DateienShared; diff --git a/src/components/Dateien/DateienTable.module.css b/src/components/Dateien/DateienTable.module.css new file mode 100644 index 0000000..2f31632 --- /dev/null +++ b/src/components/Dateien/DateienTable.module.css @@ -0,0 +1,249 @@ +.dateienTable { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; +} + +.dateienFormGenerator { + flex: 1; + height: 100%; +} + +/* Error state styling */ +.errorState { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 2rem; + text-align: center; + color: var(--color-error, #dc3545); + background-color: var(--color-error-bg, #f8d7da); + border: 1px solid var(--color-error-border, #f5c6cb); + border-radius: 8px; + margin: 1rem; +} + +.retryButton { + padding: 0.5rem 1rem; + background-color: var(--color-primary, #007bff); + color: white; + border: none; + border-radius: 4px; + cursor: pointer; + margin-top: 1rem; + transition: background-color 0.2s ease; +} + +.retryButton:hover { + background-color: var(--color-primary, #0056b3); +} + +/* Table cell styling */ +.fileName { + font-weight: 500; + color: var(--color-text) !important; + display: block; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.fileTypeBadge { + display: inline-block; + padding: 0.25rem 0.5rem; + border-radius: 12px; + font-size: 0.85em; + font-weight: 500; + text-transform: capitalize; + text-align: center; + min-width: 60px; +} + +.type-bild, +.type-image { + background-color: #e3f2fd; + color: #1565c0; + border: 1px solid #bbdefb; +} + +.type-pdf { + background-color: #ffebee; + color: #c62828; + border: 1px solid #ffcdd2; +} + +.type-dokument, +.type-document { + background-color: #e8f5e8; + color: #2e7d32; + border: 1px solid #c8e6c9; +} + +.type-tabelle, +.type-spreadsheet { + background-color: #fff3e0; + color: #ef6c00; + border: 1px solid #ffe0b2; +} + +.type-text { + background-color: #f3e5f5; + color: #7b1fa2; + border: 1px solid #e1bee7; +} + +.type-video { + background-color: #fce4ec; + color: #ad1457; + border: 1px solid #f8bbd9; +} + +.type-audio { + background-color: #e0f2f1; + color: #00695c; + border: 1px solid #b2dfdb; +} + +.type-datei, +.type-file { + background-color: #f5f5f5; + color: #495057; + border: 1px solid #dee2e6; +} + +.fileSize { + font-weight: 500; + color: var(--color-text-secondary, #666); + background-color: var(--color-bg-secondary, #f8f9fa); + padding: 0.25rem 0.5rem; + border-radius: 8px; + font-size: 0.9em; + text-align: center; + display: inline-block; + min-width: 60px; +} + +.sourceBadge { + display: inline-block; + padding: 0.25rem 0.5rem; + border-radius: 12px; + font-size: 0.85em; + font-weight: 500; + text-align: center; + min-width: 80px; +} + +.source-user-uploaded { + background-color: #d4edda; + color: #155724; + border: 1px solid #c3e6cb; +} + +.source-agent-created { + background-color: #d1ecf1; + color: #0c5460; + border: 1px solid #bee5eb; +} + +.source-shared-with-me { + background-color: #fff3cd; + color: #856404; + border: 1px solid #ffeaa7; +} + +/* Responsive design */ +@media (max-width: 768px) { + .fileName { + font-size: 0.9em; + } + + .fileTypeBadge, + .sourceBadge { + font-size: 0.8em; + padding: 0.2rem 0.4rem; + } + + .fileSize { + font-size: 0.8em; + padding: 0.2rem 0.4rem; + } +} + +/* Dark mode support */ +@media (prefers-color-scheme: dark) { + .fileName { + color: #f8f9fa; + } + + .fileSize { + background-color: #374151; + color: #d1d5db; + } + + .type-bild, + .type-image { + background-color: #1e3a8a; + color: #bfdbfe; + } + + .type-pdf { + background-color: #7f1d1d; + color: #fecaca; + } + + .type-dokument, + .type-document { + background-color: #14532d; + color: #bbf7d0; + } + + .type-tabelle, + .type-spreadsheet { + background-color: #9a3412; + color: #fed7aa; + } + + .type-text { + background-color: #581c87; + color: #e9d5ff; + } + + .type-video { + background-color: #831843; + color: #fbcfe8; + } + + .type-audio { + background-color: #0f766e; + color: #99f6e4; + } + + .type-datei, + .type-file { + background-color: #374151; + color: #d1d5db; + } + + .source-user-uploaded { + background-color: #14532d; + color: #bbf7d0; + } + + .source-agent-created { + background-color: #0c4a6e; + color: #bae6fd; + } + + .source-shared-with-me { + background-color: #92400e; + color: #fde68a; + } + + .errorState { + background-color: #2d1b1e; + border-color: #5c2b33; + color: #f5c6cb; + } +} diff --git a/src/components/Dateien/DateienTable.tsx b/src/components/Dateien/DateienTable.tsx new file mode 100644 index 0000000..8f58406 --- /dev/null +++ b/src/components/Dateien/DateienTable.tsx @@ -0,0 +1,80 @@ +import { FormGenerator } from '../FormGenerator'; +import { useLanguage } from '../../contexts/LanguageContext'; +import { Popup, EditForm } from '../Popup'; +import styles from './DateienTable.module.css'; +import { useDateienLogic } from './dateienLogic.tsx'; +import type { DateienTableProps } from './dateienInterfaces'; + +export function DateienTable({ className = '' }: DateienTableProps) { + const { t } = useLanguage(); + + // Use the custom hook for all business logic + const { + files, + loading, + error, + columns, + actions, + editModalOpen, + editingFile, + editFileFields, + handleSaveFile, + handleCancelEdit + } = useDateienLogic(); + + // Show error state + if (error) { + return ( +
    +
    +

    {t('files.error.loading')} {error}

    + +
    +
    + ); + } + + return ( +
    + + + {/* Edit File Modal */} + + {editingFile && ( + + )} + +
    + ); +} + +export default DateienTable; \ No newline at end of file diff --git a/src/components/Dateien/DateienUploadModal.module.css b/src/components/Dateien/DateienUploadModal.module.css new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Dateien/DateienUploadModal.tsx b/src/components/Dateien/DateienUploadModal.tsx new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Dateien/DateienUploads.tsx b/src/components/Dateien/DateienUploads.tsx deleted file mode 100644 index 0da4cab..0000000 --- a/src/components/Dateien/DateienUploads.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import React, { useState } from 'react'; -import { FaSort, FaSortUp, FaSortDown } from "react-icons/fa"; -import { motion, AnimatePresence } from "framer-motion"; -import DateienItem from './DateienItem'; -import { UserFile } from '../../hooks/useFiles'; -import { useLanguage } from '../../contexts/LanguageContext'; -import styles from './DateienLists.module.css'; - -// Sort types -type SortField = 'file_name' | 'action' | 'size' | 'created_at'; -type SortDirection = 'asc' | 'desc'; - -interface DateienUploadsProps { - files: UserFile[]; - onFileDeleted: () => void; - onOptimisticDelete?: (fileId: number) => void; -} - -const DateienUploads: React.FC = ({ files, onFileDeleted, onOptimisticDelete }) => { - const { t } = useLanguage(); - const [sortField, setSortField] = useState('created_at'); - const [sortDirection, setSortDirection] = useState('desc'); - - // Filter files for uploads (user_uploaded) - const uploadedFiles = files.filter(file => file.source === 'user_uploaded'); - - // Handle sorting - const handleSort = (field: SortField) => { - if (field === sortField) { - setSortDirection(sortDirection === 'asc' ? 'desc' : 'asc'); - } else { - setSortField(field); - setSortDirection(field === 'created_at' ? 'desc' : 'asc'); - } - }; - - // Sort files - const sortedFiles = [...uploadedFiles].sort((a, b) => { - let result = 0; - - switch (sortField) { - case 'file_name': - result = a.file_name.localeCompare(b.file_name); - break; - case 'action': - result = a.action.localeCompare(b.action); - break; - case 'size': - const sizeA = a.size ?? 0; - const sizeB = b.size ?? 0; - result = sizeA - sizeB; - break; - case 'created_at': - result = new Date(a.created_at).getTime() - new Date(b.created_at).getTime(); - break; - } - - return sortDirection === 'asc' ? result : -result; - }); - - // Helper to render sort icon - const renderSortIcon = (field: SortField) => { - if (sortField !== field) return ; - return sortDirection === 'asc' ? - : - ; - }; - - if (sortedFiles.length === 0) { - return ( - -

    {t('files.no_uploaded_files', 'No uploaded files found.')}

    -
    - ); - } - - return ( - - {/* Table Headers */} -
    -
    handleSort('file_name')}> - {t('files.header.name', 'Name')} - {renderSortIcon('file_name')} -
    -
    handleSort('action')}> - {t('files.header.type', 'Type')} - {renderSortIcon('action')} -
    -
    handleSort('size')}> - {t('files.header.size', 'Size')} - {renderSortIcon('size')} -
    -
    handleSort('created_at')}> - {t('files.header.date', 'Date')} - {renderSortIcon('created_at')} -
    -
    - - {/* Files List */} - - - {sortedFiles.map((file: UserFile) => ( - - onOptimisticDelete(file.id) : undefined} - /> - - ))} - - -
    - ); -}; - -export default DateienUploads; diff --git a/src/components/Dateien/dateienInterfaces.ts b/src/components/Dateien/dateienInterfaces.ts new file mode 100644 index 0000000..ad596bc --- /dev/null +++ b/src/components/Dateien/dateienInterfaces.ts @@ -0,0 +1,90 @@ +import { ColumnConfig } from '../FormGenerator'; +import React from 'react'; +import { EditFieldConfig } from '../Popup/EditForm'; + +// Re-export file-related interfaces from hooks +export type { UserFile, FileInfo } from '../../hooks/useFiles'; + +// Import for local use +import type { UserFile } from '../../hooks/useFiles'; + +// Component Props Interfaces +export interface DateienTableProps { + className?: string; +} + +// Table Action Interface +export interface TableAction { + label: string; + onClick: (file: UserFile) => Promise | void; + icon: React.ReactNode | ((file: UserFile) => React.ReactNode); +} + +// File Operation Handler Types +export interface FileHandlers { + handleFileDownload: (fileId: string, fileName: string) => Promise; + handleFileDelete: (fileId: string, onOptimisticDelete?: () => void) => Promise; + handleFileUpload: (file: globalThis.File, workflowId?: string) => Promise<{ success: boolean; fileData?: any; error?: string }>; + handleFileUpdate: (fileId: string, updateData: Partial<{ filename: string }>) => Promise<{ success: boolean; fileData?: any; error?: string }>; +} + +// Hook Return Types for File Operations +export interface FileOperationsReturn extends FileHandlers { + downloadingFiles: Set; + deletingFiles: Set; + uploadingFile: boolean; + downloadError: string | null; + deleteError: string | null; + uploadError: string | null; + isLoading: boolean; +} + +// Hook Return Types for User Files +export interface UserFilesReturn { + files: UserFile[]; + loading: boolean; + error: string | null; + refetch: () => Promise; + removeFileOptimistically: (fileId: string) => void; + addFileOptimistically: (newFile: UserFile) => void; +} + +// File Table Configuration +export interface FileTableConfig { + columns: ColumnConfig[]; + actions: TableAction[]; + pageSize: number; + searchable: boolean; + filterable: boolean; + sortable: boolean; + resizable: boolean; + pagination: boolean; +} + +// File Size Formatter Function Type +export type FileSizeFormatter = (sizeInBytes?: number) => string; + +// Date Formatter Function Type +export type DateFormatter = (value?: string) => string; + +// Hook Return Type for Dateien Logic +export interface DateienLogicReturn { + files: UserFile[]; + loading: boolean; + error: string | null; + refetch: () => Promise; + columns: ColumnConfig[]; + actions: TableAction[]; + downloadingFiles: Set; + deletingFiles: Set; + downloadError: string | null; + deleteError: string | null; + editModalOpen: boolean; + editingFile: UserFile | null; + editFileFields: EditFieldConfig[]; + handleEditFile: (file: UserFile) => void; + handleSaveFile: (updatedFile: UserFile) => Promise; + handleCancelEdit: () => void; +} + + diff --git a/src/components/Dateien/dateienLogic.tsx b/src/components/Dateien/dateienLogic.tsx new file mode 100644 index 0000000..01b9948 --- /dev/null +++ b/src/components/Dateien/dateienLogic.tsx @@ -0,0 +1,274 @@ +import { useMemo, useState } from 'react'; +import { IoIosTrash, IoIosDownload } from 'react-icons/io'; +import { MdModeEdit } from 'react-icons/md'; + +import { ColumnConfig } from '../FormGenerator'; +import { useUserFiles, useFileOperations } from '../../hooks/useFiles'; +import { useLanguage } from '../../contexts/LanguageContext'; +import { EditFieldConfig } from '../Popup/EditForm'; +import type { + TableAction, + FileSizeFormatter, + DateFormatter, + UserFile, + DateienLogicReturn +} from './dateienInterfaces'; + +export function useDateienLogic(): DateienLogicReturn { + const { files, loading, error, refetch } = useUserFiles(); + const { + handleFileDownload, + handleFileDelete, + handleFileUpdate, + downloadingFiles, + deletingFiles, + downloadError, + deleteError + } = useFileOperations(); + const { t } = useLanguage(); + + // Edit modal state + const [editModalOpen, setEditModalOpen] = useState(false); + const [editingFile, setEditingFile] = useState(null); + + // Configure edit fields for filename editing + const editFileFields: EditFieldConfig[] = useMemo(() => [ + { + key: 'file_name', + label: t('files.field.filename', 'Filename'), + type: 'string', + editable: true, + required: true, + validator: (value: string) => { + if (!value || value.trim() === '') { + return 'Filename cannot be empty'; + } + if (value.includes('/') || value.includes('\\')) { + return 'Filename cannot contain / or \\ characters'; + } + return null; + } + } + ], [t]); + + // Handle edit file + const handleEditFile = (file: UserFile) => { + setEditingFile(file); + setEditModalOpen(true); + }; + + // Handle save file + const handleSaveFile = async (updatedFile: UserFile) => { + if (!editingFile) return; + + try { + // Call API to update filename + const result = await handleFileUpdate(editingFile.id, { + filename: updatedFile.file_name + }); + + if (result.success) { + // Close modal + setEditModalOpen(false); + setEditingFile(null); + + // Refresh file list + await refetch(); + } else { + console.error('Failed to update file:', result.error); + // TODO: Show error message to user + } + } catch (error) { + console.error('Failed to update file:', error); + // TODO: Show error message to user + } + }; + + // Handle cancel edit + const handleCancelEdit = () => { + setEditModalOpen(false); + setEditingFile(null); + }; + + // Helper function to format file size + const formatFileSize: FileSizeFormatter = (sizeInBytes) => { + if (!sizeInBytes || sizeInBytes === 0) return '-'; + + const units = ['Bytes', 'KB', 'MB', 'GB']; + let size = sizeInBytes; + let unitIndex = 0; + + while (size >= 1024 && unitIndex < units.length - 1) { + size /= 1024; + unitIndex++; + } + + return `${size.toFixed(1)} ${units[unitIndex]}`; + }; + + // Helper function to format date + const formatDate: DateFormatter = (value) => { + if (!value) return '-'; + try { + const date = new Date(value); + const pad = (n: number) => n.toString().padStart(2, '0'); + const yyyy = date.getFullYear(); + const mm = pad(date.getMonth() + 1); + const dd = pad(date.getDate()); + const hh = pad(date.getHours()); + const mi = pad(date.getMinutes()); + const ss = pad(date.getSeconds()); + return `${yyyy}-${mm}-${dd} ${hh}:${mi}:${ss}`; + } catch { + return value; + } + }; + + // Configure columns for the files table + const columns: ColumnConfig[] = useMemo(() => [ + { + key: 'file_name', + label: 'Filename', + type: 'string', + width: 300, + minWidth: 200, + maxWidth: 400, + sortable: true, + filterable: true, + searchable: true, + formatter: (value: string) => ( + + {value} + + ) + }, + { + key: 'mime_type', + label: 'mime type', + type: 'string', + width: 200, + minWidth: 150, + maxWidth: 300, + sortable: true, + filterable: true, + searchable: true, + }, + { + key: 'size', + label: 'filesize', + type: 'number', + width: 140, + minWidth: 120, + maxWidth: 180, + sortable: true, + filterable: false, + formatter: (value: number | string | undefined) => ( + + {formatFileSize(typeof value === 'string' ? parseInt(value, 10) : value)} + + ) + }, + { + key: 'created_at', + label: 'creation date', + type: 'date', + width: 200, + minWidth: 180, + maxWidth: 240, + sortable: true, + filterable: true, + formatter: (value: string | undefined) => formatDate(value) + }, + ], []); + + // Handle file download + const handleDownload = async (file: UserFile) => { + const success = await handleFileDownload(file.id, file.file_name); + if (!success && downloadError) { + console.error('Download failed:', downloadError); + } + }; + + // Handle file deletion + const handleDelete = async (file: UserFile) => { + if (window.confirm(t('files.delete.confirm').replace('{name}', file.file_name))) { + const success = await handleFileDelete(file.id, () => { + // Optimistic update - this will be called immediately + refetch(); + }); + + if (!success && deleteError) { + console.error('Delete failed:', deleteError); + // Refetch to restore the file in case of failure + refetch(); + } + } + }; + + // Configure action buttons + const actions: TableAction[] = useMemo(() => [ + { + label: t('files.action.edit', 'Edit'), + icon: , + onClick: (row: UserFile) => { + handleEditFile(row); + } + }, + { + label: t('files.action.download'), + icon: (row: UserFile) => { + const isDownloadingThis = downloadingFiles.has(row.id); + if (isDownloadingThis) return '⏳'; + return ; + }, + onClick: (row: UserFile) => { + if (!downloadingFiles.has(row.id)) { + handleDownload(row); + } + } + }, + { + label: t('files.action.delete'), + icon: (row: UserFile) => { + const isDeletingThis = deletingFiles.has(row.id); + if (isDeletingThis) return '⏳'; + return ; + }, + onClick: (row: UserFile) => { + if (!deletingFiles.has(row.id)) { + handleDelete(row); + } + } + } + ], [t, downloadingFiles, deletingFiles, handleDownload, handleDelete]); + + return { + files, + loading, + error, + refetch, + columns, + actions, + downloadingFiles, + deletingFiles, + downloadError, + deleteError, + editModalOpen, + editingFile, + editFileFields, + handleEditFile, + handleSaveFile, + handleCancelEdit + }; +} diff --git a/src/components/Dateien/index.ts b/src/components/Dateien/index.ts new file mode 100644 index 0000000..7b0be53 --- /dev/null +++ b/src/components/Dateien/index.ts @@ -0,0 +1,3 @@ +export { default as DateienTable } from './DateienTable'; +export { useDateienLogic } from './dateienLogic.tsx'; +export * from './dateienInterfaces'; \ No newline at end of file diff --git a/src/components/FormGenerator/FormGenerator.module.css b/src/components/FormGenerator/FormGenerator.module.css index ccb87ac..2d462bb 100644 --- a/src/components/FormGenerator/FormGenerator.module.css +++ b/src/components/FormGenerator/FormGenerator.module.css @@ -328,35 +328,45 @@ transform: scale(1.2); } -/* Actions Column */ +/* Actions Column - Resizable like other columns */ .actionsColumn { white-space: nowrap; - text-align: center; - padding: 12px 8px !important; + text-align: left; + padding: 8px !important; font-weight: 400; + box-sizing: border-box; } + + +/* Actions Column header */ +thead .actionsColumn { + text-align: center; + padding: 8px !important; +} + + + /* Actions Column border only on body cells, not header */ tbody .actionsColumn { border-top: 1px solid var(--color-primary); + text-align: center; } .actionButtons { display: flex; - gap: 4px; + gap: 2px; justify-content: center; align-items: center; - width: fit-content; + width: 100%; margin: 0 auto; - - } .actionButton { display: flex; align-items: center; justify-content: center; - padding: 8px; + padding: 6px; border: none; border-radius: 50%; font-size: 12px; @@ -365,16 +375,14 @@ tbody .actionsColumn { transition: all 0.2s ease; white-space: nowrap; position: relative; - min-width: 32px; - min-height: 32px; + min-width: 28px; + min-height: 28px; background: var(--color-secondary); color: var(--color-bg); } .actionButton:hover { background: var(--color-secondary-hover); - transform: scale(1.05); - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); } .actionIcon { @@ -386,43 +394,6 @@ tbody .actionsColumn { justify-content: center; } -/* Custom Tooltip */ -.tooltip { - position: absolute; - bottom: 120%; - left: 50%; - transform: translateX(-50%); - background: var(--color-text); - color: var(--color-bg); - padding: 6px 10px; - border-radius: 6px; - font-size: 12px; - white-space: nowrap; - opacity: 0; - visibility: hidden; - transition: opacity 0.2s ease, visibility 0.2s ease; - z-index: 1000; - pointer-events: none; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); -} - -/* Tooltip arrow */ -.tooltip::after { - content: ''; - position: absolute; - top: 100%; - left: 50%; - transform: translateX(-50%); - border: 5px solid transparent; - border-top-color: var(--color-text); -} - -/* Show tooltip on button hover */ -.actionButton:hover .tooltip { - opacity: 1; - visibility: visible; -} - /* Pagination */ .pagination { display: flex; @@ -575,4 +546,30 @@ tbody .actionsColumn { .tableContainer::-webkit-scrollbar-thumb:hover { background: var(--color-secondary); +} + +/* Loading State */ +.loadingState { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 4rem 2rem; + text-align: center; + color: var(--color-text-secondary, #666); +} + +.loadingSpinner { + width: 40px; + height: 40px; + border: 3px solid var(--color-bg-secondary, #e9ecef); + border-top: 3px solid var(--color-primary, #007bff); + border-radius: 50%; + animation: spin 1s linear infinite; + margin-bottom: 1rem; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } } \ No newline at end of file diff --git a/src/components/FormGenerator/FormGenerator.tsx b/src/components/FormGenerator/FormGenerator.tsx index df77ab0..abc26d5 100644 --- a/src/components/FormGenerator/FormGenerator.tsx +++ b/src/components/FormGenerator/FormGenerator.tsx @@ -1,4 +1,5 @@ import React, { useState, useMemo, useRef, useEffect } from 'react'; +import { useLanguage } from '../../contexts/LanguageContext'; import styles from './FormGenerator.module.css'; // Types for the FormGenerator @@ -55,6 +56,7 @@ export function FormGenerator>({ actions = [], className = '' }: FormGeneratorProps) { + const { t } = useLanguage(); // Auto-detect columns if not provided const detectedColumns = useMemo((): ColumnConfig[] => { if (providedColumns) return providedColumns; @@ -108,12 +110,18 @@ export function FormGenerator>({ // Initialize column widths useEffect(() => { const initialWidths: Record = {}; + + // Add actions column if present + if (actions.length > 0) { + initialWidths['actions'] = 120; // Default width for actions column + } + detectedColumns.forEach(col => { // Set a default width if none specified to ensure all columns have explicit widths initialWidths[col.key] = col.width || 150; }); setColumnWidths(initialWidths); - }, [detectedColumns]); + }, [detectedColumns, actions]); // Filter and search data const filteredData = useMemo(() => { @@ -143,15 +151,6 @@ export function FormGenerator>({ } else if (column?.type === 'number') { return Number(value) === Number(filterValue); } else if (column?.type === 'date') { - // Convert DD.MM.YYYY to comparable format - const parseDate = (dateStr: string) => { - if (dateStr.includes('.')) { - const [day, month, year] = dateStr.split('.'); - return new Date(parseInt(year), parseInt(month) - 1, parseInt(day)); - } - return new Date(dateStr); - }; - // Convert row value to DD.MM.YYYY format for comparison const rowDate = new Date(value); const rowFormatted = `${rowDate.getDate().toString().padStart(2, '0')}.${(rowDate.getMonth() + 1).toString().padStart(2, '0')}.${rowDate.getFullYear()}`; @@ -281,7 +280,7 @@ export function FormGenerator>({ const tableContainer = tableRef.current?.parentElement; if (tableContainer) { const containerWidth = tableContainer.clientWidth; - const actionsColumnWidth = actions.length > 0 ? 120 : 0; + const actionsColumnWidth = 0; // Actions column is now resizable like other columns const selectColumnWidth = selectable ? 40 : 0; const fixedWidth = actionsColumnWidth + selectColumnWidth; @@ -334,6 +333,8 @@ export function FormGenerator>({ return (
    + + {(searchable || filterable) && (
    {searchable && ( @@ -348,7 +349,7 @@ export function FormGenerator>({ onBlur={() => setSearchFocused(false)} className={`${styles.searchInput} ${searchFocused || searchTerm ? styles.focused : ''}`} /> - +
    )} @@ -365,15 +366,15 @@ export function FormGenerator>({ className={`${styles.filterSelect} ${filters[column.key] ? styles.hasValue : ''}`} > - - + + {filters[column.key] && ( @@ -397,7 +398,7 @@ export function FormGenerator>({ type="button" onClick={() => handleFilter(column.key, '')} className={styles.clearFilterButton} - title="Clear filter" + title={t('formgen.filter.clear')} > ✕ @@ -490,7 +491,7 @@ export function FormGenerator>({ className={`${styles.filterInput} ${filterFocused[column.key] || filters[column.key] ? styles.focused : ''}`} /> )} @@ -503,10 +504,33 @@ export function FormGenerator>({ {/* Table */}
    - {( + {loading ? ( +
    +
    +

    {t('common.loading', 'Loading...')}

    +
    + ) : ( + {actions.length > 0 && ( + + )} {selectable && ( )} - {actions.length > 0 && ( - - - )} {detectedColumns.map(column => ( - )} - {actions.length > 0 && ( - )} + {selectable && ( + + )} {detectedColumns.map(column => (
    + + {resizable && ( +
    handleMouseDown(e, 'actions')} + /> + )} +
    >({ /> - Actions - >({ className={`${styles.tr} ${selectedRows.has(index) ? styles.selected : ''} ${onRowClick ? styles.clickable : ''}`} onClick={() => onRowClick?.(row, index)} > - {selectable && ( - - handleRowSelect(index)} - onClick={(e) => e.stopPropagation()} - /> - + {actions.length > 0 && ( +
    {actions.map((action, actionIndex) => ( ))}
    + handleRowSelect(index)} + onClick={(e) => e.stopPropagation()} + /> + >({ onClick={() => setCurrentPage(1)} disabled={currentPage === 1} className={styles.paginationButton} + title={t('formgen.pagination.first')} > «« @@ -629,18 +654,23 @@ export function FormGenerator>({ onClick={() => setCurrentPage(currentPage - 1)} disabled={currentPage === 1} className={styles.paginationButton} + title={t('formgen.pagination.prev')} > « - Page {currentPage} of {totalPages} ({filteredData.length} items) + {t('formgen.pagination.info') + .replace('{page}', currentPage.toString()) + .replace('{total}', totalPages.toString()) + .replace('{count}', filteredData.length.toString())} @@ -648,6 +678,7 @@ export function FormGenerator>({ onClick={() => setCurrentPage(totalPages)} disabled={currentPage === totalPages} className={styles.paginationButton} + title={t('formgen.pagination.last')} > »» diff --git a/src/components/Sidebar/SidebarStyles/Sidebar.module.css b/src/components/Sidebar/SidebarStyles/Sidebar.module.css index 30928ba..eb9351e 100644 --- a/src/components/Sidebar/SidebarStyles/Sidebar.module.css +++ b/src/components/Sidebar/SidebarStyles/Sidebar.module.css @@ -2,7 +2,11 @@ .sidebarContainer { border-radius: 0px; background: var(--color-bg); - box-shadow: 0px 2px 6px 0px rgba(194, 194, 194, 0.10); + /*background-image: url('../../../assets/styles/bg.jpg'); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + box-shadow: 0px 2px 6px 0px rgba(194, 194, 194, 0.10);*/ width: 240px; padding-bottom: 1px; display: flex; diff --git a/src/components/Workflows/WorkflowsTable.module.css b/src/components/Workflows/WorkflowsTable.module.css new file mode 100644 index 0000000..6fbeb00 --- /dev/null +++ b/src/components/Workflows/WorkflowsTable.module.css @@ -0,0 +1,189 @@ +.workflowsTable { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; +} + +.workflowsFormGenerator { + flex: 1; + height: 100%; +} + +/* Error state styling */ +.errorState { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 2rem; + text-align: center; + color: var(--color-error, #dc3545); + background-color: var(--color-error-bg, #f8d7da); + border: 1px solid var(--color-error-border, #f5c6cb); + border-radius: 8px; + margin: 1rem; +} + +.retryButton { + padding: 0.5rem 1rem; + background-color: var(--color-primary, #007bff); + color: white; + border: none; + border-radius: 4px; + cursor: pointer; + margin-top: 1rem; + transition: background-color 0.2s ease; +} + +.retryButton:hover { + background-color: var(--color-primary-dark, #0056b3); +} + +/* Table cell styling */ +.workflowId { + font-family: 'Courier New', monospace; + font-size: 0.9em; + color: var(--color-text-secondary, #666); + cursor: help; +} + +.workflowName { + font-weight: 500; + color: var(--color-text-primary, #333); +} + +.statusBadge { + display: inline-block; + padding: 0.25rem 0.5rem; + border-radius: 12px; + font-size: 0.85em; + font-weight: 500; + text-transform: capitalize; + text-align: center; + min-width: 60px; +} + +.status-running { + background-color: #d4edda; + color: #155724; + border: 1px solid #c3e6cb; +} + +.status-completed { + background-color: #d1ecf1; + color: #0c5460; + border: 1px solid #bee5eb; +} + +.status-failed { + background-color: #f8d7da; + color: #721c24; + border: 1px solid #f5c6cb; +} + +.status-stopped { + background-color: #f5f5f5; + color: #495057; + border: 1px solid #dee2e6; +} + +.status-pending { + background-color: #fff3cd; + color: #856404; + border: 1px solid #ffeaa7; +} + +.roundNumber { + font-weight: 600; + color: var(--color-primary, #007bff); + background-color: var(--color-primary-light, #e3f2fd); + padding: 0.25rem 0.5rem; + border-radius: 8px; + font-size: 0.9em; + min-width: 24px; + text-align: center; + display: inline-block; +} + +.messageCount { + font-weight: 500; + color: var(--color-text-secondary, #666); + background-color: var(--color-bg-secondary, #f8f9fa); + padding: 0.25rem 0.5rem; + border-radius: 8px; + font-size: 0.9em; + min-width: 24px; + text-align: center; + display: inline-block; +} + +/* Responsive design */ +@media (max-width: 768px) { + .workflowId { + font-size: 0.8em; + } + + .statusBadge { + font-size: 0.8em; + padding: 0.2rem 0.4rem; + } + + .roundNumber, + .messageCount { + font-size: 0.8em; + padding: 0.2rem 0.4rem; + } +} + +/* Dark mode support */ +@media (prefers-color-scheme: dark) { + .workflowId { + color: #adb5bd; + } + + .workflowName { + color: #f8f9fa; + } + + .status-running { + background-color: #155724; + color: #d4edda; + } + + .status-completed { + background-color: #0c5460; + color: #d1ecf1; + } + + .status-failed { + background-color: #721c24; + color: #f8d7da; + } + + .status-stopped { + background-color: #495057; + color: #f5f5f5; + } + + .status-pending { + background-color: #856404; + color: #fff3cd; + } + + .roundNumber { + background-color: #1e3a8a; + color: #bfdbfe; + } + + .messageCount { + background-color: #374151; + color: #d1d5db; + } + + .errorState { + background-color: #2d1b1e; + border-color: #5c2b33; + color: #f5c6cb; + } +} diff --git a/src/components/Workflows/WorkflowsTable.tsx b/src/components/Workflows/WorkflowsTable.tsx new file mode 100644 index 0000000..c3f7d0f --- /dev/null +++ b/src/components/Workflows/WorkflowsTable.tsx @@ -0,0 +1,227 @@ +import { useMemo } from 'react'; +import { FormGenerator, ColumnConfig } from '../FormGenerator/FormGenerator'; +import { useWorkflows, useWorkflowOperations, Workflow } from '../../hooks/useWorkflows'; +import { useLanguage } from '../../contexts/LanguageContext'; +import styles from './WorkflowsTable.module.css'; + +interface WorkflowsTableProps { + className?: string; +} + +function WorkflowsTable({ className = '' }: WorkflowsTableProps) { + const { workflows, loading, error, refetch } = useWorkflows(); + const { + stopWorkflow, + deleteWorkflow, + stoppingWorkflows, + deletingWorkflows + } = useWorkflowOperations(); + const { t } = useLanguage(); + + // Configure columns for the workflows table + const columns: ColumnConfig[] = useMemo(() => [ + { + key: 'id', + label: t('workflows.column.id'), + type: 'string', + width: 180, + minWidth: 150, + maxWidth: 250, + sortable: true, + filterable: true, + searchable: true, + formatter: (value: string) => ( + + {value.length > 8 ? `${value.substring(0, 8)}...` : value} + + ) + }, + { + key: 'name', + label: t('workflows.column.name'), + type: 'string', + width: 200, + minWidth: 150, + maxWidth: 300, + sortable: true, + filterable: true, + searchable: true, + formatter: (value: string | undefined, row: Workflow) => ( + + {value || row.title || t('workflows.unnamed')} + + ) + }, + { + key: 'status', + label: t('workflows.column.status'), + type: 'enum', + width: 120, + minWidth: 100, + maxWidth: 150, + sortable: true, + filterable: true, + filterOptions: ['running', 'completed', 'failed', 'stopped', 'pending'], + formatter: (value: string) => ( + + {t(`workflows.status.${value}`, value)} + + ) + }, + { + key: 'currentRound', + label: t('workflows.column.round'), + type: 'number', + width: 80, + minWidth: 60, + maxWidth: 100, + sortable: true, + filterable: true, + formatter: (value: number | undefined) => ( + + {value || 1} + + ) + }, + { + key: 'startedAt', + label: t('workflows.column.started'), + type: 'date', + width: 140, + minWidth: 120, + maxWidth: 180, + sortable: true, + filterable: true, + formatter: (value: string | undefined) => { + if (!value) return '-'; + try { + const date = new Date(value); + return date.toLocaleDateString() + ' ' + date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); + } catch { + return value; + } + } + }, + { + key: 'lastActivity', + label: t('workflows.column.lastActivity'), + type: 'date', + width: 140, + minWidth: 120, + maxWidth: 180, + sortable: true, + filterable: true, + formatter: (value: string | undefined) => { + if (!value) return '-'; + try { + const date = new Date(value); + return date.toLocaleDateString() + ' ' + date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); + } catch { + return value; + } + } + }, + { + key: 'messages', + label: t('workflows.column.messages'), + type: 'number', + width: 100, + minWidth: 80, + maxWidth: 120, + sortable: true, + filterable: false, + formatter: (value: any[] | undefined) => ( + + {value?.length || 0} + + ) + } + ], [t]); + + // Handle workflow actions + const handleStopWorkflow = async (workflow: Workflow) => { + const success = await stopWorkflow(workflow.id); + if (success) { + refetch(); // Refresh the workflows list + } + }; + + const handleDeleteWorkflow = async (workflow: Workflow) => { + const workflowName = workflow.name || workflow.title || workflow.id; + if (window.confirm(t('workflows.delete.confirm').replace('{name}', workflowName))) { + const success = await deleteWorkflow(workflow.id); + if (success) { + refetch(); // Refresh the workflows list + } + } + }; + + // Configure action buttons + const actions = useMemo(() => [ + { + label: t('workflows.action.stop'), + icon: (row: Workflow) => { + const isStoppingThis = stoppingWorkflows.has(row.id); + if (isStoppingThis) return '⏳'; + return '⏹️'; + }, + onClick: (row: Workflow) => { + if (row.status === 'running' && !stoppingWorkflows.has(row.id)) { + handleStopWorkflow(row); + } + } + }, + { + label: t('workflows.action.delete'), + icon: (row: Workflow) => { + const isDeletingThis = deletingWorkflows.has(row.id); + if (isDeletingThis) return '⏳'; + return '🗑️'; + }, + onClick: (row: Workflow) => { + if (!deletingWorkflows.has(row.id)) { + handleDeleteWorkflow(row); + } + } + } + ], [t, stoppingWorkflows, deletingWorkflows, handleStopWorkflow, handleDeleteWorkflow]); + + // Show error state + if (error) { + return ( +
    +
    +

    {t('workflows.error.loading')} {error}

    + +
    +
    + ); + } + + return ( +
    + { + // TODO: Navigate to workflow detail view + console.log('Clicked workflow:', workflow); + }} + /> +
    + ); +} + +export default WorkflowsTable; diff --git a/src/components/Workflows/index.ts b/src/components/Workflows/index.ts new file mode 100644 index 0000000..e7b0989 --- /dev/null +++ b/src/components/Workflows/index.ts @@ -0,0 +1 @@ +export { default as WorkflowsTable } from './WorkflowsTable'; \ No newline at end of file diff --git a/src/hooks/useFiles.ts b/src/hooks/useFiles.ts index 1171672..f970053 100644 --- a/src/hooks/useFiles.ts +++ b/src/hooks/useFiles.ts @@ -3,21 +3,21 @@ import { useApiRequest } from './useApi'; // File interfaces export interface FileInfo { - id: number; - name: string; + id: string; + filename: string; mimeType: string; - size?: number; + fileSize: number; creationDate: string; fileHash?: string; - mandateId?: number; - userId?: number; + mandateId?: string; workflowId?: string; source?: string; // 'user_uploaded', 'agent_created', or 'shared_with_me' } export interface UserFile { - id: number; + id: string; file_name: string; + mime_type?: string; action: string; created_at: string; size?: number; @@ -32,7 +32,7 @@ export function useUserFiles() { const fetchFiles = async () => { try { const data = await request({ - url: '/api/files', + url: '/api/files/list', method: 'get' }); @@ -73,10 +73,11 @@ export function useUserFiles() { return { id: apiFile.id, - file_name: apiFile.name, + file_name: apiFile.filename, + mime_type: apiFile.mimeType, action: action, created_at: apiFile.creationDate, - size: apiFile.size, + size: apiFile.fileSize, source: apiFile.source }; }); @@ -88,7 +89,7 @@ export function useUserFiles() { }; // Optimistically remove a file from the local state - const removeFileOptimistically = (fileId: number) => { + const removeFileOptimistically = (fileId: string) => { setFiles(prevFiles => prevFiles.filter(file => file.id !== fileId)); }; @@ -113,21 +114,21 @@ export function useUserFiles() { // File operations hook export function useFileOperations() { - const [downloadingFiles, setDownloadingFiles] = useState>(new Set()); - const [deletingFiles, setDeletingFiles] = useState>(new Set()); + const [downloadingFiles, setDownloadingFiles] = useState>(new Set()); + const [deletingFiles, setDeletingFiles] = useState>(new Set()); const [uploadingFile, setUploadingFile] = useState(false); - const { request, error: apiError, isLoading } = useApiRequest(); + const { request, isLoading } = useApiRequest(); const [downloadError, setDownloadError] = useState(null); const [deleteError, setDeleteError] = useState(null); const [uploadError, setUploadError] = useState(null); - const handleFileDownload = async (fileId: number, fileName: string) => { + const handleFileDownload = async (fileId: string, fileName: string) => { setDownloadError(null); setDownloadingFiles(prev => new Set(prev).add(fileId)); try { const blob = await request({ - url: `/api/files/${fileId}`, + url: `/api/files/${fileId}/download`, method: 'get', // Override axios config for blob response additionalConfig: { responseType: 'blob' } @@ -156,7 +157,7 @@ export function useFileOperations() { } }; - const handleFileDelete = async (fileId: number, onOptimisticDelete?: () => void) => { + const handleFileDelete = async (fileId: string, onOptimisticDelete?: () => void) => { setDeleteError(null); setDeletingFiles(prev => new Set(prev).add(fileId)); @@ -220,6 +221,23 @@ export function useFileOperations() { } }; + const handleFileUpdate = async (fileId: string, updateData: Partial<{ filename: string }>) => { + setUploadError(null); // Reuse upload error state for update operations + + try { + const updatedFile = await request({ + url: `/api/files/${fileId}`, + method: 'put', + data: updateData + }); + + return { success: true, fileData: updatedFile }; + } catch (error: any) { + setUploadError(error.message); + return { success: false, error: error.message }; + } + }; + return { downloadingFiles, deletingFiles, @@ -230,6 +248,7 @@ export function useFileOperations() { handleFileDownload, handleFileDelete, handleFileUpload, + handleFileUpdate, isLoading }; } \ No newline at end of file diff --git a/src/hooks/useWorkflows.ts b/src/hooks/useWorkflows.ts index ae63283..c4f609c 100644 --- a/src/hooks/useWorkflows.ts +++ b/src/hooks/useWorkflows.ts @@ -1,18 +1,23 @@ -import { useState, useEffect, useCallback, useRef } from 'react'; +import { useState, useEffect } from 'react'; import { useApiRequest } from './useApi'; -// Workflow interfaces +// Workflow interfaces (matching backend ChatWorkflow model) export interface Workflow { id: string; - name?: string; - title?: string; + mandateId: string; status: string; - startedAt?: string; - lastActivity?: string; - currentRound?: number; - dataStats?: Record; - userId?: number; - messageIds?: string[]; + name?: string; + title?: string; // Keep for backward compatibility + currentRound: number; + lastActivity: string; + startedAt: string; + logs?: any[]; + messages?: any[]; + stats?: Record; + tasks?: any[]; + dataStats?: Record; // Keep for backward compatibility + userId?: number; // Keep for backward compatibility + messageIds?: string[]; // Keep for backward compatibility } export interface WorkflowMessage { @@ -43,7 +48,7 @@ export function useWorkflows() { const fetchWorkflows = async () => { try { const data = await request({ - url: '/api/workflows', + url: '/api/workflows/', method: 'get' }); @@ -65,7 +70,7 @@ export function useWorkflowOperations() { const [startingWorkflow, setStartingWorkflow] = useState(false); const [stoppingWorkflows, setStoppingWorkflows] = useState>(new Set()); const [deletingWorkflows, setDeletingWorkflows] = useState>(new Set()); - const { request, error: apiError, isLoading } = useApiRequest(); + const { request, isLoading } = useApiRequest(); const [startError, setStartError] = useState(null); const [stopError, setStopError] = useState(null); const [deleteError, setDeleteError] = useState(null); @@ -274,10 +279,10 @@ export function useFilePreview() { throw new Error(`Invalid file ID format: "${fileId}" (type: ${typeof fileId}). Expected a numeric file ID, but got a document UUID. Make sure the document object has a 'fileId' property with the numeric file ID.`); } - const response = await request({ - url: `/api/workflows/files/${numericFileId}/preview`, - method: 'get' - }); + const response = await request({ + url: `/api/files/${numericFileId}/preview`, + method: 'get' + }); // Handle response as object with metadata and preview content if (typeof response === 'object' && response !== null) { @@ -315,7 +320,7 @@ export function useFilePreview() { try { // Try to fetch the raw file content using download endpoint const rawResponse = await request({ - url: `/api/workflows/files/${numericFileId}/download`, + url: `/api/files/${numericFileId}/download`, method: 'get', additionalConfig: { responseType: 'text' } }); @@ -389,7 +394,7 @@ export function useFileDownload() { // Use the same approach as useFiles.ts - use request with blob response type const blob = await request({ - url: `/api/workflows/files/${numericFileId}/download`, + url: `/api/files/${numericFileId}/download`, method: 'get', // Override axios config for blob response additionalConfig: { responseType: 'blob' } diff --git a/src/locales/de.ts b/src/locales/de.ts index b934c93..6daf96d 100644 --- a/src/locales/de.ts +++ b/src/locales/de.ts @@ -253,6 +253,10 @@ export default { 'files.upload.unexpected_error': 'Beim Hochladen ist ein unerwarteter Fehler aufgetreten.', // Files Page + 'files.title': 'Dateien', + 'files.table.title': 'Dateien', + 'files.error.loading': 'Fehler beim Laden der Dateien:', + 'files.button.retry': 'Wiederholen', 'files.page.tab.all': 'Alle Dateien', 'files.page.tab.uploads': 'Meine Uploads', 'files.page.tab.created': 'Erstellte Dateien', @@ -260,4 +264,78 @@ export default { 'files.page.add_file': 'Datei hinzufügen', 'files.page.loading': 'Dateien werden geladen...', 'files.page.error': 'Fehler:', + + // File Table Columns + 'files.column.name': 'Name', + 'files.column.type': 'Typ', + 'files.column.size': 'Größe', + 'files.column.created': 'Erstellt', + 'files.column.source': 'Quelle', + + // File Types + 'files.type.image': 'Bild', + 'files.type.pdf': 'PDF', + 'files.type.document': 'Dokument', + 'files.type.spreadsheet': 'Tabelle', + 'files.type.text': 'Text', + 'files.type.video': 'Video', + 'files.type.audio': 'Audio', + 'files.type.file': 'Datei', + + // File Sources + 'files.source.uploaded': 'Hochgeladen', + 'files.source.created': 'KI Erstellt', + 'files.source.shared': 'Geteilt', + + // File Actions + 'files.action.download': 'Herunterladen', + 'files.action.delete': 'Löschen', + 'files.delete.confirm': 'Sind Sie sicher, dass Sie die Datei "{name}" löschen möchten?', + + // Workflows Page + 'workflows.title': 'Workflows', + 'workflows.table.title': 'Workflows', + 'workflows.error.loading': 'Fehler beim Laden der Workflows:', + 'workflows.button.retry': 'Wiederholen', + 'workflows.table.empty': 'Keine Workflows gefunden', + + // Workflow Table Columns + 'workflows.column.id': 'ID', + 'workflows.column.name': 'Name', + 'workflows.column.status': 'Status', + 'workflows.column.round': 'Runde', + 'workflows.column.started': 'Gestartet', + 'workflows.column.lastActivity': 'Letzte Aktivität', + 'workflows.column.messages': 'Nachrichten', + + // Workflow Status + 'workflows.status.running': 'Läuft', + 'workflows.status.completed': 'Abgeschlossen', + 'workflows.status.failed': 'Fehlgeschlagen', + 'workflows.status.stopped': 'Gestoppt', + 'workflows.status.pending': 'Wartend', + + // Workflow Actions + 'workflows.action.stop': 'Stoppen', + 'workflows.action.delete': 'Löschen', + 'workflows.action.stop.tooltip': 'Workflow stoppen', + 'workflows.action.delete.tooltip': 'Workflow löschen', + + // Workflow Messages + 'workflows.unnamed': 'Unbenannter Workflow', + 'workflows.delete.confirm': 'Sind Sie sicher, dass Sie den Workflow "{name}" löschen möchten?', + 'workflows.loading': 'Workflows werden geladen...', + + // FormGenerator + 'formgen.search.placeholder': 'Suchen...', + 'formgen.filter.yes': 'Ja', + 'formgen.filter.no': 'Nein', + 'formgen.filter.clear': 'Filter löschen', + 'formgen.filter.placeholder': '{column} filtern', + 'formgen.actions.column': 'Aktionen', + 'formgen.pagination.info': 'Seite {page} von {total} ({count} Einträge)', + 'formgen.pagination.first': 'Erste Seite', + 'formgen.pagination.prev': 'Vorherige Seite', + 'formgen.pagination.next': 'Nächste Seite', + 'formgen.pagination.last': 'Letzte Seite', }; \ No newline at end of file diff --git a/src/locales/en.ts b/src/locales/en.ts index 83ab5c6..32f7a50 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -254,6 +254,10 @@ export default { 'files.upload.unexpected_error': 'An unexpected error occurred while uploading.', // Files Page + 'files.title': 'Files', + 'files.table.title': 'Files', + 'files.error.loading': 'Error loading files:', + 'files.button.retry': 'Retry', 'files.page.tab.all': 'All Files', 'files.page.tab.uploads': 'My Uploads', 'files.page.tab.created': 'Created Files', @@ -261,4 +265,78 @@ export default { 'files.page.add_file': 'Add File', 'files.page.loading': 'Loading files...', 'files.page.error': 'Error:', + + // File Table Columns + 'files.column.name': 'Name', + 'files.column.type': 'Type', + 'files.column.size': 'Size', + 'files.column.created': 'Created', + 'files.column.source': 'Source', + + // File Types + 'files.type.image': 'Image', + 'files.type.pdf': 'PDF', + 'files.type.document': 'Document', + 'files.type.spreadsheet': 'Spreadsheet', + 'files.type.text': 'Text', + 'files.type.video': 'Video', + 'files.type.audio': 'Audio', + 'files.type.file': 'File', + + // File Sources + 'files.source.uploaded': 'Uploaded', + 'files.source.created': 'AI Created', + 'files.source.shared': 'Shared', + + // File Actions + 'files.action.download': 'Download', + 'files.action.delete': 'Delete', + 'files.delete.confirm': 'Are you sure you want to delete the file "{name}"?', + + // Workflows Page + 'workflows.title': 'Workflows', + 'workflows.table.title': 'Workflows', + 'workflows.error.loading': 'Error loading workflows:', + 'workflows.button.retry': 'Retry', + 'workflows.table.empty': 'No workflows found', + + // Workflow Table Columns + 'workflows.column.id': 'ID', + 'workflows.column.name': 'Name', + 'workflows.column.status': 'Status', + 'workflows.column.round': 'Round', + 'workflows.column.started': 'Started', + 'workflows.column.lastActivity': 'Last Activity', + 'workflows.column.messages': 'Messages', + + // Workflow Status + 'workflows.status.running': 'Running', + 'workflows.status.completed': 'Completed', + 'workflows.status.failed': 'Failed', + 'workflows.status.stopped': 'Stopped', + 'workflows.status.pending': 'Pending', + + // Workflow Actions + 'workflows.action.stop': 'Stop', + 'workflows.action.delete': 'Delete', + 'workflows.action.stop.tooltip': 'Stop workflow', + 'workflows.action.delete.tooltip': 'Delete workflow', + + // Workflow Messages + 'workflows.unnamed': 'Unnamed Workflow', + 'workflows.delete.confirm': 'Are you sure you want to delete workflow "{name}"?', + 'workflows.loading': 'Loading workflows...', + + // FormGenerator + 'formgen.search.placeholder': 'Search...', + 'formgen.filter.yes': 'Yes', + 'formgen.filter.no': 'No', + 'formgen.filter.clear': 'Clear filter', + 'formgen.filter.placeholder': 'Filter {column}', + 'formgen.actions.column': 'Actions', + 'formgen.pagination.info': 'Page {page} of {total} ({count} items)', + 'formgen.pagination.first': 'First page', + 'formgen.pagination.prev': 'Previous page', + 'formgen.pagination.next': 'Next page', + 'formgen.pagination.last': 'Last page', }; \ No newline at end of file diff --git a/src/locales/fr.ts b/src/locales/fr.ts index a5b077f..d7806e7 100644 --- a/src/locales/fr.ts +++ b/src/locales/fr.ts @@ -253,6 +253,10 @@ export default { 'files.upload.unexpected_error': 'Une erreur inattendue s\'est produite lors du téléchargement.', // Files Page + 'files.title': 'Fichiers', + 'files.table.title': 'Fichiers', + 'files.error.loading': 'Erreur lors du chargement des fichiers:', + 'files.button.retry': 'Réessayer', 'files.page.tab.all': 'Tous les fichiers', 'files.page.tab.uploads': 'Mes téléchargements', 'files.page.tab.created': 'Fichiers créés', @@ -260,4 +264,78 @@ export default { 'files.page.add_file': 'Ajouter un fichier', 'files.page.loading': 'Chargement des fichiers...', 'files.page.error': 'Erreur:', + + // File Table Columns + 'files.column.name': 'Nom', + 'files.column.type': 'Type', + 'files.column.size': 'Taille', + 'files.column.created': 'Créé', + 'files.column.source': 'Source', + + // File Types + 'files.type.image': 'Image', + 'files.type.pdf': 'PDF', + 'files.type.document': 'Document', + 'files.type.spreadsheet': 'Feuille de calcul', + 'files.type.text': 'Texte', + 'files.type.video': 'Vidéo', + 'files.type.audio': 'Audio', + 'files.type.file': 'Fichier', + + // File Sources + 'files.source.uploaded': 'Téléchargé', + 'files.source.created': 'Créé par IA', + 'files.source.shared': 'Partagé', + + // File Actions + 'files.action.download': 'Télécharger', + 'files.action.delete': 'Supprimer', + 'files.delete.confirm': 'Êtes-vous sûr de vouloir supprimer le fichier "{name}"?', + + // Workflows Page + 'workflows.title': 'Workflows', + 'workflows.table.title': 'Workflows', + 'workflows.error.loading': 'Erreur lors du chargement des workflows:', + 'workflows.button.retry': 'Réessayer', + 'workflows.table.empty': 'Aucun workflow trouvé', + + // Workflow Table Columns + 'workflows.column.id': 'ID', + 'workflows.column.name': 'Nom', + 'workflows.column.status': 'Statut', + 'workflows.column.round': 'Tour', + 'workflows.column.started': 'Démarré', + 'workflows.column.lastActivity': 'Dernière activité', + 'workflows.column.messages': 'Messages', + + // Workflow Status + 'workflows.status.running': 'En cours', + 'workflows.status.completed': 'Terminé', + 'workflows.status.failed': 'Échoué', + 'workflows.status.stopped': 'Arrêté', + 'workflows.status.pending': 'En attente', + + // Workflow Actions + 'workflows.action.stop': 'Arrêter', + 'workflows.action.delete': 'Supprimer', + 'workflows.action.stop.tooltip': 'Arrêter le workflow', + 'workflows.action.delete.tooltip': 'Supprimer le workflow', + + // Workflow Messages + 'workflows.unnamed': 'Workflow sans nom', + 'workflows.delete.confirm': 'Êtes-vous sûr de vouloir supprimer le workflow "{name}"?', + 'workflows.loading': 'Chargement des workflows...', + + // FormGenerator + 'formgen.search.placeholder': 'Rechercher...', + 'formgen.filter.yes': 'Oui', + 'formgen.filter.no': 'Non', + 'formgen.filter.clear': 'Effacer le filtre', + 'formgen.filter.placeholder': 'Filtrer {column}', + 'formgen.actions.column': 'Actions', + 'formgen.pagination.info': 'Page {page} sur {total} ({count} éléments)', + 'formgen.pagination.first': 'Première page', + 'formgen.pagination.prev': 'Page précédente', + 'formgen.pagination.next': 'Page suivante', + 'formgen.pagination.last': 'Dernière page', }; \ No newline at end of file diff --git a/src/pages/Home/Dateien.tsx b/src/pages/Home/Dateien.tsx index b41dbe6..78eb642 100644 --- a/src/pages/Home/Dateien.tsx +++ b/src/pages/Home/Dateien.tsx @@ -1,156 +1,104 @@ -import styles from './HomeStyles/Dateien.module.css' -import sharedStyles from './HomeStyles/pages.module.css' -import { IoAddCircleOutline } from "react-icons/io5"; -import DateienUpload from '../../components/Dateien/DateienHinzufügen/DateienUploadTool'; -import DateienAll from '../../components/Dateien/DateienAll'; -import DateienUploads from '../../components/Dateien/DateienUploads'; -import DateienCreated from '../../components/Dateien/DateienCreated'; -import DateienShared from '../../components/Dateien/DateienShared'; -import { useState } from 'react'; -import { useUserFiles, useFileOperations } from '../../hooks/useFiles'; -import { motion, AnimatePresence } from "framer-motion"; -import { useLanguage } from '../../contexts/LanguageContext'; -// Tab types -type TabType = 'alle' | 'uploads' | 'erstellt' | 'geteilt'; +import { useRef, useState } from 'react'; +import { IoMdCloudUpload } from 'react-icons/io'; +import { useLanguage } from '../../contexts/LanguageContext'; +import sharedStyles from './HomeStyles/pages.module.css' +import styles from './HomeStyles/Dateien.module.css' +import { DateienTable } from '../../components/Dateien' +import { useFileOperations } from '../../hooks/useFiles'; function Dateien() { const { t } = useLanguage(); - const { files, loading, error, refetch, removeFileOptimistically } = useUserFiles(); - const [isUploadOpen, setIsUploadOpen] = useState(false); - const { uploadError, downloadError, deleteError } = useFileOperations(); - const [activeTab, setActiveTab] = useState('alle'); + const { handleFileUpload, uploadingFile } = useFileOperations(); + const fileInputRef = useRef(null); + const [tableRefreshKey, setTableRefreshKey] = useState(0); + const [isDragOver, setIsDragOver] = useState(false); - // Tab configuration with translations - const tabs = [ - { key: 'alle' as TabType, label: t('files.page.tab.all', 'All Files') }, - { key: 'uploads' as TabType, label: t('files.page.tab.uploads', 'My Uploads') }, - { key: 'erstellt' as TabType, label: t('files.page.tab.created', 'Created Files') }, - { key: 'geteilt' as TabType, label: t('files.page.tab.shared', 'Shared Files') } - ]; - - // Single function to handle file refresh - const refreshFiles = () => { - console.log('Refreshing files list'); - refetch(); + const triggerFilePicker = () => { + fileInputRef.current?.click(); }; - const handleFileUpload = async (file: File) => { - console.log('File upload completed:', file.name); - }; + const onFilesSelected = async (event: React.ChangeEvent) => { + const files = event.target.files; + if (!files || files.length === 0) return; - const handleUploadClose = () => { - setIsUploadOpen(false); - // Refresh files when upload modal is closed - setTimeout(() => { - refreshFiles(); - }, 300); - }; - - const handleFileDeleted = () => { - refreshFiles(); - }; - - // Render the appropriate component based on active tab - const renderActiveTabContent = () => { - const commonProps = { - files, - onFileDeleted: handleFileDeleted, - onOptimisticDelete: removeFileOptimistically - }; - - switch (activeTab) { - case 'alle': - return ; - case 'uploads': - return ; - case 'erstellt': - return ; - case 'geteilt': - return ; - default: - return ; + // Upload files sequentially + for (const file of Array.from(files)) { + await handleFileUpload(file); } + + // Force remount DateienTable to refetch + setTableRefreshKey(prev => prev + 1); + + // Reset input value to allow re-selecting the same file(s) + event.target.value = ''; + }; + + const handleDrop = async (event: React.DragEvent) => { + event.preventDefault(); + setIsDragOver(false); + + const files = event.dataTransfer.files; + if (files.length === 0) return; + + // Upload files sequentially + for (const file of Array.from(files)) { + await handleFileUpload(file); + } + + // Force remount DateienTable to refetch + setTableRefreshKey(prev => prev + 1); + }; + + const handleDragOver = (event: React.DragEvent) => { + event.preventDefault(); + setIsDragOver(true); + }; + + const handleDragLeave = (event: React.DragEvent) => { + event.preventDefault(); + setIsDragOver(false); }; return (
    -

    Dateien

    -
    - - {/* Combined Header with Tabs and Add Button */} - -
    - {tabs.map((tab) => ( -
    - setActiveTab(tab.key)} - whileHover={{ scale: 1.02 }} - whileTap={{ scale: 0.98 }} - > - {tab.label} - - - {activeTab === tab.key && ( - - )} - -
    - ))} +
    +

    {t('files.title')}

    +
    +
    + + {isDragOver ? 'Drop files here' : 'Drop files here or click to browse'} + +
    + +
    - - - +
    - -
    - - - {(uploadError || downloadError || deleteError) && ( -

    - {uploadError || downloadError || deleteError} -

    - )} - {loading &&

    {t('files.page.loading', 'Loading files...')}

    } - {error &&

    {t('files.page.error', 'Error:')} {error}

    } - - {!loading && !error && ( - - {renderActiveTabContent()} - - )} +
    +
    diff --git a/src/pages/Home/HomeStyles/Dateien.module.css b/src/pages/Home/HomeStyles/Dateien.module.css index 03544dd..75339f9 100644 --- a/src/pages/Home/HomeStyles/Dateien.module.css +++ b/src/pages/Home/HomeStyles/Dateien.module.css @@ -77,3 +77,49 @@ /* Any Dateien-specific content area customizations go here */ /* Base styling now comes from sharedStyles.contentArea */ } + +/* Dateien table container */ +.dateienTableContainer { + width: 100%; + height: 100%; + flex: 1; + display: flex; + flex-direction: column; + min-height: 400px; /* Ensure minimum height for table functionality */ +} + +/* Drop zone styles */ +.dropZone { + border: 2px dashed var(--color-primary); + border-radius: 30px; + padding: 15px 20px; + background: var(--color-bg); + cursor: pointer; + transition: all 0.2s ease; + min-width: 200px; + text-align: center; +} + +.dropZone:hover { + border-color: var(--color-secondary); + background: var(--color-gray-disabled); +} + +.dropZoneActive { + border-color: var(--color-secondary); + background: var(--color-gray-disabled); + border-style: solid; +} + +.dropZoneText { + color: var(--color-text); + font-size: 14px; + font-family: var(--font-family); + font-weight: 400; + opacity: 0.8; +} + +.dropZoneActive .dropZoneText { + opacity: 1; + font-weight: 500; +} \ No newline at end of file diff --git a/src/pages/Home/HomeStyles/Home.module.css b/src/pages/Home/HomeStyles/Home.module.css index ddc6de4..e2a3784 100644 --- a/src/pages/Home/HomeStyles/Home.module.css +++ b/src/pages/Home/HomeStyles/Home.module.css @@ -1,6 +1,6 @@ .homeContainer { position: relative; - background-color: var(--color-surface); + background-color: var(--color-bg); min-height: 100vh; max-height: 100vh; width: 100vw; @@ -14,7 +14,6 @@ position: absolute; top: 0; left: 0; width: 100%; height: 100%; - background-image: radial-gradient(circle, var(--color-gray-disabled) 1px, transparent 1px); background-size: 8px 8px; opacity: 0.4; z-index: -1; diff --git a/src/pages/Home/HomeStyles/Workflows.module.css b/src/pages/Home/HomeStyles/Workflows.module.css index adcb8ff..79c8cc7 100644 --- a/src/pages/Home/HomeStyles/Workflows.module.css +++ b/src/pages/Home/HomeStyles/Workflows.module.css @@ -6,7 +6,17 @@ /* Remove old .workflowsContainer - now using sharedStyles.pageContainer + sharedStyles.pageCard */ -/* Workflow-specific styles go here */ +/* Workflow table container */ +.workflowsTableContainer { + width: 100%; + height: 100%; + flex: 1; + display: flex; + flex-direction: column; + min-height: 400px; /* Ensure minimum height for table functionality */ +} + +/* Future workflow-specific styles go here */ .workflowItem { /* Future workflow item styling */ } diff --git a/src/pages/Home/Workflows.tsx b/src/pages/Home/Workflows.tsx index 85adc7c..d508cda 100644 --- a/src/pages/Home/Workflows.tsx +++ b/src/pages/Home/Workflows.tsx @@ -1,16 +1,19 @@ import styles from './HomeStyles/Workflows.module.css' import sharedStyles from './HomeStyles/pages.module.css' +import { WorkflowsTable } from '../../components/Workflows' +import { useLanguage } from '../../contexts/LanguageContext' function Workflows () { + const { t } = useLanguage() + return (
    -

    Workflows

    +

    {t('workflows.title')}

    - {/* Workflow content will go here */} -

    Workflow management coming soon...

    +