Loading angepasst

This commit is contained in:
MarcWieland
2026-06-26 21:35:23 +02:00
parent 6ff8743dad
commit 0c3eb3a323
19 changed files with 1991 additions and 188 deletions
@@ -48,6 +48,9 @@
</MudLayout> </MudLayout>
@code { @code {
[PersistentState(AllowUpdates = true)]
public TenantInfo? PersistentTenantInfo { get; set; }
private bool _drawerOpen = true; private bool _drawerOpen = true;
private bool _isDarkMode; private bool _isDarkMode;
@@ -55,44 +58,60 @@
{ {
UserNotificationService.OnUserDeleted += HandleUserDeleted; UserNotificationService.OnUserDeleted += HandleUserDeleted;
try if (PersistentTenantInfo != null)
{ {
var tenantInfo = await Http.GetFromJsonAsync<TenantInfo>("api/tenant/current"); ApplyTheme(PersistentTenantInfo);
if (tenantInfo?.IsTenant == true && !string.IsNullOrEmpty(tenantInfo.PrimaryColor)) }
else
{
try
{ {
var primaryColor = tenantInfo.PrimaryColor; var tenantInfo = await Http.GetFromJsonAsync<TenantInfo>("api/tenant/current");
var secondaryColor = tenantInfo.SecondaryColor ?? tenantInfo.PrimaryColor; if (tenantInfo != null)
{
_theme.PaletteLight.Primary = primaryColor; ApplyTheme(tenantInfo);
_theme.PaletteLight.Secondary = secondaryColor; PersistentTenantInfo = tenantInfo;
_theme.PaletteDark.Primary = primaryColor; }
_theme.PaletteDark.Secondary = secondaryColor; }
catch
// Dynamically apply background colors to navbar {
_theme.PaletteLight.AppbarBackground = primaryColor; // Ignore background error
_theme.PaletteLight.DrawerBackground = primaryColor;
_theme.PaletteDark.AppbarBackground = primaryColor;
_theme.PaletteDark.DrawerBackground = primaryColor;
// Adjust text/icon contrast based on background luminance
var isLight = IsLightColor(primaryColor);
var textCol = isLight ? "#0F172A" : "#FFFFFF";
var subTextCol = isLight ? "rgba(15, 23, 42, 0.70)" : "rgba(255, 255, 255, 0.70)";
_theme.PaletteLight.AppbarText = textCol;
_theme.PaletteLight.DrawerText = subTextCol;
_theme.PaletteLight.DrawerIcon = subTextCol;
_theme.PaletteLight.PrimaryContrastText = textCol;
_theme.PaletteDark.AppbarText = textCol;
_theme.PaletteDark.DrawerText = subTextCol;
_theme.PaletteDark.DrawerIcon = subTextCol;
_theme.PaletteDark.PrimaryContrastText = textCol;
} }
} }
catch }
private void ApplyTheme(TenantInfo tenantInfo)
{
if (tenantInfo.IsTenant && !string.IsNullOrEmpty(tenantInfo.PrimaryColor))
{ {
// Ignore background error var primaryColor = tenantInfo.PrimaryColor;
var secondaryColor = tenantInfo.SecondaryColor ?? tenantInfo.PrimaryColor;
_theme.PaletteLight.Primary = primaryColor;
_theme.PaletteLight.Secondary = secondaryColor;
_theme.PaletteDark.Primary = primaryColor;
_theme.PaletteDark.Secondary = secondaryColor;
// Dynamically apply background colors to navbar
_theme.PaletteLight.AppbarBackground = primaryColor;
_theme.PaletteLight.DrawerBackground = primaryColor;
_theme.PaletteDark.AppbarBackground = primaryColor;
_theme.PaletteDark.DrawerBackground = primaryColor;
// Adjust text/icon contrast based on background luminance
var isLight = IsLightColor(primaryColor);
var textCol = isLight ? "#0F172A" : "#FFFFFF";
var subTextCol = isLight ? "rgba(15, 23, 42, 0.70)" : "rgba(255, 255, 255, 0.70)";
_theme.PaletteLight.AppbarText = textCol;
_theme.PaletteLight.DrawerText = subTextCol;
_theme.PaletteLight.DrawerIcon = subTextCol;
_theme.PaletteLight.PrimaryContrastText = textCol;
_theme.PaletteDark.AppbarText = textCol;
_theme.PaletteDark.DrawerText = subTextCol;
_theme.PaletteDark.DrawerIcon = subTextCol;
_theme.PaletteDark.PrimaryContrastText = textCol;
} }
} }
@@ -96,6 +96,9 @@
</div> </div>
@code { @code {
[PersistentState(AllowUpdates = true)]
public string? PersistentCompanyName { get; set; }
[Parameter] public EventCallback OnToggleDrawer { get; set; } [Parameter] public EventCallback OnToggleDrawer { get; set; }
private bool _showVersionBadge; private bool _showVersionBadge;
@@ -103,17 +106,25 @@
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
try if (PersistentCompanyName != null)
{ {
var tenantInfo = await Http.GetFromJsonAsync<TenantInfo>("api/tenant/current"); _companyName = PersistentCompanyName;
if (tenantInfo?.IsTenant == true && !string.IsNullOrEmpty(tenantInfo.Name))
{
_companyName = tenantInfo.Name;
}
} }
catch else
{ {
// Ignore background error try
{
var tenantInfo = await Http.GetFromJsonAsync<TenantInfo>("api/tenant/current");
if (tenantInfo?.IsTenant == true && !string.IsNullOrEmpty(tenantInfo.Name))
{
_companyName = tenantInfo.Name;
PersistentCompanyName = _companyName;
}
}
catch
{
// Ignore background error
}
} }
} }
@@ -152,6 +152,12 @@ else
} }
@code { @code {
[PersistentState(AllowUpdates = true)]
public List<User>? PersistentUsers { get; set; }
[PersistentState(AllowUpdates = true)]
public List<TenantStats>? PersistentTenants { get; set; }
private List<User> _users = []; private List<User> _users = [];
private List<TenantStats> _tenants = []; private List<TenantStats> _tenants = [];
private bool _loading = true; private bool _loading = true;
@@ -161,23 +167,35 @@ else
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
if (PersistentUsers != null)
{
_users = PersistentUsers;
_tenants = PersistentTenants ?? [];
_loading = false;
}
var claim = (await AuthStateProvider.GetAuthenticationStateAsync()) var claim = (await AuthStateProvider.GetAuthenticationStateAsync())
.User.FindFirst(ClaimTypes.NameIdentifier); .User.FindFirst(ClaimTypes.NameIdentifier);
if (claim == null) return; if (claim == null) return;
UserNotificationService.OnUsersChanged += RefreshUsers; UserNotificationService.OnUsersChanged += RefreshUsers;
try if (PersistentUsers == null)
{ {
_users = await AuthService.GetAllUsersAsync(); try
_tenants = await Http.GetFromJsonAsync<List<TenantStats>>("api/superadmin/tenants") ?? []; {
_users = await AuthService.GetAllUsersAsync();
_tenants = await Http.GetFromJsonAsync<List<TenantStats>>("api/superadmin/tenants") ?? [];
PersistentUsers = _users;
PersistentTenants = _tenants;
_loading = false;
}
catch (Exception ex)
{
Snackbar.Add($"Fehler beim Laden der Daten: {ex.Message}", Severity.Error);
}
} }
catch (Exception ex)
{
Snackbar.Add($"Fehler beim Laden der Daten: {ex.Message}", Severity.Error);
}
_loading = false;
} }
private async Task RefreshUsers() private async Task RefreshUsers()
@@ -60,15 +60,19 @@
public static readonly List<Release> Releases = public static readonly List<Release> Releases =
[ [
new("1.5", "25.06.2026", true, new("1.7", "27.06.2026", true,
[
new("Neu", "Excel-Export"),
new("Upgrade", "Besseres Page-Loading")
], Highlighted: true),
new("1.6", "25.06.2026", true,
[ [
new("Neu", "Userprofil angelegt"), new("Neu", "Userprofil angelegt"),
new("Upgrade", "Früheste Gehenszeit wird angezeigt"), new("Upgrade", "Früheste Gehenszeit wird angezeigt"),
new("Upgrade", "Pausen werden dynamisch berechnet"), new("Upgrade", "Pausen werden dynamisch berechnet"),
new("Neu", "Excel-Export"),
new("Neu", "Multi-Tenant Integration"), new("Neu", "Multi-Tenant Integration"),
new("Upgrade", "Verbesserte Single-User Ansicht") new("Upgrade", "Verbesserte Single-User Ansicht")
], Highlighted: true), ]),
new("1.4", "08.06.2026", true, new("1.4", "08.06.2026", true,
[ [
new("Neu", "Timebot implementiert"), new("Neu", "Timebot implementiert"),
@@ -183,6 +183,18 @@ else
@code { @code {
private static readonly System.Globalization.CultureInfo _deCulture = new("de-DE"); private static readonly System.Globalization.CultureInfo _deCulture = new("de-DE");
[PersistentState(AllowUpdates = true)]
public AppSettings? PersistentSettings { get; set; }
[PersistentState(AllowUpdates = true)]
public List<PublicHoliday>? PersistentHolidays { get; set; }
[PersistentState(AllowUpdates = true)]
public string? PersistentSubLabel { get; set; }
[PersistentState(AllowUpdates = true)]
public int? PersistentYear { get; set; }
private bool _loading = true; private bool _loading = true;
private int _year = DateTime.Today.Year; private int _year = DateTime.Today.Year;
private List<PublicHoliday> _holidays = []; private List<PublicHoliday> _holidays = [];
@@ -193,15 +205,38 @@ else
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
if (PersistentSettings != null && PersistentHolidays != null)
{
_settings = PersistentSettings;
_holidays = PersistentHolidays;
_subLabel = PersistentSubLabel ?? "";
_year = PersistentYear ?? DateTime.Today.Year;
_loading = false;
}
var authState = await AuthStateProvider.GetAuthenticationStateAsync(); var authState = await AuthStateProvider.GetAuthenticationStateAsync();
var claim = authState.User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier); var claim = authState.User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier);
if (claim != null) if (claim != null)
{ {
_userId = int.Parse(claim.Value); _userId = int.Parse(claim.Value);
_settings = await TrackerService.GetSettingsAsync(_userId);
if (PersistentSettings == null || PersistentHolidays == null)
{
_settings = await TrackerService.GetSettingsAsync(_userId);
await LoadHolidays();
PersistentSettings = _settings;
PersistentHolidays = _holidays;
PersistentSubLabel = _subLabel;
PersistentYear = _year;
_loading = false;
}
}
else
{
await LoadHolidays();
_loading = false;
} }
await LoadHolidays();
_loading = false;
} }
private async Task LoadHolidays() private async Task LoadHolidays()
+59 -10
View File
@@ -388,6 +388,30 @@ else
@code { @code {
private static readonly System.Globalization.CultureInfo _deCulture = new("de-DE"); private static readonly System.Globalization.CultureInfo _deCulture = new("de-DE");
[PersistentState(AllowUpdates = true)]
public AppSettings? PersistentSettings { get; set; }
[PersistentState(AllowUpdates = true)]
public List<DayVm>? PersistentDays { get; set; }
[PersistentState(AllowUpdates = true)]
public TimeSpan? PersistentTotalOvertime { get; set; }
[PersistentState(AllowUpdates = true)]
public Dictionary<DateOnly, string>? PersistentHolidays { get; set; }
[PersistentState(AllowUpdates = true)]
public int? PersistentHolidayYear { get; set; }
[PersistentState(AllowUpdates = true)]
public List<VacationDay>? PersistentVacations { get; set; }
[PersistentState(AllowUpdates = true)]
public string? PersistentWeekLabel { get; set; }
[PersistentState(AllowUpdates = true)]
public string? PersistentWeekSubLabel { get; set; }
private bool _loading = true; private bool _loading = true;
private int _userId; private int _userId;
private DateOnly _monday; private DateOnly _monday;
@@ -409,18 +433,45 @@ else
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
if (PersistentSettings != null && PersistentDays != null && PersistentTotalOvertime != null)
{
_settings = PersistentSettings;
_days = PersistentDays;
_totalOvertime = PersistentTotalOvertime.Value;
_holidays = PersistentHolidays ?? [];
_holidayYear = PersistentHolidayYear ?? -1;
_vacations = PersistentVacations ?? [];
_weekLabel = PersistentWeekLabel ?? "";
_weekSubLabel = PersistentWeekSubLabel ?? "";
_loading = false;
}
var authState = await AuthStateProvider.GetAuthenticationStateAsync(); var authState = await AuthStateProvider.GetAuthenticationStateAsync();
var claim = authState.User.FindFirst(ClaimTypes.NameIdentifier); var claim = authState.User.FindFirst(ClaimTypes.NameIdentifier);
if (claim == null) return; // Prerender-Pass Circuit noch nicht authentifiziert if (claim == null) return; // Prerender-Pass Circuit noch nicht authentifiziert
_userId = int.Parse(claim.Value); _userId = int.Parse(claim.Value);
_monday = GetMonday(DateOnly.FromDateTime(DateTime.Today)); _monday = GetMonday(DateOnly.FromDateTime(DateTime.Today));
_settings = await TrackerService.GetSettingsAsync(_userId);
var loadWeekTask = LoadWeek(); if (PersistentSettings == null || PersistentDays == null || PersistentTotalOvertime == null)
var overtimeTask = TrackerService.GetTotalOvertimeAsync(_userId, _settings); {
_settings = await TrackerService.GetSettingsAsync(_userId);
await Task.WhenAll(loadWeekTask, overtimeTask);
_totalOvertime = await overtimeTask; var loadWeekTask = LoadWeek();
var overtimeTask = TrackerService.GetTotalOvertimeAsync(_userId, _settings);
await Task.WhenAll(loadWeekTask, overtimeTask);
_totalOvertime = await overtimeTask;
PersistentSettings = _settings;
PersistentDays = _days;
PersistentTotalOvertime = _totalOvertime;
PersistentHolidays = _holidays;
PersistentHolidayYear = _holidayYear;
PersistentVacations = _vacations;
PersistentWeekLabel = _weekLabel;
PersistentWeekSubLabel = _weekSubLabel;
_loading = false;
}
try try
{ {
@@ -431,8 +482,6 @@ else
{ {
// Ignored during prerendering/SSR // Ignored during prerendering/SSR
} }
_loading = false;
} }
private async Task HandleOnboardingFinished() private async Task HandleOnboardingFinished()
@@ -693,7 +742,7 @@ else
} }
// ── ViewModels ──────────────────────────────────────────────── // ── ViewModels ────────────────────────────────────────────────
private sealed class DayVm public sealed class DayVm
{ {
public int Id { get; set; } public int Id { get; set; }
public int UserId { get; set; } public int UserId { get; set; }
@@ -743,7 +792,7 @@ else
}; };
} }
private sealed class BreakVm public sealed class BreakVm
{ {
public int Id { get; set; } public int Id { get; set; }
public TimeSpan? Start { get; set; } public TimeSpan? Start { get; set; }
+23 -18
View File
@@ -9,7 +9,7 @@
<PageTitle>@GetPageTitle()</PageTitle> <PageTitle>@GetPageTitle()</PageTitle>
@if (_tenantInfo == null) @if (TenantInfo == null)
{ {
@* Loading indicator while resolving Tenant *@ @* Loading indicator while resolving Tenant *@
<MudContainer MaxWidth="MaxWidth.Small" Class="mt-16 text-center"> <MudContainer MaxWidth="MaxWidth.Small" Class="mt-16 text-center">
@@ -17,7 +17,7 @@
<MudText Class="mt-4" Color="Color.Secondary">Lade Timetracker…</MudText> <MudText Class="mt-4" Color="Color.Secondary">Lade Timetracker…</MudText>
</MudContainer> </MudContainer>
} }
else if (_tenantInfo.IsTenant && !_tenantInfo.IsApproved) else if (TenantInfo.IsTenant && !TenantInfo.IsApproved)
{ {
@* Pending Approval Screen *@ @* Pending Approval Screen *@
<MudContainer MaxWidth="MaxWidth.Small" Class="mt-16"> <MudContainer MaxWidth="MaxWidth.Small" Class="mt-16">
@@ -34,7 +34,7 @@ else if (_tenantInfo.IsTenant && !_tenantInfo.IsApproved)
Class="mb-4" /> Class="mb-4" />
<MudText Typo="Typo.h5" Style="font-weight: 700;" Class="mb-2">Freischaltung ausstehend</MudText> <MudText Typo="Typo.h5" Style="font-weight: 700;" Class="mb-2">Freischaltung ausstehend</MudText>
<MudText Typo="Typo.body1" Color="Color.Secondary" Class="mb-6"> <MudText Typo="Typo.body1" Color="Color.Secondary" Class="mb-6">
Die Firma <strong>@_tenantInfo.Name</strong> wurde erfolgreich registriert. Die Firma <strong>@TenantInfo.Name</strong> wurde erfolgreich registriert.
Der Zugang wird derzeit von unserem SuperAdmin geprüft und in Kürze freigeschaltet. Der Zugang wird derzeit von unserem SuperAdmin geprüft und in Kürze freigeschaltet.
</MudText> </MudText>
<MudDivider Class="my-4" /> <MudDivider Class="my-4" />
@@ -64,9 +64,9 @@ else
<MudIcon Icon="@Icons.Material.Filled.AccessTime" <MudIcon Icon="@Icons.Material.Filled.AccessTime"
Style="font-size:4rem; color:#0EA5E9" /> Style="font-size:4rem; color:#0EA5E9" />
<MudText Typo="Typo.h4" Style="font-weight:700; color:#0EA5E9"> <MudText Typo="Typo.h4" Style="font-weight:700; color:#0EA5E9">
@(_tenantInfo.IsTenant ? _tenantInfo.Name : "Timetracker SaaS") @(TenantInfo.IsTenant ? TenantInfo.Name : "Timetracker SaaS")
</MudText> </MudText>
@if (!_tenantInfo.IsTenant) @if (!TenantInfo.IsTenant)
{ {
<MudText Typo="Typo.caption" Color="Color.Secondary">Zentrales Portal</MudText> <MudText Typo="Typo.caption" Color="Color.Secondary">Zentrales Portal</MudText>
} }
@@ -168,7 +168,7 @@ else
} }
else if (_activeTab == 1) else if (_activeTab == 1)
{ {
@if (_tenantInfo.IsTenant) @if (TenantInfo.IsTenant)
{ {
@* ── Employee Register Form ── *@ @* ── Employee Register Form ── *@
<MudStack Spacing="3"> <MudStack Spacing="3">
@@ -359,7 +359,7 @@ else
</MudStack> </MudStack>
} }
@if (!_tenantInfo.IsTenant && _activeTab != 2) @if (!TenantInfo.IsTenant && _activeTab != 2)
{ {
<MudDivider Class="my-4" /> <MudDivider Class="my-4" />
<MudStack AlignItems="AlignItems.Center"> <MudStack AlignItems="AlignItems.Center">
@@ -378,7 +378,9 @@ else
} }
@code { @code {
private TenantInfo? _tenantInfo; [PersistentState(AllowUpdates = true)]
public TenantInfo? TenantInfo { get; set; }
private int _activeTab = 0; private int _activeTab = 0;
private string? _error; private string? _error;
private bool _loading; private bool _loading;
@@ -399,15 +401,18 @@ else
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
try if (TenantInfo is null)
{ {
_tenantInfo = await Http.GetFromJsonAsync<TenantInfo>("api/tenant/current"); try
} {
catch (Exception ex) TenantInfo = await Http.GetFromJsonAsync<TenantInfo>("api/tenant/current");
{ }
Console.WriteLine($"Fehler beim Abrufen der TenantInfo: {ex.Message}"); catch (Exception ex)
// Fallback {
_tenantInfo = new TenantInfo { IsTenant = false }; Console.WriteLine($"Fehler beim Abrufen der TenantInfo: {ex.Message}");
// Fallback
TenantInfo = new TenantInfo { IsTenant = false };
}
} }
} }
@@ -430,8 +435,8 @@ else
private string GetPageTitle() private string GetPageTitle()
{ {
if (_tenantInfo == null) return "Lade…"; if (TenantInfo == null) return "Lade…";
return _tenantInfo.IsTenant ? $"Anmelden bei {_tenantInfo.Name} Timetracker" : "Anmelden Timetracker SaaS"; return TenantInfo.IsTenant ? $"Anmelden bei {TenantInfo.Name} Timetracker" : "Anmelden Timetracker SaaS";
} }
private string GetDomainSuffix() private string GetDomainSuffix()
@@ -155,6 +155,33 @@ else
@code { @code {
private static readonly System.Globalization.CultureInfo _deCulture = new("de-DE"); private static readonly System.Globalization.CultureInfo _deCulture = new("de-DE");
[PersistentState(AllowUpdates = true)]
public AppSettings? PersistentSettings { get; set; }
[PersistentState(AllowUpdates = true)]
public List<MonthDayVm>? PersistentDays { get; set; }
[PersistentState(AllowUpdates = true)]
public string? PersistentSubLabel { get; set; }
[PersistentState(AllowUpdates = true)]
public TimeSpan? PersistentMonthNet { get; set; }
[PersistentState(AllowUpdates = true)]
public TimeSpan? PersistentMonthOvertime { get; set; }
[PersistentState(AllowUpdates = true)]
public int? PersistentRecordedWorkDays { get; set; }
[PersistentState(AllowUpdates = true)]
public int? PersistentTotalWorkDays { get; set; }
[PersistentState(AllowUpdates = true)]
public int? PersistentVacationCount { get; set; }
[PersistentState(AllowUpdates = true)]
public int? PersistentHolidayCount { get; set; }
private bool _loading = true; private bool _loading = true;
private int _userId; private int _userId;
private int _year = DateTime.Today.Year; private int _year = DateTime.Today.Year;
@@ -174,13 +201,41 @@ else
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
if (PersistentSettings != null && PersistentDays != null)
{
_settings = PersistentSettings;
_days = PersistentDays;
_subLabel = PersistentSubLabel ?? "";
_monthNet = PersistentMonthNet ?? TimeSpan.Zero;
_monthOvertime = PersistentMonthOvertime ?? TimeSpan.Zero;
_recordedWorkDays = PersistentRecordedWorkDays ?? 0;
_totalWorkDays = PersistentTotalWorkDays ?? 0;
_vacationCount = PersistentVacationCount ?? 0;
_holidayCount = PersistentHolidayCount ?? 0;
_loading = false;
}
var authState = await AuthStateProvider.GetAuthenticationStateAsync(); var authState = await AuthStateProvider.GetAuthenticationStateAsync();
var claim = authState.User.FindFirst(ClaimTypes.NameIdentifier); var claim = authState.User.FindFirst(ClaimTypes.NameIdentifier);
if (claim == null) return; if (claim == null) return;
_userId = int.Parse(claim.Value); _userId = int.Parse(claim.Value);
_settings = await TrackerService.GetSettingsAsync(_userId);
await LoadMonth(); if (PersistentSettings == null || PersistentDays == null)
_loading = false; {
_settings = await TrackerService.GetSettingsAsync(_userId);
await LoadMonth();
PersistentSettings = _settings;
PersistentDays = _days;
PersistentSubLabel = _subLabel;
PersistentMonthNet = _monthNet;
PersistentMonthOvertime = _monthOvertime;
PersistentRecordedWorkDays = _recordedWorkDays;
PersistentTotalWorkDays = _totalWorkDays;
PersistentVacationCount = _vacationCount;
PersistentHolidayCount = _holidayCount;
_loading = false;
}
} }
private async Task LoadMonth() private async Task LoadMonth()
@@ -317,7 +372,7 @@ else
else Chip("Ausstehend", "#CFD8DC"); else Chip("Ausstehend", "#CFD8DC");
}; };
private sealed class MonthDayVm public sealed class MonthDayVm
{ {
public DateOnly Date { get; set; } public DateOnly Date { get; set; }
public TimeOnly? StartTime { get; set; } public TimeOnly? StartTime { get; set; }
@@ -163,6 +163,21 @@ else
} }
@code { @code {
[PersistentState(AllowUpdates = true)]
public AppSettings? PersistentSettings { get; set; }
[PersistentState(AllowUpdates = true)]
public string? PersistentUsername { get; set; }
[PersistentState(AllowUpdates = true)]
public string? PersistentNewUsername { get; set; }
[PersistentState(AllowUpdates = true)]
public bool? PersistentIsAdmin { get; set; }
[PersistentState(AllowUpdates = true)]
public TimeSpan? PersistentOvertime { get; set; }
private bool _loading = true; private bool _loading = true;
private int _userId; private int _userId;
private string _username = ""; private string _username = "";
@@ -184,18 +199,38 @@ else
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
if (PersistentSettings != null)
{
_settings = PersistentSettings;
_username = PersistentUsername ?? "";
_newUsername = PersistentNewUsername ?? "";
_isAdmin = PersistentIsAdmin ?? false;
_overtime = PersistentOvertime ?? TimeSpan.Zero;
_loading = false;
}
var authState = await AuthStateProvider.GetAuthenticationStateAsync(); var authState = await AuthStateProvider.GetAuthenticationStateAsync();
var claim = authState.User.FindFirst(ClaimTypes.NameIdentifier); var claim = authState.User.FindFirst(ClaimTypes.NameIdentifier);
if (claim == null) return; if (claim == null) return;
_userId = int.Parse(claim.Value); _userId = int.Parse(claim.Value);
_username = authState.User.Identity?.Name ?? "";
_newUsername = _username; if (PersistentSettings == null)
_isAdmin = _username.Equals("marc", StringComparison.OrdinalIgnoreCase); {
_username = authState.User.Identity?.Name ?? "";
_newUsername = _username;
_isAdmin = _username.Equals("marc", StringComparison.OrdinalIgnoreCase);
_settings = await TrackerService.GetSettingsAsync(_userId); _settings = await TrackerService.GetSettingsAsync(_userId);
_overtime = await TrackerService.GetTotalOvertimeAsync(_userId, _settings); _overtime = await TrackerService.GetTotalOvertimeAsync(_userId, _settings);
_loading = false;
PersistentSettings = _settings;
PersistentUsername = _username;
PersistentNewUsername = _newUsername;
PersistentIsAdmin = _isAdmin;
PersistentOvertime = _overtime;
_loading = false;
}
} }
private string GetInitials(string? name) private string GetInitials(string? name)
@@ -511,6 +511,27 @@ else
@code { @code {
private static readonly System.Globalization.CultureInfo _deCulture = new("de-DE"); private static readonly System.Globalization.CultureInfo _deCulture = new("de-DE");
[PersistentState(AllowUpdates = true)]
public AppSettings? PersistentSettings { get; set; }
[PersistentState(AllowUpdates = true)]
public TenantInfo? PersistentTenantInfo { get; set; }
[PersistentState(AllowUpdates = true)]
public List<VacationDay>? PersistentVacationDays { get; set; }
[PersistentState(AllowUpdates = true)]
public List<PublicHoliday>? PersistentHolHolidays { get; set; }
[PersistentState(AllowUpdates = true)]
public string? PersistentTenantName { get; set; }
[PersistentState(AllowUpdates = true)]
public string? PersistentTenantPrimaryColor { get; set; }
[PersistentState(AllowUpdates = true)]
public string? PersistentTenantSecondaryColor { get; set; }
private AppSettings? _settings; private AppSettings? _settings;
private int _userId; private int _userId;
private bool _isTenantAdmin; private bool _isTenantAdmin;
@@ -571,36 +592,63 @@ else
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
if (PersistentSettings != null)
{
_settings = PersistentSettings;
_tenantInfo = PersistentTenantInfo;
_vacationDays = PersistentVacationDays ?? [];
_holHolidays = PersistentHolHolidays ?? [];
_tenantName = PersistentTenantName ?? "";
_tenantPrimaryColor = PersistentTenantPrimaryColor ?? "#0EA5E9";
_tenantSecondaryColor = PersistentTenantSecondaryColor ?? "#0EA5E9";
}
var authState = await AuthStateProvider.GetAuthenticationStateAsync(); var authState = await AuthStateProvider.GetAuthenticationStateAsync();
var claim = authState.User.FindFirst(ClaimTypes.NameIdentifier); var claim = authState.User.FindFirst(ClaimTypes.NameIdentifier);
if (claim == null) return; if (claim == null) return;
_userId = int.Parse(claim.Value); _userId = int.Parse(claim.Value);
_settings = await TrackerService.GetSettingsAsync(_userId);
_isTenantAdmin = authState.User.IsInRole("TenantAdmin") || authState.User.HasClaim("IsTenantAdmin", "true"); if (PersistentSettings != null)
if (_isTenantAdmin)
{ {
try _isTenantAdmin = authState.User.IsInRole("TenantAdmin") || authState.User.HasClaim("IsTenantAdmin", "true");
}
else
{
_isTenantAdmin = authState.User.IsInRole("TenantAdmin") || authState.User.HasClaim("IsTenantAdmin", "true");
_settings = await TrackerService.GetSettingsAsync(_userId);
if (_isTenantAdmin)
{ {
_tenantInfo = await Http.GetFromJsonAsync<TenantInfo>("api/tenant/current"); try
if (_tenantInfo != null)
{ {
_tenantName = _tenantInfo.Name ?? ""; _tenantInfo = await Http.GetFromJsonAsync<TenantInfo>("api/tenant/current");
_tenantPrimaryColor = _tenantInfo.PrimaryColor ?? "#0EA5E9"; if (_tenantInfo != null)
_tenantSecondaryColor = _tenantInfo.SecondaryColor ?? "#0EA5E9"; {
_tenantName = _tenantInfo.Name ?? "";
_tenantPrimaryColor = _tenantInfo.PrimaryColor ?? "#0EA5E9";
_tenantSecondaryColor = _tenantInfo.SecondaryColor ?? "#0EA5E9";
}
}
catch (Exception ex)
{
Snackbar.Add($"Fehler beim Laden der Firmen-Einstellungen: {ex.Message}", Severity.Error);
} }
} }
catch (Exception ex)
{ var loadVacationsTask = LoadVacations();
Snackbar.Add($"Fehler beim Laden der Firmen-Einstellungen: {ex.Message}", Severity.Error); var loadHolidaysTask = HolidayService.GetHolidaysAsync(_holYear, _settings.GermanState);
}
await Task.WhenAll(loadVacationsTask, loadHolidaysTask);
_holHolidays = await loadHolidaysTask;
PersistentSettings = _settings;
PersistentTenantInfo = _tenantInfo;
PersistentVacationDays = _vacationDays;
PersistentHolHolidays = _holHolidays;
PersistentTenantName = _tenantName;
PersistentTenantPrimaryColor = _tenantPrimaryColor;
PersistentTenantSecondaryColor = _tenantSecondaryColor;
} }
var loadVacationsTask = LoadVacations();
var loadHolidaysTask = HolidayService.GetHolidaysAsync(_holYear, _settings.GermanState);
await Task.WhenAll(loadVacationsTask, loadHolidaysTask);
_holHolidays = await loadHolidaysTask;
} }
private async Task LoadVacations() private async Task LoadVacations()
+106 -63
View File
@@ -324,6 +324,27 @@ else
} }
@code { @code {
[PersistentState(AllowUpdates = true)]
public AppSettings? PersistentSettings { get; set; }
[PersistentState(AllowUpdates = true)]
public List<DayStat>? PersistentDays { get; set; }
[PersistentState(AllowUpdates = true)]
public TimeSpan? PersistentTotalOvertime { get; set; }
[PersistentState(AllowUpdates = true)]
public double? PersistentWeekWorkedHours { get; set; }
[PersistentState(AllowUpdates = true)]
public double? PersistentWeekTargetHours { get; set; }
[PersistentState(AllowUpdates = true)]
public double? PersistentWeekOvertimeHours { get; set; }
[PersistentState(AllowUpdates = true)]
public double? PersistentMaxHoursValue { get; set; }
private bool _loading = true; private bool _loading = true;
private int _userId; private int _userId;
private AppSettings _settings = new(); private AppSettings _settings = new();
@@ -349,84 +370,106 @@ else
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
if (PersistentSettings != null && PersistentDays != null)
{
_settings = PersistentSettings;
_days = PersistentDays;
_totalOvertime = PersistentTotalOvertime ?? TimeSpan.Zero;
_weekWorkedHours = PersistentWeekWorkedHours ?? 0.0;
_weekTargetHours = PersistentWeekTargetHours ?? 0.0;
_weekOvertimeHours = PersistentWeekOvertimeHours ?? 0.0;
_maxHoursValue = PersistentMaxHoursValue ?? 10.0;
_loading = false;
}
var authState = await AuthStateProvider.GetAuthenticationStateAsync(); var authState = await AuthStateProvider.GetAuthenticationStateAsync();
var claim = authState.User.FindFirst(ClaimTypes.NameIdentifier); var claim = authState.User.FindFirst(ClaimTypes.NameIdentifier);
if (claim == null) return; if (claim == null) return;
_userId = int.Parse(claim.Value); _userId = int.Parse(claim.Value);
_settings = await TrackerService.GetSettingsAsync(_userId); if (PersistentSettings == null || PersistentDays == null)
var today = DateOnly.FromDateTime(DateTime.Today);
var monday = GetMonday(today);
var dbDays = await TrackerService.GetWeekAsync(_userId, monday);
_rawDbDaysCount = dbDays.Count;
_totalOvertime = await TrackerService.GetTotalOvertimeAsync(_userId, _settings);
_weekTargetHours = 0;
_weekWorkedHours = 0;
_dbMatchStatus.Clear();
_days = Enumerable.Range(0, 7).Select(i =>
{ {
var date = monday.AddDays(i); _settings = await TrackerService.GetSettingsAsync(_userId);
bool isWorkDay = _settings.IsWorkDay(date.DayOfWeek);
double target = isWorkDay ? _settings.DailyTargetHours : 0.0;
if (isWorkDay) var today = DateOnly.FromDateTime(DateTime.Today);
{ var monday = GetMonday(today);
_weekTargetHours += _settings.DailyTargetHours;
} var dbDays = await TrackerService.GetWeekAsync(_userId, monday);
_rawDbDaysCount = dbDays.Count;
_totalOvertime = await TrackerService.GetTotalOvertimeAsync(_userId, _settings);
var wd = dbDays.FirstOrDefault(d => d.Date == date); _weekTargetHours = 0;
double worked = 0.0; _weekWorkedHours = 0;
_dbMatchStatus.Clear();
if (wd != null)
_days = Enumerable.Range(0, 7).Select(i =>
{ {
_dbMatchStatus[date] = $"Ja (Id={wd.Id}, Start={wd.StartTime}, Ende={wd.EndTime})"; var date = monday.AddDays(i);
bool isWorkDay = _settings.IsWorkDay(date.DayOfWeek);
double target = isWorkDay ? _settings.DailyTargetHours : 0.0;
if (wd.StartTime != null && wd.EndTime != null) if (isWorkDay)
{ {
var gross = wd.EndTime.Value.ToTimeSpan() - wd.StartTime.Value.ToTimeSpan(); _weekTargetHours += _settings.DailyTargetHours;
if (gross > TimeSpan.Zero) }
var wd = dbDays.FirstOrDefault(d => d.Date == date);
double worked = 0.0;
if (wd != null)
{
_dbMatchStatus[date] = $"Ja (Id={wd.Id}, Start={wd.StartTime}, Ende={wd.EndTime})";
if (wd.StartTime != null && wd.EndTime != null)
{ {
var breakTotal = wd.Breaks var gross = wd.EndTime.Value.ToTimeSpan() - wd.StartTime.Value.ToTimeSpan();
.Where(b => b.StartTime.HasValue && b.EndTime.HasValue && b.EndTime > b.StartTime) if (gross > TimeSpan.Zero)
.Aggregate(TimeSpan.Zero, (s, b) => {
s + (b.EndTime!.Value.ToTimeSpan() - b.StartTime!.Value.ToTimeSpan())); var breakTotal = wd.Breaks
var minMinutes = gross.TotalHours >= 9.0 ? 45 : 30; .Where(b => b.StartTime.HasValue && b.EndTime.HasValue && b.EndTime > b.StartTime)
var minBreak = TimeSpan.FromMinutes(Math.Max(minMinutes, _settings.MinimumBreakMinutes)); .Aggregate(TimeSpan.Zero, (s, b) =>
var finalBreak = breakTotal > minBreak ? breakTotal : minBreak; s + (b.EndTime!.Value.ToTimeSpan() - b.StartTime!.Value.ToTimeSpan()));
worked = (gross - finalBreak).TotalHours; var minMinutes = gross.TotalHours >= 9.0 ? 45 : 30;
if (worked < 0) worked = 0.0; var minBreak = TimeSpan.FromMinutes(Math.Max(minMinutes, _settings.MinimumBreakMinutes));
var finalBreak = breakTotal > minBreak ? breakTotal : minBreak;
worked = (gross - finalBreak).TotalHours;
if (worked < 0) worked = 0.0;
}
} }
} }
} else
else {
{ _dbMatchStatus[date] = "Nein";
_dbMatchStatus[date] = "Nein"; }
}
_weekWorkedHours += worked;
return new DayStat
{
Date = date,
DayName = date.ToString("dddd", _deCulture),
DayShortName = date.ToString("ddd", _deCulture),
WorkedHours = worked,
TargetHours = target,
IsToday = date == today,
IsWorkDay = isWorkDay
};
}).ToList();
_weekOvertimeHours = _weekWorkedHours - _weekTargetHours;
_weekWorkedHours += worked; var maxWorked = _days.Max(d => d.WorkedHours);
_maxHoursValue = Math.Max(10.0, Math.Max(maxWorked, _settings.DailyTargetHours));
return new DayStat PersistentSettings = _settings;
{ PersistentDays = _days;
Date = date, PersistentTotalOvertime = _totalOvertime;
DayName = date.ToString("dddd", _deCulture), PersistentWeekWorkedHours = _weekWorkedHours;
DayShortName = date.ToString("ddd", _deCulture), PersistentWeekTargetHours = _weekTargetHours;
WorkedHours = worked, PersistentWeekOvertimeHours = _weekOvertimeHours;
TargetHours = target, PersistentMaxHoursValue = _maxHoursValue;
IsToday = date == today, _loading = false;
IsWorkDay = isWorkDay }
};
}).ToList();
_weekOvertimeHours = _weekWorkedHours - _weekTargetHours;
var maxWorked = _days.Max(d => d.WorkedHours);
_maxHoursValue = Math.Max(10.0, Math.Max(maxWorked, _settings.DailyTargetHours));
_loading = false;
} }
private static DateOnly GetMonday(DateOnly date) private static DateOnly GetMonday(DateOnly date)
@@ -468,7 +511,7 @@ else
NavigationManager.NavigateTo($"api/tracker/export/year?year={_exportYear}", forceLoad: true); NavigationManager.NavigateTo($"api/tracker/export/year?year={_exportYear}", forceLoad: true);
} }
private sealed class DayStat public sealed class DayStat
{ {
public DateOnly Date { get; set; } public DateOnly Date { get; set; }
public string DayName { get; set; } = ""; public string DayName { get; set; } = "";
@@ -167,12 +167,23 @@ else
} }
@code { @code {
[PersistentState(AllowUpdates = true)]
public List<TenantStats>? PersistentTenants { get; set; }
private bool _loading = true; private bool _loading = true;
private List<TenantStats> _tenants = []; private List<TenantStats> _tenants = [];
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
await LoadTenants(); if (PersistentTenants != null)
{
_tenants = PersistentTenants;
_loading = false;
}
else
{
await LoadTenants();
}
} }
private async Task LoadTenants() private async Task LoadTenants()
@@ -181,6 +192,7 @@ else
try try
{ {
_tenants = await Http.GetFromJsonAsync<List<TenantStats>>("api/superadmin/tenants") ?? []; _tenants = await Http.GetFromJsonAsync<List<TenantStats>>("api/superadmin/tenants") ?? [];
PersistentTenants = _tenants;
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -226,6 +226,27 @@ else
@code { @code {
private static readonly System.Globalization.CultureInfo _deCulture = new("de-DE"); private static readonly System.Globalization.CultureInfo _deCulture = new("de-DE");
[PersistentState(AllowUpdates = true)]
public AppSettings? PersistentSettings { get; set; }
[PersistentState(AllowUpdates = true)]
public Dictionary<DateOnly, string>? PersistentHolidays { get; set; }
[PersistentState(AllowUpdates = true)]
public List<DateOnly>? PersistentVacationList { get; set; }
[PersistentState(AllowUpdates = true)]
public int? PersistentRemainingDays { get; set; }
[PersistentState(AllowUpdates = true)]
public List<Suggestion>? PersistentSuggestions { get; set; }
[PersistentState(AllowUpdates = true)]
public string? PersistentSubLabel { get; set; }
[PersistentState(AllowUpdates = true)]
public int? PersistentYear { get; set; }
private bool _loading = true; private bool _loading = true;
private int _year = DateTime.Today.Year; private int _year = DateTime.Today.Year;
private AppSettings _settings = new(); private AppSettings _settings = new();
@@ -238,13 +259,37 @@ else
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
if (PersistentSettings != null && PersistentSuggestions != null)
{
_settings = PersistentSettings;
_holidays = PersistentHolidays ?? [];
_vacationSet = (PersistentVacationList ?? []).ToHashSet();
_remainingDays = PersistentRemainingDays ?? 0;
_suggestions = PersistentSuggestions;
_subLabel = PersistentSubLabel ?? "";
_year = PersistentYear ?? DateTime.Today.Year;
_loading = false;
}
var authState = await AuthStateProvider.GetAuthenticationStateAsync(); var authState = await AuthStateProvider.GetAuthenticationStateAsync();
var claim = authState.User.FindFirst(ClaimTypes.NameIdentifier); var claim = authState.User.FindFirst(ClaimTypes.NameIdentifier);
if (claim == null) return; if (claim == null) return;
_userId = int.Parse(claim.Value); _userId = int.Parse(claim.Value);
_settings = await TrackerService.GetSettingsAsync(_userId);
await LoadYear(); if (PersistentSettings == null || PersistentSuggestions == null)
_loading = false; {
_settings = await TrackerService.GetSettingsAsync(_userId);
await LoadYear();
PersistentSettings = _settings;
PersistentHolidays = _holidays;
PersistentVacationList = _vacationSet.ToList();
PersistentRemainingDays = _remainingDays;
PersistentSuggestions = _suggestions;
PersistentSubLabel = _subLabel;
PersistentYear = _year;
_loading = false;
}
} }
private async Task LoadYear() private async Task LoadYear()
@@ -283,7 +328,7 @@ else
// ── Algorithmus ────────────────────────────────────────────────────── // ── Algorithmus ──────────────────────────────────────────────────────
private enum DayKind { Free, WorkAvailable, WorkTaken } private enum DayKind { Free, WorkAvailable, WorkTaken }
private sealed record Suggestion( public sealed record Suggestion(
DateOnly SpanStart, DateOnly SpanStart,
DateOnly SpanEnd, DateOnly SpanEnd,
List<DateOnly> VacationDaysToTake, List<DateOnly> VacationDaysToTake,
@@ -1,5 +1,6 @@
using System.Security.Claims; using System.Security.Claims;
using System.Net.Http.Json; using System.Net.Http.Json;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.Components.Authorization;
using timetracker.Shared; using timetracker.Shared;
@@ -8,12 +9,14 @@ namespace timetracker.Client.Services;
public class HostAuthenticationStateProvider : AuthenticationStateProvider public class HostAuthenticationStateProvider : AuthenticationStateProvider
{ {
private readonly HttpClient _http; private readonly HttpClient _http;
private readonly PersistentComponentState _state;
private static readonly ClaimsPrincipal Anonymous = new(new ClaimsIdentity()); private static readonly ClaimsPrincipal Anonymous = new(new ClaimsIdentity());
private ClaimsPrincipal? _currentUser; private ClaimsPrincipal? _currentUser;
public HostAuthenticationStateProvider(HttpClient http) public HostAuthenticationStateProvider(HttpClient http, PersistentComponentState state)
{ {
_http = http; _http = http;
_state = state;
} }
public override async Task<AuthenticationState> GetAuthenticationStateAsync() public override async Task<AuthenticationState> GetAuthenticationStateAsync()
@@ -23,20 +26,40 @@ public class HostAuthenticationStateProvider : AuthenticationStateProvider
return new AuthenticationState(_currentUser); return new AuthenticationState(_currentUser);
} }
if (_state.TryTakeFromJson<UserInfo>("UserInfoState", out var userInfo) && userInfo != null)
{
if (!userInfo.IsAuthenticated)
{
_currentUser = Anonymous;
return new AuthenticationState(_currentUser);
}
var claims = new[]
{
new Claim(ClaimTypes.NameIdentifier, userInfo.Id.ToString()),
new Claim(ClaimTypes.Name, userInfo.Username),
new Claim("IsTenantAdmin", userInfo.IsTenantAdmin ? "true" : "false"),
new Claim(ClaimTypes.Role, userInfo.IsTenantAdmin ? "TenantAdmin" : "Employee")
};
var identity = new ClaimsIdentity(claims, "Cookie");
_currentUser = new ClaimsPrincipal(identity);
return new AuthenticationState(_currentUser);
}
try try
{ {
var response = await _http.GetAsync("api/auth/me"); var response = await _http.GetAsync("api/auth/me");
if (response.IsSuccessStatusCode) if (response.IsSuccessStatusCode)
{ {
var userInfo = await response.Content.ReadFromJsonAsync<UserInfo>(); var apiUserInfo = await response.Content.ReadFromJsonAsync<UserInfo>();
if (userInfo != null) if (apiUserInfo != null)
{ {
var claims = new[] var claims = new[]
{ {
new Claim(ClaimTypes.NameIdentifier, userInfo.Id.ToString()), new Claim(ClaimTypes.NameIdentifier, apiUserInfo.Id.ToString()),
new Claim(ClaimTypes.Name, userInfo.Username), new Claim(ClaimTypes.Name, apiUserInfo.Username),
new Claim("IsTenantAdmin", userInfo.IsTenantAdmin ? "true" : "false"), new Claim("IsTenantAdmin", apiUserInfo.IsTenantAdmin ? "true" : "false"),
new Claim(ClaimTypes.Role, userInfo.IsTenantAdmin ? "TenantAdmin" : "Employee") new Claim(ClaimTypes.Role, apiUserInfo.IsTenantAdmin ? "TenantAdmin" : "Employee")
}; };
var identity = new ClaimsIdentity(claims, "Cookie"); var identity = new ClaimsIdentity(claims, "Cookie");
_currentUser = new ClaimsPrincipal(identity); _currentUser = new ClaimsPrincipal(identity);
+1
View File
@@ -27,6 +27,7 @@
<body> <body>
<Routes /> <Routes />
<persist-component-state />
<script src="@Assets["_framework/blazor.web.js"]"></script> <script src="@Assets["_framework/blazor.web.js"]"></script>
<script src="_content/MudBlazor/MudBlazor.min.js"></script> <script src="_content/MudBlazor/MudBlazor.min.js"></script>
<script> <script>
@@ -0,0 +1,59 @@
using System.Diagnostics;
using System.Security.Claims;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Server;
using Microsoft.AspNetCore.Components.Web;
using timetracker.Shared;
namespace timetracker.Server;
public class PersistingServerAuthenticationStateProvider : ServerAuthenticationStateProvider, IDisposable
{
private readonly PersistentComponentState _state;
private readonly PersistingComponentStateSubscription _subscription;
public PersistingServerAuthenticationStateProvider(PersistentComponentState state)
{
_state = state;
_subscription = state.RegisterOnPersisting(PersistAuthenticationState);
}
private async Task PersistAuthenticationState()
{
var authState = await GetAuthenticationStateAsync();
var user = authState.User;
if (user.Identity?.IsAuthenticated == true)
{
var idClaim = user.FindFirst(ClaimTypes.NameIdentifier)?.Value;
var name = user.Identity.Name;
var isAdminClaim = user.FindFirst("IsTenantAdmin")?.Value;
if (idClaim != null && name != null)
{
var userInfo = new UserInfo
{
Id = int.Parse(idClaim),
Username = name,
IsTenantAdmin = isAdminClaim == "true",
IsAuthenticated = true
};
_state.PersistAsJson("UserInfoState", userInfo);
}
}
else
{
var userInfo = new UserInfo
{
IsAuthenticated = false
};
_state.PersistAsJson("UserInfoState", userInfo);
}
}
public void Dispose()
{
_subscription.Dispose();
}
}
+3
View File
@@ -7,8 +7,10 @@ using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Components.Authorization;
using MudBlazor.Services; using MudBlazor.Services;
using Serilog; using Serilog;
using timetracker.Server;
using timetracker.Server.Components; using timetracker.Server.Components;
using timetracker.Data; using timetracker.Data;
using timetracker.Shared; using timetracker.Shared;
@@ -68,6 +70,7 @@ builder.Services.AddAuthorization(options =>
}); });
builder.Services.AddCascadingAuthenticationState(); builder.Services.AddCascadingAuthenticationState();
builder.Services.AddScoped<AuthenticationStateProvider, PersistingServerAuthenticationStateProvider>();
builder.Services.AddHttpContextAccessor(); builder.Services.AddHttpContextAccessor();
builder.Services.AddTransient<ITenantProvider, TenantProvider>(); builder.Services.AddTransient<ITenantProvider, TenantProvider>();
File diff suppressed because it is too large Load Diff
+1
View File
@@ -5,4 +5,5 @@ public class UserInfo
public int Id { get; set; } public int Id { get; set; }
public string Username { get; set; } = ""; public string Username { get; set; } = "";
public bool IsTenantAdmin { get; set; } public bool IsTenantAdmin { get; set; }
public bool IsAuthenticated { get; set; }
} }