utp_service/frontend/src/api/dashboard.ts

343 lines
9.8 KiB
TypeScript

import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { api } from './client'
export interface DashboardScope {
city?: string
client?: string
object_ids?: number[]
tag_ids?: number[]
}
export type DashboardAvailabilityWindow = '24h' | '3d' | '7d'
export interface DashboardCheckDefinition {
check_key: string
enabled: boolean
interval_sec_default: number
plugin_action: string
categories: string[]
timeout_sec: number
concurrency: number
updated_at: string
}
export interface DashboardObjectOverride {
object_id: number
check_key: string
enabled_override: boolean | null
interval_sec_override: number | null
categories_override: string[] | null
updated_at: string
}
export interface DashboardMonitorStatus {
status: string
run_type: string | null
scope: Record<string, unknown> | null
started_at: string | null
finished_at: string | null
last_success_at: string | null
last_error: string | null
last_counts: Record<string, unknown> | null
}
export interface DashboardObjectPolicy {
object_id: number
mode: 'inherit' | 'include' | 'exclude'
updated_at: string
}
export interface DashboardTagPolicy {
tag_id: number
enabled: boolean
updated_at: string
}
export interface DashboardPolicyResponse {
object_policies: DashboardObjectPolicy[]
tag_policies: DashboardTagPolicy[]
}
export interface DashboardObjectCheckSummary {
status_counts: Record<string, number>
last_checked_at: string | null
max_age_sec: number | null
}
export interface DashboardObjectSummary {
object_id: number
object_name: string
city: string | null
client: string | null
allowed: boolean
monitor_mode: 'inherit' | 'include' | 'exclude'
inclusion_reason: string
device_count: number
checks: Record<string, DashboardObjectCheckSummary>
health_score: number | null
}
export interface DashboardHomeSummary {
generated_at: string
scope: DashboardScope
totals: Record<string, number>
checks_meta: DashboardCheckDefinition[]
objects: DashboardObjectSummary[]
problem_objects: DashboardObjectSummary[]
included_count: number
excluded_count: number
included_objects: DashboardObjectSummary[]
excluded_objects: DashboardObjectSummary[]
}
export interface DashboardDeviceNOCItem {
device_id: number
object_id: number
rack_id: number | null
rack_name: string | null
ip: string
hostname: string | null
category: string
role: string | null
status: string | null
monitor_enabled: boolean
last_seen: string | null
last_ping_ms: number | null
ping_status: string
ping_checked_at: string | null
ping_age_sec: number | null
ping_fresh: boolean
disk_status: string | null
disk_max_pct: number | null
has_problem: boolean
}
export interface DashboardObjectSummaryResponse {
generated_at: string
scope: DashboardScope
object: DashboardObjectSummary
totals: Record<string, number>
checks_meta: DashboardCheckDefinition[]
top_problem_devices: DashboardDeviceNOCItem[]
}
export interface DashboardObjectDevicesResponse {
generated_at: string
scope: DashboardScope
object_id: number
devices: DashboardDeviceNOCItem[]
}
export interface DashboardAvailabilityPoint {
bucket_start: string
bucket_end: string
availability_pct: number | null
samples: number
online: number
offline: number
}
export interface DashboardAvailabilityInterval {
status: string
started_at: string
ended_at: string
duration_sec: number
}
export interface DashboardDeviceAvailability {
device_id: number
ip: string
hostname: string | null
availability_pct: number | null
samples: number
online: number
offline: number
last_checked_at: string | null
last_status: string | null
last_ping_ms: number | null
series: DashboardAvailabilityPoint[]
intervals: DashboardAvailabilityInterval[]
}
export interface DashboardObjectAvailabilityResponse {
generated_at: string
object_id: number
window: DashboardAvailabilityWindow
start_at: string
end_at: string
bucket_sec: number
overall_availability_pct: number | null
overall_series: DashboardAvailabilityPoint[]
devices: DashboardDeviceAvailability[]
insufficient_data: boolean
}
export interface DashboardChecksResponse {
checks: DashboardCheckDefinition[]
object_overrides: DashboardObjectOverride[]
}
export const useDashboardHomeSummary = (scope: DashboardScope) =>
useQuery({
queryKey: ['dashboard-home-summary', scope],
queryFn: () =>
api
.get<DashboardHomeSummary>('/api/v1/dashboard/home-summary', { params: scope })
.then((r) => r.data),
refetchInterval: 30_000,
})
export const useDashboardObjectSummary = (objectId: number, scope: DashboardScope) =>
useQuery({
queryKey: ['dashboard-object-summary', objectId, scope],
queryFn: () =>
api
.get<DashboardObjectSummaryResponse>(`/api/v1/dashboard/object/${objectId}/summary`, { params: scope })
.then((r) => r.data),
enabled: Number.isFinite(objectId) && objectId > 0,
refetchInterval: 30_000,
})
export const useDashboardObjectDevices = (objectId: number, scope: DashboardScope) =>
useQuery({
queryKey: ['dashboard-object-devices', objectId, scope],
queryFn: () =>
api
.get<DashboardObjectDevicesResponse>(`/api/v1/dashboard/object/${objectId}/devices`, { params: scope })
.then((r) => r.data),
enabled: Number.isFinite(objectId) && objectId > 0,
refetchInterval: 30_000,
})
export const useDashboardObjectAvailability = (
objectId: number,
window: DashboardAvailabilityWindow,
deviceIds?: number[],
compact?: boolean
) =>
useQuery({
queryKey: ['dashboard-object-availability', objectId, window, deviceIds, compact],
queryFn: () =>
api
.get<DashboardObjectAvailabilityResponse>(`/api/v1/dashboard/object/${objectId}/availability`, {
params: { window, device_ids: deviceIds, compact: compact ?? false },
})
.then((r) => r.data),
enabled:
Number.isFinite(objectId) &&
objectId > 0 &&
(deviceIds == null || deviceIds.length > 0),
refetchInterval: 45_000,
})
export const useDashboardMonitorStatus = () =>
useQuery({
queryKey: ['dashboard-monitor-status'],
queryFn: () =>
api
.get<DashboardMonitorStatus>('/api/v1/dashboard/monitor/status')
.then((r) => r.data),
refetchInterval: 10_000,
})
export const useDashboardRunNow = () => {
const qc = useQueryClient()
return useMutation({
mutationFn: (body: DashboardScope & { force?: boolean }) =>
api.post('/api/v1/dashboard/monitor/run', body).then((r) => r.data),
onSuccess: () => {
qc.invalidateQueries({ queryKey: ['dashboard-monitor-status'] })
qc.invalidateQueries({ queryKey: ['dashboard-home-summary'] })
qc.invalidateQueries({ queryKey: ['dashboard-object-summary'] })
qc.invalidateQueries({ queryKey: ['dashboard-object-devices'] })
qc.invalidateQueries({ queryKey: ['dashboard-object-availability'] })
},
})
}
export const useDashboardPolicy = () =>
useQuery({
queryKey: ['dashboard-policy'],
queryFn: () =>
api
.get<DashboardPolicyResponse>('/api/v1/dashboard/monitor/policy')
.then((r) => r.data),
})
export const usePatchDashboardObjectPolicy = () => {
const qc = useQueryClient()
return useMutation({
mutationFn: (body: Array<{ object_id: number; mode: 'inherit' | 'include' | 'exclude' }>) =>
api.patch('/api/v1/dashboard/monitor/policy/objects', body).then((r) => r.data),
onSuccess: () => {
qc.invalidateQueries({ queryKey: ['dashboard-policy'] })
qc.invalidateQueries({ queryKey: ['dashboard-home-summary'] })
qc.invalidateQueries({ queryKey: ['dashboard-object-summary'] })
},
})
}
export const usePatchDashboardTagPolicy = () => {
const qc = useQueryClient()
return useMutation({
mutationFn: (body: Array<{ tag_id: number; enabled: boolean }>) =>
api.patch('/api/v1/dashboard/monitor/policy/tags', body).then((r) => r.data),
onSuccess: () => {
qc.invalidateQueries({ queryKey: ['dashboard-policy'] })
qc.invalidateQueries({ queryKey: ['dashboard-home-summary'] })
qc.invalidateQueries({ queryKey: ['dashboard-object-summary'] })
},
})
}
export const useDashboardChecks = () =>
useQuery({
queryKey: ['dashboard-checks'],
queryFn: () =>
api
.get<DashboardChecksResponse>('/api/v1/dashboard/checks')
.then((r) => r.data),
})
export const usePatchDashboardChecks = () => {
const qc = useQueryClient()
return useMutation({
mutationFn: (
body: Array<{
check_key: string
enabled?: boolean
interval_sec_default?: number
categories?: string[]
timeout_sec?: number
concurrency?: number
}>
) => api.patch('/api/v1/dashboard/checks', body).then((r) => r.data),
onSuccess: () => {
qc.invalidateQueries({ queryKey: ['dashboard-checks'] })
qc.invalidateQueries({ queryKey: ['dashboard-home-summary'] })
qc.invalidateQueries({ queryKey: ['dashboard-object-summary'] })
qc.invalidateQueries({ queryKey: ['dashboard-object-devices'] })
},
})
}
export const usePatchDashboardObjectOverrides = () => {
const qc = useQueryClient()
return useMutation({
mutationFn: (
body: Array<{
object_id: number
check_key: string
enabled_override?: boolean | null
interval_sec_override?: number | null
categories_override?: string[] | null
}>
) => api.patch('/api/v1/dashboard/checks/object-overrides', body).then((r) => r.data),
onSuccess: () => {
qc.invalidateQueries({ queryKey: ['dashboard-checks'] })
qc.invalidateQueries({ queryKey: ['dashboard-home-summary'] })
qc.invalidateQueries({ queryKey: ['dashboard-object-summary'] })
qc.invalidateQueries({ queryKey: ['dashboard-object-devices'] })
},
})
}