Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
4d47f46
initial commit
tkdjohn Mar 23, 2025
810e40e
Code initial entities, set project structure
tkdjohn Mar 30, 2025
db82350
more intial setup
tkdjohn Mar 30, 2025
61822fd
add ef core - still needs pieces
tkdjohn Apr 6, 2025
8fba546
add stubbed repos and base repository
tkdjohn Apr 7, 2025
b74ec31
update repositories, entities need another analysis to make sure thin…
tkdjohn Apr 13, 2025
61101a4
rework of entities and repos
tkdjohn Jun 22, 2025
a6cbc8e
reslove notImplemented exceptions
tkdjohn Jun 22, 2025
191cb8a
fix folder and project names
tkdjohn Jun 22, 2025
06a5e07
Initial DB create; nuget updates
tkdjohn Jun 22, 2025
32ff43a
Update TODO, add stubbed microservices`; git push
tkdjohn Aug 17, 2025
c49299f
update nuget pkgs
tkdjohn Aug 17, 2025
3d9a9a1
add repostiory interfaces, clean up repository methods, add event ser…
tkdjohn Aug 17, 2025
5a8a43d
add ansyc analyzers, fix reported async issues
tkdjohn Aug 17, 2025
0a5c8be
a bit more cleanup
tkdjohn Aug 17, 2025
7a3ca60
move entities to .Data, remove .DomainEntities project, other prep fo…
tkdjohn Aug 17, 2025
f7560a7
Add Automapper and convert services to consume/return DTOs
tkdjohn Aug 18, 2025
29a3782
fix ef migrations to use entities from new file locations
tkdjohn Aug 18, 2025
0e33ca2
pdates to entities, attempt to add test data via cli (wip), mappers a…
tkdjohn Aug 18, 2025
e710139
pdates to entities, attempt to add test data via cli (wip), mappers a…
tkdjohn Aug 18, 2025
e6ceb5e
updates to entities, and dtos, initial mappings should work
tkdjohn Aug 19, 2025
bd6915b
final? initial migration. cli menu works, basic crud for Event and Ev…
tkdjohn Aug 19, 2025
440c57b
data restructure, adds almost work except need to move defaults back …
tkdjohn Aug 24, 2025
86973e2
fix enum to string converter
tkdjohn Aug 24, 2025
38f7d80
WIP restructure entities, repos, and services to make dependant entit…
tkdjohn Aug 31, 2025
59b40d4
WIP update readme to relrect current state
tkdjohn Aug 31, 2025
bf25aab
WIP repo/entity structrue fixed - well almost
tkdjohn Sep 1, 2025
0f7fd8d
Update services to properly handle loading user defined types when sa…
tkdjohn Sep 7, 2025
cedbf51
Fix more issues with add/update data
tkdjohn Sep 8, 2025
f571b78
Add Bootstrap WIP
tkdjohn Oct 5, 2025
ec023cd
Basic DI working, need to get apsettings/config working
tkdjohn Oct 5, 2025
b1af4a4
Configuration settings work
tkdjohn Oct 12, 2025
50936c3
Add JsonSeralizerSettings to boot strap, clean up how db settings was…
tkdjohn Oct 19, 2025
768f8cc
Merge branch 'main' into initial-development
tkdjohn Nov 23, 2025
a1630c7
version updates
tkdjohn Nov 30, 2025
888cbec
Merge branch 'initial-development' of https://github.com/tkdjohn/Hipp…
tkdjohn Nov 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
!**/.gitignore
!.git/HEAD
!.git/config
!.git/packed-refs
!.git/refs/heads/**
50 changes: 50 additions & 0 deletions EventJournal.CLI/CLIUtilities.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
namespace EventJournal.CLI {
public static class CLIUtilities {
public static string GetStringFromUser(string prompt) {
string? userInput = null;

while (string.IsNullOrWhiteSpace(userInput)) {
Console.Write(prompt);
userInput = Console.ReadLine();
}
return userInput;
}

public static int GetIntFromUser(string prompt) {
var intFromUser = 0;

var isInvalidInput = true;
while (isInvalidInput) {
Console.Write(prompt);
isInvalidInput = !int.TryParse(Console.ReadLine(),
System.Globalization.NumberStyles.AllowLeadingWhite
| System.Globalization.NumberStyles.AllowTrailingWhite,
System.Globalization.CultureInfo.CurrentCulture,
out intFromUser);
if (isInvalidInput) {
Console.WriteLine("Must be an integer.");
}
}

return intFromUser;
}

public static decimal GetDecimalFromUser(string prompt) {
var decimalFromUser = 0.0M;
var isInvalidInput = true;
while (isInvalidInput) {
Console.Write(prompt);
isInvalidInput = !decimal.TryParse(Console.ReadLine(),
System.Globalization.NumberStyles.AllowLeadingWhite
| System.Globalization.NumberStyles.AllowTrailingWhite
| System.Globalization.NumberStyles.Currency,
System.Globalization.CultureInfo.CurrentCulture,
out decimalFromUser);
if (isInvalidInput) {
Console.WriteLine("Must be a number.");
}
}
return decimalFromUser;
}
}
}
24 changes: 24 additions & 0 deletions EventJournal.CLI/DesignTimeDbContextFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using EventJournal.Common.Configuration;
using EventJournal.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;

namespace EventJournal.CLI {
public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<DatabaseContext> {
public DatabaseContext CreateDbContext(string[] args) {
IConfiguration configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();

var dbSettings = configuration.GetSection(DatabaseSettings.ConfigurationSectionName).Get<DatabaseSettings>()
?? throw new InvalidOperationException("Configuration settings does not contain a valid DatabaseSettings section.");

var builder = new DbContextOptionsBuilder<DatabaseContext>();
DatabaseContext.ConfigureFromSettings(builder, dbSettings);

return new DatabaseContext(builder.Options);
}
}
}
39 changes: 39 additions & 0 deletions EventJournal.CLI/EventJournal.CLI.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<RootNamespace>EventJournal.CLI</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AsyncFixer" Version="1.6.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.11">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.11" />
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.14.15">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Eventjournal.Bootstrap\EventJournal.BootStrap.csproj" />
<ProjectReference Include="..\EventJournal.Data\EventJournal.Data.csproj" />
<ProjectReference Include="..\EventJournal.DomainService\EventJournal.DomainService.csproj" />
<ProjectReference Include="..\EventJournal.Models\EventJournal.PublicModels.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
119 changes: 119 additions & 0 deletions EventJournal.CLI/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// See https://aka.ms/new-console-template for more information
using EventJournal.BootStrap;
using EventJournal.CLI;
using EventJournal.Common.Bootstrap;
using EventJournal.DomainService;
using EventJournal.PublicModels;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System.Text.Json;
internal class Program {
private static async Task Main(string[] args) {

var services = CreateServiceCollection();
var eventService = services.GetService<IEventService>() ?? throw new Exception("Unable to locate a valid Event Service");
var userTypeService = services.GetService<IUserTypesService>() ?? throw new Exception("Unable to locate a valid User Types Service");
var defaultDataProvider = services.GetService<IDefaultDataProvider>() ?? throw new Exception("Unable to locate a valid Default Data Provider");
var jsonSerializerOptions = services.GetService<JsonSerializerOptions>() ?? throw new Exception("Unable to locate a valid Json Serializer Options");
bool userIsDone = false;
while (!userIsDone) {
//Console.WriteLine("Type '1' to ");
//Console.WriteLine("Type '2' to ");
//Console.WriteLine("Type '3' to ");
//Console.WriteLine("Type '4' to ");
//Console.WriteLine("Type '6' to ");
//Console.WriteLine("Type '7' to ");
//Console.WriteLine("Type '8' to ");

Console.WriteLine("Type 'v' to view all data");
Console.WriteLine("Type 't' to add default test data.");
Console.WriteLine("Type 'x' to delete all data.");
Console.WriteLine("Type 'q' to quit.");

// application will block here waiting for user to press <Enter>
var userInput = CLIUtilities.GetStringFromUser("===> ").ToLower() ?? "";

switch (userInput[0]) {
case 'q':
userIsDone = true;
break;
// case '1':
// await AddUpdateEntity(GetEntityFromUser<Product>()).ConfigureAwait(false);
// break;
// case '2':
// await ViewProduct().ConfigureAwait(false);
// break;
// case '3':
// await ViewInStockProducts().ConfigureAwait(false);
// break;
// case '4':
// await ViewAllProduct().ConfigureAwait(false);
// break;
// case '5':

// break;
// case '6':
// await AddUpdateEntity(GetEntityFromUser<Order>()).ConfigureAwait(false);
// break;
// case '7':
// await ViewOrder().ConfigureAwait(false);
// break;
//case '8':
// break;
//case '9':
// break;
case 'v':
await ViewallDataAsync(jsonSerializerOptions, eventService, userTypeService).ConfigureAwait(false);
break;
case 't':
await AddTestDataAsync(defaultDataProvider).ConfigureAwait(false);
break;
case 'x':
await DeleteAllDataAsync(eventService, userTypeService).ConfigureAwait(false);
break;
}
Console.WriteLine("\n=================================================\n");
}
}

private static ServiceProvider CreateServiceCollection() {
IConfiguration Configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();

return new ServiceCollection()
// setup and register bootstrapper and it's installers -- needs to be last
.AddBootStrapper<DefaultApplicationBootStrapper>(Configuration, o => {
// Add any application specific installers here.
}).BuildServiceProvider();
}

static Task AddTestDataAsync(IDefaultDataProvider defaultDataProvider) {
Console.WriteLine("Adding/Resetting test data.");
return defaultDataProvider.AddResetDefaultDataAsync();
}
static async Task DeleteAllDataAsync(IEventService eventService, IUserTypesService userTypeService) {

Console.WriteLine("Deleting all data.");
foreach (var e in await eventService.GetAllEventsAsync().ConfigureAwait(false)) {
await eventService.DeleteEventAsync(e.ResourceId).ConfigureAwait(false);
}
foreach (var e in await userTypeService.GetAllEventTypesAsync().ConfigureAwait(false)) {
await userTypeService.DeleteEventTypeAsync(e.ResourceId).ConfigureAwait(false);
}
foreach (var e in await userTypeService.GetAllDetailTypesAsync().ConfigureAwait(false)) {
await userTypeService.DeleteDetailTypeAsync(e.ResourceId).ConfigureAwait(false);
}
}

static async Task ViewallDataAsync(JsonSerializerOptions options, IEventService eventService, IUserTypesService userTypeService) {
EventDataResponseModel eventData = new() {
DetailTypes = await userTypeService.GetAllDetailTypesAsync().ConfigureAwait(false),
EventTypes = await userTypeService.GetAllEventTypesAsync().ConfigureAwait(false),
Events = await eventService.GetAllEventsAsync().ConfigureAwait(false)
};

Console.WriteLine(JsonSerializer.Serialize(eventData, options));
}
}
14 changes: 14 additions & 0 deletions EventJournal.CLI/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
// Configuration settings for the EventJournal.CLI application
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"Database": {
//"ConnectionString": "Server=myServer;Database=myDatabase;User ID=myUser;Password=myPassword;",
"ConnectionString": "Default",
"Provider": "Sqlite"
}
}
104 changes: 104 additions & 0 deletions EventJournal.Common/Bootstrap/BootStrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
using EventJournal.Common.IOC;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace EventJournal.Common.Bootstrap {
public class BootStrapper {
protected IList<IInstaller> installers;

public BootStrapper() {
installers = [];
}

public virtual void AddInstaller(IInstaller installer) {
ArgumentNullException.ThrowIfNull(installer, nameof(installer));
installers.Add(installer);
}
/// <summary>
/// Installs all of the specified installers, overriding the internal list of installers.
/// </summary>
/// <param name="installers">A list of installers to register with the IoC.</param>
public virtual IServiceProvider InitIoCContainer(params IInstaller[] installers) {
if (installers == null) {
throw new ArgumentNullException(nameof(installers), "Installers cannot be null");
}
IServiceProvider container = InternalInitialize(installers);
return container;
}

/// <summary>
/// Installs all the internally specified installers, while adding the [applicationInstaller]
/// </summary>
/// <param name="applicationInstaller">The additional installer for the root level application.</param>
public virtual IServiceProvider InitIoCContainer(IInstaller applicationInstaller) {
if (applicationInstaller == null) {
throw new ArgumentNullException(nameof(applicationInstaller), "Application installer cannot be null");
}
installers.Add(applicationInstaller);
return InternalInitialize([.. installers]);
}

public virtual IServiceProvider InitIoCContainer() {
return InternalInitialize([.. installers]);
}

public virtual IServiceProvider InitIoCContainer(IServiceCollection services) {
if (services == null) {
throw new ArgumentNullException(nameof(services), "Service collection cannot be null");
}
return InternalInitialize(services, [.. installers]);
}

public virtual IServiceProvider InitIoCContainer(IConfigurationBuilder config, IServiceCollection services) {
if (config == null) {
throw new ArgumentNullException(nameof(config), "Configuration builder cannot be null");
}
return InternalInitialize(config, services, [.. installers]);
}
public virtual IServiceProvider InitIoCContainer(IConfiguration configuration, IServiceCollection services) {
if (configuration == null) {
throw new ArgumentNullException(nameof(configuration), "Configuration cannot be null");
}
if (services == null) {
throw new ArgumentNullException(nameof(services), "Service collection cannot be null");
}
return InternalInitialize(configuration, services, [.. installers]);
}

protected internal virtual IServiceProvider InternalInitialize(IInstaller[] installers) {
var services = new ServiceCollection().AddOptions();
return InternalInitialize(services, installers);
}

protected internal virtual IServiceProvider InternalInitialize(IConfigurationBuilder config, IInstaller[] installers) {
var services = new ServiceCollection().AddOptions();
return InternalInitialize(config, services, installers);
}

protected internal virtual IServiceProvider InternalInitialize(IServiceCollection services, IInstaller[] installers) {
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json");
return InternalInitialize(configuration, services, installers);
}

protected internal virtual IServiceProvider InternalInitialize(IConfigurationBuilder config, IServiceCollection services, IInstaller[] installers) {
var configuration = config.Build();
return InternalInitialize(configuration, services, installers);
}

protected internal virtual IServiceProvider InternalInitialize(IConfiguration configuration, IServiceCollection services, IInstaller[] installers) {
DI.SetConfiguration(configuration);

foreach (var i in installers) {
i.Install(services, configuration);
}

services.AddSingleton<IConfiguration>(configuration);
var serviceProvider = services.BuildServiceProvider();

DI.SetContainer(serviceProvider);
return serviceProvider;
}
}

}
Loading