feat: IT Glue integration, workflow engine, pipelines, Zabbix WAN, notification channels, backup status UI improvements, nav alignment fixes

This commit is contained in:
lorentz 2026-02-27 14:52:14 -05:00
parent ed6c4a8b65
commit 19605f82aa
97 changed files with 17080 additions and 304 deletions

View file

@ -72,6 +72,7 @@ export default function RMMSiteMappingsPage() {
const [companies, setCompanies] = useState<Company[]>([]);
const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState<string | null>(null);
const [syncing, setSyncing] = useState(false);
const [searchTerm, setSearchTerm] = useState('');
const [filterStatus, setFilterStatus] = useState<'all' | 'mapped' | 'unmapped'>('all');
const [filterCompany, setFilterCompany] = useState<string>('all');
@ -111,6 +112,26 @@ export default function RMMSiteMappingsPage() {
}
};
const handleSyncCompanies = async () => {
setSyncing(true);
try {
const res = await fetch('/api/sync/entity', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ entities: ['companies'], triggeredBy: 'manual' }),
});
if (!res.ok) throw new Error('Sync failed');
// Poll briefly then refresh — companies sync is fast
await new Promise(r => setTimeout(r, 4000));
await fetchData();
toast({ title: 'Done', description: 'Companies synced from Autotask' });
} catch (error) {
toast({ title: 'Error', description: 'Failed to sync companies', variant: 'destructive' });
} finally {
setSyncing(false);
}
};
const handleSaveMapping = async (
siteUid: string,
siteName: string,
@ -120,9 +141,6 @@ export default function RMMSiteMappingsPage() {
setSaving(siteUid);
try {
const company = companies.find((c) => c.id === companyId);
if (!company) {
throw new Error('Company not found');
}
const response = await fetch('/api/rmm/site-mappings', {
method: 'POST',
@ -131,7 +149,7 @@ export default function RMMSiteMappingsPage() {
rmmSiteUid: siteUid,
rmmSiteName: siteName,
companyId: companyId,
companyName: company.companyName,
companyName: company?.companyName ?? null,
isPrimary: isPrimary,
}),
});
@ -142,7 +160,7 @@ export default function RMMSiteMappingsPage() {
toast({
title: 'Success',
description: `Mapped ${siteName} to ${company.companyName}`,
description: `Mapped ${siteName} to ${company?.companyName ?? `Company #${companyId}`}`,
});
await fetchData();
@ -227,10 +245,19 @@ export default function RMMSiteMappingsPage() {
Map RMM (Datto) sites to Autotask companies for complete device coverage
</p>
</div>
<Button onClick={fetchData} variant="outline" size="sm">
<RefreshCw className="w-4 h-4 mr-2" />
Refresh
</Button>
<div className="flex gap-2">
<Button onClick={handleSyncCompanies} variant="outline" size="sm" disabled={syncing}>
{syncing ? (
<><RefreshCw className="w-4 h-4 mr-2 animate-spin" />Syncing...</>
) : (
<><Building2 className="w-4 h-4 mr-2" />Sync Companies</>
)}
</Button>
<Button onClick={fetchData} variant="outline" size="sm">
<RefreshCw className="w-4 h-4 mr-2" />
Refresh
</Button>
</div>
</div>
{/* Stats Cards */}