diff --git a/Elwig/App.xaml.cs b/Elwig/App.xaml.cs index 0af2671..df7f047 100644 --- a/Elwig/App.xaml.cs +++ b/Elwig/App.xaml.cs @@ -1,20 +1,21 @@ -using System; -using System.Data; -using System.Linq; -using System.Windows; -using System.IO; -using Elwig.Helpers; -using Elwig.Helpers.Weighing; -using System.Collections.Generic; -using System.Windows.Threading; -using System.Reflection; -using Elwig.Helpers.Printing; -using Elwig.Windows; using Elwig.Dialogs; -using System.Threading.Tasks; +using Elwig.Helpers; using Elwig.Helpers.Billing; +using Elwig.Helpers.Export; +using Elwig.Helpers.Printing; +using Elwig.Helpers.Weighing; using Elwig.Models.Entities; +using Elwig.Windows; +using System; +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Linq; +using System.Reflection; using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Threading; namespace Elwig { public partial class App : Application { @@ -239,6 +240,17 @@ namespace Elwig { } } + public static void ReplaceDatabase(string filename) { + try { + ElwigData.ImportDatabase(filename); + MessageBox.Show("Das Ersetzen war erfolgreich!\n\nBitte starten Sie Elwig neu!", "Datenbank ersetzen", MessageBoxButton.OK, MessageBoxImage.Information); + ForceShutdown = true; + Current.Shutdown(); + } catch (Exception exc) { + MessageBox.Show("Fehler beim Ersetzen:\n\n" + exc.Message, "Datenbank ersetzen", MessageBoxButton.OK, MessageBoxImage.Error); + } + } + private static T FocusWindow(Func constructor, Predicate? selector = null) where T : Window { foreach (Window w in CurrentApp.Windows) { if (w is T t && (selector == null || selector(t))) { diff --git a/Elwig/Helpers/Export/ElwigData.cs b/Elwig/Helpers/Export/ElwigData.cs index af91321..c196c43 100644 --- a/Elwig/Helpers/Export/ElwigData.cs +++ b/Elwig/Helpers/Export/ElwigData.cs @@ -370,6 +370,28 @@ namespace Elwig.Helpers.Export { }.Export(filename); } + public static void ImportDatabase(string filename) { + var oldName = Path.ChangeExtension(App.Config.DatabaseFile, ".old.sqlite3"); + var newName = Path.ChangeExtension(App.Config.DatabaseFile, ".new.sqlite3"); + try { + using (var zip = ZipFile.Open(filename, ZipArchiveMode.Read)) { + var db = zip.GetEntry("database.sqlite3")!; + db.ExtractToFile(newName, true); + } + File.Move(App.Config.DatabaseFile, oldName, true); + File.Move(newName, App.Config.DatabaseFile, false); + } finally { + if (File.Exists(newName)) + File.Delete(newName); + } + } + + public static void ExportDatabase(string filename) { + File.Delete(filename); + using var zip = ZipFile.Open(filename, ZipArchiveMode.Create); + var db = zip.CreateEntryFromFile(App.Config.DatabaseFile, "database.sqlite3", CompressionLevel.SmallestSize); + } + public class ElwigExport { public (IEnumerable Members, IEnumerable Filters)? Members { get; set; } public (IEnumerable AreaComs, IEnumerable Filters)? AreaComs { get; set; } diff --git a/Elwig/Windows/MainWindow.xaml b/Elwig/Windows/MainWindow.xaml index 845400f..3835407 100644 --- a/Elwig/Windows/MainWindow.xaml +++ b/Elwig/Windows/MainWindow.xaml @@ -41,6 +41,17 @@ + + + + + + + + + + + diff --git a/Elwig/Windows/MainWindow.xaml.cs b/Elwig/Windows/MainWindow.xaml.cs index 115fafa..e5f8351 100644 --- a/Elwig/Windows/MainWindow.xaml.cs +++ b/Elwig/Windows/MainWindow.xaml.cs @@ -31,6 +31,8 @@ namespace Elwig.Windows { Menu_Help_Smtp.IsEnabled = App.Config.Smtp != null; DownloadButton.Visibility = App.Config.SyncUrl != null ? Visibility.Visible : Visibility.Hidden; UploadButton.Visibility = App.Config.SyncUrl != null ? Visibility.Visible : Visibility.Hidden; + Menu_Database_Upload.IsEnabled = App.Config.SyncUrl != null; + Menu_Database_Download.IsEnabled = App.Config.SyncUrl != null; } private void Window_Loaded(object sender, RoutedEventArgs evt) { @@ -156,7 +158,7 @@ namespace Elwig.Windows { Name = f!["name"]!.AsValue().GetValue(), Timestamp = f!["timestamp"] != null && DateTime.TryParseExact(f!["timestamp"]!.AsValue().GetValue(), "yyyy-MM-ddTHH:mm:ssK", CultureInfo.InvariantCulture, DateTimeStyles.None, out var dt) ? dt : (DateTime?)null, ZwstId = f!["meta"]?["zwstid"]?.AsValue().GetValue() ?? f!["zwstid"]?.AsValue().GetValue(), - Device = f!["meta"]?["device"]!.AsValue().GetValue(), + Device = f!["meta"]?["device"]?.AsValue().GetValue(), Url = f!["url"]!.AsValue().GetValue(), Size = f!["size"]!.AsValue().GetValue(), }) @@ -178,11 +180,11 @@ namespace Elwig.Windows { } await ElwigData.Import(paths, ElwigData.ImportMode.FromBranches); } catch (HttpRequestException exc) { - MessageBox.Show("Eventuell Internetverbindung prüfen!\n\n" + exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); + MessageBox.Show("Eventuell Internetverbindung prüfen!\n\n" + exc.Message, "Daten herunterladen", MessageBoxButton.OK, MessageBoxImage.Error); } catch (TaskCanceledException exc) { - MessageBox.Show("Eventuell Internetverbindung prüfen!\n\n" + exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); + MessageBox.Show("Eventuell Internetverbindung prüfen!\n\n" + exc.Message, "Daten herunterladen", MessageBoxButton.OK, MessageBoxImage.Error); } catch (Exception exc) { - MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); + MessageBox.Show(exc.Message, "Daten herunterladen", MessageBoxButton.OK, MessageBoxImage.Error); } }); Mouse.OverrideCursor = null; @@ -225,6 +227,87 @@ namespace Elwig.Windows { Mouse.OverrideCursor = null; } + private async void Menu_Database_Download_Click(object sender, RoutedEventArgs evt) { + if (App.Config.SyncUrl == null) + return; + Mouse.OverrideCursor = Cursors.Wait; + await Task.Run(async () => { + try { + var data = await Utils.GetExportMetaData(App.Config.SyncUrl, App.Config.SyncUsername, App.Config.SyncPassword); + var file = data + .Select(f => new { + Name = f!["name"]!.AsValue().GetValue(), + Timestamp = f!["modified"] != null && DateTime.TryParseExact(f!["modified"]!.AsValue().GetValue(), "yyyy-MM-ddTHH:mm:ssK", CultureInfo.InvariantCulture, DateTimeStyles.None, out var dt) ? dt : (DateTime?)null, + Url = f!["url"]!.AsValue().GetValue(), + Size = f!["size"]!.AsValue().GetValue(), + }) + .Where(f => f.Name == "database.sqlite3.zip") + .FirstOrDefault(); + + if (file == null) { + MessageBox.Show("Die Datenbank wurde noch nicht vom Hauptgerät hochgeladen!", "Datenbank herunterladen", + MessageBoxButton.OK, MessageBoxImage.Error); + return; + } + + var res = MessageBox.Show($"Es wurde eine komprimierte Datenbank (ca. {file.Size / 1024 / 1024} MB) vom {file.Timestamp:dd.MM.yyyy, HH:mm} gefunden.\n\nWollen Sie wirklich die aktuelle Datenbank unwiederruflich\nlöschen und durch die gefundene ersetzen?\n\nDas kann zu Datenverlust führen!", "Datenbank herunterladen", + MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel); + if (res != MessageBoxResult.OK) + return; + + var filename = Path.Combine(App.TempPath, file.Name); + using (var client = Utils.GetHttpClient(App.Config.SyncUsername, App.Config.SyncPassword)) { + using var stream = new FileStream(filename, FileMode.Create); + await client.DownloadAsync(file.Url, stream); + } + + res = MessageBox.Show("Die Datenbank wurde erfolgreich heruntergeladen!\n\nSoll die Datenbank wirklich unwiederruflich ersetzt werden?\n\nWenn Sie unsicher sind sprechen Sie sich mit dem Benutzer des Hauptgerätes ab!", "Datenbank herunterladen", + MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel); + if (res != MessageBoxResult.OK) + return; + + await App.MainDispatcher.BeginInvoke(() => { + App.ReplaceDatabase(filename); + }); + } catch (HttpRequestException exc) { + MessageBox.Show("Eventuell Internetverbindung prüfen!\n\n" + exc.Message, "Datenbank herunterladen", MessageBoxButton.OK, MessageBoxImage.Error); + } catch (TaskCanceledException exc) { + MessageBox.Show("Eventuell Internetverbindung prüfen!\n\n" + exc.Message, "Datenbank herunterladen", MessageBoxButton.OK, MessageBoxImage.Error); + } catch (Exception exc) { + MessageBox.Show(exc.Message, "Datenbank herunterladen", MessageBoxButton.OK, MessageBoxImage.Error); + } + }); + Mouse.OverrideCursor = null; + } + + private async void Menu_Database_Upload_Click(object sender, RoutedEventArgs evt) { + if (App.Config.SyncUrl == null) + return; + + var res = MessageBox.Show("Sind Sie wirklich sicher, dass Sie die Datenbank dieses\nGerätes hochladen möchten? Das sollte nur vom Hauptgerät aus passieren!", "Datenbank hochladen", + MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel); + if (res != MessageBoxResult.OK) + return; + + Mouse.OverrideCursor = Cursors.Wait; + await Task.Run(async () => { + try { + var path = Path.Combine(App.TempPath, "database.sqlite3.zip"); + ElwigData.ExportDatabase(path); + await Utils.UploadExportData(path, App.Config.SyncUrl, App.Config.SyncUsername, App.Config.SyncPassword); + MessageBox.Show($"Hochladen der gesamten Datenbank erfolgreich!", "Datenbank hochladen", + MessageBoxButton.OK, MessageBoxImage.Information); + } catch (HttpRequestException exc) { + MessageBox.Show("Eventuell Internetverbindung prüfen!\n\n" + exc.Message, "Datenbank hochladen", MessageBoxButton.OK, MessageBoxImage.Error); + } catch (TaskCanceledException exc) { + MessageBox.Show("Eventuell Internetverbindung prüfen!\n\n" + exc.Message, "Datenbank hochladen", MessageBoxButton.OK, MessageBoxImage.Error); + } catch (Exception exc) { + MessageBox.Show(exc.Message, "Datenbank hochladen", MessageBoxButton.OK, MessageBoxImage.Error); + } + }); + Mouse.OverrideCursor = null; + } + private void MemberAdminButton_Click(object sender, RoutedEventArgs evt) { var w = new MemberAdminWindow(); w.Show();