Feature/setup #54

Merged
leon.hoppe merged 17 commits from feature/setup into dev 2025-01-18 13:30:40 +01:00
9 changed files with 71 additions and 41 deletions
Showing only changes of commit c3c69466d4 - Show all commits

View File

@@ -9,17 +9,14 @@
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="0648788e-7696-4e60-bf12-5d5601f33d8c" name="Changes" comment="Added reload button and animation">
<change afterPath="$PROJECT_DIR$/src/HopFrame.Web/Components/Dialogs/HopFrameRelationPicker.razor" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/HopFrame.Web/Models/RelationPickerDialogData.cs" afterDir="false" />
<list default="true" id="0648788e-7696-4e60-bf12-5d5601f33d8c" name="Changes" comment="Added relation picker dialog">
<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/PropertyConfig.cs" beforeDir="false" afterPath="$PROJECT_DIR$/src/HopFrame.Core/Config/PropertyConfig.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/HopFrame.Core/Config/TableConfig.cs" beforeDir="false" afterPath="$PROJECT_DIR$/src/HopFrame.Core/Config/TableConfig.cs" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/HopFrame.Web/Components/Dialogs/HopFrameEditor.razor" beforeDir="false" afterPath="$PROJECT_DIR$/src/HopFrame.Web/Components/Dialogs/HopFrameEditor.razor" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/HopFrame.Web/Components/Pages/HopFrameListView.razor" beforeDir="false" afterPath="$PROJECT_DIR$/src/HopFrame.Web/Components/Pages/HopFrameTablePage.razor" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/HopFrame.Web/Components/Pages/HopFrameListView.razor.css" beforeDir="false" afterPath="$PROJECT_DIR$/src/HopFrame.Web/Components/Pages/HopFrameTablePage.razor.css" 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$/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/Dialogs/HopFrameRelationPicker.razor" beforeDir="false" afterPath="$PROJECT_DIR$/src/HopFrame.Web/Components/Dialogs/HopFrameRelationPicker.razor" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/HopFrame.Web/Components/Pages/HopFrameTablePage.razor" beforeDir="false" afterPath="$PROJECT_DIR$/src/HopFrame.Web/Components/Pages/HopFrameTablePage.razor" 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" />
@@ -154,7 +151,7 @@
<workItem from="1736875984621" duration="8464000" />
<workItem from="1736884461354" duration="1075000" />
<workItem from="1736962119221" duration="8119000" />
<workItem from="1737021098746" duration="13969000" />
<workItem from="1737021098746" duration="16566000" />
</task>
<task id="LOCAL-00001" summary="Added basic configuration">
<option name="closed" value="true" />
@@ -204,7 +201,15 @@
<option name="project" value="LOCAL" />
<updated>1737023058093</updated>
</task>
<option name="localTasksCounter" value="7" />
<task id="LOCAL-00007" summary="Added relation picker dialog">
<option name="closed" value="true" />
<created>1737035288104</created>
<option name="number" value="00007" />
<option name="presentableId" value="LOCAL-00007" />
<option name="project" value="LOCAL" />
<updated>1737035288104</updated>
</task>
<option name="localTasksCounter" value="8" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
@@ -220,6 +225,7 @@
<MESSAGE value="Started working on listing page" />
<MESSAGE value="Added entry saving support" />
<MESSAGE value="Added reload button and animation" />
<option name="LAST_COMMIT_MESSAGE" value="Added reload button and animation" />
<MESSAGE value="Added relation picker dialog" />
<option name="LAST_COMMIT_MESSAGE" value="Added relation picker dialog" />
</component>
</project>

View File

@@ -79,10 +79,4 @@ public class PropertyConfig<TProp>(PropertyConfig config) {
InnerConfig.DisplayValue = display;
return this;
}
public PropertyConfig<TProp> IsRelation(bool isRelation) {
InnerConfig.IsRelation = isRelation;
return this;
}
}

View File

@@ -8,8 +8,10 @@ namespace HopFrame.Core.Config;
public class TableConfig {
public Type TableType { get; }
public string PropertyName { get; }
public string DisplayName { get; set; }
public DbContextConfig ContextConfig { get; }
public bool Ignored { get; set; }
internal bool Seeded { get; set; }
public List<PropertyConfig> Properties { get; } = new();
@@ -17,6 +19,7 @@ public class TableConfig {
TableType = tableType;
PropertyName = propertyName;
ContextConfig = config;
DisplayName = PropertyName;
foreach (var info in tableType.GetProperties()) {
var propConfig = new PropertyConfig(info, this);
@@ -55,6 +58,11 @@ public class TableConfig<TModel>(TableConfig config) {
configurator.Invoke(prop);
return this;
}
public TableConfig<TModel> SetDisplayName(string name) {
InnerConfig.DisplayName = name;
return this;
}
internal static PropertyInfo GetPropertyInfo<TSource, TProperty>(Expression<Func<TSource, TProperty>> propertyLambda) {
if (propertyLambda.Body is not MemberExpression member) {

View File

@@ -4,7 +4,7 @@ namespace HopFrame.Core.Services;
public interface IContextExplorer {
public IEnumerable<string> GetTableNames();
public TableConfig? GetTable(string tableName);
public TableConfig? GetTable(string tableDisplayName);
public TableConfig? GetTable(Type tableEntity);
public ITableManager? GetTableManager(string tableName);
public ITableManager? GetTableManager(string tablePropertyName);
}

View File

@@ -1,23 +1,26 @@
using HopFrame.Core.Config;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace HopFrame.Core.Services.Implementations;
internal sealed class ContextExplorer(HopFrameConfig config, IServiceProvider provider) : IContextExplorer {
internal sealed class ContextExplorer(HopFrameConfig config, IServiceProvider provider, ILogger<ContextExplorer> logger) : IContextExplorer {
public IEnumerable<string> GetTableNames() {
foreach (var context in config.Contexts) {
foreach (var table in context.Tables) {
if (table.Ignored) continue;
yield return table.PropertyName;
yield return table.DisplayName;
}
}
}
public TableConfig? GetTable(string tableName) {
public TableConfig? GetTable(string tableDisplayName) {
foreach (var context in config.Contexts) {
var table = context.Tables.FirstOrDefault(table => table.PropertyName.Equals(tableName, StringComparison.CurrentCultureIgnoreCase));
if (table is not null)
return table;
var table = context.Tables.FirstOrDefault(table => table.DisplayName.Equals(tableDisplayName, StringComparison.CurrentCultureIgnoreCase));
if (table is null) continue;
SeedTableData(table);
return table;
}
return null;
@@ -26,16 +29,18 @@ internal sealed class ContextExplorer(HopFrameConfig config, IServiceProvider pr
public TableConfig? GetTable(Type tableEntity) {
foreach (var context in config.Contexts) {
var table = context.Tables.FirstOrDefault(table => table.TableType == tableEntity);
if (table is not null)
return table;
if (table is null) continue;
SeedTableData(table);
return table;
}
return null;
}
public ITableManager? GetTableManager(string tableName) {
public ITableManager? GetTableManager(string tablePropertyName) {
foreach (var context in config.Contexts) {
var table = context.Tables.FirstOrDefault(table => table.PropertyName == tableName);
var table = context.Tables.FirstOrDefault(table => table.PropertyName == tablePropertyName);
if (table is null) continue;
var dbContext = provider.GetService(context.ContextType) as DbContext;
@@ -48,4 +53,20 @@ internal sealed class ContextExplorer(HopFrameConfig config, IServiceProvider pr
return null;
}
private void SeedTableData(TableConfig table) {
if (table.Seeded) return;
var dbContext = (provider.GetService(table.ContextConfig.ContextType) as DbContext)!;
var entity = dbContext.Model.FindEntityType(table.TableType)!;
foreach (var key in entity.GetForeignKeys()) {
var propConfig = table.Properties
.SingleOrDefault(prop => prop.Info == key.DependentToPrincipal?.PropertyInfo);
if (propConfig is null) continue;
propConfig.IsRelation = true;
}
logger.LogInformation("Extracted information for table '" + table.PropertyName + "'");
table.Seeded = true;
}
}

View File

@@ -5,7 +5,7 @@
@using HopFrame.Web.Components.Pages
<FluentDialogBody Style="overflow-x: auto">
<HopFrameTablePage DisplayActions="false" DisplaySelection="true" TableName="@Content.SourceTable.PropertyName" PerPage="15" DialogData="Content" />
<HopFrameTablePage DisplayActions="false" DisplaySelection="true" TableDisplayName="@Content.SourceTable.DisplayName" PerPage="15" DialogData="Content" />
</FluentDialogBody>
@code {

View File

@@ -1,4 +1,4 @@
@page "/admin/{TableName}"
@page "/admin/{TableDisplayName}"
@layout HopFrameLayout
@rendermode InteractiveServer
@implements IDisposable
@@ -13,7 +13,7 @@
<div style="display: flex; flex-direction: column; height: 100%">
<FluentToolbar Class="hopframe-toolbar">
<h3>@_config?.PropertyName</h3>
<h3>@_config?.DisplayName</h3>
<FluentButton
IconStart="@(new Icons.Regular.Size16.ArrowClockwise())"
OnClick="Reload"
@@ -120,7 +120,7 @@
@code {
[Parameter]
public required string TableName { get; set; }
public required string TableDisplayName { get; set; }
[Parameter]
public bool DisplaySelection { get; set; }
@@ -145,9 +145,9 @@
private int _selectedIndex = -1;
protected override void OnInitialized() {
_config ??= Explorer.GetTable(TableName);
_config ??= Explorer.GetTable(TableDisplayName);
if (_config is null) {
if (_config is null || (_config.Ignored && DialogData is null)) {
Navigator.NavigateTo("/admin", true);
}
}

View File

@@ -16,13 +16,13 @@ public class Post {
[ForeignKey("author")]
public User? Author { get; set; }
/*public bool Published { get; set; }
public bool Published { get; set; }
public DateTime CreatedAt { get; set; }
public DateOnly Created { get; set; }
public TimeOnly At { get; set; }*/
public TimeOnly At { get; set; }
public ListSortDirection Type { get; set; }
}

View File

@@ -23,8 +23,7 @@ builder.Services.AddHopFrame(options => {
options.AddDbContext<DatabaseContext>(context => {
context.Table<User>(table => {
table.Property(u => u.Password)
.List(false)
.DisplayValue(false);
.ValueParser(pwd => pwd + "-edited");
table.Property(u => u.FirstName)
.SetDisplayName("First Name");
@@ -35,6 +34,8 @@ builder.Services.AddHopFrame(options => {
table.Property(u => u.Id)
.Sortable(false)
.ValueTemplate(Guid.CreateVersion7);
table.SetDisplayName("Benutzer");
});
context.Table<Post>()
@@ -46,8 +47,8 @@ builder.Services.AddHopFrame(options => {
.SetDisplayName("ID");
context.Table<Post>()
.Property(p => p.Author)
.IsRelation(true);
.Property(p => p.CreatedAt)
.ValueTemplate(() => DateTime.UtcNow);
});
});