Skip to content

Commit 52c41ec

Browse files
authored
feat(templates): add current user cascading parameter to Boilerplate #10913 (#10915)
1 parent 1fffc8f commit 52c41ec

File tree

23 files changed

+247
-247
lines changed

23 files changed

+247
-247
lines changed

src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Layout/AppAiChatPanel.razor

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
Variant="BitVariant.Outline"
1414
OnClick="() => isOpen = true"
1515
FloatPosition="BitPosition.BottomRight"
16-
IconUrl="@($"_content/Boilerplate.Client.Core/images/icons/ai-icon-{currentTheme?.ToString().ToLower()}.png")" />
16+
IconUrl="@($"_content/Boilerplate.Client.Core/images/icons/ai-icon-{CurrentTheme?.ToString().ToLower()}.png")" />
1717

1818
<BitProPanel ShowCloseButton
1919
@bind-IsOpen="isOpen"
@@ -120,7 +120,7 @@
120120
OnClick="WrapHandled(SendMessage)"
121121
Title="@Localizer[nameof(AppStrings.Send)]"
122122
IsEnabled=@(string.IsNullOrEmpty(userInput) is false)
123-
IconName="@(currentDir is BitDir.Rtl ? BitIconName.SendMirrored : BitIconName.Send)" />
123+
IconName="@(CurrentDir is BitDir.Rtl ? BitIconName.SendMirrored : BitIconName.Send)" />
124124
</BitStack>
125125
</BitStack>
126126
</Body>

src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Layout/AppAiChatPanel.razor.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ public partial class AppAiChatPanel
2828

2929

3030
[CascadingParameter(Name = Parameters.CurrentTheme)]
31-
private AppThemeType? currentTheme { get; set; }
31+
public AppThemeType? CurrentTheme { get; set; }
3232

33-
[CascadingParameter]
34-
private BitDir? currentDir { get; set; }
33+
[CascadingParameter(Name = Parameters.CurrentDir)]
34+
public BitDir? CurrentDir { get; set; }
3535

3636

3737
protected override Task OnInitAsync()

src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Layout/AppMenu.razor

Lines changed: 65 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -6,72 +6,72 @@
66
Classes="@(new() { Callout = "app-menu-callout" })">
77
<Template>
88
<BitIcon IconName="@BitIconName.ChevronDown" Size="BitSize.Small" Color="BitColor.Info" Class="menu-chevron" />
9-
@if (isAuthenticated is true)
10-
{
11-
<BitText Class="menu-displayname">@user.DisplayName</BitText>
12-
<BitPersona Class="persona"
13-
ImageUrl="@ProfileImageUrl"
14-
Size=@BitPersonaSize.Size32
15-
PrimaryText="@user.DisplayName"
16-
Classes="@(new() { DetailsContainer = "persona-details" })"
17-
Presence="@(IsOnline is null ? BitPersonaPresence.None : IsOnline is true ? BitPersonaPresence.Online : BitPersonaPresence.Offline)" />
18-
}
19-
else if (isAuthenticated is false)
20-
{
21-
<BitPersona Class="persona"
22-
Size=@BitPersonaSize.Size32
23-
CoinVariant="BitVariant.Text"
24-
Classes="@(new() { DetailsContainer = "persona-details" })"
25-
Presence="@(IsOnline is null ? BitPersonaPresence.None : IsOnline is true ? BitPersonaPresence.Online : BitPersonaPresence.Offline)">
26-
<CoinTemplate>
27-
<BitIcon IconName="@BitIconName.Contact" Size="BitSize.Small" Color="BitColor.Info" Class="menu-icon" />
28-
</CoinTemplate>
29-
</BitPersona>
30-
}
9+
<AuthorizeView>
10+
<Authorized>
11+
<BitText Class="menu-displayname">@CurrentUser?.DisplayName</BitText>
12+
<BitPersona Class="persona"
13+
ImageUrl="@ProfileImageUrl"
14+
Size=@BitPersonaSize.Size32
15+
PrimaryText="@CurrentUser?.DisplayName"
16+
Classes="@(new() { DetailsContainer = "persona-details" })"
17+
Presence="@(IsOnline is null ? BitPersonaPresence.None : IsOnline is true ? BitPersonaPresence.Online : BitPersonaPresence.Offline)" />
18+
</Authorized>
19+
<NotAuthorized>
20+
<BitPersona Class="persona"
21+
Size=@BitPersonaSize.Size32
22+
CoinVariant="BitVariant.Text"
23+
Classes="@(new() { DetailsContainer = "persona-details" })"
24+
Presence="@(IsOnline is null ? BitPersonaPresence.None : IsOnline is true ? BitPersonaPresence.Online : BitPersonaPresence.Offline)">
25+
<CoinTemplate>
26+
<BitIcon IconName="@BitIconName.Contact" Size="BitSize.Small" Color="BitColor.Info" Class="menu-icon" />
27+
</CoinTemplate>
28+
</BitPersona>
29+
</NotAuthorized>
30+
</AuthorizeView>
3131
</Template>
3232
<Body>
3333
<BitCard FullSize Class="app-menu-card">
3434
@if (showCultures is false)
3535
{
3636
<BitStack AutoSize>
37-
@if (isAuthenticated is true)
38-
{
39-
<BitPersona Class="persona"
40-
ImageUrl="@ProfileImageUrl"
41-
OnImageClick="GoToProfile"
42-
Size="BitPersonaSize.Size48"
43-
PrimaryText="@user.DisplayName"
44-
SecondaryText="@(user.Email ?? user.PhoneNumber)"
45-
Presence="@(IsOnline is null ? BitPersonaPresence.None : IsOnline is true ? BitPersonaPresence.Online : BitPersonaPresence.Offline)">
46-
<ImageOverlayTemplate>
47-
<span>@Localizer[nameof(AppStrings.Edit)]</span>
48-
</ImageOverlayTemplate>
49-
</BitPersona>
37+
<AuthorizeView>
38+
<Authorized>
39+
<BitPersona Class="persona"
40+
ImageUrl="@ProfileImageUrl"
41+
OnImageClick="GoToProfile"
42+
Size="BitPersonaSize.Size48"
43+
PrimaryText="@CurrentUser?.DisplayName"
44+
SecondaryText="@(CurrentUser?.Email ?? CurrentUser?.PhoneNumber)"
45+
Presence="@(IsOnline is null ? BitPersonaPresence.None : IsOnline is true ? BitPersonaPresence.Online : BitPersonaPresence.Offline)">
46+
<ImageOverlayTemplate>
47+
<span>@Localizer[nameof(AppStrings.Edit)]</span>
48+
</ImageOverlayTemplate>
49+
</BitPersona>
5050

51-
<BitSeparator />
51+
<BitSeparator />
5252

53-
<BitActionButton IconName="@BitIconName.Contact" Href="@($"{Urls.SettingsPage}/{Urls.SettingsSections.Profile}")" FullWidth OnClick="() => isOpen = false">
54-
@Localizer[nameof(AppStrings.ProfileTitle)]
55-
</BitActionButton>
56-
}
57-
else if (isAuthenticated is false)
58-
{
59-
<BitActionButton FullWidth
60-
IconName="@BitIconName.Signin"
61-
Href="@($"{Urls.SignInPage}?return-url={Uri.EscapeDataString(NavigationManager.GetRelativePath())}")">
62-
@Localizer[nameof(AppStrings.SignIn)]
63-
</BitActionButton>
64-
<BitActionButton FullWidth
65-
IconName="@BitIconName.UserWindow"
66-
OnClick="WrapHandled(ModalSignIn)">
67-
@Localizer[nameof(AppStrings.SignInByModal)]
68-
</BitActionButton>
69-
<BitActionButton FullWidth
70-
IconName="@BitIconName.AddFriend"
71-
Href="@($"{Urls.SignUpPage}?return-url={Uri.EscapeDataString(NavigationManager.GetRelativePath())}")">
72-
@Localizer[nameof(AppStrings.SignUp)]
73-
</BitActionButton>
74-
}
53+
<BitActionButton IconName="@BitIconName.Contact" Href="@($"{Urls.SettingsPage}/{Urls.SettingsSections.Profile}")" FullWidth OnClick="() => isOpen = false">
54+
@Localizer[nameof(AppStrings.ProfileTitle)]
55+
</BitActionButton>
56+
</Authorized>
57+
<NotAuthorized>
58+
<BitActionButton FullWidth
59+
IconName="@BitIconName.Signin"
60+
Href="@($"{Urls.SignInPage}?return-url={Uri.EscapeDataString(NavigationManager.GetRelativePath())}")">
61+
@Localizer[nameof(AppStrings.SignIn)]
62+
</BitActionButton>
63+
<BitActionButton FullWidth
64+
IconName="@BitIconName.UserWindow"
65+
OnClick="WrapHandled(ModalSignIn)">
66+
@Localizer[nameof(AppStrings.SignInByModal)]
67+
</BitActionButton>
68+
<BitActionButton FullWidth
69+
IconName="@BitIconName.AddFriend"
70+
Href="@($"{Urls.SignUpPage}?return-url={Uri.EscapeDataString(NavigationManager.GetRelativePath())}")">
71+
@Localizer[nameof(AppStrings.SignUp)]
72+
</BitActionButton>
73+
</NotAuthorized>
74+
</AuthorizeView>
7575

7676
@if (CultureInfoManager.InvariantGlobalization is false)
7777
{
@@ -81,29 +81,28 @@
8181
<BitSpacer />
8282
<BitIcon Size="BitSize.Small"
8383
Color="BitColor.SecondaryForeground"
84-
IconName="@(currentDir is BitDir.Rtl ? BitIconName.ChevronLeft : BitIconName.ChevronRight)" />
84+
IconName="@(CurrentDir is BitDir.Rtl ? BitIconName.ChevronLeft : BitIconName.ChevronRight)" />
8585
</BitStack>
8686
</BitActionButton>
8787
}
8888

8989
<BitStack Horizontal VerticalAlign="BitAlignment.Center" Gap="0">
9090
<BitActionButton Style="flex-grow:1"
9191
OnClick="ToggleTheme"
92-
IconName="@(currentTheme == AppThemeType.Light ? BitIconName.Sunny : BitIconName.ClearNight)">
93-
@(currentTheme == AppThemeType.Light ? Localizer[nameof(AppStrings.Light)] : Localizer[nameof(AppStrings.Dark)])
92+
IconName="@(CurrentTheme == AppThemeType.Light ? BitIconName.Sunny : BitIconName.ClearNight)">
93+
@(CurrentTheme == AppThemeType.Light ? Localizer[nameof(AppStrings.Light)] : Localizer[nameof(AppStrings.Dark)])
9494
</BitActionButton>
95-
<BitToggle OnChange="ToggleTheme" Value="currentTheme == AppThemeType.Light" ValueChanged="v => { }" />
95+
<BitToggle OnChange="ToggleTheme" Value="CurrentTheme == AppThemeType.Light" ValueChanged="v => { }" />
9696
</BitStack>
9797

98-
@if (isAuthenticated is true)
99-
{
98+
<AuthorizeView>
10099
<BitActionButton FullWidth
101100
Color="BitColor.Error"
102101
IconName="@BitIconName.SignOut"
103102
OnClick="() => { isSignOutConfirmOpen = true; isOpen = false; }">
104103
@Localizer[nameof(AppStrings.SignOut)]
105104
</BitActionButton>
106-
}
105+
</AuthorizeView>
107106
</BitStack>
108107
}
109108
else
@@ -112,7 +111,7 @@
112111
<BitActionButton FullWidth
113112
Style="align-items:flex-end"
114113
OnClick="() => showCultures = false"
115-
IconName="@(currentDir is BitDir.Rtl ? BitIconName.ChromeBackMirrored : BitIconName.ChromeBack)">
114+
IconName="@(CurrentDir is BitDir.Rtl ? BitIconName.ChromeBackMirrored : BitIconName.ChromeBack)">
116115
@Localizer[nameof(AppStrings.SelectLanguage)]
117116
</BitActionButton>
118117

src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Layout/AppMenu.razor.cs

Lines changed: 8 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@ public partial class AppMenu
88
{
99
private bool isOpen;
1010
private bool showCultures;
11-
private bool isAuthenticated;
12-
private UserDto user = new();
1311
private bool isSignOutConfirmOpen;
14-
private Action unsubscribeUerDataUpdated = default!;
1512
private BitChoiceGroupItem<string>[] cultures = default!;
1613

1714
[AutoInject] private Cookie cookie = default!;
@@ -22,18 +19,22 @@ public partial class AppMenu
2219
[AutoInject] private SignInModalService signInModalService = default!;
2320

2421

25-
[CascadingParameter] private BitDir? currentDir { get; set; }
26-
[CascadingParameter(Name = Parameters.CurrentTheme)] private AppThemeType? currentTheme { get; set; }
22+
[CascadingParameter(Name = Parameters.CurrentDir)]
23+
public BitDir? CurrentDir { get; set; }
2724

25+
[CascadingParameter(Name = Parameters.CurrentTheme)]
26+
public AppThemeType? CurrentTheme { get; set; }
2827

29-
private string? ProfileImageUrl => user.GetProfileImageUrl(AbsoluteServerAddress);
28+
[CascadingParameter(Name = Parameters.CurrentUser)]
29+
public UserDto? CurrentUser { get; set; }
30+
31+
private string? ProfileImageUrl => CurrentUser?.GetProfileImageUrl(AbsoluteServerAddress);
3032

3133

3234
protected override async Task OnInitAsync()
3335
{
3436
await base.OnInitAsync();
3537

36-
AuthManager.AuthenticationStateChanged += AuthManager_AuthenticationStateChanged;
3738
NavigationManager.LocationChanged += NavigationManager_LocationChanged;
3839

3940
if (CultureInfoManager.InvariantGlobalization is false)
@@ -42,54 +43,15 @@ protected override async Task OnInitAsync()
4243
.Select(sc => new BitChoiceGroupItem<string> { Value = sc.Culture.Name, Text = sc.DisplayName })
4344
.ToArray();
4445
}
45-
46-
unsubscribeUerDataUpdated = PubSubService.Subscribe(ClientPubSubMessages.PROFILE_UPDATED, async payload =>
47-
{
48-
if (payload is null) return;
49-
50-
user = payload is JsonElement jsonDocument
51-
? jsonDocument.Deserialize(JsonSerializerOptions.GetTypeInfo<UserDto>())! // PROFILE_UPDATED can be invoked from server through SignalR
52-
: (UserDto)payload;
53-
54-
await InvokeAsync(StateHasChanged);
55-
});
56-
57-
await GetCurrentUser(AuthenticationStateTask);
5846
}
5947

60-
6148
private void NavigationManager_LocationChanged(object? sender, LocationChangedEventArgs e)
6249
{
6350
// The sign-in and sign-up buttons href are bound to NavigationManager.GetRelativePath().
6451
// To ensure the bound values update with each route change, it's necessary to call StateHasChanged on location changes.
6552
StateHasChanged();
6653
}
6754

68-
private async void AuthManager_AuthenticationStateChanged(Task<AuthenticationState> task)
69-
{
70-
try
71-
{
72-
await GetCurrentUser(task);
73-
}
74-
catch (Exception ex)
75-
{
76-
ExceptionHandler.Handle(ex);
77-
}
78-
finally
79-
{
80-
await InvokeAsync(StateHasChanged);
81-
}
82-
}
83-
84-
private async Task GetCurrentUser(Task<AuthenticationState> task)
85-
{
86-
isAuthenticated = (await task).User.IsAuthenticated();
87-
if (isAuthenticated)
88-
{
89-
user = await userController.GetCurrentUser(CurrentCancellationToken);
90-
}
91-
}
92-
9355
private async Task OnCultureChanged(string? cultureName)
9456
{
9557
await cultureService.ChangeCulture(cultureName);
@@ -110,9 +72,7 @@ protected override async ValueTask DisposeAsync(bool disposing)
11072
{
11173
await base.DisposeAsync(disposing);
11274

113-
unsubscribeUerDataUpdated?.Invoke();
11475
NavigationManager.LocationChanged -= NavigationManager_LocationChanged;
115-
AuthManager.AuthenticationStateChanged -= AuthManager_AuthenticationStateChanged;
11676
}
11777

11878
private async Task ModalSignIn()

src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Layout/Header.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
@if (showGoBackButton)
1616
{
1717
<BitButton Variant="BitVariant.Text"
18-
IconName="@(currentDir is BitDir.Rtl ? BitIconName.ChromeBackMirrored : BitIconName.ChromeBack)"
18+
IconName="@(CurrentDir is BitDir.Rtl ? BitIconName.ChromeBackMirrored : BitIconName.ChromeBack)"
1919
OnClick="GoBack"
2020
Title="@Localizer[nameof(AppStrings.Back)]" />
2121
}

src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Layout/Header.razor.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using Microsoft.AspNetCore.Components.Routing;
1+
using Microsoft.AspNetCore.Components.Routing;
22

33
namespace Boilerplate.Client.Core.Components.Layout;
44

@@ -9,7 +9,9 @@ public partial class Header : AppComponentBase
99
private bool showGoBackButton;
1010
private Action unsubscribePageTitleChanged = default!;
1111

12-
[CascadingParameter] private BitDir? currentDir { get; set; }
12+
[CascadingParameter(Name = Parameters.CurrentDir)]
13+
public BitDir? CurrentDir { get; set; }
14+
1315

1416
[AutoInject] private History history = default!;
1517

src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Layout/IdentityHeader.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
Variant="BitVariant.Text"
1717
OnClick="WrapHandled(ToggleTheme)"
1818
Color="BitColor.SecondaryBackground"
19-
IconName="@(currentTheme == AppThemeType.Light ? BitIconName.ClearNight : BitIconName.Sunny)" />
19+
IconName="@(CurrentTheme == AppThemeType.Light ? BitIconName.ClearNight : BitIconName.Sunny)" />
2020

2121
@if (CultureInfoManager.InvariantGlobalization is false)
2222
{

src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Layout/IdentityHeader.razor.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ public partial class IdentityHeader : AppComponentBase
1010
[AutoInject] private CultureService cultureService = default!;
1111

1212

13-
[CascadingParameter] private BitDir? currentDir { get; set; }
14-
[CascadingParameter(Name = Parameters.CurrentTheme)] private AppThemeType? currentTheme { get; set; }
13+
[CascadingParameter(Name = Parameters.CurrentDir)]
14+
public BitDir? CurrentDir { get; set; }
15+
16+
[CascadingParameter(Name = Parameters.CurrentTheme)]
17+
public AppThemeType? CurrentTheme { get; set; }
1518

1619

1720
protected override async Task OnInitAsync()

0 commit comments

Comments
 (0)