{selectedZone.name}
{selectedProvider} {records.length} records {syncedAt ? Last synced: {formatSyncedAt(syncedAt)} : Never synced — press Sync to load records }Loading…
: !syncedAt ?Press Sync to fetch records from {selectedProvider}.
import { useState, useEffect, useCallback } from 'react'; import { getProviders, getZones, getRecords, syncRecords, addRecord, updateRecord, deleteRecord, getMe, setToken } from './api/dns'; import RecordsTable from './components/RecordsTable'; import AddRecordForm from './components/AddRecordForm'; import Dashboard from './components/Dashboard'; import SettingsPage from './components/SettingsPage'; import ProviderOverview from './components/ProviderOverview'; import LoginPage from './components/LoginPage'; import ProfilePage from './components/ProfilePage'; import AuditPage from './components/AuditPage'; import SecretsPage from './components/SecretsPage'; import IpamPage from './components/IpamPage'; import DomainsPage from './components/DomainsPage'; import { useProviderColors, providerBadgeStyle } from './context/ProviderColors'; import { useTheme } from './context/Theme'; import ConfirmDialog from './components/ConfirmDialog'; import './App.css'; function formatSyncedAt(iso) { if (!iso) return null; const d = new Date(iso); const date = d.toLocaleDateString('sv-SE'); // YYYY-MM-DD const time = d.toLocaleTimeString('sv-SE', { hour: '2-digit', minute: '2-digit' }); return `${date} ${time}`; } // ─── Main app (shown when authenticated) ───────────────────────────────────── function AppShell({ currentUser, onLogout }) { const [providers, setProviders] = useState([]); const [selectedProvider, setSelectedProvider] = useState(null); const [zones, setZones] = useState([]); const [selectedZone, setSelectedZone] = useState(null); const [records, setRecords] = useState([]); const [syncedAt, setSyncedAt] = useState(null); const [loadingZones, setLoadingZones] = useState(false); const [loadingRecords, setLoadingRecords] = useState(false); const [syncing, setSyncing] = useState(false); const [view, setView] = useState('dashboard'); const [showForm, setShowForm] = useState(false); const [editingRecord, setEditingRecord] = useState(null); const { colors: providerColors } = useProviderColors(); const { theme, toggleTheme } = useTheme(); const [deletingId, setDeletingId] = useState(null); const [confirmDelete, setConfirmDelete] = useState(null); const [error, setError] = useState(''); const [filter, setFilter] = useState(''); useEffect(() => { getProviders() .then(setProviders) .catch(e => setError(e.message)); }, []); useEffect(() => { if (!selectedProvider) return; setZones([]); setSelectedZone(null); setRecords([]); setSyncedAt(null); setError(''); setLoadingZones(true); getZones(selectedProvider) .then(setZones) .catch(e => setError(e.message)) .finally(() => setLoadingZones(false)); }, [selectedProvider]); const loadRecords = useCallback((provider, zone) => { setLoadingRecords(true); setError(''); getRecords(provider, zone.id) .then(({ records, synced_at }) => { setRecords(records); setSyncedAt(synced_at); }) .catch(e => setError(e.message)) .finally(() => setLoadingRecords(false)); }, []); function selectZone(zone) { setSelectedZone(zone); setFilter(''); loadRecords(selectedProvider, zone); } async function handleSync() { setSyncing(true); setError(''); try { const { records, synced_at } = await syncRecords(selectedProvider, selectedZone.id, selectedZone.name); setRecords(records); setSyncedAt(synced_at); } catch (e) { setError(e.message); } finally { setSyncing(false); } } function openAddForm() { setEditingRecord(null); setShowForm(true); } function openEditForm(record) { setEditingRecord(record); setShowForm(true); } function closeForm() { setShowForm(false); setEditingRecord(null); } async function handleFormSubmit(formData) { if (editingRecord) { const result = await updateRecord(selectedProvider, selectedZone.id, editingRecord.id, formData); setRecords(rs => rs.map(r => r.id === editingRecord.id ? { ...formData, id: result.id ?? editingRecord.id } : r)); } else { const result = await addRecord(selectedProvider, selectedZone.id, formData); setRecords(rs => [...rs, { ...formData, id: result.id }]); } closeForm(); } function handleDeleteRecord(record) { setConfirmDelete(record); } async function confirmDeleteRecord() { const record = confirmDelete; setConfirmDelete(null); setDeletingId(record.id); try { await deleteRecord(selectedProvider, selectedZone.id, record.id); setRecords(rs => rs.filter(r => r.id !== record.id)); } catch (e) { setError(e.message); } finally { setDeletingId(null); } } const filteredRecords = records.filter(r => { const q = filter.toLowerCase(); return !q || r.name.toLowerCase().includes(q) || r.content.toLowerCase().includes(q) || r.type.toLowerCase().includes(q); }); return (
Loading…
: !syncedAt ?Press Sync to fetch records from {selectedProvider}.