Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
5ba74c8368 | |||
3c9b3c2db1 | |||
98f8907817 | |||
44dcc5e19f | |||
d7012ebfa1 | |||
a9b5317e79 | |||
f02598760f | |||
4b8cd2a0d7 | |||
104798d4f2 | |||
4653a4f129 | |||
07f9a0f522 |
36
CHANGELOG.md
36
CHANGELOG.md
@@ -2,6 +2,42 @@
|
|||||||
Changelog
|
Changelog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
[v1.0.0.5][v1.0.0.5] (2025-09-15) {#v1.0.0.5}
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
### Neue Funktionen {#v1.0.0.5-features}
|
||||||
|
|
||||||
|
* Die Datenbank kann im Haupt-Fenster (`MainWindow`) gesichert und wiederhergestellt werden. (f02598760f)
|
||||||
|
|
||||||
|
### Sonstiges {#v1.0.0.5-misc}
|
||||||
|
|
||||||
|
* In der WGM ist eine Auswahl eines Zu/-Abschlags im Übernahme-Fenster (`DeliveryAdminWindow`) nun erforderlich. (a9b5317e79)
|
||||||
|
* In der Konfigurationsdatei kann im `[general]` Block `weighing = gross`, `weighing = net`, oder `weighing = box` angegeben werden. (d7012ebfa1)
|
||||||
|
* Über-Fenser (`AboutWindow`) hinzugefügt. (3c9b3c2db1)
|
||||||
|
* Abhängigkeiten aktualisiert. (44dcc5e19f, 98f8907817)
|
||||||
|
|
||||||
|
[v1.0.0.5]: https://git.necronda.net/winzer/elwig/releases/tag/v1.0.0.5
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[v1.0.0.4][v1.0.0.4] (2025-09-01) {#v1.0.0.4}
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
### Behobene Fehler {#v1.0.0.4-bugfixes}
|
||||||
|
|
||||||
|
* Absturz beim Verschicken von einzelnen E-Mails außerhalb des Rundschreiben-Fensters (`MailWindow`) behoben. (07f9a0f522)
|
||||||
|
|
||||||
|
### Sonstiges {#v1.0.0.4-misc}
|
||||||
|
|
||||||
|
* Ladezeit des Fehler-Protokoll-Fensters (`LogWindow`) verbessert. (4653a4f129)
|
||||||
|
* Im Übernahme-Fenster (`DeliveryAdminWindow`) ist es nun möglich die Qualitätsstufe zu verändern. (104798d4f2)
|
||||||
|
|
||||||
|
[v1.0.0.4]: https://git.necronda.net/winzer/elwig/releases/tag/v1.0.0.4
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[v1.0.0.3][v1.0.0.3] (2025-08-11) {#v1.0.0.3}
|
[v1.0.0.3][v1.0.0.3] (2025-08-11) {#v1.0.0.3}
|
||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
|
|
||||||
|
@@ -115,6 +115,16 @@ namespace Elwig {
|
|||||||
BranchNum = branches.Count;
|
BranchNum = branches.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config.WeighingMode == null) {
|
||||||
|
if (App.Client.IsMatzen || App.Client.IsWolkersdorf) {
|
||||||
|
Config.WeighingMode = WeighingMode.Net;
|
||||||
|
} else if (App.Client.IsHaugsdorf || App.Client.IsSitzendorf) {
|
||||||
|
Config.WeighingMode = WeighingMode.Box;
|
||||||
|
} else if (App.Client.IsBaden || App.Client.IsGrInzersdorf) {
|
||||||
|
Config.WeighingMode = WeighingMode.Gross;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Utils.RunBackground("Temp File Cleanup", () => {
|
Utils.RunBackground("Temp File Cleanup", () => {
|
||||||
Utils.CleanupTempFiles();
|
Utils.CleanupTempFiles();
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
@@ -242,7 +252,9 @@ namespace Elwig {
|
|||||||
|
|
||||||
public static async Task ReplaceDatabase(string filename) {
|
public static async Task ReplaceDatabase(string filename) {
|
||||||
try {
|
try {
|
||||||
await ElwigData.ImportDatabase(filename);
|
await Task.Run(async () => {
|
||||||
|
await Database.Import(filename);
|
||||||
|
});
|
||||||
MessageBox.Show("Das Ersetzen war erfolgreich!\n\nBitte starten Sie Elwig neu!", "Datenbank ersetzen", MessageBoxButton.OK, MessageBoxImage.Information);
|
MessageBox.Show("Das Ersetzen war erfolgreich!\n\nBitte starten Sie Elwig neu!", "Datenbank ersetzen", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||||
ForceShutdown = true;
|
ForceShutdown = true;
|
||||||
Current.Shutdown();
|
Current.Shutdown();
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<UseWPF>true</UseWPF>
|
<UseWPF>true</UseWPF>
|
||||||
<PreserveCompilationContext>true</PreserveCompilationContext>
|
<PreserveCompilationContext>true</PreserveCompilationContext>
|
||||||
<ApplicationIcon>Resources\Images\Elwig.ico</ApplicationIcon>
|
<ApplicationIcon>Resources\Images\Elwig.ico</ApplicationIcon>
|
||||||
<Version>1.0.0.3</Version>
|
<Version>1.0.0.5</Version>
|
||||||
<SatelliteResourceLanguages>de-AT</SatelliteResourceLanguages>
|
<SatelliteResourceLanguages>de-AT</SatelliteResourceLanguages>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
@@ -25,19 +25,19 @@
|
|||||||
<PackageReference Include="LinqKit" Version="1.3.8" />
|
<PackageReference Include="LinqKit" Version="1.3.8" />
|
||||||
<PackageReference Include="MailKit" Version="4.13.0" />
|
<PackageReference Include="MailKit" Version="4.13.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Razor.Language" Version="6.0.36" />
|
<PackageReference Include="Microsoft.AspNetCore.Razor.Language" Version="6.0.36" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="9.0.8" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="9.0.9" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.8" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.9" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="9.0.8" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="9.0.9" />
|
||||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3405.78" />
|
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3485.44" />
|
||||||
<PackageReference Include="NJsonSchema" Version="11.4.0" />
|
<PackageReference Include="NJsonSchema" Version="11.4.0" />
|
||||||
<PackageReference Include="PdfiumViewer" Version="2.13.0" />
|
<PackageReference Include="PdfiumViewer" Version="2.13.0" />
|
||||||
<PackageReference Include="PdfiumViewer.Native.x86_64.no_v8-no_xfa" Version="2018.4.8.256" />
|
<PackageReference Include="PdfiumViewer.Native.x86_64.no_v8-no_xfa" Version="2018.4.8.256" />
|
||||||
<PackageReference Include="RazorLight" Version="2.3.1" />
|
<PackageReference Include="RazorLight" Version="2.3.1" />
|
||||||
<PackageReference Include="ScottPlot.WPF" Version="5.0.55" />
|
<PackageReference Include="ScottPlot.WPF" Version="5.0.56" />
|
||||||
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="3.0.1" />
|
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="3.0.2" />
|
||||||
<PackageReference Include="System.IO.Hashing" Version="9.0.8" />
|
<PackageReference Include="System.IO.Hashing" Version="9.0.9" />
|
||||||
<PackageReference Include="System.IO.Ports" Version="9.0.8" />
|
<PackageReference Include="System.IO.Ports" Version="9.0.9" />
|
||||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="9.0.8" />
|
<PackageReference Include="System.Text.Encoding.CodePages" Version="9.0.9" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@@ -19,14 +19,6 @@ namespace Elwig.Helpers {
|
|||||||
public bool IsSitzendorf => IsWinzerkeller && App.ZwstId == "S";
|
public bool IsSitzendorf => IsWinzerkeller && App.ZwstId == "S";
|
||||||
public bool IsGrInzersdorf => IsWeinland;
|
public bool IsGrInzersdorf => IsWeinland;
|
||||||
|
|
||||||
public bool HasNetWeighing(string? zwstId) => IsMatzen || (IsWinzerkeller && zwstId == "W");
|
|
||||||
public bool HasNetWeighing(Branch? b) => HasNetWeighing(b?.ZwstId);
|
|
||||||
public bool HasNetWeighing() => HasNetWeighing(App.ZwstId);
|
|
||||||
|
|
||||||
public bool HasBoxWeighing(string? zwstId) => IsWinzerkeller && (zwstId != "W");
|
|
||||||
public bool HasBoxWeighing(Branch? b) => HasBoxWeighing(b?.ZwstId);
|
|
||||||
public bool HasBoxWeighing() => HasBoxWeighing(App.ZwstId);
|
|
||||||
|
|
||||||
public string NameToken;
|
public string NameToken;
|
||||||
public string NameShort;
|
public string NameShort;
|
||||||
public string Name;
|
public string Name;
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -5,6 +6,8 @@ using Microsoft.Extensions.Configuration;
|
|||||||
|
|
||||||
namespace Elwig.Helpers {
|
namespace Elwig.Helpers {
|
||||||
|
|
||||||
|
public enum WeighingMode { Gross, Net, Box }
|
||||||
|
|
||||||
public record struct ScaleConfig {
|
public record struct ScaleConfig {
|
||||||
public string Id;
|
public string Id;
|
||||||
public string? Type;
|
public string? Type;
|
||||||
@@ -41,6 +44,7 @@ namespace Elwig.Helpers {
|
|||||||
public string DatabaseFile = App.DataPath + "database.sqlite3";
|
public string DatabaseFile = App.DataPath + "database.sqlite3";
|
||||||
public string? DatabaseLog = null;
|
public string? DatabaseLog = null;
|
||||||
public string? Branch = null;
|
public string? Branch = null;
|
||||||
|
public WeighingMode? WeighingMode;
|
||||||
public string? UpdateUrl = null;
|
public string? UpdateUrl = null;
|
||||||
public bool UpdateAuto = false;
|
public bool UpdateAuto = false;
|
||||||
public string? SyncUrl = null;
|
public string? SyncUrl = null;
|
||||||
@@ -74,6 +78,8 @@ namespace Elwig.Helpers {
|
|||||||
DatabaseLog = log != null ? Path.Combine(Path.GetDirectoryName(FileName) ?? App.DataPath, log) : null;
|
DatabaseLog = log != null ? Path.Combine(Path.GetDirectoryName(FileName) ?? App.DataPath, log) : null;
|
||||||
Branch = config["general:branch"];
|
Branch = config["general:branch"];
|
||||||
Debug = TrueValues.Contains(config["general:debug"]?.ToLower());
|
Debug = TrueValues.Contains(config["general:debug"]?.ToLower());
|
||||||
|
var weighing = config["general:weighing"];
|
||||||
|
WeighingMode = weighing != null && Enum.TryParse<WeighingMode>(weighing, true, out var w) ? w : null;
|
||||||
UpdateUrl = config["update:url"];
|
UpdateUrl = config["update:url"];
|
||||||
UpdateAuto = TrueValues.Contains(config["update:auto"]?.ToLower());
|
UpdateAuto = TrueValues.Contains(config["update:auto"]?.ToLower());
|
||||||
SyncUrl = config["sync:url"];
|
SyncUrl = config["sync:url"];
|
||||||
|
188
Elwig/Helpers/Export/Database.cs
Normal file
188
Elwig/Helpers/Export/Database.cs
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Elwig.Helpers.Export {
|
||||||
|
public static class Database {
|
||||||
|
|
||||||
|
public static async Task ExportSqlite(string filename, bool zipFile) {
|
||||||
|
if (zipFile) {
|
||||||
|
File.Delete(filename);
|
||||||
|
using var zip = ZipFile.Open(filename, ZipArchiveMode.Create);
|
||||||
|
await zip.CheckIntegrity();
|
||||||
|
var db = zip.CreateEntryFromFile(App.Config.DatabaseFile, "database.sqlite3", CompressionLevel.SmallestSize);
|
||||||
|
} else {
|
||||||
|
File.Copy(App.Config.DatabaseFile, filename, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task ExportSql(string filename, bool zipFile) {
|
||||||
|
if (zipFile) {
|
||||||
|
File.Delete(filename);
|
||||||
|
using var zip = ZipFile.Open(filename, ZipArchiveMode.Create);
|
||||||
|
var entry = zip.CreateEntry("database.sql", CompressionLevel.SmallestSize);
|
||||||
|
using var stream = entry.Open();
|
||||||
|
using var writer = new StreamWriter(stream, Utils.UTF8);
|
||||||
|
await ExportSql(writer);
|
||||||
|
} else {
|
||||||
|
using var stream = File.OpenWrite(filename);
|
||||||
|
using var writer = new StreamWriter(stream, Utils.UTF8);
|
||||||
|
await ExportSql(writer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task ExportSql(StreamWriter writer) {
|
||||||
|
using var cnx = await AppDbContext.ConnectAsync();
|
||||||
|
|
||||||
|
var tables = new List<(string Name, string Sql)>();
|
||||||
|
using (var cmd = cnx.CreateCommand()) {
|
||||||
|
cmd.CommandText = "SELECT name, sql FROM sqlite_schema WHERE type = 'table'";
|
||||||
|
using var reader = await cmd.ExecuteReaderAsync();
|
||||||
|
while (await reader.ReadAsync()) {
|
||||||
|
tables.Add((reader.GetString(0), reader.GetString(1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var applId = (long?)await AppDbContext.ExecuteScalar(cnx, "PRAGMA application_id") ?? 0;
|
||||||
|
var userVers = (long?)await AppDbContext.ExecuteScalar(cnx, "PRAGMA user_version") ?? 0;
|
||||||
|
var schemaVers = (long?)await AppDbContext.ExecuteScalar(cnx, "PRAGMA schema_version") ?? 0;
|
||||||
|
|
||||||
|
await writer.WriteLineAsync($"-- Elwig database dump, {DateTime.Now:yyyy-MM-dd, HH:mm:ss}");
|
||||||
|
await writer.WriteLineAsync($"-- {Environment.MachineName}, Zwst. {App.BranchName}, {App.Client.Name}");
|
||||||
|
await writer.WriteLineAsync("BEGIN TRANSACTION;");
|
||||||
|
await writer.WriteLineAsync("PRAGMA foreign_keys=OFF;");
|
||||||
|
await writer.WriteLineAsync($"PRAGMA application_id=0x{applId:X8};");
|
||||||
|
await writer.WriteLineAsync($"PRAGMA user_version=0x{userVers:X8};");
|
||||||
|
|
||||||
|
foreach (var t in tables) {
|
||||||
|
await writer.WriteAsync(t.Sql);
|
||||||
|
await writer.WriteLineAsync(";");
|
||||||
|
|
||||||
|
var columnNames = new List<string>();
|
||||||
|
using (var cmd = cnx.CreateCommand()) {
|
||||||
|
cmd.CommandText = $"PRAGMA table_info({t.Name})";
|
||||||
|
using var reader = await cmd.ExecuteReaderAsync();
|
||||||
|
while (await reader.ReadAsync()) {
|
||||||
|
columnNames.Add(reader.GetString(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var cmd = cnx.CreateCommand()) {
|
||||||
|
cmd.CommandText = $"SELECT {string.Join(',', columnNames)} FROM {t.Name}";
|
||||||
|
using var reader = await cmd.ExecuteReaderAsync();
|
||||||
|
var columns = await reader.GetColumnSchemaAsync();
|
||||||
|
var values = new object[reader.FieldCount];
|
||||||
|
while (await reader.ReadAsync()) {
|
||||||
|
await writer.WriteAsync($"INSERT INTO {t.Name} VALUES (");
|
||||||
|
|
||||||
|
reader.GetValues(values);
|
||||||
|
for (int i = 0; i < columns.Count; i++) {
|
||||||
|
var c = columns[i];
|
||||||
|
var v = values[i];
|
||||||
|
if (i > 0) await writer.WriteAsync(",");
|
||||||
|
if (v == null || v is DBNull) {
|
||||||
|
await writer.WriteAsync("NULL");
|
||||||
|
} else if (c.DataTypeName == "TEXT") {
|
||||||
|
await writer.WriteAsync($"'{v.ToString()?.Replace("'", "''")}'");
|
||||||
|
} else {
|
||||||
|
await writer.WriteAsync(v.ToString()?.Replace(',', '.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await writer.WriteLineAsync(");");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var cmd = cnx.CreateCommand()) {
|
||||||
|
cmd.CommandText = "SELECT sql FROM sqlite_schema WHERE type != 'table' AND sql IS NOT NULL";
|
||||||
|
using var reader = await cmd.ExecuteReaderAsync();
|
||||||
|
while (await reader.ReadAsync()) {
|
||||||
|
await writer.WriteAsync(reader.GetString(0));
|
||||||
|
await writer.WriteLineAsync(";");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await writer.WriteLineAsync($"PRAGMA schema_version={schemaVers};");
|
||||||
|
await writer.WriteLineAsync("PRAGMA foreign_keys=ON;");
|
||||||
|
await writer.WriteLineAsync("COMMIT;");
|
||||||
|
await writer.WriteLineAsync("VACUUM;");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task Import(string filename) {
|
||||||
|
if (filename.EndsWith(".sql")) {
|
||||||
|
await ImportSql(filename, false);
|
||||||
|
} else if (filename.EndsWith(".sql.zip")) {
|
||||||
|
await ImportSql(filename, true);
|
||||||
|
} else if (filename.EndsWith(".sqlite3")) {
|
||||||
|
await ImportSqlite(filename, false);
|
||||||
|
} else if (filename.EndsWith(".sqlite3.zip")) {
|
||||||
|
await ImportSqlite(filename, true);
|
||||||
|
} else {
|
||||||
|
throw new ArgumentException($"Unknown file extension for importing: '{filename}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task ImportSql(string filename, bool zipFile = false) {
|
||||||
|
if (zipFile) {
|
||||||
|
using var zip = ZipFile.Open(filename, ZipArchiveMode.Read);
|
||||||
|
await zip.CheckIntegrity();
|
||||||
|
foreach (var entry in zip.Entries) {
|
||||||
|
if (entry.Name.EndsWith(".sql")) {
|
||||||
|
using var stream = entry.Open();
|
||||||
|
using var reader = new StreamReader(stream, Utils.UTF8);
|
||||||
|
await ImportSql(reader);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new FileFormatException("ZIP archive has to contain at least one .sql file");
|
||||||
|
} else {
|
||||||
|
using var stream = File.Open(filename, FileMode.Open);
|
||||||
|
using var reader = new StreamReader(stream, Utils.UTF8);
|
||||||
|
await ImportSql(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task ImportSqlite(string filename, bool zipFile = false) {
|
||||||
|
if (zipFile) {
|
||||||
|
var newName = Path.ChangeExtension(App.Config.DatabaseFile, ".new.sqlite3");
|
||||||
|
try {
|
||||||
|
using var zip = ZipFile.Open(filename, ZipArchiveMode.Read);
|
||||||
|
await zip.CheckIntegrity();
|
||||||
|
foreach (var entry in zip.Entries) {
|
||||||
|
if (entry.Name.EndsWith(".sqlite3")) {
|
||||||
|
entry.ExtractToFile(newName);
|
||||||
|
await ImportSqlite(newName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new FileFormatException("ZIP archive has to contain at least one .sqlite3 file");
|
||||||
|
} finally {
|
||||||
|
if (File.Exists(newName)) File.Delete(newName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var oldName = Path.ChangeExtension(App.Config.DatabaseFile, ".old.sqlite3");
|
||||||
|
File.Move(App.Config.DatabaseFile, oldName, true);
|
||||||
|
File.Move(filename, App.Config.DatabaseFile, false);
|
||||||
|
|
||||||
|
using var cnx = await AppDbContext.ConnectAsync();
|
||||||
|
await AppDbContext.ExecuteBatch(cnx, "VACUUM");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task ImportSql(StreamReader reader) {
|
||||||
|
var newName = Path.ChangeExtension(App.Config.DatabaseFile, ".new.sqlite3");
|
||||||
|
File.Delete(newName);
|
||||||
|
try {
|
||||||
|
using (var cnx = await AppDbContext.ConnectAsync($"Data Source=\"{newName}\"; Mode=ReadWriteCreate; Foreign Keys=False; Cache=Default; Pooling=False")) {
|
||||||
|
await AppDbContext.ExecuteBatch(cnx, await reader.ReadToEndAsync());
|
||||||
|
}
|
||||||
|
await ImportSqlite(newName);
|
||||||
|
} finally {
|
||||||
|
if (File.Exists(newName)) File.Delete(newName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -405,29 +405,6 @@ namespace Elwig.Helpers.Export {
|
|||||||
}.Export(filename);
|
}.Export(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task 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)) {
|
|
||||||
await zip.CheckIntegrity();
|
|
||||||
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 class ElwigExport {
|
||||||
public (IEnumerable<WbKg> WbKgs, IEnumerable<string> Filters)? WbKgs { get; set; }
|
public (IEnumerable<WbKg> WbKgs, IEnumerable<string> Filters)? WbKgs { get; set; }
|
||||||
public (IEnumerable<Member> Members, IEnumerable<string> Filters)? Members { get; set; }
|
public (IEnumerable<Member> Members, IEnumerable<string> Filters)? Members { get; set; }
|
||||||
|
@@ -498,10 +498,7 @@ namespace Elwig.Helpers {
|
|||||||
public static async Task<bool> SendEmail(Member member, string subject, string text, IEnumerable<Document> docs) {
|
public static async Task<bool> SendEmail(Member member, string subject, string text, IEnumerable<Document> docs) {
|
||||||
if (App.Config.Smtp == null)
|
if (App.Config.Smtp == null)
|
||||||
return false;
|
return false;
|
||||||
|
return await Task.Run(async () => {
|
||||||
Mouse.OverrideCursor = Cursors.Wait;
|
|
||||||
|
|
||||||
var success = await Task.Run(async () => {
|
|
||||||
SmtpClient? client = null;
|
SmtpClient? client = null;
|
||||||
try {
|
try {
|
||||||
client = await GetSmtpClient();
|
client = await GetSmtpClient();
|
||||||
@@ -529,18 +526,15 @@ namespace Elwig.Helpers {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
Mouse.OverrideCursor = null;
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task ExportDocument(Document doc, ExportMode mode, string? filename = null, (Member, string, string)? emailData = null) {
|
public static async Task ExportDocument(Document doc, ExportMode mode, string? filename = null, (Member Member, string Subject, string Text)? emailData = null) {
|
||||||
if (mode == ExportMode.Print && !App.Config.Debug) {
|
if (mode == ExportMode.Print && !App.Config.Debug) {
|
||||||
await doc.Generate();
|
await doc.Generate();
|
||||||
await doc.Print();
|
await doc.Print();
|
||||||
} else if (mode == ExportMode.Email && emailData is (Member, string, string) e) {
|
} else if (mode == ExportMode.Email && emailData is (Member, string, string) e) {
|
||||||
await doc.Generate();
|
await doc.Generate();
|
||||||
var success = await SendEmail(e.Item1, e.Item2, e.Item3, [doc]);
|
var success = await SendEmail(e.Member, e.Subject, e.Text, [doc]);
|
||||||
if (success)
|
if (success)
|
||||||
MessageBox.Show("Die E-Mail wurde erfolgreich verschickt!", "E-Mail verschickt",
|
MessageBox.Show("Die E-Mail wurde erfolgreich verschickt!", "E-Mail verschickt",
|
||||||
MessageBoxButton.OK, MessageBoxImage.Information);
|
MessageBoxButton.OK, MessageBoxImage.Information);
|
||||||
@@ -567,9 +561,7 @@ namespace Elwig.Helpers {
|
|||||||
Log = "Application",
|
Log = "Application",
|
||||||
Source = ".NET Runtime",
|
Source = ".NET Runtime",
|
||||||
};
|
};
|
||||||
return log.Entries.Cast<EventLogEntry>()
|
return [.. log.Entries.OfType<EventLogEntry>().Where(e => e.InstanceId == 1026).Where(e => e.Message.StartsWith("Application: Elwig.exe"))];
|
||||||
.Where(e => e.Message.StartsWith("Application: Elwig.exe"))
|
|
||||||
.ToList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int GetEntityIdetifierForPk(params object?[] primaryKey) {
|
public static int GetEntityIdetifierForPk(params object?[] primaryKey) {
|
||||||
|
32
Elwig/Windows/AboutWindow.xaml
Normal file
32
Elwig/Windows/AboutWindow.xaml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<Window x:Class="Elwig.Windows.AboutWindow"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:local="clr-namespace:Elwig.Windows"
|
||||||
|
Title="Über - Elwig" Height="340" Width="480" ResizeMode="NoResize">
|
||||||
|
<Grid>
|
||||||
|
<TextBlock Margin="20,10" FontSize="12">
|
||||||
|
<Bold>Produkt:</Bold> Elwig<LineBreak/>
|
||||||
|
<Bold>Beschreibung:</Bold> Elektronische Winzergenossenschaftsveraltung<LineBreak/>
|
||||||
|
<Bold>Typ:</Bold> Warenwirschaftssystem<LineBreak/>
|
||||||
|
<Bold>Version:</Bold> <Run x:Name="Version">0.0.0.0</Run> (<Hyperlink NavigateUri="https://elwig.at/changelog" RequestNavigate="Hyperlink_RequestNavigate">Änderungsprotokoll</Hyperlink>)<LineBreak/>
|
||||||
|
<Bold>Lizenz:</Bold> <Hyperlink NavigateUri="https://www.gnu.org/licenses/gpl-3.0.html" RequestNavigate="Hyperlink_RequestNavigate">GNU General Public License 3.0 (GPLv3)</Hyperlink><LineBreak/>
|
||||||
|
<Bold>Website:</Bold> <Hyperlink NavigateUri="https://elwig.at/" RequestNavigate="Hyperlink_RequestNavigate">https://elwig.at/</Hyperlink><LineBreak/>
|
||||||
|
<Bold>Entwickler:</Bold> Lorenz Stechauner, Thomas Hilscher<LineBreak/>
|
||||||
|
<Bold>Kontakt:</Bold> <Hyperlink NavigateUri="mailto:lorenz.stechauner@necronda.net" RequestNavigate="Hyperlink_RequestNavigate">lorenz.stechauner@necronda.net</Hyperlink>, <Hyperlink NavigateUri="mailto:thomas.hilscher@gmail.com" RequestNavigate="Hyperlink_RequestNavigate">thomas.hilscher@gmail.com</Hyperlink><LineBreak/>
|
||||||
|
<Bold>Quellcode:</Bold> <Hyperlink NavigateUri="https://git.necronda.net/winzer/elwig" RequestNavigate="Hyperlink_RequestNavigate">https://git.necronda.net/winzer/elwig</Hyperlink><LineBreak/>
|
||||||
|
<Bold>Entwicklungszeitraum:</Bold> 2022–2025<LineBreak/>
|
||||||
|
<LineBreak/>
|
||||||
|
<Bold>Verwendete Technologien:</Bold><LineBreak/>
|
||||||
|
Programmiersprache: C#<LineBreak/>
|
||||||
|
Framework: Windows Presentation Framework (WPF)<LineBreak/>
|
||||||
|
Datenbank: <Hyperlink NavigateUri="https://sqlite.org/" RequestNavigate="Hyperlink_RequestNavigate">SQLite</Hyperlink><LineBreak/>
|
||||||
|
PDF-Erstellung: <Hyperlink NavigateUri="https://weasyprint.org/" RequestNavigate="Hyperlink_RequestNavigate">WeasyPrint</Hyperlink>, <Hyperlink NavigateUri="https://github.com/toddams/RazorLight" RequestNavigate="Hyperlink_RequestNavigate">RazorLight</Hyperlink>, <Hyperlink NavigateUri="https://github.com/pvginkel/PdfiumViewer" RequestNavigate="Hyperlink_RequestNavigate">PdfiumViewer</Hyperlink><LineBreak/>
|
||||||
|
Paketierung: <Hyperlink NavigateUri="https://www.firegiant.com/wixtoolset/" RequestNavigate="Hyperlink_RequestNavigate">WiX Toolset</Hyperlink>
|
||||||
|
</TextBlock>
|
||||||
|
|
||||||
|
<Image Source="\Resources\Images\Elwig.png" RenderOptions.BitmapScalingMode="HighQuality" Height="96"
|
||||||
|
HorizontalAlignment="Right" Margin="10" VerticalAlignment="Top"/>
|
||||||
|
</Grid>
|
||||||
|
</Window>
|
17
Elwig/Windows/AboutWindow.xaml.cs
Normal file
17
Elwig/Windows/AboutWindow.xaml.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Navigation;
|
||||||
|
|
||||||
|
namespace Elwig.Windows {
|
||||||
|
public partial class AboutWindow : Window {
|
||||||
|
|
||||||
|
public AboutWindow() {
|
||||||
|
InitializeComponent();
|
||||||
|
Version.Text = App.Version.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e) {
|
||||||
|
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri) { UseShellExecute = true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -13,8 +13,8 @@ using System.Windows.Input;
|
|||||||
namespace Elwig.Windows {
|
namespace Elwig.Windows {
|
||||||
public abstract class AdministrationWindow : ContextWindow {
|
public abstract class AdministrationWindow : ContextWindow {
|
||||||
|
|
||||||
protected Control[] ExemptInputs { private get; set; }
|
protected Control[] ExemptInputs { get; set; }
|
||||||
protected Control[] RequiredInputs { private get; set; }
|
protected Control[] RequiredInputs { get; set; }
|
||||||
|
|
||||||
private bool _isEditing;
|
private bool _isEditing;
|
||||||
private bool _isCreating;
|
private bool _isCreating;
|
||||||
@@ -166,8 +166,10 @@ namespace Elwig.Windows {
|
|||||||
Valid[input] = false;
|
Valid[input] = false;
|
||||||
} else if (input is ComboBox cb && cb.SelectedItem == null && cb.ItemsSource != null && cb.ItemsSource.Cast<object>().Any()) {
|
} else if (input is ComboBox cb && cb.SelectedItem == null && cb.ItemsSource != null && cb.ItemsSource.Cast<object>().Any()) {
|
||||||
ControlUtils.SetInputInvalid(input);
|
ControlUtils.SetInputInvalid(input);
|
||||||
|
Valid[input] = false;
|
||||||
} else if (input is ListBox lb && lb.SelectedItem == null && lb.ItemsSource != null && lb.ItemsSource.Cast<object>().Any()) {
|
} else if (input is ListBox lb && lb.SelectedItem == null && lb.ItemsSource != null && lb.ItemsSource.Cast<object>().Any()) {
|
||||||
ControlUtils.SetInputInvalid(input);
|
ControlUtils.SetInputInvalid(input);
|
||||||
|
Valid[input] = false;
|
||||||
} else if (input is CheckBox ckb && ((ckb.IsThreeState && ckb.IsChecked == null) || (!ckb.IsThreeState && ckb.IsChecked != true))) {
|
} else if (input is CheckBox ckb && ((ckb.IsThreeState && ckb.IsChecked == null) || (!ckb.IsThreeState && ckb.IsChecked != true))) {
|
||||||
ControlUtils.SetInputInvalid(input);
|
ControlUtils.SetInputInvalid(input);
|
||||||
Valid[input] = false;
|
Valid[input] = false;
|
||||||
|
@@ -89,6 +89,9 @@ namespace Elwig.Windows {
|
|||||||
foreach (var s in App.EventScales) {
|
foreach (var s in App.EventScales) {
|
||||||
s.WeighingEvent += Scale_Weighing;
|
s.WeighingEvent += Scale_Weighing;
|
||||||
}
|
}
|
||||||
|
if (App.Client.IsMatzen) {
|
||||||
|
RequiredInputs = [.. RequiredInputs, ModifiersInput];
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
WeighingManualButton.Visibility = Visibility.Hidden;
|
WeighingManualButton.Visibility = Visibility.Hidden;
|
||||||
WeighingAButton.Visibility = Visibility.Hidden;
|
WeighingAButton.Visibility = Visibility.Hidden;
|
||||||
@@ -278,6 +281,7 @@ namespace Elwig.Windows {
|
|||||||
DateInput.IsReadOnly = false;
|
DateInput.IsReadOnly = false;
|
||||||
TimeInput.IsReadOnly = false;
|
TimeInput.IsReadOnly = false;
|
||||||
BranchInput.IsEnabled = true;
|
BranchInput.IsEnabled = true;
|
||||||
|
GerebeltGewogenInput.IsEnabled = true;
|
||||||
if (IsCreating) ViewModel.Time = "";
|
if (IsCreating) ViewModel.Time = "";
|
||||||
OnSecondPassed(null, null);
|
OnSecondPassed(null, null);
|
||||||
}
|
}
|
||||||
@@ -287,6 +291,7 @@ namespace Elwig.Windows {
|
|||||||
DateInput.IsReadOnly = true;
|
DateInput.IsReadOnly = true;
|
||||||
TimeInput.IsReadOnly = true;
|
TimeInput.IsReadOnly = true;
|
||||||
BranchInput.IsEnabled = false;
|
BranchInput.IsEnabled = false;
|
||||||
|
GerebeltGewogenInput.IsEnabled = App.Config.WeighingMode != WeighingMode.Net;
|
||||||
OnSecondPassed(null, null);
|
OnSecondPassed(null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,7 +306,7 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void InitialDefaultInputs() {
|
private void InitialDefaultInputs() {
|
||||||
if (App.Client.HasNetWeighing(ViewModel.Branch)) {
|
if (App.Config.WeighingMode == WeighingMode.Net) {
|
||||||
GerebeltGewogenInput.IsEnabled = false;
|
GerebeltGewogenInput.IsEnabled = false;
|
||||||
SetDefaultValue(GerebeltGewogenInput, true);
|
SetDefaultValue(GerebeltGewogenInput, true);
|
||||||
} else {
|
} else {
|
||||||
@@ -310,7 +315,7 @@ namespace Elwig.Windows {
|
|||||||
UnsetDefaultValue(GerebeltGewogenInput);
|
UnsetDefaultValue(GerebeltGewogenInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (App.Client.HasBoxWeighing(ViewModel.Branch)) {
|
if (App.Config.WeighingMode == WeighingMode.Box) {
|
||||||
LesewagenInput.IsEnabled = false;
|
LesewagenInput.IsEnabled = false;
|
||||||
SetDefaultValue(LesewagenInput, false);
|
SetDefaultValue(LesewagenInput, false);
|
||||||
} else {
|
} else {
|
||||||
@@ -318,7 +323,7 @@ namespace Elwig.Windows {
|
|||||||
UnsetDefaultValue(LesewagenInput);
|
UnsetDefaultValue(LesewagenInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!App.Client.HasNetWeighing(ViewModel.Branch)) {
|
if (App.Config.WeighingMode != WeighingMode.Net) {
|
||||||
HandPickedInput.IsThreeState = false;
|
HandPickedInput.IsThreeState = false;
|
||||||
UnsetDefaultValue(HandPickedInput);
|
UnsetDefaultValue(HandPickedInput);
|
||||||
} else {
|
} else {
|
||||||
@@ -344,13 +349,13 @@ namespace Elwig.Windows {
|
|||||||
ClearOriginalValues();
|
ClearOriginalValues();
|
||||||
ClearDefaultValues();
|
ClearDefaultValues();
|
||||||
|
|
||||||
ViewModel.IsNetWeight = App.Client.HasNetWeighing(ViewModel.Branch);
|
ViewModel.IsNetWeight = App.Config.WeighingMode == WeighingMode.Net;
|
||||||
ViewModel.IsLesewagen = false;
|
ViewModel.IsLesewagen = false;
|
||||||
ViewModel.IsHandPicked = !App.Client.HasNetWeighing(ViewModel.Branch) ? true : null;
|
ViewModel.IsHandPicked = App.Config.WeighingMode != WeighingMode.Net ? true : null;
|
||||||
ViewModel.IsGebunden = null;
|
ViewModel.IsGebunden = null;
|
||||||
InitialDefaultInputs();
|
InitialDefaultInputs();
|
||||||
|
|
||||||
WineQualityLevelInput.IsEnabled = false;
|
//WineQualityLevelInput.IsEnabled = false; // disable wine quality level input in Übernahme
|
||||||
ValidateRequiredInputs();
|
ValidateRequiredInputs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1139,6 +1144,7 @@ namespace Elwig.Windows {
|
|||||||
DateInput.IsReadOnly = !Menu_Settings_EnableFreeEditing.IsChecked;
|
DateInput.IsReadOnly = !Menu_Settings_EnableFreeEditing.IsChecked;
|
||||||
TimeInput.IsReadOnly = !Menu_Settings_EnableFreeEditing.IsChecked;
|
TimeInput.IsReadOnly = !Menu_Settings_EnableFreeEditing.IsChecked;
|
||||||
BranchInput.IsEnabled = Menu_Settings_EnableFreeEditing.IsChecked;
|
BranchInput.IsEnabled = Menu_Settings_EnableFreeEditing.IsChecked;
|
||||||
|
GerebeltGewogenInput.IsEnabled = App.Config.WeighingMode == WeighingMode.Net || Menu_Settings_EnableFreeEditing.IsChecked;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DisableWeighingButtons() {
|
private void DisableWeighingButtons() {
|
||||||
@@ -1389,17 +1395,17 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void GerebeltGewogenInput_Changed(object sender, RoutedEventArgs evt) {
|
private void GerebeltGewogenInput_Changed(object sender, RoutedEventArgs evt) {
|
||||||
if ((IsEditing || IsCreating) && !App.Client.HasNetWeighing(ViewModel.Branch)) {
|
if ((IsEditing || IsCreating) && App.Config.WeighingMode != WeighingMode.Net) {
|
||||||
HandPickedInput.IsChecked = !GerebeltGewogenInput.IsChecked;
|
HandPickedInput.IsChecked = !GerebeltGewogenInput.IsChecked;
|
||||||
}
|
}
|
||||||
if (!ViewModel.IsReceipt || App.Client.HasNetWeighing(ViewModel.Branch)) {
|
if (!ViewModel.IsReceipt || App.Config.WeighingMode == WeighingMode.Net) {
|
||||||
GerebeltGewogenInput.IsChecked ??= false;
|
GerebeltGewogenInput.IsChecked ??= false;
|
||||||
}
|
}
|
||||||
CheckBox_Changed(sender, evt);
|
CheckBox_Changed(sender, evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandPickedInput_Changed(object sender, RoutedEventArgs evt) {
|
private void HandPickedInput_Changed(object sender, RoutedEventArgs evt) {
|
||||||
if ((IsEditing || IsCreating) && !App.Client.HasNetWeighing(ViewModel.Branch)) {
|
if ((IsEditing || IsCreating) && App.Config.WeighingMode != WeighingMode.Net) {
|
||||||
GerebeltGewogenInput.IsChecked = !HandPickedInput.IsChecked;
|
GerebeltGewogenInput.IsChecked = !HandPickedInput.IsChecked;
|
||||||
}
|
}
|
||||||
CheckBox_Changed(sender, evt);
|
CheckBox_Changed(sender, evt);
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
using Elwig.Helpers;
|
using Elwig.Helpers;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Input;
|
||||||
|
|
||||||
namespace Elwig.Windows {
|
namespace Elwig.Windows {
|
||||||
public partial class LogWindow : Window {
|
public partial class LogWindow : Window {
|
||||||
@@ -11,28 +13,34 @@ namespace Elwig.Windows {
|
|||||||
WindowState = WindowState.Maximized;
|
WindowState = WindowState.Maximized;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Window_Loaded(object sender, RoutedEventArgs evt) {
|
private async void Window_Loaded(object sender, RoutedEventArgs evt) {
|
||||||
var log = Utils.GetLogEntries();
|
Mouse.OverrideCursor = Cursors.Wait;
|
||||||
EventList.ItemsSource = log
|
await Task.Run(async () => {
|
||||||
.Select(e => new {
|
var list = Utils.GetLogEntries()
|
||||||
Event = e,
|
.Select(e => new {
|
||||||
Lines = e.Message.Split('\n').ToArray(),
|
Event = e,
|
||||||
})
|
Lines = e.Message.Split('\n').ToArray(),
|
||||||
.Select(e => new {
|
})
|
||||||
e.Event,
|
.Select(e => new {
|
||||||
Exception = e.Lines.FirstOrDefault(l => l.StartsWith("Exception Info: "))?[16..].Trim().Split(':', 2),
|
e.Event,
|
||||||
Location = e.Lines.FirstOrDefault(l => l.StartsWith(" at Elwig."))?[5..].Trim(),
|
Exception = e.Lines.FirstOrDefault(l => l.StartsWith("Exception Info: "))?[16..].Trim().Split(':', 2),
|
||||||
})
|
Location = e.Lines.FirstOrDefault(l => l.StartsWith(" at Elwig."))?[5..].Trim(),
|
||||||
.Select(e => new {
|
})
|
||||||
e.Event,
|
.Select(e => new {
|
||||||
e.Exception,
|
e.Event,
|
||||||
ExceptionName = e.Exception?[0].Trim(),
|
e.Exception,
|
||||||
ExceptionMessage = e.Exception?.Length >= 2 ? e.Exception?[1].Trim() : null,
|
ExceptionName = e.Exception?[0].Trim(),
|
||||||
e.Location,
|
ExceptionMessage = e.Exception?.Length >= 2 ? e.Exception?[1].Trim() : null,
|
||||||
})
|
e.Location,
|
||||||
.OrderByDescending(e => e.Event.TimeGenerated)
|
})
|
||||||
.ToList();
|
.OrderByDescending(e => e.Event.TimeGenerated)
|
||||||
EventList.SelectedIndex = 0;
|
.ToList();
|
||||||
|
await App.MainDispatcher.BeginInvoke(() => {
|
||||||
|
EventList.ItemsSource = list;
|
||||||
|
EventList.SelectedIndex = 0;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Mouse.OverrideCursor = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EventList_SelectionChanged(object sender, RoutedEventArgs evt) {
|
private void EventList_SelectionChanged(object sender, RoutedEventArgs evt) {
|
||||||
|
@@ -31,6 +31,17 @@
|
|||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<Separator/>
|
<Separator/>
|
||||||
|
<MenuItem Header="Datenbank sichern..." Click="Menu_Database_Backup_Click">
|
||||||
|
<MenuItem.Icon>
|
||||||
|
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="16" Text=""/>
|
||||||
|
</MenuItem.Icon>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem Header="Datenbank wiederherstellen..." Click="Menu_Database_Restore_Click">
|
||||||
|
<MenuItem.Icon>
|
||||||
|
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="16" Text=""/>
|
||||||
|
</MenuItem.Icon>
|
||||||
|
</MenuItem>
|
||||||
|
<Separator/>
|
||||||
<MenuItem Header="Abfragen stellen" Click="Menu_Database_Query_Click">
|
<MenuItem Header="Abfragen stellen" Click="Menu_Database_Query_Click">
|
||||||
<MenuItem.Icon>
|
<MenuItem.Icon>
|
||||||
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="16" Text=""/>
|
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="16" Text=""/>
|
||||||
@@ -61,7 +72,7 @@
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem x:Name="HelpMenu" Header="Hilfe">
|
<MenuItem x:Name="HelpMenu" Header="Hilfe">
|
||||||
<MenuItem Header="Über">
|
<MenuItem Header="Über" Click="Menu_Help_About_Click">
|
||||||
<MenuItem.Icon>
|
<MenuItem.Icon>
|
||||||
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="16" Text=""/>
|
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="16" Text=""/>
|
||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
|
@@ -59,6 +59,11 @@ namespace Elwig.Windows {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Menu_Help_About_Click(object sender, RoutedEventArgs evt) {
|
||||||
|
var w = new AboutWindow();
|
||||||
|
w.Show();
|
||||||
|
}
|
||||||
|
|
||||||
private async void Menu_Help_Update_Click(object sender, RoutedEventArgs evt) {
|
private async void Menu_Help_Update_Click(object sender, RoutedEventArgs evt) {
|
||||||
await App.CheckForUpdates(true);
|
await App.CheckForUpdates(true);
|
||||||
}
|
}
|
||||||
@@ -146,6 +151,48 @@ namespace Elwig.Windows {
|
|||||||
Mouse.OverrideCursor = null;
|
Mouse.OverrideCursor = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async void Menu_Database_Backup_Click(object sender, RoutedEventArgs evt) {
|
||||||
|
try {
|
||||||
|
var d = new SaveFileDialog() {
|
||||||
|
Title = "Datenbank sichern - Elwig",
|
||||||
|
FileName = $"database_{Utils.Today:yyyy-MM-dd}.sql.zip",
|
||||||
|
DefaultExt = "sql.zip",
|
||||||
|
Filter = "Komprimierte SQL-Datei (*.sql.zip)|*.sql.zip",
|
||||||
|
};
|
||||||
|
if (d.ShowDialog() == true) {
|
||||||
|
Mouse.OverrideCursor = Cursors.Wait;
|
||||||
|
await Task.Run(async () => {
|
||||||
|
await Database.ExportSql(d.FileName, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (Exception exc) {
|
||||||
|
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
Mouse.OverrideCursor = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void Menu_Database_Restore_Click(object sender, RoutedEventArgs evt) {
|
||||||
|
try {
|
||||||
|
var d = new OpenFileDialog() {
|
||||||
|
Title = "Datenbank wiederherstellen - Elwig",
|
||||||
|
DefaultExt = "sql.zip",
|
||||||
|
Filter = "SQLite-Datenbank (*.sqlite3, *.sqlite3.zip, *.sql, *.sql.zip)|*.sqlite3;*.sqlite3.zip;*.sql;*.sql.zip",
|
||||||
|
};
|
||||||
|
if (d.ShowDialog() == true) {
|
||||||
|
var res = MessageBox.Show("Soll die Datenbank wirklich unwiederruflich durch die wiederhergestellte Version ersetzt werden?", "Datenbank wiederherstellen",
|
||||||
|
MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel);
|
||||||
|
if (res != MessageBoxResult.OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Mouse.OverrideCursor = Cursors.Wait;
|
||||||
|
await App.ReplaceDatabase(d.FileName);
|
||||||
|
}
|
||||||
|
} catch (Exception exc) {
|
||||||
|
MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
Mouse.OverrideCursor = null;
|
||||||
|
}
|
||||||
|
|
||||||
private async void DownloadButton_Click(object sender, RoutedEventArgs evt) {
|
private async void DownloadButton_Click(object sender, RoutedEventArgs evt) {
|
||||||
if (App.Config.SyncUrl == null)
|
if (App.Config.SyncUrl == null)
|
||||||
return;
|
return;
|
||||||
@@ -243,21 +290,23 @@ namespace Elwig.Windows {
|
|||||||
await Task.Run(async () => {
|
await Task.Run(async () => {
|
||||||
try {
|
try {
|
||||||
var data = await Utils.GetExportMetaData(App.Config.SyncUrl, App.Config.SyncUsername, App.Config.SyncPassword);
|
var data = await Utils.GetExportMetaData(App.Config.SyncUrl, App.Config.SyncUsername, App.Config.SyncPassword);
|
||||||
var file = data
|
var files = data
|
||||||
.Select(f => new {
|
.Select(f => new {
|
||||||
Name = f!["name"]!.AsValue().GetValue<string>(),
|
Name = f!["name"]!.AsValue().GetValue<string>(),
|
||||||
Timestamp = f!["modified"] != null && DateTime.TryParseExact(f!["modified"]!.AsValue().GetValue<string>(), "yyyy-MM-ddTHH:mm:ssK", CultureInfo.InvariantCulture, DateTimeStyles.None, out var dt) ? dt : (DateTime?)null,
|
Timestamp = f!["modified"] != null && DateTime.TryParseExact(f!["modified"]!.AsValue().GetValue<string>(), "yyyy-MM-ddTHH:mm:ssK", CultureInfo.InvariantCulture, DateTimeStyles.None, out var dt) ? dt : (DateTime?)null,
|
||||||
Url = f!["url"]!.AsValue().GetValue<string>(),
|
Url = f!["url"]!.AsValue().GetValue<string>(),
|
||||||
Size = f!["size"]!.AsValue().GetValue<long>(),
|
Size = f!["size"]!.AsValue().GetValue<long>(),
|
||||||
})
|
})
|
||||||
.Where(f => f.Name == "database.sqlite3.zip")
|
.Where(f => f.Name.StartsWith("database.") && f.Name.EndsWith(".zip"))
|
||||||
.FirstOrDefault();
|
.OrderBy(f => f.Size)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
if (file == null) {
|
if (files.Count == 0) {
|
||||||
MessageBox.Show("Die Datenbank wurde noch nicht vom Hauptgerät hochgeladen!", "Datenbank herunterladen",
|
MessageBox.Show("Die Datenbank wurde noch nicht vom Hauptgerät hochgeladen!", "Datenbank herunterladen",
|
||||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
var file = files[0];
|
||||||
|
|
||||||
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",
|
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);
|
MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel);
|
||||||
@@ -301,8 +350,8 @@ namespace Elwig.Windows {
|
|||||||
Mouse.OverrideCursor = Cursors.Wait;
|
Mouse.OverrideCursor = Cursors.Wait;
|
||||||
await Task.Run(async () => {
|
await Task.Run(async () => {
|
||||||
try {
|
try {
|
||||||
var path = Path.Combine(App.TempPath, "database.sqlite3.zip");
|
var path = Path.Combine(App.TempPath, "database.sql.zip");
|
||||||
ElwigData.ExportDatabase(path);
|
await Database.ExportSql(path, true);
|
||||||
await Utils.UploadExportData(path, App.Config.SyncUrl, App.Config.SyncUsername, App.Config.SyncPassword);
|
await Utils.UploadExportData(path, App.Config.SyncUrl, App.Config.SyncUsername, App.Config.SyncPassword);
|
||||||
MessageBox.Show($"Hochladen der gesamten Datenbank erfolgreich!", "Datenbank hochladen",
|
MessageBox.Show($"Hochladen der gesamten Datenbank erfolgreich!", "Datenbank hochladen",
|
||||||
MessageBoxButton.OK, MessageBoxImage.Information);
|
MessageBoxButton.OK, MessageBoxImage.Information);
|
||||||
|
@@ -38,7 +38,7 @@ namespace Elwig.Windows {
|
|||||||
IList<DbColumn> header;
|
IList<DbColumn> header;
|
||||||
|
|
||||||
using (var cnx = await AppDbContext.ConnectAsync()) {
|
using (var cnx = await AppDbContext.ConnectAsync()) {
|
||||||
var cmd = cnx.CreateCommand();
|
using var cmd = cnx.CreateCommand();
|
||||||
cmd.CommandText = sqlQuery;
|
cmd.CommandText = sqlQuery;
|
||||||
using var reader = await cmd.ExecuteReaderAsync();
|
using var reader = await cmd.ExecuteReaderAsync();
|
||||||
header = await reader.GetColumnSchemaAsync();
|
header = await reader.GetColumnSchemaAsync();
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
</Target>
|
</Target>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Installer\Installer.wixproj" />
|
<ProjectReference Include="..\Installer\Installer.wixproj" />
|
||||||
<PackageReference Include="WixToolset.Bal.wixext" Version="6.0.1" />
|
<PackageReference Include="WixToolset.Bal.wixext" Version="6.0.2" />
|
||||||
<PackageReference Include="WixToolset.Util.wixext" Version="6.0.1" />
|
<PackageReference Include="WixToolset.Util.wixext" Version="6.0.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Reference in New Issue
Block a user