feat: IT Glue integration, workflow engine, pipelines, Zabbix WAN, notification channels, backup status UI improvements, nav alignment fixes
This commit is contained in:
parent
ed6c4a8b65
commit
19605f82aa
97 changed files with 17080 additions and 304 deletions
|
|
@ -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 */}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue