Moved SignalR hub connection setup from OnInitializedAsync to OnAfterRenderAsync, ensuring initialization occurs only after the component's first render. This prevents premature connection attempts and aligns with best practices for component lifecycle management.
123 lines
4.2 KiB
Plaintext
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();
|
|
}
|
|
|
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
{
|
|
if (!firstRender) return;
|
|
|
|
_hubConnection = new HubConnectionBuilder()
|
|
.WithUrl(HubEndpoint)
|
|
.WithAutomaticReconnect()
|
|
.Build();
|
|
|
|
_hubConnection.On("DashboardsChanged", async () =>
|
|
{
|
|
await RefreshDashboards();
|
|
});
|
|
|
|
await _hubConnection.StartAsync();
|
|
}
|
|
|
|
protected override async Task OnParametersSetAsync()
|
|
{
|
|
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();
|
|
}
|
|
}
|
|
} |