Added AdminPages to admin dashboard and navigation + created 2.0 todo list
This commit is contained in:
@@ -7,6 +7,14 @@ A simple backend management api for ASP.NET Core Web APIs
|
|||||||
- [x] Permission management
|
- [x] Permission management
|
||||||
- [x] Frontend dashboards
|
- [x] Frontend dashboards
|
||||||
|
|
||||||
|
## 2.0 Todo list
|
||||||
|
- [x] 1.0 bug fixes
|
||||||
|
- [x] Code cleanup
|
||||||
|
- [x] Relations in database
|
||||||
|
- [ ] Generated Admin pages
|
||||||
|
- [ ] Pretty Login page for administration
|
||||||
|
- [ ] Clean documentation
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
There are two different versions of HopFrame, either the Web API version or the full Blazor web version.
|
There are two different versions of HopFrame, either the Web API version or the full Blazor web version.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace HopFrame.Web.Admin.Attributes.Classes;
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public class AdminUrlAttribute(string url) : Attribute {
|
||||||
|
public string Url { get; set; } = url;
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ public interface IAdminPageGenerator<TModel> {
|
|||||||
|
|
||||||
IAdminPageGenerator<TModel> Title(string title);
|
IAdminPageGenerator<TModel> Title(string title);
|
||||||
IAdminPageGenerator<TModel> Description(string description);
|
IAdminPageGenerator<TModel> Description(string description);
|
||||||
|
IAdminPageGenerator<TModel> Url(string url);
|
||||||
|
|
||||||
IAdminPageGenerator<TModel> ViewPermission(string permission);
|
IAdminPageGenerator<TModel> ViewPermission(string permission);
|
||||||
IAdminPageGenerator<TModel> CreatePermission(string permission);
|
IAdminPageGenerator<TModel> CreatePermission(string permission);
|
||||||
|
|||||||
@@ -73,6 +73,11 @@ internal class AdminContextGenerator : IAdminContextGenerator {
|
|||||||
generator.Description(attribute?.Description);
|
generator.Description(attribute?.Description);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (attributes.Any(a => a is AdminUrlAttribute)) {
|
||||||
|
var attribute = attributes.Single(a => a is AdminUrlAttribute) as AdminUrlAttribute;
|
||||||
|
generator.Url(attribute?.Url);
|
||||||
|
}
|
||||||
|
|
||||||
if (attributes.Any(a => a is AdminPermissionsAttribute)) {
|
if (attributes.Any(a => a is AdminPermissionsAttribute)) {
|
||||||
var attribute = attributes.Single(a => a is AdminPermissionsAttribute) as AdminPermissionsAttribute;
|
var attribute = attributes.Single(a => a is AdminPermissionsAttribute) as AdminPermissionsAttribute;
|
||||||
generator.CreatePermission(attribute?.Permissions.Create);
|
generator.CreatePermission(attribute?.Permissions.Create);
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ internal sealed class AdminPageGenerator<TModel> : IAdminPageGenerator<TModel>,
|
|||||||
|
|
||||||
public IAdminPageGenerator<TModel> Title(string title) {
|
public IAdminPageGenerator<TModel> Title(string title) {
|
||||||
_page.Title = title;
|
_page.Title = title;
|
||||||
|
_page.Url ??= title.ToLower();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,6 +48,11 @@ internal sealed class AdminPageGenerator<TModel> : IAdminPageGenerator<TModel>,
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IAdminPageGenerator<TModel> Url(string url) {
|
||||||
|
_page.Url = url;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public IAdminPageGenerator<TModel> ViewPermission(string permission) {
|
public IAdminPageGenerator<TModel> ViewPermission(string permission) {
|
||||||
_page.Permissions.View = permission;
|
_page.Permissions.View = permission;
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ public sealed class AdminPage<TModel> : AdminPage;
|
|||||||
public class AdminPage {
|
public class AdminPage {
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
|
public string Url { get; set; }
|
||||||
public AdminPagePermissions Permissions { get; set; }
|
public AdminPagePermissions Permissions { get; set; }
|
||||||
public IList<AdminPageProperty> Properties { get; set; }
|
public IList<AdminPageProperty> Properties { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
@using BlazorStrap
|
@using BlazorStrap
|
||||||
@using HopFrame.Web.Pages.Administration.Layout
|
@using HopFrame.Web.Pages.Administration.Layout
|
||||||
@using BlazorStrap.V5
|
@using BlazorStrap.V5
|
||||||
|
@using HopFrame.Web.Admin.Providers
|
||||||
@using HopFrame.Web.Components
|
@using HopFrame.Web.Components
|
||||||
@using Microsoft.AspNetCore.Components.Web
|
@using Microsoft.AspNetCore.Components.Web
|
||||||
@layout AdminLayout
|
@layout AdminLayout
|
||||||
@@ -13,15 +14,15 @@
|
|||||||
|
|
||||||
<BSContainer>
|
<BSContainer>
|
||||||
<BSRow Justify="Justify.Center">
|
<BSRow Justify="Justify.Center">
|
||||||
@foreach (var view in AdminMenu.Subpages) {
|
@foreach (var adminPage in Pages.LoadRegisteredAdminPages()) {
|
||||||
<AuthorizedView Permission="@view.Permission">
|
<AuthorizedView Permission="@adminPage.Permissions.View">
|
||||||
<BSCol Column="4" style="margin-bottom: 10px">
|
<BSCol Column="4" style="margin-bottom: 10px">
|
||||||
<BSCard CardType="CardType.Card" Color="BSColor.Dark" style="min-height: 200px">
|
<BSCard CardType="CardType.Card" Color="BSColor.Dark" style="min-height: 200px">
|
||||||
<BSCard CardType="CardType.Body" style="display: flex; flex-direction: column">
|
<BSCard CardType="CardType.Body" style="display: flex; flex-direction: column">
|
||||||
<BSCard CardType="CardType.Title">@view.Name</BSCard>
|
<BSCard CardType="CardType.Title">@adminPage.Title</BSCard>
|
||||||
<BSCard CardType="CardType.Subtitle"><span style="color: gray">@view.Permission</span></BSCard>
|
<BSCard CardType="CardType.Subtitle"><span style="color: gray">@adminPage.Permissions.View</span></BSCard>
|
||||||
<BSCard CardType="CardType.Text">@view.Description</BSCard>
|
<BSCard CardType="CardType.Text">@adminPage.Description</BSCard>
|
||||||
<BSButton IsOutlined="true" MarginTop="Margins.Auto" style="width: max-content; align-self: center" OnClick="() => Navigator.NavigateTo(view.Url, true)" Color="BSColor.Light">Open</BSButton>
|
<BSButton IsOutlined="true" MarginTop="Margins.Auto" style="width: max-content; align-self: center" OnClick="() => NavigateTo(adminPage.Url)" Color="BSColor.Light">Open</BSButton>
|
||||||
</BSCard>
|
</BSCard>
|
||||||
</BSCard>
|
</BSCard>
|
||||||
</BSCol>
|
</BSCol>
|
||||||
@@ -31,3 +32,12 @@
|
|||||||
</BSContainer>
|
</BSContainer>
|
||||||
|
|
||||||
@inject NavigationManager Navigator
|
@inject NavigationManager Navigator
|
||||||
|
@inject IAdminPagesProvider Pages
|
||||||
|
|
||||||
|
@code {
|
||||||
|
|
||||||
|
public void NavigateTo(string url) {
|
||||||
|
Navigator.NavigateTo("administration/" + url, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
@using BlazorStrap
|
@using BlazorStrap
|
||||||
@using BlazorStrap.V5
|
@using BlazorStrap.V5
|
||||||
@using HopFrame.Security.Claims
|
@using HopFrame.Security.Claims
|
||||||
|
@using HopFrame.Web.Admin.Providers
|
||||||
@using HopFrame.Web.Services
|
@using HopFrame.Web.Services
|
||||||
@using static Microsoft.AspNetCore.Components.Web.RenderMode
|
@using static Microsoft.AspNetCore.Components.Web.RenderMode
|
||||||
@using HopFrame.Web.Components.Administration
|
@using HopFrame.Web.Components.Administration
|
||||||
@using HopFrame.Web.Model
|
|
||||||
@using HopFrame.Web.Components
|
@using HopFrame.Web.Components
|
||||||
|
|
||||||
|
|
||||||
@@ -23,9 +23,9 @@
|
|||||||
<BSNav MarginEnd="Margins.Auto" Class="mb-lg-0">
|
<BSNav MarginEnd="Margins.Auto" Class="mb-lg-0">
|
||||||
<BSNavItem IsActive="IsDashboardActive()" OnClick="NavigateToDashboard">Dashboard</BSNavItem>
|
<BSNavItem IsActive="IsDashboardActive()" OnClick="NavigateToDashboard">Dashboard</BSNavItem>
|
||||||
|
|
||||||
@foreach (var nav in Subpages) {
|
@foreach (var adminPage in Pages.LoadRegisteredAdminPages()) {
|
||||||
<AuthorizedView Permission="@nav.Permission">
|
<AuthorizedView Permission="@adminPage.Permissions.View">
|
||||||
<BSNavItem IsActive="IsNavItemActive(nav.Url)" OnClick="() => Navigate(nav.Url)">@nav.Name</BSNavItem>
|
<BSNavItem IsActive="IsNavItemActive(adminPage.Url)" OnClick="() => Navigate(adminPage.Url)">@adminPage.Title</BSNavItem>
|
||||||
</AuthorizedView>
|
</AuthorizedView>
|
||||||
}
|
}
|
||||||
</BSNav>
|
</BSNav>
|
||||||
@@ -46,25 +46,11 @@
|
|||||||
@inject NavigationManager Navigator
|
@inject NavigationManager Navigator
|
||||||
@inject ITokenContext Context
|
@inject ITokenContext Context
|
||||||
@inject IAuthService Auth
|
@inject IAuthService Auth
|
||||||
|
@inject IAdminPagesProvider Pages
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
public static IList<NavigationItem> Subpages = new List<NavigationItem> {
|
|
||||||
new () {
|
|
||||||
Name = "Users",
|
|
||||||
Url = "administration/users",
|
|
||||||
Description = "On this page you can manage all user accounts.",
|
|
||||||
Permission = Security.AdminPermissions.ViewUsers
|
|
||||||
},
|
|
||||||
new () {
|
|
||||||
Name = "Groups",
|
|
||||||
Url = "administration/groups",
|
|
||||||
Description = "On this page you can view, create, edit and delete permission groups.",
|
|
||||||
Permission = Security.AdminPermissions.ViewGroups
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private bool IsNavItemActive(string element) {
|
private bool IsNavItemActive(string element) {
|
||||||
return Navigator.Uri.Contains(element);
|
return Navigator.Uri.TrimEnd('/').EndsWith(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsDashboardActive() {
|
private bool IsDashboardActive() {
|
||||||
@@ -72,11 +58,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void NavigateToDashboard() {
|
private void NavigateToDashboard() {
|
||||||
Navigate("administration");
|
Navigator.NavigateTo("administration", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Navigate(string url) {
|
private void Navigate(string url) {
|
||||||
Navigator.NavigateTo(url, true);
|
Navigator.NavigateTo("administration/" + url, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Logout() {
|
private void Logout() {
|
||||||
|
|||||||
12
test/FrontendTest/AdminContext.cs
Normal file
12
test/FrontendTest/AdminContext.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using HopFrame.Web.Admin;
|
||||||
|
using HopFrame.Web.Admin.Models;
|
||||||
|
using RestApiTest.Models;
|
||||||
|
|
||||||
|
namespace FrontendTest;
|
||||||
|
|
||||||
|
public class AdminContext : AdminPagesContext {
|
||||||
|
|
||||||
|
public AdminPage<Address> Addresses { get; set; }
|
||||||
|
public AdminPage<Employee> Employees { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
18
test/FrontendTest/Models/Address.cs
Normal file
18
test/FrontendTest/Models/Address.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||||
|
|
||||||
|
namespace RestApiTest.Models;
|
||||||
|
|
||||||
|
public class Address {
|
||||||
|
[ForeignKey("Employee")]
|
||||||
|
public int AddressId { get; set; }
|
||||||
|
public string AddressDetails { get; set; }
|
||||||
|
public string City { get; set; }
|
||||||
|
public int ZipCode { get; set; }
|
||||||
|
public string State { get; set; }
|
||||||
|
public string Country { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public virtual Employee Employee { get; set; }
|
||||||
|
}
|
||||||
8
test/FrontendTest/Models/Employee.cs
Normal file
8
test/FrontendTest/Models/Employee.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace RestApiTest.Models;
|
||||||
|
|
||||||
|
public class Employee {
|
||||||
|
public int EmployeeId { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public virtual Address Address { get; set; }
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ var builder = WebApplication.CreateBuilder(args);
|
|||||||
|
|
||||||
builder.Services.AddDbContext<DatabaseContext>();
|
builder.Services.AddDbContext<DatabaseContext>();
|
||||||
builder.Services.AddHopFrame<DatabaseContext>();
|
builder.Services.AddHopFrame<DatabaseContext>();
|
||||||
|
builder.Services.AddAdminContext<AdminContext>();
|
||||||
|
|
||||||
// Add services to the container.
|
// Add services to the container.
|
||||||
builder.Services.AddRazorComponents()
|
builder.Services.AddRazorComponents()
|
||||||
|
|||||||
Reference in New Issue
Block a user