diff --git a/paperless-frontend/src/pages/SettingsPage.tsx b/paperless-frontend/src/pages/SettingsPage.tsx index b779018..c1081f9 100644 --- a/paperless-frontend/src/pages/SettingsPage.tsx +++ b/paperless-frontend/src/pages/SettingsPage.tsx @@ -20,6 +20,7 @@ import { INBOX_ACTION_LABELS, type InboxAction, type InboxActionType, agrarmonitorApi, type AgrarmonitorStatusData, + type SettingClient, type AgrarmonitorPollingConfig, type AgrarmonitorPollingResult, } from '../api/settings'; import { clientsApi, type Client } from '../api/inbox'; import { apiKeysApi, type ApiKey } from '../api/api-keys'; @@ -213,7 +214,9 @@ function FilterBuilder({ value, onChange, tags, docTypes, correspondents, custom function UserClientsTab() { const [data, setData] = useState([]); const [clients, setClients] = useState([]); + const [allClients, setAllClients] = useState([]); const [loading, setLoading] = useState(true); + const [clientsLoading, setClientsLoading] = useState(false); const [modalOpen, setModalOpen] = useState(false); const [form] = Form.useForm(); @@ -229,7 +232,15 @@ function UserClientsTab() { } finally { setLoading(false); } }, []); - useEffect(() => { load(); }, [load]); + const loadAllClients = useCallback(async () => { + setClientsLoading(true); + try { + const cls = await settingsApi.getClients(); + setAllClients(cls); + } finally { setClientsLoading(false); } + }, []); + + useEffect(() => { load(); loadAllClients(); }, [load, loadAllClients]); const handleAdd = async () => { const values = await form.validateFields(); @@ -246,6 +257,37 @@ function UserClientsTab() { load(); }; + const handleUpdateBetriebId = async (id: number, val: number | null) => { + try { + const updated = await settingsApi.updateClient(id, val); + setAllClients(prev => prev.map(c => c.Id === id ? updated : c)); + } catch { + message.error('Speichern fehlgeschlagen'); + } + }; + + const allClientColumns: ColumnsType = [ + { title: 'Name', dataIndex: 'Name', key: 'name' }, + { + title: 'Agrarmonitor-BetriebId', + dataIndex: 'AgrarmonitorBetriebId', + key: 'betriebId', + render: (val: number | null, record) => ( + { + const parsed = e.target.value ? parseInt(e.target.value, 10) : null; + const current = val ?? null; + if (parsed !== current) handleUpdateBetriebId(record.Id, isNaN(parsed as number) ? null : parsed); + }} + /> + ), + }, + ]; + const columns: ColumnsType = [ { title: 'User ID', dataIndex: 'UserId', key: 'userId' }, { @@ -277,6 +319,21 @@ function UserClientsTab() { Zuordnung hinzufügen + + + Betriebe — Agrarmonitor-Zuordnung + + Ordne jedem Betrieb die zugehörige Agrarmonitor-BetriebId zu. Wird beim Polling verwendet. + +
+ setModalOpen(false)}>
@@ -2228,10 +2285,15 @@ function BarcodeTemplatesTab() { function AgrarmonitorTab() { const [form] = Form.useForm(); + const [pollingForm] = Form.useForm(); const [loading, setLoading] = useState(false); const [registering, setRegistering] = useState(false); + const [pollingConfigLoading, setPollingConfigLoading] = useState(false); + const [pollingSaving, setPollingSaving] = useState(false); + const [pollingRunning, setPollingRunning] = useState(false); const [status, setStatus] = useState(null); const [registerResult, setRegisterResult] = useState<{ success: boolean; message: string } | null>(null); + const [pollingResult, setPollingResult] = useState(null); const handleLoadStatus = async () => { setLoading(true); @@ -2267,6 +2329,46 @@ function AgrarmonitorTab() { } }; + const handleLoadPollingConfig = useCallback(async () => { + setPollingConfigLoading(true); + try { + const cfg = await agrarmonitorApi.getPollingConfig(); + pollingForm.setFieldsValue(cfg); + } catch { + message.error('Polling-Konfiguration konnte nicht geladen werden'); + } finally { + setPollingConfigLoading(false); + } + }, [pollingForm]); + + useEffect(() => { handleLoadPollingConfig(); }, [handleLoadPollingConfig]); + + const handleSavePollingConfig = async () => { + const values = await pollingForm.validateFields() as AgrarmonitorPollingConfig; + setPollingSaving(true); + try { + await agrarmonitorApi.updatePollingConfig(values); + message.success('Konfiguration gespeichert'); + } catch { + message.error('Speichern fehlgeschlagen'); + } finally { + setPollingSaving(false); + } + }; + + const handleRunPolling = async () => { + setPollingRunning(true); + setPollingResult(null); + try { + const result = await agrarmonitorApi.runPolling(); + setPollingResult(result); + } catch { + message.error('Polling fehlgeschlagen'); + } finally { + setPollingRunning(false); + } + }; + const renderStatusTag = (value: boolean | null, labelTrue: string, labelFalse: string) => { if (value === null) return ; return value @@ -2343,6 +2445,53 @@ function AgrarmonitorTab() { )} )} + + + + + + + + + + + + + + + + + {pollingResult && ( +
+ {pollingResult.processed} verarbeitet + {pollingResult.updated} aktualisiert + {pollingResult.skipped} übersprungen + {pollingResult.errors.length > 0 && ( + {pollingResult.errors.length} Fehler + )} + {pollingResult.errors.length > 0 && ( +
    + {pollingResult.errors.map((e, i) => ( +
  • {e}
  • + ))} +
+ )} +
+ )} +
+
);