Added database loading logic
This commit is contained in:
41
.idea/.idea.HopFrame/.idea/workspace.xml
generated
41
.idea/.idea.HopFrame/.idea/workspace.xml
generated
@@ -9,18 +9,19 @@
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="0648788e-7696-4e60-bf12-5d5601f33d8c" name="Changes" comment="Added basic configuration">
|
||||
<change afterPath="$PROJECT_DIR$/src/HopFrame.Core/Services/IHopFrameAuthHandler.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/HopFrame.Web/Components/Layout/HopFrameLayout.razor" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/HopFrame.Web/Components/Layout/HopFrameNavigation.razor" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/HopFrame.Web/Components/Layout/HopFrameSideMenu.razor" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/HopFrame.Web/Components/Pages/HopFrameHome.razor" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/HopFrame.Web/wwwroot/hopframe.css" afterDir="false" />
|
||||
<list default="true" id="0648788e-7696-4e60-bf12-5d5601f33d8c" name="Changes" comment="Added admin page navigation">
|
||||
<change afterPath="$PROJECT_DIR$/src/HopFrame.Core/Services/IModelManager.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/HopFrame.Core/Services/Implementations/ModelManager.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/testing/HopFrame.Testing/Models/Post.cs" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/testing/HopFrame.Testing/Services/AuthService.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/.idea.HopFrame/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.HopFrame/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/HopFrame.Core/Config/HopFrameConfig.cs" beforeDir="false" afterPath="$PROJECT_DIR$/src/HopFrame.Core/Config/HopFrameConfig.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/HopFrame.Web/HopFrame.Web.csproj" beforeDir="false" afterPath="$PROJECT_DIR$/src/HopFrame.Web/HopFrame.Web.csproj" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/HopFrame.Web/ServiceCollectionExtensions.cs" beforeDir="false" afterPath="$PROJECT_DIR$/src/HopFrame.Web/ServiceCollectionExtensions.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/HopFrame.Web/_Imports.razor" beforeDir="false" afterPath="$PROJECT_DIR$/src/HopFrame.Web/_Imports.razor" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/HopFrame.Core/Services/IContextExplorer.cs" beforeDir="false" afterPath="$PROJECT_DIR$/src/HopFrame.Core/Services/IContextExplorer.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/HopFrame.Core/Services/Implementations/ContextExplorer.cs" beforeDir="false" afterPath="$PROJECT_DIR$/src/HopFrame.Core/Services/Implementations/ContextExplorer.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/HopFrame.Web/Components/Layout/HopFrameLayout.razor" beforeDir="false" afterPath="$PROJECT_DIR$/src/HopFrame.Web/Components/Layout/HopFrameLayout.razor" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/HopFrame.Web/Components/Layout/HopFrameNavigation.razor" beforeDir="false" afterPath="$PROJECT_DIR$/src/HopFrame.Web/Components/Layout/HopFrameNavigation.razor" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/testing/HopFrame.Testing/Components/Pages/Home.razor" beforeDir="false" afterPath="$PROJECT_DIR$/testing/HopFrame.Testing/Components/Pages/Home.razor" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/testing/HopFrame.Testing/DatabaseContext.cs" beforeDir="false" afterPath="$PROJECT_DIR$/testing/HopFrame.Testing/DatabaseContext.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/testing/HopFrame.Testing/Models/User.cs" beforeDir="false" afterPath="$PROJECT_DIR$/testing/HopFrame.Testing/Models/User.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/testing/HopFrame.Testing/Program.cs" beforeDir="false" afterPath="$PROJECT_DIR$/testing/HopFrame.Testing/Program.cs" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
@@ -62,6 +63,9 @@
|
||||
"second": "2d65fdcb-5f13-45ad-a7ba-91dd4a88d6e4"
|
||||
}
|
||||
}</component>
|
||||
<component name="HighlightingSettingsPerFile">
|
||||
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/SourcesCache/d858ddb35a8e36df5573b7612542f9ad50f426b8ab43818587d1ac65fab14829/DatabaseGeneratedAttribute.cs" root0="FORCE_HIGHLIGHTING" />
|
||||
</component>
|
||||
<component name="MetaFilesCheckinStateConfiguration" checkMetaFiles="true" />
|
||||
<component name="ProjectColorInfo">{
|
||||
"associatedIndex": 3
|
||||
@@ -140,7 +144,7 @@
|
||||
<workItem from="1736788853462" duration="780000" />
|
||||
<workItem from="1736845367516" duration="283000" />
|
||||
<workItem from="1736845655122" duration="165000" />
|
||||
<workItem from="1736845825812" duration="9326000" />
|
||||
<workItem from="1736845825812" duration="13786000" />
|
||||
</task>
|
||||
<task id="LOCAL-00001" summary="Added basic configuration">
|
||||
<option name="closed" value="true" />
|
||||
@@ -150,7 +154,15 @@
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1736850899254</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="2" />
|
||||
<task id="LOCAL-00002" summary="Added admin page navigation">
|
||||
<option name="closed" value="true" />
|
||||
<created>1736855209077</created>
|
||||
<option name="number" value="00002" />
|
||||
<option name="presentableId" value="LOCAL-00002" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1736855209077</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="3" />
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
@@ -161,6 +173,7 @@
|
||||
<component name="VcsManagerConfiguration">
|
||||
<option name="CLEAR_INITIAL_COMMIT_MESSAGE" value="true" />
|
||||
<MESSAGE value="Added basic configuration" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="Added basic configuration" />
|
||||
<MESSAGE value="Added admin page navigation" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="Added admin page navigation" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -4,5 +4,6 @@ namespace HopFrame.Core.Services;
|
||||
|
||||
public interface IContextExplorer {
|
||||
public IEnumerable<string> GetTableNames();
|
||||
public TableConfig? GetTable(string name);
|
||||
public TableConfig? GetTable(string tableName);
|
||||
public ITableManager? GetTableManager(string tableName);
|
||||
}
|
||||
5
src/HopFrame.Core/Services/ITableManager.cs
Normal file
5
src/HopFrame.Core/Services/ITableManager.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
namespace HopFrame.Core.Services;
|
||||
|
||||
public interface ITableManager {
|
||||
public Task<IEnumerable<object>> LoadPage(int page, int perPage = 25);
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
using HopFrame.Core.Config;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace HopFrame.Core.Services.Implementations;
|
||||
|
||||
internal sealed class ContextExplorer(HopFrameConfig config) : IContextExplorer {
|
||||
internal sealed class ContextExplorer(HopFrameConfig config, IServiceProvider provider) : IContextExplorer {
|
||||
public IEnumerable<string> GetTableNames() {
|
||||
foreach (var context in config.Contexts) {
|
||||
foreach (var table in context.Tables) {
|
||||
@@ -12,13 +13,28 @@ internal sealed class ContextExplorer(HopFrameConfig config) : IContextExplorer
|
||||
}
|
||||
}
|
||||
|
||||
public TableConfig? GetTable(string name) {
|
||||
public TableConfig? GetTable(string tableName) {
|
||||
foreach (var context in config.Contexts) {
|
||||
var table = context.Tables.FirstOrDefault(table => table.PropertyName == name);
|
||||
var table = context.Tables.FirstOrDefault(table => table.PropertyName == tableName);
|
||||
if (table is not null)
|
||||
return table;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ITableManager? GetTableManager(string tableName) {
|
||||
foreach (var context in config.Contexts) {
|
||||
var table = context.Tables.FirstOrDefault(table => table.PropertyName == tableName);
|
||||
if (table is null) continue;
|
||||
|
||||
var dbContext = provider.GetService(context.ContextType) as DbContext;
|
||||
if (dbContext is null) return null;
|
||||
|
||||
var type = typeof(TableManager<>).MakeGenericType(table.TableType);
|
||||
return Activator.CreateInstance(type, dbContext) as ITableManager;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
15
src/HopFrame.Core/Services/Implementations/TableManager.cs
Normal file
15
src/HopFrame.Core/Services/Implementations/TableManager.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace HopFrame.Core.Services.Implementations;
|
||||
|
||||
internal sealed class TableManager<TModel>(DbContext context) : ITableManager where TModel : class {
|
||||
|
||||
public async Task<IEnumerable<object>> LoadPage(int page, int perPage = 25) {
|
||||
var table = context.Set<TModel>();
|
||||
return await table
|
||||
.Skip(page * perPage)
|
||||
.Take(perPage)
|
||||
.ToArrayAsync();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
@using HopFrame.Core.Config
|
||||
@using HopFrame.Core.Services
|
||||
@using Microsoft.Extensions.DependencyInjection
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
<link rel="stylesheet" type='text/css' href="https://cdn.jsdelivr.net/gh/devicons/devicon@latest/devicon.min.css" />
|
||||
@@ -29,19 +30,16 @@
|
||||
</FluentFooter>
|
||||
</FluentLayout>
|
||||
|
||||
@inject IServiceProvider Provider
|
||||
@inject IHopFrameAuthHandler Handler
|
||||
@inject HopFrameConfig Config
|
||||
@inject NavigationManager Navigator
|
||||
|
||||
@code {
|
||||
|
||||
protected override async Task OnInitializedAsync() {
|
||||
if (!string.IsNullOrEmpty(Config.BasePolicy)) {
|
||||
var handler = Provider.GetService(Config.AuthHandler!) as IHopFrameAuthHandler;
|
||||
var authorized = await handler!.IsAuthenticatedAsync(Config.BasePolicy);
|
||||
if (!authorized) {
|
||||
Navigator.NavigateTo((Config.LoginPageRewrite ?? "/login") + "?redirect=" + Navigator.Uri);
|
||||
}
|
||||
var authorized = await Handler.IsAuthenticatedAsync(Config.BasePolicy);
|
||||
if (!authorized) {
|
||||
Navigator.NavigateTo((Config.LoginPageRewrite ?? "/login") + "?redirect=/" + Navigator.ToBaseRelativePath(Navigator.Uri), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
@using System.Text
|
||||
@using HopFrame.Core.Config
|
||||
@using HopFrame.Core.Services
|
||||
|
||||
<FluentHeader Class="hopframe-header">
|
||||
<a href="/admin" style="text-decoration: none; color: @Color.Neutral.ToAttributeValue()">HopFrame</a>
|
||||
<FluentSpacer/>
|
||||
<a href="/admin" style="text-decoration: none; color: @Color.Neutral.ToAttributeValue();">HopFrame</a>
|
||||
|
||||
@if (Config.DisplayUserInfo) {
|
||||
<FluentPersona Name="@_displayName" Initials="@_initials" ImageSize="32px" TextPosition="TextPosition.Start"/>
|
||||
<FluentPersona Name="@_displayName" Initials="@_initials" ImageSize="32px" TextPosition="TextPosition.Start" Style="margin-left: auto"/>
|
||||
}
|
||||
|
||||
</FluentHeader>
|
||||
|
||||
@inject HopFrameConfig Config
|
||||
@inject IServiceProvider Provider
|
||||
@inject IHopFrameAuthHandler Handler
|
||||
|
||||
@code {
|
||||
|
||||
private string? _displayName;
|
||||
private string? _initials;
|
||||
private string? _searchValue;
|
||||
|
||||
protected override async Task OnInitializedAsync() {
|
||||
if (Config.DisplayUserInfo) {
|
||||
var handler = Provider.GetService(Config.AuthHandler!) as IHopFrameAuthHandler;
|
||||
_displayName = await handler!.GetCurrentUserDisplayNameAsync();
|
||||
_displayName = await Handler.GetCurrentUserDisplayNameAsync();
|
||||
_initials = GetInitials(_displayName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,11 +8,22 @@
|
||||
Welcome to your new Fluent Blazor app.
|
||||
|
||||
@inject IContextExplorer Explorer
|
||||
@inject DatabaseContext Context
|
||||
|
||||
@code {
|
||||
|
||||
protected override void OnInitialized() {
|
||||
Console.WriteLine(string.Join(", ", Explorer.GetTableNames()));
|
||||
protected override async Task OnInitializedAsync() {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
Context.Users.Add(new() {
|
||||
Email = "leon@ladenbau-hoppe.de",
|
||||
Id = Guid.CreateVersion7()
|
||||
});
|
||||
}
|
||||
await Context.SaveChangesAsync();
|
||||
|
||||
var manager = Explorer.GetTableManager("Users");
|
||||
var page = await manager!.LoadPage(0);
|
||||
Console.WriteLine(string.Join(", ", page));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,5 +6,13 @@ namespace HopFrame.Testing;
|
||||
public class DatabaseContext(DbContextOptions<DatabaseContext> options) : DbContext(options) {
|
||||
|
||||
public DbSet<User> Users { get; set; }
|
||||
|
||||
public DbSet<Post> Posts { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder) {
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
modelBuilder.Entity<Post>()
|
||||
.HasOne<User>()
|
||||
.WithMany();
|
||||
}
|
||||
}
|
||||
17
testing/HopFrame.Testing/Models/Post.cs
Normal file
17
testing/HopFrame.Testing/Models/Post.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace HopFrame.Testing.Models;
|
||||
|
||||
public class Post {
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public int Id { get; set; }
|
||||
|
||||
[MaxLength(255)]
|
||||
public required string Caption { get; set; }
|
||||
|
||||
public required string Content { get; set; }
|
||||
|
||||
[ForeignKey("author")]
|
||||
public User? Author { get; set; }
|
||||
}
|
||||
@@ -7,4 +7,8 @@ public class User {
|
||||
public string? Password { get; set; }
|
||||
public string? FirstName { get; set; }
|
||||
public string? LastName { get; set; }
|
||||
|
||||
public override string ToString() {
|
||||
return Id.ToString();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
using HopFrame.Core.Services;
|
||||
using HopFrame.Testing;
|
||||
using Microsoft.FluentUI.AspNetCore.Components;
|
||||
using HopFrame.Testing.Components;
|
||||
using HopFrame.Testing.Services;
|
||||
using HopFrame.Web;
|
||||
using HopFrame.Web.Components.Pages;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@@ -17,10 +19,12 @@ builder.Services.AddDbContext<DatabaseContext>(options => {
|
||||
});
|
||||
|
||||
builder.Services.AddHopFrame(options => {
|
||||
options.DisplayUserInfo(false);
|
||||
options.SetAuthHandler<AuthService>();
|
||||
options.AddDbContext<DatabaseContext>();
|
||||
});
|
||||
|
||||
builder.Services.AddTransient<IHopFrameAuthHandler, AuthService>();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
|
||||
12
testing/HopFrame.Testing/Services/AuthService.cs
Normal file
12
testing/HopFrame.Testing/Services/AuthService.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using HopFrame.Core.Services;
|
||||
|
||||
namespace HopFrame.Testing.Services;
|
||||
|
||||
public class AuthService : IHopFrameAuthHandler {
|
||||
public Task<bool> IsAuthenticatedAsync(string? policy) {
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
public Task<string> GetCurrentUserDisplayNameAsync() {
|
||||
return Task.FromResult("Leon Hoppe");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user