@page "/" @using RackPeek.Domain.Graph.Serialisers @using RackPeek.Domain.Graph.UseCases @using RackPeek.Domain.Resources @using RackPeek.Domain.Resources.Hardware @using RackPeek.Domain.Resources.Services.UseCases @using RackPeek.Domain.Resources.SystemResources.UseCases @using Shared.Rcl.Components @using Shared.Rcl.Components.Graphs @inject GetSystemSummaryUseCase SystemSummaryUseCase @inject GetServiceSummaryUseCase ServiceSummaryUseCase @inject GetHardwareUseCaseSummary HardwareSummaryUseCase @inject BuildPhysicalTopologyUseCase TopologyUseCase @inject BuildLogicalGraphUseCase LogicalUseCase Home
@if (_loading) {
loading summary…
} else {
Totals
→ Hardware
@_hardware!.TotalHardware
→ Systems
@_system!.TotalSystems
→ Services
@_service!.TotalServices
Tools
  • → Visualise
  • → Subnet Browser
  • → CLI Emulator
  • → YAML Editor
  • → Ansible Inventory Generator
  • → SSH Config Export
  • → Hosts File Export
  • → Documentation
Physical Topology
open →
Logical View
open →
Hardware
  • ├─ Hardware (@_hardware!.TotalHardware)
  • @if (_hardware.HardwareByKind.Any()) {
      @foreach (var (kind, count) in _hardware.HardwareByKind.OrderByDescending(x => x.Value)) { var pluralKind = Resource.KindToPlural(kind);
    • └─ @pluralKind (@count)
    • }
    }
Systems
  • ├─ Total (@_system!.TotalSystems)
    @if (_system.SystemsByType.Any()) {
    • Types
    • @foreach (var (type, count) in _system.SystemsByType.OrderByDescending(x => x.Value)) {
    • └─ @type (@count)
    • }
    } @if (_system.SystemsByOs.Any()) {
    • Operating Systems
    • @foreach (var (os, count) in _system.SystemsByOs.OrderByDescending(x => x.Value)) {
    • └─ @os (@count)
    • }
    }
Services
  • ├─ Total (@_service!.TotalServices)
  • └─ IP Addresses (@_service!.TotalIpAddresses)
}
@code { private bool _loading = true; private SystemSummary? _system; private AllServicesSummary? _service; private HardwareSummary? _hardware; private string? _topologySource; private string? _logicalSource; private static readonly MermaidSerialiser _serialiser = new(); // Shared card chrome — defined once so every card looks identical. // Card height is set by the parent grid's `auto-rows-[20rem]`; cards // that span multiple rows (e.g. diagram cards with `row-span-2`) get // the combined height plus gap automatically. private const string _cardClass = "border border-zinc-800 rounded-md p-4 bg-zinc-900/30 flex flex-col overflow-hidden"; private const string _cardHeaderClass = "text-xs text-zinc-500 uppercase tracking-wider mb-3 flex-shrink-0"; private const string _cardBodyClass = "flex-1 min-h-0 overflow-y-auto pr-1"; protected override async Task OnInitializedAsync() { Task systemTask = SystemSummaryUseCase.ExecuteAsync(); Task serviceTask = ServiceSummaryUseCase.ExecuteAsync(); Task hardwareTask = HardwareSummaryUseCase.ExecuteAsync(); Task topologyTask = TopologyUseCase.ExecuteAsync(); Task logicalTask = LogicalUseCase.ExecuteAsync(); await Task.WhenAll(systemTask, serviceTask, hardwareTask, topologyTask, logicalTask); _system = systemTask.Result; _service = serviceTask.Result; _hardware = hardwareTask.Result; _topologySource = _serialiser.Serialise(topologyTask.Result); _logicalSource = _serialiser.Serialise(logicalTask.Result); _loading = false; } }