feat(devices): exibe bateria, sensores termicos, rede, monitores e chassis
Some checks failed
CI/CD Web + Desktop / Deploy Convex functions (push) Blocked by required conditions
CI/CD Web + Desktop / Detect changes (push) Successful in 5s
CI/CD Web + Desktop / Deploy (VPS Linux) (push) Has been cancelled
Quality Checks / Lint, Test and Build (push) Has been cancelled
Some checks failed
CI/CD Web + Desktop / Deploy Convex functions (push) Blocked by required conditions
CI/CD Web + Desktop / Detect changes (push) Successful in 5s
CI/CD Web + Desktop / Deploy (VPS Linux) (push) Has been cancelled
Quality Checks / Lint, Test and Build (push) Has been cancelled
- Adiciona tipos TypeScript para novos dados do Windows - Exibe informacoes de bateria com status traduzido - Exibe sensores termicos em tabela - Exibe adaptadores de rede com velocidade e status - Exibe monitores conectados com fabricante e serial - Exibe info do chassis/gabinete com tipo traduzido 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
f0c2bdc283
commit
3e63589055
1 changed files with 215 additions and 0 deletions
|
|
@ -271,6 +271,64 @@ type WindowsDiskEntry = {
|
|||
MediaType?: string
|
||||
}
|
||||
|
||||
type WindowsBattery = {
|
||||
Name?: string
|
||||
DeviceID?: string
|
||||
Status?: string
|
||||
BatteryStatus?: number
|
||||
BatteryStatusText?: string
|
||||
EstimatedChargeRemaining?: number
|
||||
EstimatedRunTime?: number
|
||||
DesignCapacity?: number
|
||||
FullChargeCapacity?: number
|
||||
DesignVoltage?: number
|
||||
Chemistry?: number
|
||||
BatteryRechargeTime?: number
|
||||
}
|
||||
|
||||
type WindowsBatteryInfo = {
|
||||
Present: boolean
|
||||
Batteries: WindowsBattery[]
|
||||
}
|
||||
|
||||
type WindowsThermalSensor = {
|
||||
Source?: string
|
||||
Name?: string
|
||||
TemperatureCelsius?: number
|
||||
CriticalTripPoint?: number
|
||||
Parent?: string
|
||||
}
|
||||
|
||||
type WindowsNetworkAdapter = {
|
||||
Name?: string
|
||||
Description?: string
|
||||
MACAddress?: string
|
||||
Speed?: number
|
||||
NetConnectionStatus?: number
|
||||
StatusText?: string
|
||||
AdapterType?: string
|
||||
Manufacturer?: string
|
||||
NetConnectionID?: string
|
||||
PNPDeviceID?: string
|
||||
}
|
||||
|
||||
type WindowsMonitor = {
|
||||
ManufacturerName?: string
|
||||
ProductCodeID?: string
|
||||
SerialNumberID?: string
|
||||
UserFriendlyName?: string
|
||||
YearOfManufacture?: number
|
||||
WeekOfManufacture?: number
|
||||
}
|
||||
|
||||
type WindowsChassis = {
|
||||
ChassisTypes?: number[]
|
||||
ChassisTypesText?: string[]
|
||||
Manufacturer?: string
|
||||
SerialNumber?: string
|
||||
SMBIOSAssetTag?: string
|
||||
}
|
||||
|
||||
type WindowsExtended = {
|
||||
software?: DeviceSoftware[]
|
||||
services?: Array<{ name?: string; status?: string; displayName?: string }>
|
||||
|
|
@ -292,6 +350,11 @@ type WindowsExtended = {
|
|||
windowsUpdate?: Record<string, unknown>
|
||||
computerSystem?: Record<string, unknown>
|
||||
azureAdStatus?: Record<string, unknown>
|
||||
battery?: WindowsBatteryInfo
|
||||
thermal?: WindowsThermalSensor[]
|
||||
networkAdapters?: WindowsNetworkAdapter[]
|
||||
monitors?: WindowsMonitor[]
|
||||
chassis?: WindowsChassis
|
||||
}
|
||||
|
||||
type MacExtended = {
|
||||
|
|
@ -3015,6 +3078,21 @@ export function DeviceDetails({ device }: DeviceDetailsProps) {
|
|||
return a.id.localeCompare(b.id)
|
||||
})
|
||||
}, [windowsExt?.hotfix])
|
||||
// Novos dados do agente: bateria, sensores termicos, adaptadores de rede, monitores, chassis
|
||||
const windowsBatteryInfo = windowsExt?.battery ?? null
|
||||
const windowsThermalSensors = useMemo(() => {
|
||||
if (Array.isArray(windowsExt?.thermal)) return windowsExt.thermal
|
||||
return []
|
||||
}, [windowsExt?.thermal])
|
||||
const windowsNetworkAdapters = useMemo(() => {
|
||||
if (Array.isArray(windowsExt?.networkAdapters)) return windowsExt.networkAdapters
|
||||
return []
|
||||
}, [windowsExt?.networkAdapters])
|
||||
const windowsMonitors = useMemo(() => {
|
||||
if (Array.isArray(windowsExt?.monitors)) return windowsExt.monitors
|
||||
return []
|
||||
}, [windowsExt?.monitors])
|
||||
const windowsChassisInfo = windowsExt?.chassis ?? null
|
||||
const osNameDisplay = useMemo(() => {
|
||||
const base = device?.osName?.trim()
|
||||
const edition = windowsEditionLabel?.trim()
|
||||
|
|
@ -5506,6 +5584,143 @@ export function DeviceDetails({ device }: DeviceDetailsProps) {
|
|||
</div>
|
||||
) : null}
|
||||
|
||||
{/* Bateria */}
|
||||
{windowsBatteryInfo?.Present && windowsBatteryInfo.Batteries.length > 0 ? (
|
||||
<div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
|
||||
<p className="text-xs font-semibold uppercase text-slate-500">Bateria</p>
|
||||
<div className="mt-2 space-y-2">
|
||||
{windowsBatteryInfo.Batteries.map((battery, idx) => (
|
||||
<div key={`bat-${idx}`} className="grid gap-1 text-sm text-muted-foreground">
|
||||
<DetailLine label="Nome" value={battery.Name ?? "Bateria"} />
|
||||
<DetailLine
|
||||
label="Status"
|
||||
value={battery.BatteryStatusText ?? (battery.BatteryStatus != null ? `Código ${battery.BatteryStatus}` : "—")}
|
||||
/>
|
||||
{battery.EstimatedChargeRemaining != null && (
|
||||
<DetailLine label="Carga" value={`${battery.EstimatedChargeRemaining}%`} />
|
||||
)}
|
||||
{battery.EstimatedRunTime != null && battery.EstimatedRunTime > 0 && battery.EstimatedRunTime < 71582788 && (
|
||||
<DetailLine label="Tempo restante" value={`${Math.floor(battery.EstimatedRunTime / 60)}h ${battery.EstimatedRunTime % 60}min`} />
|
||||
)}
|
||||
{battery.DesignCapacity != null && battery.DesignCapacity > 0 && (
|
||||
<DetailLine label="Capacidade de projeto" value={`${battery.DesignCapacity} mWh`} />
|
||||
)}
|
||||
{battery.FullChargeCapacity != null && battery.FullChargeCapacity > 0 && (
|
||||
<DetailLine label="Capacidade atual" value={`${battery.FullChargeCapacity} mWh`} />
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{/* Sensores térmicos */}
|
||||
{windowsThermalSensors.length > 0 ? (
|
||||
<div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
|
||||
<p className="text-xs font-semibold uppercase text-slate-500">Sensores térmicos</p>
|
||||
<div className="mt-2 overflow-hidden rounded-md border border-slate-200">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow className="border-slate-200 bg-slate-100/80">
|
||||
<TableHead className="text-xs text-slate-500">Sensor</TableHead>
|
||||
<TableHead className="text-xs text-slate-500">Temperatura</TableHead>
|
||||
<TableHead className="text-xs text-slate-500">Crítico</TableHead>
|
||||
<TableHead className="text-xs text-slate-500">Fonte</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{windowsThermalSensors.map((sensor, idx) => (
|
||||
<TableRow key={`thermal-${idx}`} className="border-slate-100">
|
||||
<TableCell className="text-sm">{sensor.Name ?? sensor.Parent ?? "Sensor"}</TableCell>
|
||||
<TableCell className="text-sm text-muted-foreground">
|
||||
{sensor.TemperatureCelsius != null ? `${sensor.TemperatureCelsius}°C` : "—"}
|
||||
</TableCell>
|
||||
<TableCell className="text-sm text-muted-foreground">
|
||||
{sensor.CriticalTripPoint != null ? `${sensor.CriticalTripPoint}°C` : "—"}
|
||||
</TableCell>
|
||||
<TableCell className="text-sm text-muted-foreground">{sensor.Source ?? "—"}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{/* Adaptadores de rede */}
|
||||
{windowsNetworkAdapters.length > 0 ? (
|
||||
<div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
|
||||
<p className="text-xs font-semibold uppercase text-slate-500">Adaptadores de rede</p>
|
||||
<div className="mt-2 overflow-hidden rounded-md border border-slate-200">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow className="border-slate-200 bg-slate-100/80">
|
||||
<TableHead className="text-xs text-slate-500">Nome</TableHead>
|
||||
<TableHead className="text-xs text-slate-500">MAC</TableHead>
|
||||
<TableHead className="text-xs text-slate-500">Velocidade</TableHead>
|
||||
<TableHead className="text-xs text-slate-500">Status</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{windowsNetworkAdapters.slice(0, 10).map((adapter, idx) => (
|
||||
<TableRow key={`netadapter-${idx}`} className="border-slate-100">
|
||||
<TableCell className="text-sm">{adapter.NetConnectionID ?? adapter.Name ?? "—"}</TableCell>
|
||||
<TableCell className="text-sm text-muted-foreground">{adapter.MACAddress ?? "—"}</TableCell>
|
||||
<TableCell className="text-sm text-muted-foreground">
|
||||
{adapter.Speed != null && adapter.Speed > 0
|
||||
? adapter.Speed >= 1000000000
|
||||
? `${(adapter.Speed / 1000000000).toFixed(1)} Gbps`
|
||||
: `${(adapter.Speed / 1000000).toFixed(0)} Mbps`
|
||||
: "—"}
|
||||
</TableCell>
|
||||
<TableCell className="text-sm text-muted-foreground">{adapter.StatusText ?? "—"}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{/* Monitores */}
|
||||
{windowsMonitors.length > 0 ? (
|
||||
<div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
|
||||
<p className="text-xs font-semibold uppercase text-slate-500">Monitores</p>
|
||||
<ul className="mt-2 grid gap-2 text-sm text-muted-foreground">
|
||||
{windowsMonitors.map((monitor, idx) => (
|
||||
<li key={`monitor-${idx}`} className="rounded border border-slate-200 bg-white px-3 py-2">
|
||||
<span className="font-medium text-foreground">
|
||||
{monitor.UserFriendlyName ?? monitor.ManufacturerName ?? "Monitor"}
|
||||
</span>
|
||||
<div className="mt-1 flex flex-wrap gap-2 text-xs">
|
||||
{monitor.ManufacturerName && <span>Fabricante: {monitor.ManufacturerName}</span>}
|
||||
{monitor.SerialNumberID && <span>· Serial: {monitor.SerialNumberID}</span>}
|
||||
{monitor.YearOfManufacture && <span>· Ano: {monitor.YearOfManufacture}</span>}
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{/* Chassis / Gabinete */}
|
||||
{windowsChassisInfo ? (
|
||||
<div className="rounded-md border border-slate-200 bg-slate-50/60 p-3">
|
||||
<p className="text-xs font-semibold uppercase text-slate-500">Gabinete / Chassis</p>
|
||||
<div className="mt-2 grid gap-1 text-sm text-muted-foreground">
|
||||
<DetailLine
|
||||
label="Tipo"
|
||||
value={windowsChassisInfo.ChassisTypesText?.join(", ") ?? "—"}
|
||||
/>
|
||||
<DetailLine label="Fabricante" value={windowsChassisInfo.Manufacturer ?? "—"} />
|
||||
<DetailLine label="Serial" value={windowsChassisInfo.SerialNumber ?? "—"} />
|
||||
{windowsChassisInfo.SMBIOSAssetTag && windowsChassisInfo.SMBIOSAssetTag !== "Default string" && (
|
||||
<DetailLine label="Asset Tag" value={windowsChassisInfo.SMBIOSAssetTag} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue