fix: JSON-Serialisierung, API-Routing und Dark-Mode Dropdowns

Backend:
- Program.cs: JsonNamingPolicy.CamelCase + JsonStringEnumConverter global aktiviert
  → behebt alle Frontend-API-Calls (PascalCase statt camelCase, Integer statt String-Enums)
- AgentsController: GetMetrics nutzt jetzt 'limit' Parameter (statt 'hours')
  → Frontend-Aufruf ?limit=50 wird korrekt ausgewertet
- AgentsController: GetAll gibt MacAddress und EnrolledAt zurück
- TasksController: GET /tasks?agentId= Endpoint hinzugefügt
  → behebt Routing-Mismatch (Frontend nutzte Query-Parameter, Backend hatte Route-Parameter)

Frontend:
- SoftwarePage.tsx: Alle hardcodierten Hellmodus-Farben durch Theme-Variablen ersetzt
  (bg-white/gray → bg-card/muted, text-gray-* → text-foreground/muted-foreground)
- index.css: select option Stile für Dark-Mode Sichtbarkeit hinzugefügt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-03-24 13:30:30 +01:00
parent d7b618f02d
commit b45a9f3bdc
5 changed files with 222 additions and 237 deletions

View File

@@ -16,7 +16,7 @@ public class AgentsController : ControllerBase
{
var agents = await _db.Agents
.OrderBy(a => a.Hostname)
.Select(a => new { a.Id, a.Hostname, a.OsType, a.OsVersion, a.IpAddress, a.Status, a.AgentVersion, a.LastSeen, a.Tags })
.Select(a => new { a.Id, a.Hostname, a.OsType, a.OsVersion, a.IpAddress, a.MacAddress, a.Status, a.AgentVersion, a.LastSeen, a.EnrolledAt, a.Tags })
.ToListAsync();
return Ok(agents);
}
@@ -29,14 +29,13 @@ public class AgentsController : ControllerBase
}
[HttpGet("{id:guid}/metrics")]
public async Task<IActionResult> GetMetrics(Guid id, [FromQuery] int hours = 24)
public async Task<IActionResult> GetMetrics(Guid id, [FromQuery] int limit = 100)
{
var since = DateTime.UtcNow.AddHours(-hours);
var metrics = await _db.AgentMetrics
.Where(m => m.AgentId == id && m.Timestamp >= since)
.Where(m => m.AgentId == id)
.OrderByDescending(m => m.Timestamp)
.Take(1000)
.Select(m => new { m.Timestamp, m.Metrics })
.Take(limit)
.Select(m => new { m.Id, m.AgentId, m.Timestamp, m.Metrics })
.ToListAsync();
return Ok(metrics);
}

View File

@@ -29,23 +29,21 @@ public class TasksController : ControllerBase
return CreatedAtAction(nameof(GetById), new { id = task.Id }, task);
}
[HttpGet]
public async Task<IActionResult> GetAll([FromQuery] Guid? agentId = null)
{
var query = _db.Tasks.AsQueryable();
if (agentId.HasValue) query = query.Where(t => t.AgentId == agentId.Value);
var tasks = await query.OrderByDescending(t => t.CreatedAt).Take(50).ToListAsync();
return Ok(tasks);
}
[HttpGet("{id:guid}")]
public async Task<IActionResult> GetById(Guid id)
{
var task = await _db.Tasks.FindAsync(id);
return task is null ? NotFound() : Ok(task);
}
[HttpGet("agent/{agentId:guid}")]
public async Task<IActionResult> GetByAgent(Guid agentId)
{
var tasks = await _db.Tasks
.Where(t => t.AgentId == agentId)
.OrderByDescending(t => t.CreatedAt)
.Take(50)
.ToListAsync();
return Ok(tasks);
}
}
public record CreateTaskRequest(Guid AgentId, TaskType Type, object? Payload);

View File

@@ -20,7 +20,12 @@ builder.Services.AddDbContext<RmmDbContext>(options =>
builder.Services.AddGrpc();
builder.Services.AddSignalR();
builder.Services.AddControllers();
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase;
options.JsonSerializerOptions.Converters.Add(new System.Text.Json.Serialization.JsonStringEnumConverter());
});
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();