UI-Redesign: AegisSight Design, Filter-Popover, Header-Umbau

- Session-Timeout auf 60 Minuten erhöht (ACCESS_TOKEN_EXPIRY + SESSION_TIMEOUT)
- AegisSight Light Theme: Gold-Akzent (#C8A851) statt Indigo
- Navigation-Tabs in eigene Zeile unter Header verschoben (HTML-Struktur)
- Filter-Bar durch kompaktes Popover mit Checkboxen ersetzt (Mehrfachauswahl)
- Archiv-Funktion repariert (lädt jetzt per API statt leerem Store)
- Filter-Bugs behoben: Reset-Button ID, Default-Werte, Ohne-Datum-Filter
- Mehrspalten-Layout Feature entfernt
- Online-Status vom Header an User-Avatar verschoben (grüner Punkt)
- Lupen-Icon entfernt
- CLAUDE.md: Docker-Deploy und CSS-Tricks Regeln aktualisiert

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
Server Deploy
2026-03-19 18:49:38 +01:00
Ursprung 99a6b7437b
Commit 4bd57d653f
36 geänderte Dateien mit 5027 neuen und 2897 gelöschten Zeilen

Datei anzeigen

@@ -828,7 +828,7 @@ router.post('/:id/duplicate', (req, res) => {
router.put('/:id/archive', (req, res) => {
try {
const taskId = req.params.id;
const { archived } = req.body;
const { archived, columnId } = req.body;
const db = getDb();
@@ -837,16 +837,42 @@ router.put('/:id/archive', (req, res) => {
return res.status(404).json({ error: 'Aufgabe nicht gefunden' });
}
db.prepare('UPDATE tasks SET archived = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?')
.run(archived ? 1 : 0, taskId);
// Bei Wiederherstellung: Prüfen ob Spalte vorhanden
if (!archived && !task.column_id) {
// Task hat keine Spalte (wurde mit gelöschter Spalte archiviert)
if (!columnId) {
return res.status(400).json({
error: 'Spalte erforderlich',
requiresColumn: true
});
}
// Prüfen ob Spalte existiert und zum Projekt gehört
const column = db.prepare('SELECT * FROM columns WHERE id = ? AND project_id = ?')
.get(columnId, task.project_id);
if (!column) {
return res.status(400).json({ error: 'Ungültige Spalte' });
}
// Wiederherstellen mit neuer Spalte
db.prepare('UPDATE tasks SET archived = 0, column_id = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?')
.run(columnId, taskId);
} else {
// Normales Archivieren/Wiederherstellen
db.prepare('UPDATE tasks SET archived = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?')
.run(archived ? 1 : 0, taskId);
}
addHistory(db, taskId, req.user.id, archived ? 'archived' : 'restored');
logger.info(`Aufgabe ${archived ? 'archiviert' : 'wiederhergestellt'}: ${task.title}`);
// WebSocket
// WebSocket - vollständige Task-Daten senden
const io = req.app.get('io');
io.to(`project:${task.project_id}`).emit('task:archived', { id: taskId, archived: !!archived });
const updatedTask = getFullTask(db, taskId);
io.to(`project:${task.project_id}`).emit('task:archived', {
id: taskId,
archived: !!archived,
columnId: updatedTask?.columnId
});
res.json({ message: archived ? 'Aufgabe archiviert' : 'Aufgabe wiederhergestellt' });
} catch (error) {