-
-
@(Text)
+
}
@@ -17,7 +19,7 @@ else
{
- @(Text)
+ @(Text)
}
}
diff --git a/Moonlight/Shared/Components/Partials/Tooltip.razor b/Moonlight/Shared/Components/Partials/Tooltip.razor
new file mode 100644
index 0000000..416a37a
--- /dev/null
+++ b/Moonlight/Shared/Components/Partials/Tooltip.razor
@@ -0,0 +1,9 @@
+
+ @ChildContent
+
+
+@code
+{
+ [Parameter]
+ public RenderFragment ChildContent { get; set; }
+}
diff --git a/Moonlight/Shared/Views/Admin/Community/Filter.razor b/Moonlight/Shared/Views/Admin/Community/Filter.razor
index 567dd7b..e8b3e27 100644
--- a/Moonlight/Shared/Views/Admin/Community/Filter.razor
+++ b/Moonlight/Shared/Views/Admin/Community/Filter.razor
@@ -9,12 +9,12 @@
@attribute [RequirePermission(Permission.AdminCommunity)]
-
+
-
- To protect from trollers and toxic people you can configure words using
+
+ To protect from trollers and toxic people you can configure words using
regex expressions to block automatically to ensure no one can write bad things in the community tab.
-
+
diff --git a/Moonlight/Shared/Views/Admin/Users/Index.razor b/Moonlight/Shared/Views/Admin/Users/Index.razor
index 5b8ea12..a73473c 100644
--- a/Moonlight/Shared/Views/Admin/Users/Index.razor
+++ b/Moonlight/Shared/Views/Admin/Users/Index.razor
@@ -11,7 +11,7 @@
-
+
-
+
- @(context.Email)
+ @(context.Username)
-
+
@(Formatter.FormatDate(context.CreatedAt))
diff --git a/Moonlight/Shared/Views/Admin/Users/Sessions.razor b/Moonlight/Shared/Views/Admin/Users/Sessions.razor
index adfc0bd..dab5f2e 100644
--- a/Moonlight/Shared/Views/Admin/Users/Sessions.razor
+++ b/Moonlight/Shared/Views/Admin/Users/Sessions.razor
@@ -12,7 +12,11 @@
-
+
+ This list shows you every user connected to this moonlight instance. Its updated in realtime
+
+
+
-
+
+
+ @(context.Url)
+
+
- @(context.User?.Username ?? "Guest")
+ @if (context.User == null)
+ {
+ Guest
+ }
+ else
+ {
+ @(context.User.Username)
+ }
diff --git a/Moonlight/Shared/Views/Admin/Users/View.razor b/Moonlight/Shared/Views/Admin/Users/View.razor
new file mode 100644
index 0000000..548adb5
--- /dev/null
+++ b/Moonlight/Shared/Views/Admin/Users/View.razor
@@ -0,0 +1,237 @@
+@page "/admin/users/view/{Id:int}"
+
+@using Moonlight.App.Extensions.Attributes
+@using Moonlight.App.Models.Enums
+@using Moonlight.App.Repositories
+@using Microsoft.EntityFrameworkCore
+@using Moonlight.App.Database.Entities.Store
+@using Moonlight.App.Models.Forms.Admin.Users
+@using Moonlight.App.Services
+@using Mappy.Net
+@using BlazorTable
+@using Moonlight.App.Services.Users
+
+@attribute [RequirePermission(Permission.AdminUsers)]
+
+@inject Repository UserRepository
+@inject Repository ServiceRepository
+@inject SessionService SessionService
+@inject UserService UserService
+@inject ToastService ToastService
+@inject ConfigService ConfigService
+@inject NavigationManager Navigation
+
+
+ @if (User == null)
+ {
+
+ }
+ else
+ {
+
+
+
+
+
+
+
+
+ New password
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Online status
+ @if (Online)
+ {
+
Online
+ }
+ else
+ {
+
Offline
+ }
+
+
+
Registered at
+
+ @Formatter.FormatDate(User.CreatedAt)
+
+
+
+
+
+
+
+
+
+
+ @if (context.Price == 0)
+ {
+
+ }
+ else if (context.Price < 0)
+ {
+
+ }
+ else
+ {
+
+ }
+
+
+
+
+ @(ConfigService.Get().Store.Currency) @(Math.Abs(context.Price))
+
+
+
+
+
+
+
+
+
+
+ }
+
+
+@code
+{
+ [Parameter]
+ public int Id { get; set; }
+
+ private User? User;
+ private bool Online;
+ private Service[] Services;
+ private Transaction[] Transactions;
+
+ private UpdateUserForm UserForm;
+ private UpdateUserPasswordForm PasswordForm = new();
+
+ private async Task Load(LazyLoader lazyLoader) // We use the text feature here because users have a lot of data related to them
+ {
+ await lazyLoader.SetText("Loading user");
+ User = UserRepository
+ .Get()
+ .Include(x => x.Transactions)
+ .Include(x => x.CouponUses)
+ .Include(x => x.GiftCodeUses)
+ .FirstOrDefault(x => x.Id == Id);
+
+ if (User != null)
+ {
+ UserForm = Mapper.Map(User);
+
+ await lazyLoader.SetText("Checking online status");
+ Online = SessionService
+ .GetSessions()
+ .Where(x => x.User != null)
+ .Any(x => x.User!.Id == User.Id);
+
+ await lazyLoader.SetText("Loading user services");
+ Services = ServiceRepository
+ .Get()
+ .Include(x => x.Product)
+ .Where(x => x.Owner.Id == User.Id)
+ .ToArray();
+
+ await lazyLoader.SetText("Sorting transactions");
+ Transactions = User.Transactions
+ .OrderByDescending(x => x.Id)
+ .ToArray();
+ }
+ }
+
+ private async Task UpdateUser()
+ {
+ await UserService.Update(User!, UserForm.Username, UserForm.Email);
+ await ToastService.Success("Successfully updated user");
+ }
+
+ private async Task UpdatePassword()
+ {
+ await UserService.Auth.ChangePassword(User!, PasswordForm.Password);
+ await ToastService.Success("Successfully updated user password");
+ }
+
+ private async Task Delete()
+ {
+ await UserService.Delete(User!);
+ await ToastService.Success("Successfully deleted user");
+ Navigation.NavigateTo("/admin/users");
+ }
+}
\ No newline at end of file
diff --git a/Moonlight/_Imports.razor b/Moonlight/_Imports.razor
index dba000c..2d55684 100644
--- a/Moonlight/_Imports.razor
+++ b/Moonlight/_Imports.razor
@@ -1,11 +1,13 @@
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.JSInterop
-@using Moonlight
+
+@using Moonlight.App.Services.Interop
+@using Moonlight.App.Exceptions
+@using Moonlight.App.Database.Entities
@using Moonlight.App.Helpers
+
@using Moonlight.Shared.Components.Partials
@using Moonlight.Shared.Components.Forms
@using Moonlight.Shared.Components.Navigations
-@using Moonlight.App.Services.Interop
-@using Moonlight.App.Exceptions
-@using Moonlight.App.Database.Entities
\ No newline at end of file
+@using Moonlight.Shared.Components.Alerts
\ No newline at end of file
diff --git a/Moonlight/wwwroot/svg/nodata.svg b/Moonlight/wwwroot/svg/nodata.svg
new file mode 100644
index 0000000..acdce06
--- /dev/null
+++ b/Moonlight/wwwroot/svg/nodata.svg
@@ -0,0 +1 @@
+
\ No newline at end of file