Watch
1
0
Fork
You've already forked RedFlag
0

fix: build errors + move platform info under screenshot card

- Fix premature </div> in Docker.tsx and History.tsx (TS1005/TS1128)
- Fix unused imports/vars (noUnusedLocals): AgentStorage, AgentUpdatesModal,
  ErrorBoundary, useAgentUpdate, useHeartbeat, Dashboard, Updates
- Move Platform/Distribution/Architecture under screenshot card in Agents page
- Move Top Processes into right stats column
This commit is contained in:
Fimeg 2026-06-08 22:37:31 -04:00
commit 73c1e0ef21
10 changed files with 77 additions and 75 deletions

View file

@ -59,7 +59,7 @@ export function AgentStorage({ agentId }: AgentStorageProps) {
// Fetch storage metrics - NO auto-refresh, data persists until manual refresh
// Cache forever (24 hours) to prevent data loss on navigation
const { data: storageData, refetch: refetchStorage, error: storageError, isLoading } = useQuery({
const { data: storageData, refetch: refetchStorage, error: storageError } = useQuery({
queryKey: ['storage-metrics', agentId],
queryFn: async () => {
clientLogger.debug('Fetching storage metrics for agent:', { agentId });

View file

@ -1,6 +1,5 @@
import { useState } from 'react';
import {
X,
Download,
CheckCircle,
AlertCircle,

View file

@ -1,4 +1,4 @@
import React, { Component, ErrorInfo, ReactNode } from 'react';
import { Component, ErrorInfo, ReactNode } from 'react';
interface Props {
children: ReactNode;

View file

@ -73,7 +73,7 @@ export function useAgentUpdate(): UseAgentUpdateReturn {
clientLogger.debug('Update nonce generated', { agentId: agent.id, targetVersion });
// Step 3: Trigger the actual update
const updateResponse = await agentApi.updateAgent(agent.id, {
await agentApi.updateAgent(agent.id, {
version: targetVersion,
platform: `${agent.os_type}-${agent.os_architecture}`,
// Include nonce in request for security

View file

@ -1,4 +1,4 @@
import { useState, useMemo } from 'react';
import { useMemo } from 'react';
export interface HeartbeatStatus {
enabled: boolean;

View file

@ -897,6 +897,31 @@ const Agents: React.FC = () => {
? <span className="text-red-500">Failed</span>
: null}
</div>
{/* Platform info — under screenshot */}
{(() => {
const osInfo = parseOSInfo(selectedAgent);
return (
<div className="mt-2 space-y-1">
<div>
<p className="text-xs text-gray-500">Platform</p>
<p className="text-sm font-medium text-gray-900">{osInfo.platform}</p>
</div>
<div>
<p className="text-xs text-gray-500">Distribution</p>
<p className="text-sm font-medium text-gray-900">
{osInfo.distribution}
{osInfo.version && <span className="text-xs text-gray-500 ml-1">({osInfo.version})</span>}
</p>
</div>
<div>
<p className="text-xs text-gray-500">Architecture</p>
<p className="text-sm font-medium text-gray-900">
{selectedAgent.os_architecture || selectedAgent.architecture}
</p>
</div>
</div>
);
})()}
</div>
);
})()}
@ -904,27 +929,9 @@ const Agents: React.FC = () => {
{/* All stats — right column, stacked flush top */}
<div className="flex-1 space-y-3 min-w-0">
{(() => {
const osInfo = parseOSInfo(selectedAgent);
const meta = getSystemMetadata(selectedAgent);
return (
<>
<div>
<p className="text-xs text-gray-500">Platform</p>
<p className="text-sm font-medium text-gray-900">{osInfo.platform}</p>
</div>
<div>
<p className="text-xs text-gray-500">Distribution</p>
<p className="text-sm font-medium text-gray-900">
{osInfo.distribution}
{osInfo.version && <span className="text-xs text-gray-500 ml-1">({osInfo.version})</span>}
</p>
</div>
<div>
<p className="text-xs text-gray-500">Architecture</p>
<p className="text-sm font-medium text-gray-900">
{selectedAgent.os_architecture || selectedAgent.architecture}
</p>
</div>
<div>
<p className="text-xs text-gray-500 flex items-center gap-1">
<Cpu className="h-3 w-3" /> CPU
@ -976,55 +983,55 @@ const Agents: React.FC = () => {
</>
);
})()}
</div>
</div>
{/* Top Processes — below the split */}
<div className="mt-4 pt-4 border-t border-gray-200">
<div className="flex items-center justify-between mb-2">
<p className="text-sm font-medium text-gray-900 flex items-center gap-1">
<Activity className="h-4 w-4" /> Top Processes
</p>
<button
onClick={() => navigate(`/updates?agent=${selectedAgent.id}`)}
className="text-xs text-blue-600 hover:text-blue-800"
>
See More
</button>
{/* Top Processes */}
<div className="pt-3 border-t border-gray-200">
<div className="flex items-center justify-between mb-2">
<p className="text-xs font-medium text-gray-900 flex items-center gap-1">
<Activity className="h-3 w-3" /> Top Processes
</p>
<button
onClick={() => navigate(`/updates?agent=${selectedAgent.id}`)}
className="text-[10px] text-blue-600 hover:text-blue-800"
>
See More
</button>
</div>
{(() => {
const meta = getSystemMetadata(selectedAgent);
const topProcesses = selectedAgent.metadata?.top_processes;
if (topProcesses && Array.isArray(topProcesses) && topProcesses.length > 0) {
return (
<table className="w-full text-xs">
<thead>
<tr className="text-gray-500 border-b border-gray-100">
<th className="text-left py-1 font-medium">Name</th>
<th className="text-right py-1 font-medium">PID</th>
<th className="text-right py-1 font-medium">CPU%</th>
<th className="text-right py-1 font-medium">Mem%</th>
</tr>
</thead>
<tbody>
{topProcesses.slice(0, 5).map((proc: any, i: number) => (
<tr key={proc.pid || i} className="border-b border-gray-50 last:border-0">
<td className="py-1 text-gray-900 font-medium truncate max-w-[160px]">{proc.name}</td>
<td className="py-1 text-right text-gray-600">{proc.pid}</td>
<td className="py-1 text-right text-gray-600">{proc.cpu != null ? `${proc.cpu.toFixed(1)}%` : '—'}</td>
<td className="py-1 text-right text-gray-600">{proc.mem != null ? `${proc.mem.toFixed(1)}%` : '—'}</td>
</tr>
))}
</tbody>
</table>
);
}
return (
<p className="text-[10px] text-gray-400 italic">
Process details not reported. Count: {meta.processes}
</p>
);
})()}
</div>
</div>
{(() => {
const meta = getSystemMetadata(selectedAgent);
const topProcesses = selectedAgent.metadata?.top_processes;
if (topProcesses && Array.isArray(topProcesses) && topProcesses.length > 0) {
return (
<table className="w-full text-xs">
<thead>
<tr className="text-gray-500 border-b border-gray-100">
<th className="text-left py-1 font-medium">Name</th>
<th className="text-right py-1 font-medium">PID</th>
<th className="text-right py-1 font-medium">CPU%</th>
<th className="text-right py-1 font-medium">Mem%</th>
</tr>
</thead>
<tbody>
{topProcesses.slice(0, 5).map((proc: any, i: number) => (
<tr key={proc.pid || i} className="border-b border-gray-50 last:border-0">
<td className="py-1 text-gray-900 font-medium truncate max-w-[160px]">{proc.name}</td>
<td className="py-1 text-right text-gray-600">{proc.pid}</td>
<td className="py-1 text-right text-gray-600">{proc.cpu != null ? `${proc.cpu.toFixed(1)}%` : '—'}</td>
<td className="py-1 text-right text-gray-600">{proc.mem != null ? `${proc.mem.toFixed(1)}%` : '—'}</td>
</tr>
))}
</tbody>
</table>
);
}
return (
<p className="text-xs text-gray-400 italic">
Process details not reported by this agent. Showing count: {meta.processes}
</p>
);
})()}
</div>
</div>
</div>

View file

@ -150,7 +150,7 @@ const Dashboard: React.FC = () => {
<div
className={`h-2 rounded-full ${severity.color}`}
style={{
width: `${stats.pending_updates > 0 ? (severity.value / stats.pending_updates) * 100 : 0}%`
width: `${(stats?.pending_updates ?? 0) > 0 ? (severity.value / (stats?.pending_updates ?? 1)) * 100 : 0}%`
}}
></div>
</div>

View file

@ -173,7 +173,6 @@ const Docker: React.FC = () => {
icon={<AlertTriangle className="h-8 w-8 text-red-400" />}
/>
</div>
</div>
{/* Search + pills */}
<div className="mb-6">

View file

@ -65,7 +65,6 @@ const HistoryPage: React.FC = () => {
<p className="text-gray-600">
Command history, package events, system activity, and client errors across all agents
</p>
</div>
{/* Filter bar — Novell-style dense row */}
{showFilters && (

View file

@ -160,8 +160,6 @@ const Updates: React.FC = () => {
return true;
});
const packageTotalPages = Math.ceil(packageTotal / pageSize);
const packageHasNext = currentPage < packageTotalPages;
const packageHasPrev = currentPage > 1;
const packageTypes = [...new Set(packages.map((p) => p.package_type))];
// Handle update actions