< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 82
Coverable lines: 82
Total lines: 243
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 72
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/chronicis/chronicis/src/Chronicis.Client/Pages/Admin/Status.razor

#LineLine coverage
 1@page "/admin/status"
 2@attribute [Authorize]
 3@inject IAdminAuthService AdminAuth
 4@inject IHealthStatusApiService HealthStatusApi
 5@inject NavigationManager Navigation
 6@using Chronicis.Shared.DTOs
 7
 8<PageTitle>System Status - Chronicis</PageTitle>
 9
 010@if (_authorized == null)
 11{
 12    <MudProgressLinear Indeterminate="true" Color="Color.Primary" />
 13}
 014else if (_authorized == false)
 15{
 16    <MudAlert Severity="Severity.Error" Class="ma-4">
 17        You do not have permission to access this page.
 18    </MudAlert>
 19}
 20else
 21{
 22    <MudPaper Elevation="2" Class="admin-container pa-6">
 23        <div class="admin-header mb-6">
 24            <div class="d-flex justify-space-between align-center">
 25                <div>
 26                    <MudText Typo="Typo.h4" Class="admin-title">System Status</MudText>
 27                    <MudText Typo="Typo.body2" Class="mud-text-secondary">
 28                        Monitor the health of all system dependencies.
 29                    </MudText>
 30                </div>
 31                <MudButton Variant="Variant.Outlined"
 32                          StartIcon="@Icons.Material.Filled.Refresh"
 33                          OnClick="RefreshStatus"
 34                          Disabled="@_isLoading">
 35                    Refresh
 36                </MudButton>
 37            </div>
 38
 039            @if (_lastChecked.HasValue)
 40            {
 41                <MudText Typo="Typo.caption" Class="mud-text-secondary mt-2">
 042                    Last checked: @_lastChecked.Value.ToString("MMM dd, yyyy 'at' h:mm tt")
 43                </MudText>
 44            }
 45        </div>
 46
 47        <!-- Admin Navigation -->
 48        <div class="mb-4">
 49            <MudButtonGroup Variant="Variant.Outlined" Color="Color.Primary">
 50                <MudButton StartIcon="@Icons.Material.Filled.Build"
 51                          Href="/admin/utilities"
 52                          Variant="@(Navigation.Uri.Contains("/utilities") ? Variant.Filled : Variant.Outlined)">
 53                    Utilities
 54                </MudButton>
 55                <MudButton StartIcon="@Icons.Material.Filled.HealthAndSafety"
 56                          Href="/admin/status"
 57                          Variant="@(Navigation.Uri.Contains("/status") ? Variant.Filled : Variant.Outlined)">
 58                    System Status
 59                </MudButton>
 60            </MudButtonGroup>
 61        </div>
 62
 063        @if (_isLoading)
 64        {
 65            <div class="d-flex justify-center ma-6">
 66                <MudProgressCircular Indeterminate="true" Size="Size.Large" />
 67            </div>
 68        }
 069        else if (_healthStatus == null)
 70        {
 71            <MudAlert Severity="Severity.Error" Class="ma-4">
 72                Unable to fetch system status. The health API may be unavailable.
 73            </MudAlert>
 74        }
 75        else
 76        {
 77            <!-- Overall Status Banner -->
 78            <MudAlert Severity="@GetOverallSeverity(_healthStatus.OverallStatus)"
 79                     Class="mb-4">
 80                <div class="d-flex align-center">
 81                    <MudIcon Icon="@GetOverallStatusIcon(_healthStatus.OverallStatus)" Class="mr-2" />
 82                    <MudText Typo="Typo.h6">
 083                        System is @_healthStatus.OverallStatus.ToUpperInvariant()
 84                    </MudText>
 85                </div>
 86            </MudAlert>
 87
 88            <!-- Service Status Grid -->
 89            <MudGrid>
 090                @foreach (var service in _healthStatus.Services)
 91                {
 092                    var displayName = GetFriendlyServiceName(service.ServiceKey);
 093                    var severity = GetStatusSeverity(service.Status);
 094                    var statusColor = GetStatusColor(service.Status);
 95
 96                    <MudItem xs="12" sm="6" md="4">
 97                        <MudCard Class="mud-height-full">
 98                            <MudCardContent>
 99                                <div class="d-flex align-center mb-3">
 100                                    <MudIcon Icon="@GetServiceIcon(service.ServiceKey)"
 101                                            Color="@statusColor"
 102                                            Class="mr-3"
 103                                            Size="Size.Large" />
 104                                    <div class="flex-grow-1">
 0105                                        <MudText Typo="Typo.h6">@displayName</MudText>
 106                                        <MudChip T="string"
 107                                                Size="Size.Small"
 108                                                Color="@statusColor"
 109                                                Variant="Variant.Filled"
 110                                                Label="true"
 111                                                Text="@service.Status.ToUpperInvariant()" />
 112                                    </div>
 113                                </div>
 114
 115                                <MudDivider Class="mb-3" />
 116
 117                                <div class="status-details">
 118                                    <MudText Typo="Typo.body2" Class="mb-1">
 0119                                        <strong>Response:</strong> @($"{service.ResponseTimeMs:F0}ms")
 120                                    </MudText>
 121
 0122                                    @if (!string.IsNullOrEmpty(service.Message))
 123                                    {
 124                                        <MudText Typo="Typo.body2" Class="mb-1">
 0125                                            <strong>Details:</strong> @service.Message
 126                                        </MudText>
 127                                    }
 128
 129                                    <MudText Typo="Typo.caption" Class="mud-text-secondary">
 0130                                        Checked: @service.CheckedAt.ToString("h:mm:ss tt")
 131                                    </MudText>
 132                                </div>
 133                            </MudCardContent>
 134                        </MudCard>
 135                    </MudItem>
 136                }
 137            </MudGrid>
 138        }
 139    </MudPaper>
 140}

/home/runner/work/chronicis/chronicis/src/Chronicis.Client/Pages/Admin/Status.razor.cs

#LineLine coverage
 1using Chronicis.Shared.DTOs;
 2using MudBlazor;
 3
 4namespace Chronicis.Client.Pages.Admin;
 5
 6public partial class Status
 7{
 8    private bool? _authorized;
 9    private SystemHealthStatusDto? _healthStatus;
 010    private bool _isLoading = true;
 11    private DateTime? _lastChecked;
 12
 13    protected override async Task OnInitializedAsync()
 14    {
 015        _authorized = await AdminAuth.IsSysAdminAsync();
 16
 017        if (_authorized == true)
 18        {
 019            await LoadHealthStatus();
 20        }
 021    }
 22
 23    private async Task RefreshStatus()
 24    {
 025        await LoadHealthStatus();
 026    }
 27
 28    private async Task LoadHealthStatus()
 29    {
 030        _isLoading = true;
 031        StateHasChanged();
 32
 33        try
 34        {
 035            _healthStatus = await HealthStatusApi.GetSystemHealthAsync();
 036            _lastChecked = DateTime.Now;
 037        }
 038        catch (Exception ex)
 39        {
 40            // Log error but don't throw - we'll show the error state
 041            Console.WriteLine($"Failed to load health status: {ex.Message}");
 042        }
 43        finally
 44        {
 045            _isLoading = false;
 046            StateHasChanged();
 47        }
 048    }
 49
 050    private static string GetFriendlyServiceName(string serviceKey) => serviceKey switch
 051    {
 052        ServiceKeys.Api => "API",
 053        ServiceKeys.Database => "Database",
 054        ServiceKeys.AzureOpenAI => "AI",
 055        ServiceKeys.BlobStorage => "Storage",
 056        ServiceKeys.Auth0 => "Auth",
 057        ServiceKeys.Open5e => "External Data",
 058        _ => serviceKey
 059    };
 60
 061    private static string GetServiceIcon(string serviceKey) => serviceKey switch
 062    {
 063        ServiceKeys.Api => Icons.Material.Filled.Api,
 064        ServiceKeys.Database => Icons.Material.Filled.Storage,
 065        ServiceKeys.AzureOpenAI => Icons.Material.Filled.Psychology,
 066        ServiceKeys.BlobStorage => Icons.Material.Filled.Cloud,
 067        ServiceKeys.Auth0 => Icons.Material.Filled.Security,
 068        ServiceKeys.Open5e => Icons.Material.Filled.Extension,
 069        _ => Icons.Material.Filled.Help
 070    };
 71
 072    private static Severity GetStatusSeverity(string status) => status switch
 073    {
 074        HealthStatus.Healthy => Severity.Success,
 075        HealthStatus.Degraded => Severity.Warning,
 076        HealthStatus.Unhealthy => Severity.Error,
 077        _ => Severity.Info
 078    };
 79
 080    private static Color GetStatusColor(string status) => status switch
 081    {
 082        HealthStatus.Healthy => Color.Success,
 083        HealthStatus.Degraded => Color.Warning,
 084        HealthStatus.Unhealthy => Color.Error,
 085        _ => Color.Info
 086    };
 87
 088    private static Severity GetOverallSeverity(string overallStatus) => overallStatus switch
 089    {
 090        HealthStatus.Healthy => Severity.Success,
 091        HealthStatus.Degraded => Severity.Warning,
 092        HealthStatus.Unhealthy => Severity.Error,
 093        _ => Severity.Info
 094    };
 95
 096    private static string GetOverallStatusIcon(string overallStatus) => overallStatus switch
 097    {
 098        HealthStatus.Healthy => Icons.Material.Filled.CheckCircle,
 099        HealthStatus.Degraded => Icons.Material.Filled.Warning,
 0100        HealthStatus.Unhealthy => Icons.Material.Filled.Error,
 0101        _ => Icons.Material.Filled.Info
 0102    };
 103}