Files
DbFirst/DbFirst.BlazorWebApp/Components/Pages/Dashboard.razor
OlgunR 566c3b3276 Move dashboard styles to Dashboard.razor.css file
Separated CSS from Dashboard.razor by moving all dashboard-related styles into a new Dashboard.razor.css file. This improves maintainability and keeps styling concerns separate from markup and logic.
2026-03-25 13:34:52 +01:00

123 lines
4.2 KiB
Plaintext

@page "/dashboard"
@page "/dashboards/{DashboardId?}"
@implements IAsyncDisposable
@inject Microsoft.Extensions.Configuration.IConfiguration Configuration
@inject NavigationManager Navigation
@inject DashboardApiClient DashboardApi
<PageTitle>Dashboards</PageTitle>
<div class="dashboard-shell">
<aside class="dashboard-nav">
<div class="dashboard-nav-title">Dashboards</div>
@if (dashboards.Count == 0)
{
<div class="px-3 py-2 text-muted">Keine Dashboards vorhanden.</div>
}
else
{
@foreach (var dashboard in dashboards)
{
<NavLink class="dashboard-nav-link" href="@($"dashboards/{dashboard.Id}?mode={(IsDesigner ? "designer" : "viewer")}")">@dashboard.Name</NavLink>
}
}
</aside>
<section class="dashboard-content">
<div class="mb-3">
<DxButton RenderStyle="ButtonRenderStyle.Primary" Click="@ToggleMode">
@(IsDesigner ? "Zum Viewer wechseln" : "Zum Designer wechseln")
</DxButton>
</div>
<DxDashboard @key="DashboardKey" Endpoint="@DashboardEndpoint" InitialDashboardId="@SelectedDashboardId" WorkingMode="@CurrentMode" style="width: 100%; height: 800px;">
</DxDashboard>
</section>
</div>
@code {
[Parameter] public string? DashboardId { get; set; }
[SupplyParameterFromQuery] public string? Mode { get; set; }
private readonly List<DashboardInfoDto> dashboards = new();
private HubConnection? _hubConnection;
private bool IsDesigner => !string.Equals(Mode, "viewer", StringComparison.OrdinalIgnoreCase);
private WorkingMode CurrentMode => IsDesigner ? WorkingMode.Designer : WorkingMode.ViewerOnly;
private string SelectedDashboardId { get; set; } = string.Empty;
private string DashboardKey => $"{SelectedDashboardId}-{(IsDesigner ? "designer" : "viewer")}";
private string DashboardEndpoint => $"{Configuration["ApiBaseUrl"]?.TrimEnd('/')}/api/dashboard";
private string HubEndpoint => $"{Configuration["ApiBaseUrl"]?.TrimEnd('/')}/hubs/dashboards";
protected override async Task OnInitializedAsync()
{
await RefreshDashboards();
_hubConnection = new HubConnectionBuilder()
.WithUrl(HubEndpoint)
.WithAutomaticReconnect()
.Build();
_hubConnection.On("DashboardsChanged", async () =>
{
await RefreshDashboards();
});
await _hubConnection.StartAsync();
}
protected override async Task OnParametersSetAsync()
{
if (dashboards.Count == 0)
{
await RefreshDashboards();
}
var requestedId = string.IsNullOrWhiteSpace(DashboardId) || string.Equals(DashboardId, "default", StringComparison.OrdinalIgnoreCase)
? null
: DashboardId;
var resolved = !string.IsNullOrWhiteSpace(requestedId)
? dashboards.FirstOrDefault(d => string.Equals(d.Id, requestedId, StringComparison.OrdinalIgnoreCase))
: dashboards.FirstOrDefault(d => string.Equals(d.Id, "DefaultDashboard", StringComparison.OrdinalIgnoreCase))
?? dashboards.FirstOrDefault();
if (resolved == null)
{
return;
}
SelectedDashboardId = resolved.Id;
if (!string.Equals(DashboardId, resolved.Id, StringComparison.OrdinalIgnoreCase))
{
Navigation.NavigateTo($"dashboards/{resolved.Id}?mode={(IsDesigner ? "designer" : "viewer")}", replace: true);
}
}
private void ToggleMode()
{
var targetMode = IsDesigner ? "viewer" : "designer";
Navigation.NavigateTo($"dashboards/{SelectedDashboardId}?mode={targetMode}", replace: true);
}
private async Task RefreshDashboards()
{
var latest = await DashboardApi.GetAllAsync();
if (latest.Count == dashboards.Count && latest.All(d => dashboards.Any(x => x.Id == d.Id && x.Name == d.Name)))
{
return;
}
dashboards.Clear();
dashboards.AddRange(latest);
await InvokeAsync(StateHasChanged);
}
public async ValueTask DisposeAsync()
{
if (_hubConnection != null)
{
await _hubConnection.DisposeAsync();
}
}
}