added dateien page

This commit is contained in:
Ida Dittrich 2025-08-12 12:54:18 +02:00
parent 7cbdb0aea5
commit 10c7073cce
8 changed files with 141 additions and 66 deletions

View file

@ -49,6 +49,7 @@ function App() {
<Home /> <Home />
</ProtectedRoute> </ProtectedRoute>
}> }>
<Route index element={<Dashboard />} />
<Route path="dashboard" element={<Dashboard />} /> <Route path="dashboard" element={<Dashboard />} />
<Route path="dateien" element={<Dateien />} /> <Route path="dateien" element={<Dateien />} />
<Route path="team-bereich" element={<TeamBereich />} /> <Route path="team-bereich" element={<TeamBereich />} />

View file

@ -128,7 +128,7 @@ export function useDateienLogic(): DateienLogicReturn {
const columns: ColumnConfig[] = useMemo(() => [ const columns: ColumnConfig[] = useMemo(() => [
{ {
key: 'file_name', key: 'file_name',
label: 'Filename', label: t('files.column.filename'),
type: 'string', type: 'string',
width: 300, width: 300,
minWidth: 200, minWidth: 200,
@ -144,8 +144,7 @@ export function useDateienLogic(): DateienLogicReturn {
display: 'block', display: 'block',
whiteSpace: 'nowrap', whiteSpace: 'nowrap',
overflow: 'hidden', overflow: 'hidden',
textOverflow: 'ellipsis', textOverflow: 'ellipsis'
paddingLeft: '8px'
}} }}
title={value} title={value}
> >
@ -155,7 +154,7 @@ export function useDateienLogic(): DateienLogicReturn {
}, },
{ {
key: 'mime_type', key: 'mime_type',
label: 'mime type', label: t('files.column.mimetype'),
type: 'string', type: 'string',
width: 200, width: 200,
minWidth: 150, minWidth: 150,
@ -166,7 +165,7 @@ export function useDateienLogic(): DateienLogicReturn {
}, },
{ {
key: 'size', key: 'size',
label: 'filesize', label: t('files.column.filesize'),
type: 'number', type: 'number',
width: 140, width: 140,
minWidth: 120, minWidth: 120,
@ -181,7 +180,7 @@ export function useDateienLogic(): DateienLogicReturn {
}, },
{ {
key: 'created_at', key: 'created_at',
label: 'creation date', label: t('files.column.creationdate'),
type: 'date', type: 'date',
width: 200, width: 200,
minWidth: 180, minWidth: 180,
@ -190,7 +189,7 @@ export function useDateienLogic(): DateienLogicReturn {
filterable: true, filterable: true,
formatter: (value: string | undefined) => formatDate(value) formatter: (value: string | undefined) => formatDate(value)
}, },
], []); ], [t]);
// Handle file download // Handle file download
const handleDownload = async (file: UserFile) => { const handleDownload = async (file: UserFile) => {

View file

@ -397,7 +397,7 @@ tbody .actionsColumn {
/* Pagination */ /* Pagination */
.pagination { .pagination {
display: flex; display: flex;
justify-content: center; justify-content: space-between;
align-items: center; align-items: center;
gap: 10px; gap: 10px;
padding: 15px; padding: 15px;
@ -406,6 +406,37 @@ tbody .actionsColumn {
border-radius: 0 0 8px 8px; border-radius: 0 0 8px 8px;
} }
.pageSizeSelector {
display: flex;
align-items: center;
gap: 8px;
font-size: 14px;
color: var(--color-text);
}
.pageSizeSelector label {
white-space: nowrap;
font-family: var(--font-family);
}
.pageSizeSelect {
height: 32px;
padding: 4px 8px;
border: 1px solid var(--color-primary);
border-radius: 4px;
font-size: 14px;
font-family: var(--font-family);
background: var(--color-bg);
color: var(--color-text);
cursor: pointer;
min-width: 60px;
}
.pageSizeSelect:focus {
outline: none;
border-color: var(--color-secondary);
}
.paginationButton { .paginationButton {
padding: 8px 12px; padding: 8px 12px;
border: 1px solid var(--color-gray-disabled); border: 1px solid var(--color-gray-disabled);
@ -490,16 +521,19 @@ tbody .actionsColumn {
} }
.pagination { .pagination {
flex-wrap: wrap; flex-direction: column;
gap: 5px; gap: 10px;
padding: 10px; padding: 10px;
} }
.paginationInfo { .pageSizeSelector {
order: -1; order: -1;
width: 100%; justify-content: center;
}
.paginationInfo {
text-align: center; text-align: center;
margin: 0 0 10px 0; margin: 0;
font-size: 13px; font-size: 13px;
} }
} }

View file

@ -27,6 +27,8 @@ export interface FormGeneratorProps<T = any> {
resizable?: boolean; resizable?: boolean;
pagination?: boolean; pagination?: boolean;
pageSize?: number; pageSize?: number;
pageSizeOptions?: number[];
showPageSizeSelector?: boolean;
onRowClick?: (row: T, index: number) => void; onRowClick?: (row: T, index: number) => void;
onRowSelect?: (selectedRows: T[]) => void; onRowSelect?: (selectedRows: T[]) => void;
selectable?: boolean; selectable?: boolean;
@ -49,6 +51,8 @@ export function FormGenerator<T extends Record<string, any>>({
resizable = true, resizable = true,
pagination = true, pagination = true,
pageSize = 10, pageSize = 10,
pageSizeOptions = [10, 25, 50, 100],
showPageSizeSelector = true,
onRowClick, onRowClick,
onRowSelect, onRowSelect,
selectable = false, selectable = false,
@ -100,6 +104,7 @@ export function FormGenerator<T extends Record<string, any>>({
const [columnWidths, setColumnWidths] = useState<Record<string, number>>({}); const [columnWidths, setColumnWidths] = useState<Record<string, number>>({});
const [selectedRows, setSelectedRows] = useState<Set<number>>(new Set()); const [selectedRows, setSelectedRows] = useState<Set<number>>(new Set());
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
const [currentPageSize, setCurrentPageSize] = useState(pageSize);
// Refs for resizing // Refs for resizing
const tableRef = useRef<HTMLTableElement>(null); const tableRef = useRef<HTMLTableElement>(null);
@ -188,11 +193,11 @@ export function FormGenerator<T extends Record<string, any>>({
const paginatedData = useMemo(() => { const paginatedData = useMemo(() => {
if (!pagination) return filteredData; if (!pagination) return filteredData;
const startIndex = (currentPage - 1) * pageSize; const startIndex = (currentPage - 1) * currentPageSize;
return filteredData.slice(startIndex, startIndex + pageSize); return filteredData.slice(startIndex, startIndex + currentPageSize);
}, [filteredData, currentPage, pageSize, pagination]); }, [filteredData, currentPage, currentPageSize, pagination]);
const totalPages = Math.ceil(filteredData.length / pageSize); const totalPages = Math.ceil(filteredData.length / currentPageSize);
// Handle sorting // Handle sorting
const handleSort = (key: string) => { const handleSort = (key: string) => {
@ -257,6 +262,12 @@ export function FormGenerator<T extends Record<string, any>>({
} }
}; };
// Handle page size change
const handlePageSizeChange = (newPageSize: number) => {
setCurrentPageSize(newPageSize);
setCurrentPage(1); // Reset to first page when page size changes
};
// Handle column resizing // Handle column resizing
const handleMouseDown = (e: React.MouseEvent, columnKey: string) => { const handleMouseDown = (e: React.MouseEvent, columnKey: string) => {
if (!resizable) return; if (!resizable) return;
@ -333,6 +344,7 @@ export function FormGenerator<T extends Record<string, any>>({
return ( return (
<div className={`${styles.formGenerator} ${className}`}> <div className={`${styles.formGenerator} ${className}`}>
{title && <h2 className={styles.title}>{title}</h2>}
{(searchable || filterable) && ( {(searchable || filterable) && (
@ -640,48 +652,68 @@ export function FormGenerator<T extends Record<string, any>>({
</div> </div>
{/* Pagination */} {/* Pagination */}
{pagination && totalPages > 1 && ( {pagination && (
<div className={styles.pagination}> <div className={styles.pagination}>
<button {showPageSizeSelector && (
onClick={() => setCurrentPage(1)} <div className={styles.pageSizeSelector}>
disabled={currentPage === 1} <label htmlFor="pageSize">{t('formgen.pagination.pageSize', 'Items per page:')}</label>
className={styles.paginationButton} <select
title={t('formgen.pagination.first')} id="pageSize"
> value={currentPageSize}
«« onChange={(e) => handlePageSizeChange(Number(e.target.value))}
</button> className={styles.pageSizeSelect}
<button >
onClick={() => setCurrentPage(currentPage - 1)} {pageSizeOptions.map(size => (
disabled={currentPage === 1} <option key={size} value={size}>{size}</option>
className={styles.paginationButton} ))}
title={t('formgen.pagination.prev')} </select>
> </div>
« )}
</button>
<span className={styles.paginationInfo}> {totalPages > 1 && (
{t('formgen.pagination.info') <>
.replace('{page}', currentPage.toString()) <button
.replace('{total}', totalPages.toString()) onClick={() => setCurrentPage(1)}
.replace('{count}', filteredData.length.toString())} disabled={currentPage === 1}
</span> className={styles.paginationButton}
title={t('formgen.pagination.first')}
<button >
onClick={() => setCurrentPage(currentPage + 1)} ««
disabled={currentPage === totalPages} </button>
className={styles.paginationButton} <button
title={t('formgen.pagination.next')} onClick={() => setCurrentPage(currentPage - 1)}
> disabled={currentPage === 1}
» className={styles.paginationButton}
</button> title={t('formgen.pagination.prev')}
<button >
onClick={() => setCurrentPage(totalPages)} «
disabled={currentPage === totalPages} </button>
className={styles.paginationButton}
title={t('formgen.pagination.last')} <span className={styles.paginationInfo}>
> {t('formgen.pagination.info')
»» .replace('{page}', currentPage.toString())
</button> .replace('{total}', totalPages.toString())
.replace('{count}', filteredData.length.toString())}
</span>
<button
onClick={() => setCurrentPage(currentPage + 1)}
disabled={currentPage === totalPages}
className={styles.paginationButton}
title={t('formgen.pagination.next')}
>
»
</button>
<button
onClick={() => setCurrentPage(totalPages)}
disabled={currentPage === totalPages}
className={styles.paginationButton}
title={t('formgen.pagination.last')}
>
»»
</button>
</>
)}
</div> </div>
)} )}
</div> </div>

View file

@ -267,9 +267,13 @@ export default {
// File Table Columns // File Table Columns
'files.column.name': 'Name', 'files.column.name': 'Name',
'files.column.filename': 'Dateiname',
'files.column.type': 'Typ', 'files.column.type': 'Typ',
'files.column.mimetype': 'MIME-Typ',
'files.column.size': 'Größe', 'files.column.size': 'Größe',
'files.column.filesize': 'Dateigröße',
'files.column.created': 'Erstellt', 'files.column.created': 'Erstellt',
'files.column.creationdate': 'Erstellungsdatum',
'files.column.source': 'Quelle', 'files.column.source': 'Quelle',
// File Types // File Types
@ -334,6 +338,7 @@ export default {
'formgen.filter.placeholder': '{column} filtern', 'formgen.filter.placeholder': '{column} filtern',
'formgen.actions.column': 'Aktionen', 'formgen.actions.column': 'Aktionen',
'formgen.pagination.info': 'Seite {page} von {total} ({count} Einträge)', 'formgen.pagination.info': 'Seite {page} von {total} ({count} Einträge)',
'formgen.pagination.pageSize': 'Einträge pro Seite:',
'formgen.pagination.first': 'Erste Seite', 'formgen.pagination.first': 'Erste Seite',
'formgen.pagination.prev': 'Vorherige Seite', 'formgen.pagination.prev': 'Vorherige Seite',
'formgen.pagination.next': 'Nächste Seite', 'formgen.pagination.next': 'Nächste Seite',

View file

@ -268,9 +268,13 @@ export default {
// File Table Columns // File Table Columns
'files.column.name': 'Name', 'files.column.name': 'Name',
'files.column.filename': 'Filename',
'files.column.type': 'Type', 'files.column.type': 'Type',
'files.column.mimetype': 'MIME Type',
'files.column.size': 'Size', 'files.column.size': 'Size',
'files.column.filesize': 'File Size',
'files.column.created': 'Created', 'files.column.created': 'Created',
'files.column.creationdate': 'Creation Date',
'files.column.source': 'Source', 'files.column.source': 'Source',
// File Types // File Types
@ -335,6 +339,7 @@ export default {
'formgen.filter.placeholder': 'Filter {column}', 'formgen.filter.placeholder': 'Filter {column}',
'formgen.actions.column': 'Actions', 'formgen.actions.column': 'Actions',
'formgen.pagination.info': 'Page {page} of {total} ({count} items)', 'formgen.pagination.info': 'Page {page} of {total} ({count} items)',
'formgen.pagination.pageSize': 'Items per page:',
'formgen.pagination.first': 'First page', 'formgen.pagination.first': 'First page',
'formgen.pagination.prev': 'Previous page', 'formgen.pagination.prev': 'Previous page',
'formgen.pagination.next': 'Next page', 'formgen.pagination.next': 'Next page',

View file

@ -267,9 +267,13 @@ export default {
// File Table Columns // File Table Columns
'files.column.name': 'Nom', 'files.column.name': 'Nom',
'files.column.filename': 'Nom de fichier',
'files.column.type': 'Type', 'files.column.type': 'Type',
'files.column.mimetype': 'Type MIME',
'files.column.size': 'Taille', 'files.column.size': 'Taille',
'files.column.filesize': 'Taille du fichier',
'files.column.created': 'Créé', 'files.column.created': 'Créé',
'files.column.creationdate': 'Date de création',
'files.column.source': 'Source', 'files.column.source': 'Source',
// File Types // File Types
@ -334,6 +338,7 @@ export default {
'formgen.filter.placeholder': 'Filtrer {column}', 'formgen.filter.placeholder': 'Filtrer {column}',
'formgen.actions.column': 'Actions', 'formgen.actions.column': 'Actions',
'formgen.pagination.info': 'Page {page} sur {total} ({count} éléments)', 'formgen.pagination.info': 'Page {page} sur {total} ({count} éléments)',
'formgen.pagination.pageSize': 'Éléments par page:',
'formgen.pagination.first': 'Première page', 'formgen.pagination.first': 'Première page',
'formgen.pagination.prev': 'Page précédente', 'formgen.pagination.prev': 'Page précédente',
'formgen.pagination.next': 'Page suivante', 'formgen.pagination.next': 'Page suivante',

View file

@ -7,6 +7,8 @@ function Dashboard () {
const [isChatExpanded, setIsChatExpanded] = useState(false); const [isChatExpanded, setIsChatExpanded] = useState(false);
const [selectedPrompt, setSelectedPrompt] = useState<Prompt | null>(null); const [selectedPrompt, setSelectedPrompt] = useState<Prompt | null>(null);
const [isPromptAreaCollapsed, setIsPromptAreaCollapsed] = useState(false); const [isPromptAreaCollapsed, setIsPromptAreaCollapsed] = useState(false);
const [currentWorkflowId, setCurrentWorkflowId] = useState<string | null>(null);
const [workflowCompleted, setWorkflowCompleted] = useState(false);
const handleChatToggleExpand = () => { const handleChatToggleExpand = () => {
setIsChatExpanded(!isChatExpanded); setIsChatExpanded(!isChatExpanded);
@ -25,7 +27,7 @@ function Dashboard () {
} }
return workflowId; return workflowId;
}); });
}, []); }, [setCurrentWorkflowId, setWorkflowCompleted]);
const handleWorkflowCompletedChange = useCallback((completed: boolean) => { const handleWorkflowCompletedChange = useCallback((completed: boolean) => {
setWorkflowCompleted(completed); setWorkflowCompleted(completed);
@ -62,11 +64,3 @@ function Dashboard () {
} }
export default Dashboard; export default Dashboard;
function setCurrentWorkflowId(arg0: (prevId: any) => string | null) {
throw new Error('Function not implemented.');
}
function setWorkflowCompleted(arg0: boolean) {
throw new Error('Function not implemented.');
}