瀏覽代碼

Added window to update each database file to the latest version.

Kenric Nugteren 1 周之前
父節點
當前提交
d4ddc03a7d

+ 3 - 1
prs.server/Forms/Configuration.xaml.cs

@@ -64,8 +64,10 @@ public partial class Configuration : ThemableWindow
             ConfigurationUtils.RegisterClasses();
             CoreUtils.RegisterClasses(typeof(Configuration).Assembly);
 
+            DatabaseUpdateScripts.RegisterScripts();
+
             Logger.OnLog += MainLogger.Send;
-            MainLogger.AddLogger(new LogFileLogger(CoreUtils.GetPath()));
+            MainLogger.AddLogger(new LogFileLogger(CoreUtils.GetPath(), false));
 
             Logger.Send(LogType.Information, "", string.Format("Config Path: {0}", CoreUtils.GetPath()));
 

+ 51 - 0
prs.server/Forms/Version9Update/UpdateConsole.cs

@@ -0,0 +1,51 @@
+using InABox.Core;
+using InABox.Logging;
+using InABox.Wpf.Console;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Console = InABox.Wpf.Console.Console;
+
+namespace PRSServer.Forms.Version9Update;
+
+public class UpdateConsole : Console
+{
+    private EventLogger? logger;
+
+    public UpdateConsole(string description): base(description)
+    {
+    }
+
+    protected override void OnLoaded()
+    {
+        base.OnLoaded();
+
+        ConsoleControl.Enabled = true;
+
+        logger = new EventLogger(OnLog);
+        MainLogger.AddLogger(logger);
+    }
+
+    private void OnLog(string message)
+    {
+        Dispatcher.BeginInvoke(() =>
+        {
+            ConsoleControl.LoadLogEntry(message);
+        });
+    }
+
+    protected override void OnClosing()
+    {
+        base.OnClosing();
+        if(logger is not null)
+        {
+            MainLogger.RemoveLogger(logger);
+        }
+    }
+
+    protected override string GetLogDirectory()
+    {
+        return CoreUtils.GetPath();
+    }
+}

+ 19 - 2
prs.server/Forms/Version9Update/UpdateDatabaseFiles.xaml

@@ -5,8 +5,25 @@
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:local="clr-namespace:PRSServer.Forms.Version9Update"
         mc:Ignorable="d"
-        Title="UpdateDatabaseFiles" Height="450" Width="800">
+        Title="Update Database to Version 9" Height="500" Width="350"
+        Loaded="Window_Loaded">
     <Grid>
-        
+        <Grid.RowDefinitions>
+            <RowDefinition Height="*"/>
+            <RowDefinition Height="Auto"/>
+        </Grid.RowDefinitions>
+        <local:UpdateDatabaseFilesGrid x:Name="Grid" Margin="5"
+                                       Grid.Row="0"/>
+        <DockPanel Grid.Row="1" LastChildFill="False"
+                   Margin="5,0,5,5">
+            <Button Content="Cancel"
+                    DockPanel.Dock="Right"
+                    Padding="5"
+                    Click="Cancel_Click"/>
+            <Button Content="Proceed"
+                    DockPanel.Dock="Right"
+                    Padding="5" Margin="0,0,5,0"
+                    Click="Proceed_Click"/>
+        </DockPanel>
     </Grid>
 </Window>

+ 227 - 8
prs.server/Forms/Version9Update/UpdateDatabaseFiles.xaml.cs

@@ -1,7 +1,19 @@
-using System;
+using Comal.Stores;
+using InABox.Clients;
+using InABox.Core;
+using InABox.Database;
+using InABox.Database.SQLite;
+using InABox.DynamicGrid;
+using InABox.Wpf;
+using InABox.WPF;
+using PRSServices;
+using Stripe.Treasury;
+using System;
 using System.Collections.Generic;
+using System.ComponentModel;
 using System.Linq;
 using System.Text;
+using System.Threading;
 using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Controls;
@@ -12,16 +24,223 @@ using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using System.Windows.Shapes;
 
-namespace PRSServer.Forms.Version9Update
+namespace PRSServer.Forms.Version9Update;
+
+public class UpdateDatabaseFilesGridItem : BaseObject
+{
+    public string Name { get; set; }
+
+    public string FileName { get; set; }
+
+    public IProviderFactory ProviderFactory { get; set; }
+
+    public VersionNumber Version { get; set; }
+
+    public string VersionText => Version?.ToString() ?? "";
+
+    public bool NeedsUpdate => Version is not null && Version.MajorVersion < 9;
+}
+
+public class UpdateDatabaseFilesGrid : DynamicItemsListGrid<UpdateDatabaseFilesGridItem>
+{
+    private static readonly BitmapImage? _warning = Properties.Resources.warning.AsBitmapImage();
+    private static readonly BitmapImage? _tick = Properties.Resources.tick.AsBitmapImage();
+
+    protected override void Init()
+    {
+        base.Init();
+
+        ActionColumns.Add(new DynamicImageColumn(GetImage, UpdateClick)
+        {
+            ToolTip = UpdateToolTip
+        });
+    }
+
+    private FrameworkElement? UpdateToolTip(DynamicActionColumn column, CoreRow? row)
+    {
+        if(row is null)
+        {
+            return null;
+        }
+
+        var item = LoadItem(row);
+        if (item.NeedsUpdate)
+        {
+            return column.TextToolTip($"This database is currently version {item.VersionText} and needs updating to version 9.");
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    protected override DynamicGridColumns LoadColumns()
+    {
+        var columns = new DynamicGridColumns();
+        columns.Add<UpdateDatabaseFilesGridItem>(x => x.Name);
+        columns.Add<UpdateDatabaseFilesGridItem>(x => x.VersionText, caption: "Current Version");
+        return columns;
+    }
+
+    protected override void DoReconfigure(DynamicGridOptions options)
+    {
+        options.Clear();
+    }
+
+    private bool UpdateClick(CoreRow? row)
+    {
+        if (row is null) return false;
+
+        var item = LoadItem(row);
+        if (!item.NeedsUpdate) return false;
+
+        var currentVersion = DbFactory.GetDatabaseVersion(item.ProviderFactory);
+        if(currentVersion.MajorVersion >= 9)
+        {
+            item.Version = currentVersion;
+            return true;
+        }
+
+        var task = Task.Run(() =>
+        {
+            DbFactory.Stores = CoreUtils.TypeList(
+                AppDomain.CurrentDomain.GetAssemblies(),
+                myType =>
+                    myType.IsClass
+                    && !myType.IsAbstract
+                    && !myType.IsGenericType
+                    && myType.GetInterfaces().Contains(typeof(IStore))
+            ).ToArray();
+            DbFactory.DefaultStore = typeof(BaseStore<>);
+
+            var factory = new SQLiteProviderFactory(item.FileName);
+            DbFactory.ProviderFactory = factory;
+            DbFactory.Start(); // Doing this will run all the update scripts.
+            factory.InitializeNulls();
+        });
+
+        var window = Window.GetWindow(this);
+
+        var console = new UpdateConsole("Console");
+
+        console.Top = window.Top;
+        console.Left = window.Left + window.Width + 2;
+        console.Height = window.Height;
+        console.Loaded += (_, args) =>
+        {
+            var worker = new BackgroundWorker();
+
+            window.IsEnabled = false;
+
+            worker.DoWork += (o, e) =>
+            {
+                task.Wait();
+            };
+            worker.RunWorkerCompleted +=
+                (o, e) => console.Close();
+            worker.RunWorkerAsync();
+        };
+        console.ShowDialog();
+
+        try
+        {
+            task.Wait();
+        }
+        catch(Exception e)
+        {
+            MessageWindow.ShowError("An error occurred while trying to update this database.", e);
+        }
+
+        window.IsEnabled = true;
+
+        currentVersion = DbFactory.GetDatabaseVersion(item.ProviderFactory);
+        item.Version = currentVersion;
+        return true;
+    }
+
+    private BitmapImage? GetImage(CoreRow? row)
+    {
+        if (row is null) return _tick;
+
+        return LoadItem(row).NeedsUpdate ? _warning : _tick;
+    }
+}
+
+/// <summary>
+/// Interaction logic for UpdateDatabaseFiles.xaml
+/// </summary>
+public partial class UpdateDatabaseFiles : Window
 {
-    /// <summary>
-    /// Interaction logic for UpdateDatabaseFiles.xaml
-    /// </summary>
-    public partial class UpdateDatabaseFiles : Window
+    public UpdateDatabaseFiles()
+    {
+        InitializeComponent();
+    }
+
+    private void Window_Loaded(object sender, RoutedEventArgs e)
     {
-        public UpdateDatabaseFiles()
+        LoadData();
+    }
+
+    private void LoadData()
+    {
+        Progress.ShowModal("Loading Data", progress =>
         {
-            InitializeComponent();
+            var table = new CoreTable();
+            table.LoadColumns(typeof(Server));
+
+            var sections = PRSService.GetConfiguration().LoadAll();
+
+            foreach (var section in sections.Where(x => x.Value.Type == ServerType.Database))
+            {
+                var properties = section.Value.DeserializeServerProperties();
+                if (properties is not DatabaseServerProperties databaseProperties) continue;
+
+                Grid.Items.Add(new()
+                {
+                    Name = databaseProperties.Name,
+                    FileName = databaseProperties.FileName,
+                });
+            }
+
+            var tasks = Grid.Items.ToArray(LoadProvider);
+            Task.WaitAll(tasks);
+
+            foreach(var (item, task) in Grid.Items.Zip(tasks))
+            {
+                item.ProviderFactory = task.Result;
+                item.Version = DbFactory.GetDatabaseVersion(item.ProviderFactory);
+            }
+        });
+
+        Grid.Refresh(true, true);
+    }
+
+    private Task<IProviderFactory> LoadProvider(UpdateDatabaseFilesGridItem item)
+    {
+        return Task.Run(() =>
+        {
+            IProviderFactory factory = new SQLiteProviderFactory(item.FileName);
+            factory.Start();
+            return factory;
+        });
+    }
+
+    private void Proceed_Click(object sender, RoutedEventArgs e)
+    {
+        if(Grid.Items.Any(x => x.NeedsUpdate))
+        {
+            if(!MessageWindow.ShowYesNo("Some database files have not been updated to version 9! If you proceed, these " +
+                "databases will not work anymore. Are you sure you wish to proceed?", "Unupdated files"))
+            {
+                return;
+            }
         }
+
+        DialogResult = true;
+    }
+
+    private void Cancel_Click(object sender, RoutedEventArgs e)
+    {
+        DialogResult = false;
     }
 }