From 1173bfe81e681ca0f7ef1e279f7fd7d934756c9e Mon Sep 17 00:00:00 2001 From: eelke Date: Wed, 25 Dec 2024 12:44:46 +0100 Subject: [PATCH] misc --- Directory.Packages.props | 15 ++- pgLabII/App.axaml | 4 +- pgLabII/App.axaml.cs | 47 +++++--- pgLabII/Composition.cs | 20 ---- .../ConnectionManager/ConnectionRepository.cs | 10 ++ pgLabII/Infra/ColorConverter.cs | 13 +++ pgLabII/Infra/LocalDb.cs | 58 ++++++++++ pgLabII/Model/Database.cs | 9 ++ .../ServerConfiguration.cs | 40 ++++++- pgLabII/{ViewModels => Model}/ServerUser.cs | 8 +- pgLabII/ServiceCollectionExtensions.cs | 31 +++++ .../EditServerConfigurationViewModel.cs | 33 ++++++ pgLabII/ViewModels/MainViewModel.cs | 3 + pgLabII/ViewModels/ServerListViewModel.cs | 29 +++-- pgLabII/ViewModels/ServerViewModel.cs | 9 ++ pgLabII/Views/DatabaseListView.axaml | 8 ++ pgLabII/Views/DatabaseListView.axaml.cs | 14 +++ .../Views/EditServerConfigurationWindow.axaml | 12 +- .../EditServerConfigurationWindow.axaml.cs | 6 + pgLabII/Views/MainView.axaml | 16 ++- pgLabII/Views/MainWindow.axaml.cs | 8 +- pgLabII/Views/ServerListView.axaml | 106 +++++++++--------- pgLabII/Views/ServerListView.axaml.cs | 7 +- pgLabII/Views/ServerWindow.axaml | 10 ++ pgLabII/Views/ServerWindow.axaml.cs | 14 +++ pgLabII/pgLabII.csproj | 11 +- 26 files changed, 410 insertions(+), 131 deletions(-) delete mode 100644 pgLabII/Composition.cs create mode 100644 pgLabII/ConnectionManager/ConnectionRepository.cs create mode 100644 pgLabII/Infra/ColorConverter.cs create mode 100644 pgLabII/Infra/LocalDb.cs create mode 100644 pgLabII/Model/Database.cs rename pgLabII/{ViewModels => Model}/ServerConfiguration.cs (55%) rename pgLabII/{ViewModels => Model}/ServerUser.cs (51%) create mode 100644 pgLabII/ServiceCollectionExtensions.cs create mode 100644 pgLabII/ViewModels/EditServerConfigurationViewModel.cs create mode 100644 pgLabII/ViewModels/ServerViewModel.cs create mode 100644 pgLabII/Views/DatabaseListView.axaml create mode 100644 pgLabII/Views/DatabaseListView.axaml.cs create mode 100644 pgLabII/Views/ServerWindow.axaml create mode 100644 pgLabII/Views/ServerWindow.axaml.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index 8b5e726..47b4882 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,6 +7,7 @@ + @@ -15,14 +16,18 @@ + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + - - - - - + + + + \ No newline at end of file diff --git a/pgLabII/App.axaml b/pgLabII/App.axaml index 9a371e6..9af82b4 100644 --- a/pgLabII/App.axaml +++ b/pgLabII/App.axaml @@ -13,9 +13,7 @@ + - - - \ No newline at end of file diff --git a/pgLabII/App.axaml.cs b/pgLabII/App.axaml.cs index bcda51c..799f898 100644 --- a/pgLabII/App.axaml.cs +++ b/pgLabII/App.axaml.cs @@ -1,6 +1,9 @@ using Avalonia; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Markup.Xaml; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using pgLabII.Infra; using pgLabII.ViewModels; using pgLabII.Views; @@ -15,27 +18,37 @@ public partial class App : Application public override void OnFrameworkInitializationCompleted() { - if (Resources[nameof(Composition)] is Composition composition) + // If you use CommunityToolkit, line below is needed to remove Avalonia data validation. + // Without this line you will get duplicate validations from both Avalonia and CT + // BindingPlugins.DataValidators.RemoveAt(0); + + // Register all the services needed for the application to run + var collection = new ServiceCollection(); + collection.AddCommonServices(); + + // Creates a ServiceProvider containing services from the provided IServiceCollection + var services = collection.BuildServiceProvider(); + + MigrateLocalDb(services); + + MainWindow win = services.GetRequiredService(); + if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { - switch (ApplicationLifetime) - { - case IClassicDesktopStyleApplicationLifetime desktop: - desktop.MainWindow = composition.MainWindow; - break; - - case ISingleViewApplicationLifetime singleViewPlatform: - singleViewPlatform.MainView = composition.MainWindow; - break; - } - - // Handles disposables - if (ApplicationLifetime is IControlledApplicationLifetime controlledApplicationLifetime) - { - //controlledApplicationLifetime.Exit += (_, _) => composition.Dispose(); - } + desktop.MainWindow = win; + } + else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform) + { + singleViewPlatform.MainView = win; } base.OnFrameworkInitializationCompleted(); } + private void MigrateLocalDb(ServiceProvider services) + { + using var scope = services.CreateScope(); + + var db = services.GetRequiredService(); + //db.Database.Migrate(); + } } diff --git a/pgLabII/Composition.cs b/pgLabII/Composition.cs deleted file mode 100644 index dc16d1f..0000000 --- a/pgLabII/Composition.cs +++ /dev/null @@ -1,20 +0,0 @@ -using pgLabII.ViewModels; -using pgLabII.Views; -using Pure.DI; -using static Pure.DI.Lifetime; - -namespace pgLabII; - -internal partial class Composition -{ - public void Setup() => DI.Setup() - .Root(nameof(MainWindow)) -// .Root(nameof(ServerListView)) - .Root(nameof(MainViewModel)) -// .Bind().As(Singleton).To() - - .Root(nameof(ServerListViewModel)) -// .Bind().As(Singleton).To() - ; - -} diff --git a/pgLabII/ConnectionManager/ConnectionRepository.cs b/pgLabII/ConnectionManager/ConnectionRepository.cs new file mode 100644 index 0000000..1259b40 --- /dev/null +++ b/pgLabII/ConnectionManager/ConnectionRepository.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace pgLabII.ConnectionManager; +internal class ConnectionRepository +{ +} diff --git a/pgLabII/Infra/ColorConverter.cs b/pgLabII/Infra/ColorConverter.cs new file mode 100644 index 0000000..0274701 --- /dev/null +++ b/pgLabII/Infra/ColorConverter.cs @@ -0,0 +1,13 @@ +using Avalonia.Media; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace pgLabII.Infra; + +public class ColorConverter : ValueConverter +{ + public ColorConverter() + : base( + v => v.ToUInt32(), + v => Color.FromUInt32(v)) + { } +} diff --git a/pgLabII/Infra/LocalDb.cs b/pgLabII/Infra/LocalDb.cs new file mode 100644 index 0000000..cb4c492 --- /dev/null +++ b/pgLabII/Infra/LocalDb.cs @@ -0,0 +1,58 @@ +using System; +using Avalonia.Media; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using pgLabII.Model; + +namespace pgLabII.Infra; + +internal class LocalDb : DbContext +{ + public DbSet ServerConfigurations => Set(); + + public string DbPath { get; } + + public LocalDb() + { + var folder = Environment.SpecialFolder.LocalApplicationData; + var path = Environment.GetFolderPath(folder); + DbPath = System.IO.Path.Join(path, "local.db"); + } + + // The following configures EF to create a Sqlite database file in the + // special "local" folder for your platform. + protected override void OnConfiguring(DbContextOptionsBuilder options) + => options.UseSqlite($"Data Source={DbPath}"); + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + + + new ServerConfigurationEntityConfiguration().Configure(modelBuilder.Entity()); + } + + protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) + { + base.ConfigureConventions(configurationBuilder); + + configurationBuilder + .Properties() + .HaveConversion(); + } +} + +public class ServerConfigurationEntityConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder b) + { + b.HasKey(e => e.Id); + } +} + +public class ServerUserEntityConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder b) + { + b.HasKey(e => e.Id); + } +} diff --git a/pgLabII/Model/Database.cs b/pgLabII/Model/Database.cs new file mode 100644 index 0000000..2762fc6 --- /dev/null +++ b/pgLabII/Model/Database.cs @@ -0,0 +1,9 @@ +namespace pgLabII.Model; + +public class Database +{ + public int Oid { get; set; } + public string Name { get; set; } = ""; + public int OwnerId { get; set; } + +} diff --git a/pgLabII/ViewModels/ServerConfiguration.cs b/pgLabII/Model/ServerConfiguration.cs similarity index 55% rename from pgLabII/ViewModels/ServerConfiguration.cs rename to pgLabII/Model/ServerConfiguration.cs index 009eb52..eafdcda 100644 --- a/pgLabII/ViewModels/ServerConfiguration.cs +++ b/pgLabII/Model/ServerConfiguration.cs @@ -7,18 +7,19 @@ using Npgsql; using pgLabII.Views; using ReactiveUI; -namespace pgLabII.ViewModels; +namespace pgLabII.Model; public class ServerConfiguration : ReactiveObject { - private Color? _color; + private Color _color; + private bool _colorEnabled = true; public Guid Id { get; set; } = Guid.NewGuid(); /// /// For the user to help him identify the item /// public string Name { get; set; } = ""; - public Color? Color + public Color Color { get => _color; set @@ -32,13 +33,27 @@ public class ServerConfiguration : ReactiveObject } } + public bool ColorEnabled + { + get => _colorEnabled; + set + { + if (_colorEnabled != value) + { + _colorEnabled = value; + this.RaisePropertyChanged(); + this.RaisePropertyChanged(propertyName: nameof(BackgroundBrush)); + } + } + } + public string Host { get; set; } = ""; public ushort Port { get; set; } = 5432; public string InitialDatabase { get; set; } = ""; public SslMode DefaultSslMode { get; set; } = SslMode.Prefer; - public IBrush? BackgroundBrush => Color.HasValue ? new SolidColorBrush(Color.Value) : null; + public IBrush? BackgroundBrush => ColorEnabled ? new SolidColorBrush(Color) : null; - public ObservableCollection Users { get; } = []; + public ServerUser User { get; set; } = new(); public ReactiveCommand EditCommand { get; } @@ -46,9 +61,22 @@ public class ServerConfiguration : ReactiveObject { EditCommand = ReactiveCommand.Create(() => { - EditServerConfigurationWindow window = new() { DataContext = this }; + EditServerConfigurationWindow window = new() { DataContext = this, New = false }; window.Show(); }); } + + public ServerConfiguration(ServerConfiguration src) + : this() + { + Color = src.Color; + ColorEnabled = src.ColorEnabled; + Id = src.Id; + Name = src.Name; + Port = src.Port; + InitialDatabase = src.InitialDatabase; + DefaultSslMode = src.DefaultSslMode; + User = src.User; + } } diff --git a/pgLabII/ViewModels/ServerUser.cs b/pgLabII/Model/ServerUser.cs similarity index 51% rename from pgLabII/ViewModels/ServerUser.cs rename to pgLabII/Model/ServerUser.cs index d7742f9..c8d4574 100644 --- a/pgLabII/ViewModels/ServerUser.cs +++ b/pgLabII/Model/ServerUser.cs @@ -1,11 +1,11 @@ -using Npgsql; -using pgLabII.ViewModels; +using System; -namespace pgLabII.ViewModels; +namespace pgLabII.Model; public class ServerUser : ViewModelBase { + public Guid Id { get; set; } + public Guid ServerConfigurationId { get; set; } public string Name { get; set; } = ""; public string Password { get; set; } = ""; - public SslMode? SslModeOverride { get; set; } } diff --git a/pgLabII/ServiceCollectionExtensions.cs b/pgLabII/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..aab7efc --- /dev/null +++ b/pgLabII/ServiceCollectionExtensions.cs @@ -0,0 +1,31 @@ +using Microsoft.Extensions.DependencyInjection; +using pgLabII.Infra; +using pgLabII.ViewModels; +using pgLabII.Views; + +namespace pgLabII; + +internal static class ServiceCollectionExtensions +{ + public static void AddCommonServices(this IServiceCollection collection) + { + collection.AddTransient(); + collection.AddTransient(); + collection.AddTransient(); + collection.AddScoped(); + } +} + +/* + * .Root(nameof(MainWindow)) + // .Root(nameof(ServerListView)) + .Root(nameof(MainViewModel)) + // .Bind().As(Singleton).To() + + .Root(nameof(ServerListViewModel)) + .Bind().As(Scoped).To() + .Root(nameof(LocalDb)) + // .Bind().As(Singleton).To() + ; + +*/ diff --git a/pgLabII/ViewModels/EditServerConfigurationViewModel.cs b/pgLabII/ViewModels/EditServerConfigurationViewModel.cs new file mode 100644 index 0000000..2d27905 --- /dev/null +++ b/pgLabII/ViewModels/EditServerConfigurationViewModel.cs @@ -0,0 +1,33 @@ +using System.Reactive; +using pgLabII.Model; +using ReactiveUI; + +namespace pgLabII.ViewModels; + +public class EditServerConfigurationViewModel : ViewModelBase +{ + public ServerConfiguration Configuration { get; set; } + + public ReactiveCommand SaveAndCloseCommand { get; } + public ReactiveCommand CloseCommand { get; } + + public EditServerConfigurationViewModel() + { + Configuration = new(); + + SaveAndCloseCommand = ReactiveCommand.Create(() => + { + }); + CloseCommand = ReactiveCommand.Create(() => + { + }); + } + + public EditServerConfigurationViewModel(ServerConfiguration configuration) + : this() + { + Configuration = configuration; + } + + +} diff --git a/pgLabII/ViewModels/MainViewModel.cs b/pgLabII/ViewModels/MainViewModel.cs index 20eb607..bf3e70f 100644 --- a/pgLabII/ViewModels/MainViewModel.cs +++ b/pgLabII/ViewModels/MainViewModel.cs @@ -1,4 +1,7 @@  +using System; +using Microsoft.Extensions.DependencyInjection; + namespace pgLabII.ViewModels; public class MainViewModel : ViewModelBase diff --git a/pgLabII/ViewModels/ServerListViewModel.cs b/pgLabII/ViewModels/ServerListViewModel.cs index 1837fd0..562159b 100644 --- a/pgLabII/ViewModels/ServerListViewModel.cs +++ b/pgLabII/ViewModels/ServerListViewModel.cs @@ -1,10 +1,9 @@ -using System; -using System.Collections.ObjectModel; -using System.Linq; +using System.Collections.ObjectModel; using ReactiveUI; using System.Reactive; using Avalonia.Media; -using DynamicData; +using pgLabII.Views; +using pgLabII.Model; namespace pgLabII.ViewModels; @@ -14,19 +13,28 @@ public class ServerListViewModel : ViewModelBase [ new ServerConfiguration() { - Name = "Foo", + Name = "Local pg15", Color = Colors.Aquamarine, - Host = "db.host.nl" + ColorEnabled = true, + Host = "localhost", + Port = 5434, + User = new () + { + Name = "postgres", + Password = "admin", + }, }, new ServerConfiguration() { Name = "Bar", - Color = Colors.Bisque, + ColorEnabled = false, Host = "db.host.nl" } ]; public ReactiveCommand RemoveServerCommand { get; } + + public ReactiveCommand AddServerCommand { get; } public ServerListViewModel() { @@ -35,5 +43,12 @@ public class ServerListViewModel : ViewModelBase ServerConfigurations.Remove(sc); return Unit.Default; }); + + AddServerCommand = ReactiveCommand.Create(() => + { + ServerConfiguration sc = new(); + EditServerConfigurationWindow window = new() { DataContext = sc, New = true }; + window.Show(); + }); } } diff --git a/pgLabII/ViewModels/ServerViewModel.cs b/pgLabII/ViewModels/ServerViewModel.cs new file mode 100644 index 0000000..315fa8f --- /dev/null +++ b/pgLabII/ViewModels/ServerViewModel.cs @@ -0,0 +1,9 @@ +namespace pgLabII.ViewModels; + +/// +/// Toplevel viewmodel for the global resources of a postgresql installation. +/// +public class ServerViewModel : ViewModelBase +{ + +} diff --git a/pgLabII/Views/DatabaseListView.axaml b/pgLabII/Views/DatabaseListView.axaml new file mode 100644 index 0000000..2325a9e --- /dev/null +++ b/pgLabII/Views/DatabaseListView.axaml @@ -0,0 +1,8 @@ + + Welcome to Avalonia! + diff --git a/pgLabII/Views/DatabaseListView.axaml.cs b/pgLabII/Views/DatabaseListView.axaml.cs new file mode 100644 index 0000000..462dea5 --- /dev/null +++ b/pgLabII/Views/DatabaseListView.axaml.cs @@ -0,0 +1,14 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace pgLabII.Views; + +public partial class DatabaseListView : UserControl +{ + public DatabaseListView() + { + InitializeComponent(); + } +} + diff --git a/pgLabII/Views/EditServerConfigurationWindow.axaml b/pgLabII/Views/EditServerConfigurationWindow.axaml index 3a004df..5694da0 100644 --- a/pgLabII/Views/EditServerConfigurationWindow.axaml +++ b/pgLabII/Views/EditServerConfigurationWindow.axaml @@ -4,26 +4,28 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" xmlns:vm="clr-namespace:pgLabII.ViewModels" - x:DataType="vm:ServerConfiguration" + x:DataType="vm:EditServerConfigurationViewModel" x:Class="pgLabII.Views.EditServerConfigurationWindow" Title="EditServerConfiguration"> - + Name: - + Color: - + + Host: - + diff --git a/pgLabII/Views/EditServerConfigurationWindow.axaml.cs b/pgLabII/Views/EditServerConfigurationWindow.axaml.cs index 7e50771..40b17d5 100644 --- a/pgLabII/Views/EditServerConfigurationWindow.axaml.cs +++ b/pgLabII/Views/EditServerConfigurationWindow.axaml.cs @@ -1,6 +1,7 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Markup.Xaml; +using pgLabII.ViewModels; namespace pgLabII.Views; @@ -9,6 +10,11 @@ public partial class EditServerConfigurationWindow : Window public EditServerConfigurationWindow() { InitializeComponent(); + + DataContext = new EditServerConfigurationViewModel( + new()); } + + public bool New { get; set; } } diff --git a/pgLabII/Views/MainView.axaml b/pgLabII/Views/MainView.axaml index 0836b10..b9ccb74 100644 --- a/pgLabII/Views/MainView.axaml +++ b/pgLabII/Views/MainView.axaml @@ -7,9 +7,19 @@ xmlns:app="clr-namespace:pgLabII" DataContext="{StaticResource Composition}" x:Class="pgLabII.Views.MainView" - x:DataType="app:Composition"> - - + x:DataType="vm:MainViewModel"> + + + + + + + + + + + diff --git a/pgLabII/Views/MainWindow.axaml.cs b/pgLabII/Views/MainWindow.axaml.cs index f085ff6..a07b870 100644 --- a/pgLabII/Views/MainWindow.axaml.cs +++ b/pgLabII/Views/MainWindow.axaml.cs @@ -1,11 +1,13 @@ -using Avalonia.Controls; +using Avalonia.Controls; +using pgLabII.ViewModels; namespace pgLabII.Views; public partial class MainWindow : Window { - public MainWindow() + public MainWindow(ServerListViewModel model) { + DataContext = model; InitializeComponent(); } -} \ No newline at end of file +} diff --git a/pgLabII/Views/ServerListView.axaml b/pgLabII/Views/ServerListView.axaml index e3c2319..211c3f3 100644 --- a/pgLabII/Views/ServerListView.axaml +++ b/pgLabII/Views/ServerListView.axaml @@ -6,55 +6,61 @@ xmlns:vm="clr-namespace:pgLabII.ViewModels" xmlns:app="clr-namespace:pgLabII" DataContext="{StaticResource Composition}" - x:DataType="app:Composition" + x:DataType="vm:ServerListViewModel" x:Class="pgLabII.Views.ServerListView"> - - - - - - - - - - - - - - - + + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pgLabII/Views/ServerListView.axaml.cs b/pgLabII/Views/ServerListView.axaml.cs index d4a80df..d2d8eeb 100644 --- a/pgLabII/Views/ServerListView.axaml.cs +++ b/pgLabII/Views/ServerListView.axaml.cs @@ -1,6 +1,5 @@ -using Avalonia; -using Avalonia.Controls; -using Avalonia.Markup.Xaml; +using Avalonia.Controls; +using pgLabII.ViewModels; namespace pgLabII.Views; @@ -8,6 +7,8 @@ public partial class ServerListView : UserControl { public ServerListView() { + //DataContext = new ServerListViewModel(); + InitializeComponent(); } } diff --git a/pgLabII/Views/ServerWindow.axaml b/pgLabII/Views/ServerWindow.axaml new file mode 100644 index 0000000..9f1a78c --- /dev/null +++ b/pgLabII/Views/ServerWindow.axaml @@ -0,0 +1,10 @@ + + + diff --git a/pgLabII/Views/ServerWindow.axaml.cs b/pgLabII/Views/ServerWindow.axaml.cs new file mode 100644 index 0000000..a754f5b --- /dev/null +++ b/pgLabII/Views/ServerWindow.axaml.cs @@ -0,0 +1,14 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace pgLabII.Views; + +public partial class ServerWindow : Window +{ + public ServerWindow() + { + InitializeComponent(); + } +} + diff --git a/pgLabII/pgLabII.csproj b/pgLabII/pgLabII.csproj index e370bf8..610a935 100644 --- a/pgLabII/pgLabII.csproj +++ b/pgLabII/pgLabII.csproj @@ -12,6 +12,7 @@ + @@ -20,16 +21,16 @@ All - - - - all + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + -