after refactor cleanup

This commit is contained in:
2025-11-28 11:21:22 +01:00
parent 5db6de1503
commit 07423023a0
305 changed files with 80 additions and 13326 deletions

View File

@@ -0,0 +1,42 @@
@using DiunaBI.UI.Shared.Services
@inject AuthService AuthService
@inject NavigationManager Navigation
@if (_isLoading)
{
<div class="d-flex justify-center align-center" style="height: 100vh;">
<MudProgressCircular Indeterminate="true" Size="Size.Large" />
</div>
}
else if (_isAuthenticated)
{
@ChildContent
}
@code {
[Parameter] public RenderFragment? ChildContent { get; set; }
private bool _isLoading = true;
private bool _isAuthenticated = false;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
Console.WriteLine("AuthGuard: Checking authentication...");
_isAuthenticated = await AuthService.CheckAuthenticationAsync();
_isLoading = false;
Console.WriteLine($"AuthGuard: isAuthenticated={_isAuthenticated}");
if (!_isAuthenticated)
{
Console.WriteLine("AuthGuard: Redirecting to /login");
Navigation.NavigateTo("/login", replace: true);
}
StateHasChanged();
}
}
}

View File

@@ -0,0 +1,42 @@
@page "/dashboard"
@using DiunaBI.UI.Shared.Services
@using MudBlazor
@inject AuthService AuthService
@inject NavigationManager NavigationManager
@if (AuthService.IsAuthenticated && AuthService.CurrentUser != null)
{
<MudCard Class="mt-4" Elevation="2">
<MudCardHeader>
<CardHeaderAvatar>
@if (!string.IsNullOrEmpty(AuthService.CurrentUser.AvatarUrl))
{
<MudAvatar Size="Size.Large" Style="background: transparent;">
<img src="@AuthService.CurrentUser.AvatarUrl" alt="Avatar" style="width: 100%; height: 100%; object-fit: cover; border-radius: 50%;" />
</MudAvatar>
}
else
{
<MudAvatar Color="Color.Primary" Size="Size.Large">
@(AuthService.CurrentUser.FullName.Length > 0 ? AuthService.CurrentUser.FullName.Substring(0, 1) : "?")
</MudAvatar>
}
</CardHeaderAvatar>
<CardHeaderContent>
<MudText Typo="Typo.h6">@AuthService.CurrentUser.FullName</MudText>
<MudText Typo="Typo.body2">@AuthService.CurrentUser.Email</MudText>
</CardHeaderContent>
</MudCardHeader>
<MudCardContent>
<MudText Typo="Typo.body2">
✅ Signed in via Google
</MudText>
</MudCardContent>
</MudCard>
}
else
{
<MudAlert Severity="Severity.Warning" Class="mt-4">
You are not logged in
</MudAlert>
}

View File

@@ -0,0 +1,15 @@
@page "/"
@inject NavigationManager Navigation
@code
{
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
Navigation.NavigateTo("/dashboard");
}
await base.OnAfterRenderAsync(firstRender);
}
}

View File

@@ -0,0 +1,72 @@
@using MudBlazor.Internal
<MudExpansionPanels Class="mb-4">
<MudExpansionPanel Icon="@Icons.Material.Filled.FilterList"
Text="Filters"
Expanded="true">
<MudGrid>
<MudItem xs="12" sm="6" md="4">
<MudTextField @bind-Value="filterRequest.Search"
Label="Search"
Placeholder="Name, number..."
Immediate="true"
DebounceInterval="500"
OnDebounceIntervalElapsed="SearchLayers"
Clearable="true"/>
</MudItem>
<MudItem xs="12" sm="6" md="4">
<MudButton Variant="Variant.Outlined"
OnClick="ClearFilters"
StartIcon="Icons.Material.Filled.Clear">
Clear filters
</MudButton>
</MudItem>
</MudGrid>
</MudExpansionPanel>
</MudExpansionPanels>
<MudDivider Class="my-4"></MudDivider>
<MudTable Items="layers.Items"
Dense="true"
Hover="true"
Loading="isLoading"
LoadingProgressColor="Color.Info"
OnRowClick="@((TableRowClickEventArgs<LayerDto> args) => OnRowClick(args.Item))"
T="LayerDto"
Style="cursor: pointer;">
<HeaderContent>
<MudTh>Name</MudTh>
<MudTh>Type</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd DataLabel="Name">@context.Name</MudTd>
<MudTd DataLabel="Type">@context.Type</MudTd>
</RowTemplate>
<NoRecordsContent>
<MudText>No layers to display</MudText>
</NoRecordsContent>
<LoadingContent>
Loading...
</LoadingContent>
</MudTable>
@if (layers.TotalCount > 0)
{
<MudGrid Class="mt-4" AlignItems="Center.Center">
<MudItem xs="12" sm="6">
<MudText Typo="Typo.body2">
Results @((layers.Page - 1) * layers.PageSize + 1) - @Math.Min(layers.Page * layers.PageSize, layers.TotalCount)
of @layers.TotalCount
</MudText>
</MudItem>
<MudItem xs="12" sm="6" Class="d-flex justify-end">
<MudPagination Count="layers.TotalPages"
Selected="layers.Page"
SelectedChanged="OnPageChanged"
ShowFirstButton="true"
ShowLastButton="true"/>
</MudItem>
</MudGrid>
}

View File

@@ -0,0 +1,65 @@
using DiunaBI.UI.Shared.Services;
using Microsoft.AspNetCore.Components;
using DiunaBI.Application.DTOModels;
using DiunaBI.Application.DTOModels.Common;
using MudBlazor;
namespace DiunaBI.UI.Shared.Components;
public partial class LayerListComponent : ComponentBase
{
[Inject] private LayerService LayerService { get; set; } = default!;
[Inject] private ISnackbar Snackbar { get; set; } = default!;
[Inject] private NavigationManager NavigationManager { get; set; } = default!;
private PagedResult<LayerDto> layers = new();
private LayerFilterRequest filterRequest = new();
private bool isLoading = false;
protected override async Task OnInitializedAsync()
{
await LoadLayers();
}
private async Task LoadLayers()
{
isLoading = true;
try
{
layers = await LayerService.GetLayersAsync(filterRequest);
}
catch (Exception ex)
{
Console.WriteLine($"Loading layers failed: {ex.Message}");
}
finally
{
isLoading = false;
}
}
private async Task SearchLayers()
{
filterRequest.Page = 1;
await LoadLayers();
}
private async Task OnPageChanged(int page)
{
filterRequest.Page = page;
await LoadLayers();
}
private async Task ClearFilters()
{
filterRequest = new LayerFilterRequest();
await LoadLayers();
}
private void OnRowClick(LayerDto layer)
{
NavigationManager.NavigateTo($"/layers/{layer.Id}");
}
}

View File

@@ -0,0 +1,200 @@
@using DiunaBI.UI.Shared.Services
@using Microsoft.Extensions.Configuration
@inject IJSRuntime JS
@inject IConfiguration Configuration
@inject AuthService AuthService
@inject NavigationManager NavigationManager
@inject IGoogleAuthService? GoogleAuthService
<MudCard Class="login-card" Elevation="8">
<MudCardContent Class="pa-8 d-flex flex-column align-center">
<MudText Typo="Typo.h4" Class="mb-4">Welcome to DiunaBI</MudText>
<MudText Typo="Typo.body1" Class="mb-6 text-center">
Sign in using your Google account
</MudText>
<MudButton
Variant="Variant.Filled"
StartIcon="@Icons.Custom.Brands.Google"
Size="Size.Large"
OnClick="HandleGoogleSignIn"
Disabled="@_isLoading">
@if (_isLoading)
{
<MudProgressCircular Class="mr-3" Size="Size.Small" Indeterminate="true"></MudProgressCircular>
<span>Verifying...</span>
}
else
{
<span>Sign in with Google</span>
}
</MudButton>
@if (!string.IsNullOrEmpty(_errorMessage))
{
<MudAlert Severity="Severity.Error" Class="mt-4" Dense="true">
@_errorMessage
</MudAlert>
}
</MudCardContent>
</MudCard>
@code {
private bool _isLoading = false;
private string _errorMessage = string.Empty;
private static LoginCard? _instance;
private bool _isInitialized = false;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
_instance = this;
// Initialize JavaScript Google SDK for web (both null service and WebGoogleAuthService)
// Skip only for mobile platform-specific auth (MobileGoogleAuthService)
var isMobileAuth = GoogleAuthService != null && GoogleAuthService.GetType().Name == "MobileGoogleAuthService";
if (!isMobileAuth)
{
await InitializeGoogleSignIn();
}
else
{
Console.WriteLine("📱 Using platform-specific Google auth service");
_isInitialized = true;
}
}
}
private async Task InitializeGoogleSignIn()
{
try
{
if (_isInitialized) return;
var clientId = Configuration["GoogleAuth:ClientId"];
Console.WriteLine($"🔍 Reading GoogleAuth:ClientId from configuration: '{clientId}'");
if (string.IsNullOrEmpty(clientId))
{
_errorMessage = "Google ClientId is not configured in appsettings.";
Console.Error.WriteLine("❌ Google ClientId is NULL or EMPTY in configuration!");
return;
}
Console.WriteLine($"✅ Calling initGoogleSignIn with clientId: {clientId}");
await JS.InvokeVoidAsync("initGoogleSignIn", clientId);
_isInitialized = true;
}
catch (Exception ex)
{
_errorMessage = "Google Sign-In initialization error.";
Console.Error.WriteLine($"❌ Google Sign-In initialization error: {ex.Message}");
Console.Error.WriteLine($"Stack trace: {ex.StackTrace}");
}
}
private async Task HandleGoogleSignIn()
{
try
{
_isLoading = true;
_errorMessage = string.Empty;
StateHasChanged();
// Use platform-specific auth if available (mobile), otherwise use JavaScript (web)
if (GoogleAuthService != null)
{
Console.WriteLine("📱 Using mobile Google auth");
var success = await GoogleAuthService.SignInAsync();
if (success)
{
Console.WriteLine("✅ Mobile auth successful, navigating...");
NavigationManager.NavigateTo("/dashboard", replace: true);
}
else
{
_errorMessage = "Login failed. Please try again";
_isLoading = false;
StateHasChanged();
}
}
else
{
Console.WriteLine("🌐 Using web JavaScript Google auth");
await JS.InvokeVoidAsync("requestGoogleSignIn");
}
}
catch (Exception ex)
{
Console.Error.WriteLine($"❌ HandleGoogleSignIn error: {ex.Message}");
_errorMessage = "Login error. Please try again";
_isLoading = false;
StateHasChanged();
}
}
[JSInvokable]
public static async Task OnGoogleSignInSuccess(string googleCredential, string fullName, string email, string avatarUrl)
{
Console.WriteLine($"=== OnGoogleSignInSuccess: {email} ===");
if (_instance != null)
{
try
{
// Waliduj użytkownika w backendzie DiunaBI
var (success, errorMessage) = await _instance.AuthService.ValidateWithBackendAsync(
googleCredential, fullName, email, avatarUrl);
if (success)
{
Console.WriteLine("✅ User validated, navigating to dashboard");
_instance._isLoading = false;
_instance._errorMessage = string.Empty;
_instance.NavigationManager.NavigateTo("/dashboard", replace: true);
}
else
{
Console.WriteLine($"❌ Validation failed: {errorMessage}");
_instance._isLoading = false;
_instance._errorMessage = errorMessage ?? "Login failed.";
}
await _instance.InvokeAsync(() => _instance.StateHasChanged());
}
catch (Exception ex)
{
Console.Error.WriteLine($"❌ OnGoogleSignInSuccess error: {ex.Message}");
_instance._isLoading = false;
_instance._errorMessage = "User verification error.";
await _instance.InvokeAsync(() => _instance.StateHasChanged());
}
}
}
[JSInvokable]
public static async Task OnGoogleSignInError(string error)
{
Console.WriteLine($"Google SignIn Error: {error}");
if (_instance != null)
{
_instance._isLoading = false;
_instance._errorMessage = "Google login error. Please try again";
await _instance.InvokeAsync(() => _instance.StateHasChanged());
}
}
}
<style>
.login-card {
max-width: 400px;
width: 100%;
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
}
</style>

View File

@@ -0,0 +1,10 @@
@using Microsoft.AspNetCore.Components.Routing
@using MudBlazor
<MudNavMenu>
<MudNavLink href="dashboard" Icon="@Icons.Material.Filled.Dashboard" Match="NavLinkMatch.All">
Dashboard
</MudNavLink>
<MudNavLink Href="layers" Icon="@Icons.Material.Filled.List" Match="NavLinkMatch.All">
Layers
</MudNavLink>
</MudNavMenu>

View File

@@ -0,0 +1,18 @@
@using Microsoft.AspNetCore.Components.Routing
@using MudBlazor
<Router AppAssembly="@typeof(Routes).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="routeData" Selector="h1" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<MudCard Elevation="0">
<MudText Typo="Typo.h6">
Strona nieznaleziona.
</MudText>
</MudCard>
</LayoutView>
</NotFound>
</Router>