@page "/labels/{LabelName}" @using RackPeek.Domain.Persistence @using RackPeek.Domain.Resources @using RackPeek.Domain.Resources.SystemResources @inject IResourceCollection ResourceRepository Label: @LabelName

Label: @LabelName

@if (_resources is not null && _resources.Count > 0) {
} @if (_resources is null) {
loading resources…
} else if (_resources.Count == 0) {
no resources found for this label
} else if (!GetProcessed().Any()) {
no results match your filter
} else {
@foreach (var item in GetProcessed()) { var resource = item.Resource; var value = item.Value;
@resource.Name
@resource.Kind
Value: @FormatValue(value) [@DetectType(value)]
}
}
@code { [Parameter] public string LabelName { get; set; } = string.Empty; private IReadOnlyList<(Resource Resource, string Value)>? _resources; private string _sortBy = "Value"; private bool _ascending = true; private string _filter = string.Empty; protected override async Task OnParametersSetAsync() { var decoded = Uri.UnescapeDataString(LabelName); _resources = await ResourceRepository.GetByLabelAsync(decoded); } private IEnumerable<(Resource Resource, string Value)> GetProcessed() { if (_resources is null) return []; var query = _resources.AsEnumerable(); // Filtering if (!string.IsNullOrWhiteSpace(_filter)) { query = query.Where(r => r.Resource.Name.Contains(_filter, StringComparison.OrdinalIgnoreCase) || r.Value.Contains(_filter, StringComparison.OrdinalIgnoreCase)); } // Sorting query = _sortBy switch { "Value" => query .OrderBy(r => GetSortKey(r.Value)) .ThenBy(r => r.Resource.Name), "Kind" => query.OrderBy(r => r.Resource.Kind), _ => query.OrderBy(r => r.Resource.Name) }; if (!_ascending) query = query.Reverse(); return query.ToList(); } private void ToggleSortDirection() { _ascending = !_ascending; } private static string DetectType(string value) { if (DateTime.TryParse(value, out _)) return "DATE"; if (bool.TryParse(value, out _)) return "BOOL"; if (decimal.TryParse(value, out _)) return "NUMBER"; return "TEXT"; } private static string FormatValue(string value) { if (DateTime.TryParse(value, out var dt)) return dt.ToString("yyyy-MM-dd"); return value; } private string GetResourceUrl(Resource resource) { if (resource.Kind == SystemResource.KindLabel) return $"resources/systems/{Uri.EscapeDataString(resource.Name)}"; if (resource.Kind == Service.KindLabel) return $"resources/services/{Uri.EscapeDataString(resource.Name)}"; return $"resources/hardware/{Uri.EscapeDataString(resource.Name)}"; } private readonly record struct SortKey(int TypeRank, object Value, string Fallback) : IComparable { public int CompareTo(SortKey other) { var rank = TypeRank.CompareTo(other.TypeRank); if (rank != 0) return rank; var valueCompare = TypeRank switch { 0 => ((int)Value).CompareTo((int)other.Value), 1 => ((DateTime)Value).CompareTo((DateTime)other.Value), 2 => ((decimal)Value).CompareTo((decimal)other.Value), 3 => ((bool)Value).CompareTo((bool)other.Value), _ => string.Compare((string)Value, (string)other.Value, StringComparison.Ordinal) }; if (valueCompare != 0) return valueCompare; // Deterministic tie-breaker return string.Compare(Fallback, other.Fallback, StringComparison.Ordinal); } } private static SortKey GetSortKey(string? raw) { var s = raw?.Trim() ?? string.Empty; if (string.IsNullOrEmpty(s)) return new SortKey(0, 0, ""); // Date if (DateTime.TryParse(s, out var dt)) return new SortKey(1, dt, s); // Number if (decimal.TryParse(s, out var dec)) return new SortKey(2, dec, s); // Bool if (bool.TryParse(s, out var b)) return new SortKey(3, b, s); // Text (case-insensitive sort by normalizing) return new SortKey(4, s.ToLowerInvariant(), s); } }