/** * AdminAutomationEventsPage * * Admin page for viewing and managing automation scheduler events. * SysAdmin-only: displays all automation definitions with scheduler status. * Uses FormGeneratorTable for consistent look with other admin pages. */ import React, { useState, useEffect, useCallback, useMemo } from 'react'; import { FaSync } from 'react-icons/fa'; import api from '../../api'; import styles from './Admin.module.css'; import { FormGeneratorTable, type ColumnConfig } from '../../components/FormGenerator/FormGeneratorTable'; interface AutomationEvent { eventId: string; automationId: string; name: string; nextRunTime: string | null; trigger: string | null; createdBy: string; mandate: string; featureInstance: string; } const _formatNextRun = (nextRunTime: string | null): string => { if (!nextRunTime || nextRunTime === 'None') return ''; try { const date = new Date(nextRunTime); return date.toLocaleString('de-CH', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit', }); } catch { return nextRunTime; } }; export const AdminAutomationEventsPage: React.FC = () => { const [events, setEvents] = useState([]); const [loading, setLoading] = useState(true); const [syncing, setSyncing] = useState(false); const [error, setError] = useState(null); const [syncResult, setSyncResult] = useState(null); const _fetchEvents = useCallback(async () => { try { setLoading(true); setError(null); const response = await api.get('/api/admin/automation-events'); // Map eventId to id for FormGeneratorTable compatibility setEvents(response.data.map((e: any) => ({ ...e, id: e.eventId }))); } catch (err: any) { setError(err.response?.data?.detail || 'Fehler beim Laden der Events'); } finally { setLoading(false); } }, []); useEffect(() => { _fetchEvents(); }, [_fetchEvents]); const _handleSync = async () => { try { setSyncing(true); setError(null); setSyncResult(null); const response = await api.post('/api/admin/automation-events/sync'); const data = response.data; setSyncResult(`Sync erfolgreich: ${data.synced} Automationen synchronisiert`); await _fetchEvents(); } catch (err: any) { setError(err.response?.data?.detail || 'Fehler beim Synchronisieren'); } finally { setSyncing(false); } }; const _handleDelete = useCallback(async (eventId: string) => { try { setError(null); const _event = events.find(e => e.eventId === eventId); const encodedId = encodeURIComponent(eventId); await api.post(`/api/admin/automation-events/${encodedId}/remove`); setEvents(prev => prev.filter(e => e.eventId !== eventId)); } catch (err: any) { setError(err.response?.data?.detail || 'Fehler beim Entfernen des Events'); throw err; } }, [events]); const columns: ColumnConfig[] = useMemo(() => [ { key: 'name', label: 'Name', type: 'string' as const, sortable: true, searchable: true, width: 200, minWidth: 120, }, { key: 'mandate', label: 'Mandant', type: 'string' as const, sortable: true, filterable: true, width: 150, minWidth: 100, }, { key: 'createdBy', label: 'Erstellt von', type: 'string' as const, sortable: true, filterable: true, width: 130, minWidth: 80, }, { key: 'featureInstance', label: 'Feature', type: 'string' as const, sortable: true, filterable: true, width: 130, minWidth: 80, }, { key: 'nextRunTime', label: 'Nächste Ausführung', type: 'string' as const, sortable: true, width: 170, minWidth: 130, formatter: (value: any) => { const formatted = _formatNextRun(value); if (!formatted) return ; return formatted; }, }, { key: 'trigger', label: 'Trigger', type: 'string' as const, sortable: false, width: 160, minWidth: 100, }, ], []); return (

Automation Events

Aktive Scheduler-Jobs ({events.length} Events)

{syncResult && (
{syncResult}
)} {error && (
! {error}
)}
); }; export default AdminAutomationEventsPage;