feat: RMM Overshell, IT Glue audit/write-back, LogLift, link-aware bundles, dashboard overhaul
- RMM Overshell (migration 077): admin page, dispatch UI, executor/worker, target resolver, script registry (AD/DHCP/DNS/event-log/services/software/network/loglift) - LogLift evidence pipeline (migration 078): upload webhook, B2 storage client, receiver/matcher, EventLogCollector PowerShell script - IT Glue audit + write-back (migrations 075, 076): asset-audit runner, ticket xrefs, applications/configurations browse pages + apply/revert/audit endpoints - Link-aware analyzer bundles (migration 073) + provider toggle (migration 074): link-discovery service, OpenRouter LLM provider, related-tickets/itglue-suggestion panels, analyze-bundle endpoint - Endpoint data model + device-link reconciliation (migrations 079, 080): conflicts admin page, reconciler service, resolve endpoints - Dashboard overhaul: integration-health service + alerts, overview/health endpoints - Permissions: add itglue + rmm scopes; middleware: public /api/rmm/loglift route Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
378e68ad8a
commit
1112a06afe
132 changed files with 21352 additions and 743 deletions
|
|
@ -10,7 +10,7 @@ import { Switch } from '@/components/ui/switch';
|
|||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog';
|
||||
import { Alert, AlertDescription } from '@/components/ui/alert';
|
||||
import { Clock, Play, Pause, Trash2, Plus, Calendar, AlertCircle, CheckCircle2, XCircle } from 'lucide-react';
|
||||
import { Clock, Play, Pause, Trash2, Plus, Calendar, AlertCircle, CheckCircle2, XCircle, RefreshCw } from 'lucide-react';
|
||||
|
||||
interface ScheduleConfig {
|
||||
id: string;
|
||||
|
|
@ -37,6 +37,7 @@ interface ScheduleStatus {
|
|||
|
||||
export default function SyncScheduler() {
|
||||
const [schedules, setSchedules] = useState<ScheduleStatus[]>([]);
|
||||
const [reloading, setReloading] = useState(false);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [editingSchedule, setEditingSchedule] = useState<ScheduleConfig | null>(null);
|
||||
|
|
@ -90,6 +91,20 @@ export default function SyncScheduler() {
|
|||
}
|
||||
};
|
||||
|
||||
const reloadSchedules = async () => {
|
||||
setReloading(true);
|
||||
try {
|
||||
const res = await fetch('/api/sync/schedules/reload', { method: 'POST' });
|
||||
const data = await res.json();
|
||||
if (!res.ok) throw new Error(data.error ?? `HTTP ${res.status}`);
|
||||
await fetchSchedules();
|
||||
} catch (err) {
|
||||
alert(`Reload failed: ${err instanceof Error ? err.message : err}`);
|
||||
} finally {
|
||||
setReloading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const toggleSchedule = async (scheduleId: string, currentState: boolean) => {
|
||||
try {
|
||||
const response = await fetch(`/api/sync/schedules/${scheduleId}`, {
|
||||
|
|
@ -259,10 +274,16 @@ export default function SyncScheduler() {
|
|||
Manage automatic sync schedules
|
||||
</CardDescription>
|
||||
</div>
|
||||
<Button onClick={openCreateDialog}>
|
||||
<Plus className="h-4 w-4 mr-2" />
|
||||
New Schedule
|
||||
</Button>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button variant="outline" onClick={reloadSchedules} disabled={reloading}>
|
||||
<RefreshCw className={`h-4 w-4 mr-2 ${reloading ? 'animate-spin' : ''}`} />
|
||||
{reloading ? 'Reloading…' : 'Reload from DB'}
|
||||
</Button>
|
||||
<Button onClick={openCreateDialog}>
|
||||
<Plus className="h-4 w-4 mr-2" />
|
||||
New Schedule
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue