KIT!
ce3795bb50
Don't break Access codes into groups of 4 if they aren't a multiple of 4 or if they aren't hexadecimal only (This is useful if a user only uses a nickname as an access code and not a card id) Changed color of is-current-user on the leaderboard so text is legible in dark mode. Made Leaderboard useable on mobile as well by removing responsive breakpoints.
255 lines
10 KiB
Plaintext
255 lines
10 KiB
Plaintext
@using System.Text.Json
|
|
@using TaikoWebUI.Pages.Dialogs;
|
|
@inject Utilities.StringUtil StringUtil;
|
|
@inject IDialogService DialogService;
|
|
@inject AuthService AuthService;
|
|
@inject HttpClient Client
|
|
@inject NavigationManager NavigationManager
|
|
|
|
|
|
@if (User is not null)
|
|
{
|
|
<MudCard Outlined="true">
|
|
<MudCardHeader>
|
|
<CardHeaderContent>
|
|
<div style="display:flex;flex-wrap:wrap;align-items:center;gap:5px;">
|
|
@if (UserSetting is not null)
|
|
{
|
|
<MudText Typo="Typo.h6" Style="font-weight:bold;word-break:break-all">@UserSetting?.MyDonName</MudText>
|
|
} else
|
|
{
|
|
<MudSkeleton Width="35%" Height="32px" />
|
|
}
|
|
|
|
@if (AuthService.LoginRequired && User?.IsAdmin == true)
|
|
{
|
|
<MudChip Variant="Variant.Outlined" Color="Color.Info" Size="Size.Small" Icon="@Icons.Material.TwoTone.AdminPanelSettings">@Localizer["Admin"]</MudChip>
|
|
}
|
|
</div>
|
|
<MudText Typo="Typo.caption">@Localizer["User ID"]: @User?.Baid</MudText>
|
|
</CardHeaderContent>
|
|
<CardHeaderActions>
|
|
<MudMenu Icon="@Icons.Material.Filled.MoreVert" Dense="true" AnchorOrigin="Origin.BottomLeft"
|
|
TransformOrigin="Origin.TopLeft" Size="Size.Small">
|
|
<MudMenuItem Icon="@Icons.Material.Filled.QrCode"
|
|
OnClick="@(_ => ShowQrCode(User))"
|
|
OnTouch="@(_ => ShowQrCode(User))"
|
|
IconColor="@Color.Primary">
|
|
@Localizer["Show QR Code"]
|
|
</MudMenuItem>
|
|
<MudDivider />
|
|
<MudMenuItem Icon="@Icons.Material.Filled.FeaturedPlayList"
|
|
Href="@($"Users/{User.Baid}/AccessCode")"
|
|
IconColor="@Color.Primary">
|
|
@Localizer["Access Codes"]
|
|
</MudMenuItem>
|
|
<MudDivider />
|
|
@if (AuthService.OnlyAdmin || AuthService.LoginRequired)
|
|
{
|
|
<MudMenuItem Icon="@Icons.Material.Filled.Lock"
|
|
Href="@($"/ChangePassword")"
|
|
IconColor="@Color.Primary">
|
|
@Localizer["Change Password"]
|
|
</MudMenuItem>
|
|
<MudDivider />
|
|
}
|
|
@if (AuthService.LoginRequired && AuthService.IsAdmin)
|
|
{
|
|
<MudMenuItem Icon="@Icons.Material.Filled.Password"
|
|
OnClick="@(_ => GenerateInviteCode(User.Baid))"
|
|
OnTouch="@(_ => GenerateInviteCode(User.Baid))"
|
|
IconColor="@Color.Primary">
|
|
@Localizer["Generate Invite Code"]
|
|
</MudMenuItem>
|
|
<MudDivider />
|
|
}
|
|
@if (AuthService.LoginRequired && AuthService.IsAdmin)
|
|
{
|
|
<MudMenuItem Icon="@Icons.Material.Filled.LockReset"
|
|
OnClick="@(_ => ResetPassword(User))"
|
|
OnTouch="@(_ => ResetPassword(User))"
|
|
IconColor="@Color.Primary">
|
|
@Localizer["Unregister"]
|
|
</MudMenuItem>
|
|
<MudDivider />
|
|
}
|
|
@if (AuthService.AllowUserDelete)
|
|
{
|
|
<MudMenuItem Icon="@Icons.Material.Filled.Delete"
|
|
OnClick="@(_ => DeleteUser(User))"
|
|
OnTouch="@(_ => DeleteUser(User))"
|
|
IconColor="@Color.Error">
|
|
@Localizer["Delete User"]
|
|
</MudMenuItem>
|
|
}
|
|
</MudMenu>
|
|
</CardHeaderActions>
|
|
</MudCardHeader>
|
|
<MudCardContent>
|
|
<MudText Typo="Typo.body2" Style="font-weight:bold">@Localizer["Access Code"]</MudText>
|
|
<MudText Style="font-family:monospace;overflow:hidden;overflow-x:scroll">
|
|
@if (User.AccessCodes.Count > 0)
|
|
{
|
|
@if (User.AccessCodes[0].Length % 4 == 0 && StringUtil.OnlyHexInString(User.AccessCodes[0]))
|
|
{
|
|
foreach (var digitGroup in StringUtil.SplitIntoGroups(User.AccessCodes[0], 4))
|
|
{
|
|
<span class="mr-2">@digitGroup</span>
|
|
}
|
|
}
|
|
else
|
|
{
|
|
<span class="mr-2">@User.AccessCodes[0]</span>
|
|
}
|
|
} else
|
|
{
|
|
<span class="mr-2">@Localizer["N/A"]</span>
|
|
}
|
|
</MudText>
|
|
@if (User.AccessCodes.Count > 1)
|
|
{
|
|
<MudText Typo="Typo.caption">... @Localizer["And"] @(User.AccessCodes.Count - 1) @Localizer["other access code(s)"]</MudText>
|
|
}
|
|
else
|
|
{
|
|
// Empty line to keep the layout consistent
|
|
<MudText Typo="Typo.caption"> </MudText>
|
|
}
|
|
</MudCardContent>
|
|
<MudCardActions>
|
|
<MudStack Row="true" Style="width:100%" Spacing="4" Justify="Justify.FlexEnd">
|
|
<MudButton Href="@($"Users/{User.Baid}/Profile")"
|
|
Size="Size.Small" Variant="Variant.Text" StartIcon="@Icons.Material.Filled.Edit"
|
|
Color="Color.Primary">
|
|
@Localizer["Edit Profile"]
|
|
</MudButton>
|
|
<MudMenu Size="Size.Small"
|
|
Dense="true"
|
|
Color="Color.Primary"
|
|
Label="@Localizer["View Play Data"]"
|
|
StartIcon="@Icons.Material.Filled.EmojiEvents"
|
|
EndIcon="@Icons.Material.Filled.KeyboardArrowDown"
|
|
FullWidth="true"
|
|
AnchorOrigin="Origin.BottomCenter"
|
|
TransformOrigin="Origin.TopCenter">
|
|
<MudMenuItem Href="@($"Users/{User.Baid}/HighScores")">@Localizer["High Scores"]</MudMenuItem>
|
|
<MudMenuItem Href="@($"Users/{User.Baid}/PlayHistory")">@Localizer["Play History"]</MudMenuItem>
|
|
<MudMenuItem Href="@($"Users/{User.Baid}/Songs")">@Localizer["Song List"]</MudMenuItem>
|
|
<MudMenuItem Href="@($"Users/{User.Baid}/DaniDojo")">@Localizer["Dani Dojo"]</MudMenuItem>
|
|
</MudMenu>
|
|
</MudStack>
|
|
</MudCardActions>
|
|
</MudCard>
|
|
}
|
|
|
|
@code {
|
|
[Parameter] public User? User { get; set; }
|
|
[Parameter] public UserSetting? UserSetting { get; set; }
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
await base.OnInitializedAsync();
|
|
}
|
|
|
|
private Task ShowQrCode(User user)
|
|
{
|
|
var parameters = new DialogParameters
|
|
{
|
|
["user"] = user
|
|
};
|
|
|
|
var options = new DialogOptions { DisableBackdropClick = true };
|
|
DialogService.Show<UserQrCodeDialog>(Localizer["QR Code"], parameters, options);
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private async Task ResetPassword(User user)
|
|
{
|
|
var options = new DialogOptions { DisableBackdropClick = true };
|
|
if (AuthService.LoginRequired && !AuthService.IsAdmin)
|
|
{
|
|
await DialogService.ShowMessageBox(
|
|
Localizer["Error"],
|
|
"Only admin can reset password.",
|
|
Localizer["Dialog OK"], null, null, options);
|
|
return;
|
|
}
|
|
var parameters = new DialogParameters
|
|
{
|
|
["user"] = user
|
|
};
|
|
|
|
var dialog = await DialogService.ShowAsync<ResetPasswordConfirmDialog>(Localizer["Reset Password"], parameters, options);
|
|
await dialog.Result;
|
|
}
|
|
|
|
private async Task DeleteUser(User user)
|
|
{
|
|
var options = new DialogOptions { DisableBackdropClick = true };
|
|
if (!AuthService.AllowUserDelete)
|
|
{
|
|
await DialogService.ShowMessageBox(
|
|
Localizer["Error"],
|
|
"User deletion is disabled by admin.",
|
|
Localizer["Dialog OK"], null, null, options);
|
|
return;
|
|
}
|
|
var parameters = new DialogParameters
|
|
{
|
|
["user"] = user
|
|
};
|
|
|
|
var dialog = await DialogService.ShowAsync<UserDeleteConfirmDialog>(Localizer["Delete User"], parameters, options);
|
|
var result = await dialog.Result;
|
|
|
|
if (result.Canceled) return;
|
|
|
|
if (user.Baid == AuthService.GetLoggedInBaid())
|
|
{
|
|
await AuthService.Logout();
|
|
}
|
|
|
|
NavigationManager.NavigateTo("/Users");
|
|
}
|
|
|
|
private async Task GenerateInviteCode(uint baid)
|
|
{
|
|
var request = new GenerateOtpRequest
|
|
{
|
|
Baid = baid
|
|
};
|
|
|
|
var responseMessage = await Client.PostAsJsonAsync("api/Auth/GenerateOtp", request);
|
|
|
|
if (!responseMessage.IsSuccessStatusCode)
|
|
{
|
|
await DialogService.ShowMessageBox(
|
|
Localizer["Error"],
|
|
Localizer["Unknown Error"],
|
|
Localizer["Dialog OK"], null, null, new DialogOptions { DisableBackdropClick = true });
|
|
return;
|
|
}
|
|
|
|
var responseContent = await responseMessage.Content.ReadAsStringAsync();
|
|
var responseJson = JsonSerializer.Deserialize<Dictionary<string, string>>(responseContent);
|
|
if (responseJson == null)
|
|
{
|
|
await DialogService.ShowMessageBox(
|
|
Localizer["Error"],
|
|
Localizer["Unknown Error"],
|
|
Localizer["Dialog OK"], null, null, new DialogOptions { DisableBackdropClick = true });
|
|
return;
|
|
}
|
|
|
|
var otp = responseJson["otp"];
|
|
|
|
var parameters = new DialogParameters
|
|
{
|
|
["otp"] = otp
|
|
};
|
|
|
|
var options = new DialogOptions { DisableBackdropClick = true };
|
|
await DialogService.ShowAsync<OTPDialog>(Localizer["Invite Code"], parameters, options);
|
|
}
|
|
} |