PlanTempusAdmin/Pages/Azure/Index.cshtml
Janus C. H. Knudsen 08f8150064 Refactors page styles into separate CSS files
Extracts inline styles from Razor pages into modular CSS files
Adds new CSS files for components and specific page styles
Improves code organization and maintainability by separating styling concerns

Updates layout to include new CSS files and optional style sections
2026-02-03 15:55:44 +01:00

165 lines
6.3 KiB
Text

@page
@model PlanTempusAdmin.Pages.Azure.IndexModel
@{
ViewData["Title"] = "Azure Storage";
}
@section Styles {
<link rel="stylesheet" href="~/css/pages/azure.css" asp-append-version="true" />
}
<div class="page-header">
<h1 class="page-title">Azure Blob Storage</h1>
<p class="page-subtitle">@Model.Dashboard.AccountName</p>
</div>
@if (!Model.IsConnected)
{
<div class="card">
<div class="card-body">
<p class="text-danger">Kan ikke forbinde til Azure Storage</p>
<p class="text-muted">Tjek at <code>ConnectionStrings:AzureStorage</code> er konfigureret i appsettings.json</p>
</div>
</div>
}
else
{
var d = Model.Dashboard;
<!-- Hero Stats -->
<div class="status-grid">
<div class="status-item">
<div class="status-label">Status</div>
<div class="status-value success">ONLINE</div>
<div class="status-detail">@d.AccountName</div>
</div>
<div class="status-item">
<div class="status-label">Containers</div>
<div class="status-value">@d.TotalContainers</div>
<div class="status-detail">@d.TotalBlobs blobs total</div>
</div>
<div class="status-item">
<div class="status-label">Total Størrelse</div>
<div class="status-value">@FormatBytes(d.TotalSize)</div>
<div class="status-detail">Backup: @FormatBytes(d.BackupTotalSize)</div>
</div>
<div class="status-item">
<div class="status-label">Sidste Upload</div>
<div class="status-value @(d.LastBackupUpload.HasValue && (DateTimeOffset.Now - d.LastBackupUpload.Value).TotalHours < 24 ? "success" : "warning")">
@FormatTimeAgo(d.LastBackupUpload)
</div>
<div class="status-detail">@d.BackupFileCount backup filer</div>
</div>
</div>
<div class="dashboard-grid mt-2">
<!-- Containers -->
<div class="card">
<div class="card-header">Containers</div>
<table class="table">
<thead>
<tr>
<th>Navn</th>
<th>Blobs</th>
<th>Størrelse</th>
<th>Ændret</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var container in d.Containers)
{
<tr>
<td>
@if (container.Name.Contains("backup", StringComparison.OrdinalIgnoreCase))
{
<span class="container-icon">💾</span>
}
else
{
<span class="container-icon">📦</span>
}
<code>@container.Name</code>
</td>
<td>@container.BlobCount</td>
<td>@FormatBytes(container.TotalSize)</td>
<td>@FormatTimeAgo(container.LastModified)</td>
<td>
<a href="/Azure/Container?name=@container.Name" class="btn btn-sm">Åbn</a>
</td>
</tr>
}
</tbody>
</table>
</div>
<!-- Recent Uploads -->
<div class="card">
<div class="card-header">Seneste Uploads</div>
<div class="card-body compact-list">
@if (d.RecentBlobs.Count == 0)
{
<p class="text-muted">Ingen filer endnu</p>
}
@foreach (var blob in d.RecentBlobs)
{
<div class="list-item">
<div class="item-main">
<span class="file-icon">@GetFileIcon(blob.Name)</span>
<code class="blob-name" title="@blob.Name">@blob.FileName</code>
@if (!string.IsNullOrEmpty(blob.AccessTier))
{
<span class="badge badge-tier">@blob.AccessTier</span>
}
</div>
<div class="item-meta">
@FormatBytes(blob.Size) · @FormatTimeAgo(blob.LastModified)
@if (!string.IsNullOrEmpty(blob.Directory))
{
<text>· @blob.Directory</text>
}
</div>
</div>
}
</div>
</div>
</div>
<!-- Last Updated -->
<div class="last-updated mt-2">
Opdateret: @DateTime.Now.ToString("HH:mm:ss")
</div>
}
@functions {
string FormatBytes(long bytes)
{
if (bytes == 0) return "0 B";
var sizes = new[] { "B", "KB", "MB", "GB", "TB" };
var i = (int)Math.Floor(Math.Log(bytes) / Math.Log(1024));
return $"{Math.Round(bytes / Math.Pow(1024, i), 1)} {sizes[i]}";
}
string FormatTimeAgo(DateTimeOffset? time)
{
if (!time.HasValue) return "-";
var diff = DateTimeOffset.Now - time.Value;
if (diff.TotalMinutes < 1) return "lige nu";
if (diff.TotalMinutes < 60) return $"{(int)diff.TotalMinutes}m siden";
if (diff.TotalHours < 24) return $"{(int)diff.TotalHours}t siden";
if (diff.TotalDays < 7) return $"{(int)diff.TotalDays}d siden";
return time.Value.ToString("dd/MM");
}
string GetFileIcon(string name)
{
if (name.EndsWith(".tar.gz")) return "📦";
if (name.EndsWith(".gz") || name.EndsWith(".zip") || name.EndsWith(".7z")) return "📦";
if (name.EndsWith(".sql")) return "🐘";
if (name.EndsWith(".bak")) return "💾";
if (name.EndsWith(".log")) return "📜";
if (name.EndsWith(".json")) return "📋";
if (name.EndsWith(".xml")) return "📄";
return "📄";
}
}