sqlinsight-pro/src/SQLInsight.Hub/Portal/Pages/Overview.razor
Søren Eggert Lundsteen Olsen 2c49a1e1b1 Keep severity badge cells as table cells on both overviews
.counts is display: flex. On the <td> itself it made the cell a flex box
with its own height, so the row divider jumped in the findings column of
SQLInsight Web's overview and the hub portal's customer overview. The
class now sits on a <div> inside the cell; the CSS rule is unchanged.

TableMarkupTests checks Web, Hub and Community: no <td>/<th> may carry a
class whose rule sets display flex or grid.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 15:39:36 +02:00

69 lines
3.3 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@page "/portal"
@attribute [Authorize]
@inject PortalQueries Queries
<PageTitle>Overblik · SQLInsight Hub</PageTitle>
<h1>Kundeoverblik</h1>
<p class="lead">Betalende kunders instanser og deres aktuelle problemer.</p>
<div class="kpis">
<div class="kpi"><div><strong>@_customers.Count</strong><span>kunder</span></div></div>
<div class="kpi"><div><strong>@_customers.Sum(c => c.Instances)</strong><span>instanser</span></div></div>
<div class="kpi sev-critical"><div><strong>@_customers.Sum(c => c.Critical)</strong><span>kritiske fund</span></div></div>
<div class="kpi sev-high"><div><strong>@_customers.Sum(c => c.High)</strong><span>høje fund</span></div></div>
<div class="kpi"><div><strong>@_new</strong><span>nye fund, 7 dage</span></div></div>
<div class="kpi sev-info"><div><strong>@_silent</strong><span>instanser uden data i 1 time</span></div></div>
</div>
<section class="card">
<div class="card-head"><h2>Kunder</h2><span class="muted">sorteret efter alvor</span></div>
<table>
<thead><tr><th>Kunde</th><th>Aftale</th><th>Licens udløber</th><th class="num">Instanser</th><th>Fund</th><th>Seneste data</th></tr></thead>
<tbody>
@foreach (var c in _customers)
{
<tr>
<td><a href="/portal/kunder/@c.Id"><strong>@c.Name</strong></a></td>
<td>@(c.Plan ?? "–")</td>
<td class="nowrap @(c.LicenseExpires < Queries.Now.AddDays(30) ? "bad" : "")">@(c.LicenseExpires?.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture) ?? "–")</td>
<td class="num">@c.Instances</td>
<td><div class="counts">
@if (c.Critical > 0) { <Sev Severity="4" Count="c.Critical" /> }
@if (c.High > 0) { <Sev Severity="3" Count="c.High" /> }
@if (c.Critical == 0 && c.High == 0) { <span class="muted">ingen kritiske/høje</span> }
</div></td>
<td class="nowrap @(c.LastSubmission < Queries.Now.AddHours(-1) ? "bad" : "")">@(c.LastSubmission?.ToString("yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture) ?? "aldrig") UTC</td>
</tr>
}
</tbody>
</table>
</section>
<section class="card">
<div class="card-head"><h2>Mest udbredte problemer</h2><span class="muted">hvor en vejledning eller en produktændring hjælper flest</span></div>
<table>
<thead><tr><th>Regel</th><th>Eksempel</th><th class="num">Kunder</th><th class="num">Fund</th><th>Værst</th></tr></thead>
<tbody>
@foreach (var p in _common)
{
<tr><td class="mono">@p.RuleId</td><td>@p.Title</td><td class="num">@p.Customers</td><td class="num">@p.Findings</td><td><Sev Severity="p.WorstSeverity" /></td></tr>
}
</tbody>
</table>
</section>
@code {
private IReadOnlyList<CustomerRow> _customers = [];
private IReadOnlyList<CommonProblem> _common = [];
private int _new;
private int _silent;
protected override async Task OnInitializedAsync()
{
_customers = await Queries.CustomersAsync();
_common = await Queries.CommonProblemsAsync();
_new = await Queries.NewFindingsSinceAsync(Queries.Now.AddDays(-7));
_silent = await Queries.SilentInstancesAsync();
}
}