Save and load report PDF data to json
This commit is contained in:
@@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace ReceiptPDFBuilders.Helpers;
|
||||||
|
|
||||||
|
class Utilities
|
||||||
|
{
|
||||||
|
public static JsonSerializerOptions GetSerializerOptions()
|
||||||
|
{
|
||||||
|
var opts = new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
WriteIndented = false,
|
||||||
|
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||||
|
};
|
||||||
|
return opts;
|
||||||
|
}
|
||||||
|
}
|
||||||
+21
-5
@@ -12,14 +12,18 @@ namespace ReceiptPDFBuilder.Models;
|
|||||||
class PDFReport : ChangeNotifier
|
class PDFReport : ChangeNotifier
|
||||||
{
|
{
|
||||||
private string _baseFolder;
|
private string _baseFolder;
|
||||||
private string _name;
|
private string _title;
|
||||||
private List<ReportFile> _files;
|
private List<ReportFile> _files;
|
||||||
|
private DateTime _lastSaved;
|
||||||
|
private DateTime? _lastGenerated;
|
||||||
|
|
||||||
public PDFReport()
|
public PDFReport()
|
||||||
{
|
{
|
||||||
_baseFolder = "";
|
_baseFolder = "";
|
||||||
_name = "";
|
_title = "";
|
||||||
_files = [];
|
_files = [];
|
||||||
|
_lastSaved = DateTime.Now;
|
||||||
|
_lastGenerated = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string BaseFolder
|
public string BaseFolder
|
||||||
@@ -28,10 +32,10 @@ class PDFReport : ChangeNotifier
|
|||||||
set { _baseFolder = value; NotifyPropertyChanged(); }
|
set { _baseFolder = value; NotifyPropertyChanged(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name
|
public string Title
|
||||||
{
|
{
|
||||||
get => _name;
|
get => _title;
|
||||||
set { _name = value; NotifyPropertyChanged(); }
|
set { _title = value; NotifyPropertyChanged(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ReportFile> Files
|
public List<ReportFile> Files
|
||||||
@@ -39,4 +43,16 @@ class PDFReport : ChangeNotifier
|
|||||||
get => _files;
|
get => _files;
|
||||||
set { _files = value; NotifyPropertyChanged(); }
|
set { _files = value; NotifyPropertyChanged(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DateTime LastSaved
|
||||||
|
{
|
||||||
|
get => _lastSaved;
|
||||||
|
set { _lastSaved = value; NotifyPropertyChanged(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTime? LastGenerated
|
||||||
|
{
|
||||||
|
get => _lastGenerated;
|
||||||
|
set { _lastGenerated = value; NotifyPropertyChanged(); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+4
-13
@@ -5,6 +5,7 @@ using System.Text.Json;
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using ReceiptPDFBuilder.Helpers;
|
using ReceiptPDFBuilder.Helpers;
|
||||||
|
using ReceiptPDFBuilders.Helpers;
|
||||||
|
|
||||||
namespace ReceiptPDFBuilder.Models;
|
namespace ReceiptPDFBuilder.Models;
|
||||||
|
|
||||||
@@ -42,19 +43,9 @@ class Settings : ChangeNotifier
|
|||||||
return Path.Combine(path, GetSettingsFileName());
|
return Path.Combine(path, GetSettingsFileName());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JsonSerializerOptions GetSerializerOptions()
|
|
||||||
{
|
|
||||||
var opts = new JsonSerializerOptions
|
|
||||||
{
|
|
||||||
WriteIndented = false,
|
|
||||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
|
||||||
};
|
|
||||||
return opts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<string> SaveSettingsAsync()
|
public async Task<string> SaveSettingsAsync()
|
||||||
{
|
{
|
||||||
var jsonContext = new SourceGenerationContext(GetSerializerOptions());
|
var jsonContext = new SourceGenerationContext(Utilities.GetSerializerOptions());
|
||||||
using MemoryStream memoryStream = new MemoryStream();
|
using MemoryStream memoryStream = new MemoryStream();
|
||||||
await JsonSerializer.SerializeAsync(memoryStream, this, jsonContext.Settings);
|
await JsonSerializer.SerializeAsync(memoryStream, this, jsonContext.Settings);
|
||||||
memoryStream.Position = 0;
|
memoryStream.Position = 0;
|
||||||
@@ -72,14 +63,14 @@ class Settings : ChangeNotifier
|
|||||||
return new Settings();
|
return new Settings();
|
||||||
}
|
}
|
||||||
var json = File.ReadAllText(GetSettingsPath());
|
var json = File.ReadAllText(GetSettingsPath());
|
||||||
var jsonContext = new SourceGenerationContext(GetSerializerOptions());
|
var jsonContext = new SourceGenerationContext(Utilities.GetSerializerOptions());
|
||||||
return JsonSerializer.Deserialize<Settings>(json, jsonContext.Settings) ?? new Settings();
|
return JsonSerializer.Deserialize<Settings>(json, jsonContext.Settings) ?? new Settings();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<Settings> LoadSettingsAsync()
|
public static async Task<Settings> LoadSettingsAsync()
|
||||||
{
|
{
|
||||||
using FileStream fileStream = File.OpenRead(GetSettingsPath());
|
using FileStream fileStream = File.OpenRead(GetSettingsPath());
|
||||||
var jsonContext = new SourceGenerationContext(GetSerializerOptions());
|
var jsonContext = new SourceGenerationContext(Utilities.GetSerializerOptions());
|
||||||
var output = await JsonSerializer.DeserializeAsync<Settings>(fileStream, jsonContext.Settings) ?? new Settings();
|
var output = await JsonSerializer.DeserializeAsync<Settings>(fileStream, jsonContext.Settings) ?? new Settings();
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System.Collections.ObjectModel;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Avalonia.Platform.Storage;
|
using Avalonia.Platform.Storage;
|
||||||
using Avalonia.Themes.Fluent;
|
using Avalonia.Themes.Fluent;
|
||||||
@@ -15,32 +16,36 @@ using MigraDoc.Rendering;
|
|||||||
using PdfSharp.Fonts;
|
using PdfSharp.Fonts;
|
||||||
using PdfSharp.Pdf.IO;
|
using PdfSharp.Pdf.IO;
|
||||||
using PdfSharp.Snippets.Font;
|
using PdfSharp.Snippets.Font;
|
||||||
|
using ReceiptPDFBuilder.Helpers;
|
||||||
using ReceiptPDFBuilder.Interfaces;
|
using ReceiptPDFBuilder.Interfaces;
|
||||||
using ReceiptPDFBuilder.Models;
|
using ReceiptPDFBuilder.Models;
|
||||||
|
using ReceiptPDFBuilders.Helpers;
|
||||||
|
|
||||||
namespace ReceiptPDFBuilder.ViewModels;
|
namespace ReceiptPDFBuilder.ViewModels;
|
||||||
|
|
||||||
class MainViewModel : BaseViewModel, IFontResolver
|
class MainViewModel : BaseViewModel, IFontResolver
|
||||||
{
|
{
|
||||||
private string _baseDir;
|
private string _processDir;
|
||||||
private bool _isCreatingPDF;
|
private bool _isCreatingPDF;
|
||||||
private string _createPDFLog;
|
private string _createPDFLog;
|
||||||
private string _workingFolder;
|
private string _workingFolder;
|
||||||
|
|
||||||
private string _reportTitle;
|
private string _reportTitle;
|
||||||
private ObservableCollection<ReportFile> _reportFiles;
|
private ObservableCollection<ReportFile> _reportFiles;
|
||||||
|
private DateTime? _lastGeneratedTime;
|
||||||
|
|
||||||
private Settings _settings;
|
private Settings _settings;
|
||||||
|
|
||||||
public MainViewModel(IChangeViewModel viewModelChanger) : base(viewModelChanger)
|
public MainViewModel(IChangeViewModel viewModelChanger) : base(viewModelChanger)
|
||||||
{
|
{
|
||||||
_baseDir = Path.GetDirectoryName(Environment.ProcessPath) ?? "";
|
_processDir = Path.GetDirectoryName(Environment.ProcessPath) ?? "";
|
||||||
_isCreatingPDF = false;
|
_isCreatingPDF = false;
|
||||||
_createPDFLog = "Ready to create PDF! Choose a folder to begin...";
|
_createPDFLog = "Ready to create PDF! Choose a folder to begin...";
|
||||||
_workingFolder = "";
|
_workingFolder = "";
|
||||||
_reportFiles = new ObservableCollection<ReportFile>();
|
_reportFiles = new ObservableCollection<ReportFile>();
|
||||||
_reportFiles.CollectionChanged += ( sender, e ) => { NotifyPropertyChanged(nameof(IsCreatePDFButtonEnabled)); };
|
_reportFiles.CollectionChanged += ( sender, e ) => { NotifyPropertyChanged(nameof(IsCreatePDFButtonEnabled)); };
|
||||||
_reportTitle = "";
|
_reportTitle = "";
|
||||||
|
_lastGeneratedTime = null;
|
||||||
_settings = Settings.LoadSettings();
|
_settings = Settings.LoadSettings();
|
||||||
if (!string.IsNullOrWhiteSpace(_settings.LastUsedPath))
|
if (!string.IsNullOrWhiteSpace(_settings.LastUsedPath))
|
||||||
{
|
{
|
||||||
@@ -118,6 +123,26 @@ class MainViewModel : BaseViewModel, IFontResolver
|
|||||||
_workingFolder = path;
|
_workingFolder = path;
|
||||||
NotifyPropertyChanged(nameof(IsTitleBoxVisible));
|
NotifyPropertyChanged(nameof(IsTitleBoxVisible));
|
||||||
// TODO: Scan folder for saved info from previous reports and reload that first
|
// TODO: Scan folder for saved info from previous reports and reload that first
|
||||||
|
var reportFilePath = Path.Combine(path, GetReportSavedDataFileName());
|
||||||
|
var successfullyLoadedPriorReport = false;
|
||||||
|
if (File.Exists(reportFilePath))
|
||||||
|
{
|
||||||
|
// load prior report
|
||||||
|
var json = File.ReadAllText(reportFilePath);
|
||||||
|
var jsonContext = new SourceGenerationContext(Utilities.GetSerializerOptions());
|
||||||
|
var report = JsonSerializer.Deserialize<PDFReport>(json, jsonContext.PDFReport);
|
||||||
|
if (report != null && report.Files.Count > 0)
|
||||||
|
{
|
||||||
|
ReportFiles = new ObservableCollection<ReportFile>(report.Files);
|
||||||
|
ReportTitle = report.Title;
|
||||||
|
_workingFolder = report.BaseFolder;
|
||||||
|
_lastGeneratedTime = report.LastGenerated ?? null;
|
||||||
|
LogInfo("Reloaded report last saved at {0}", report.LastSaved);
|
||||||
|
successfullyLoadedPriorReport = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!successfullyLoadedPriorReport)
|
||||||
|
{
|
||||||
// Scan folder for files and display in DataGrid
|
// Scan folder for files and display in DataGrid
|
||||||
var filePaths = Directory.GetFiles(_workingFolder);
|
var filePaths = Directory.GetFiles(_workingFolder);
|
||||||
filePaths.Sort();
|
filePaths.Sort();
|
||||||
@@ -127,6 +152,7 @@ class MainViewModel : BaseViewModel, IFontResolver
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async void RemoveFile(ReportFile file)
|
public async void RemoveFile(ReportFile file)
|
||||||
{
|
{
|
||||||
@@ -235,26 +261,71 @@ class MainViewModel : BaseViewModel, IFontResolver
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async void SaveInterimReportInfo()
|
||||||
|
{
|
||||||
|
var report = new PDFReport()
|
||||||
|
{
|
||||||
|
Title = ReportTitle,
|
||||||
|
Files = ReportFiles.ToList(),
|
||||||
|
BaseFolder = _workingFolder,
|
||||||
|
LastSaved = DateTime.Now,
|
||||||
|
LastGenerated = _lastGeneratedTime,
|
||||||
|
};
|
||||||
|
await SavePDFReportDataToDisk(report);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SavePDFReportDataToDisk(PDFReport report)
|
||||||
|
{
|
||||||
|
var jsonContext = new SourceGenerationContext(Utilities.GetSerializerOptions());
|
||||||
|
using var memoryStream = new MemoryStream();
|
||||||
|
await JsonSerializer.SerializeAsync(memoryStream, report, jsonContext.PDFReport);
|
||||||
|
memoryStream.Position = 0;
|
||||||
|
using var reader = new StreamReader(memoryStream);
|
||||||
|
var json = await reader.ReadToEndAsync();
|
||||||
|
var savePath = Path.Combine(_workingFolder, GetReportSavedDataFileName());
|
||||||
|
await File.WriteAllTextAsync(savePath, json);
|
||||||
|
LogInfo("Saved report information to {0} (baseDir is {1})", savePath, _workingFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task CreateAndSaveReportObjectAfterReportCreation()
|
||||||
|
{
|
||||||
|
var report = new PDFReport()
|
||||||
|
{
|
||||||
|
Title = ReportTitle,
|
||||||
|
Files = ReportFiles.ToList(),
|
||||||
|
BaseFolder = _workingFolder,
|
||||||
|
LastSaved = DateTime.Now,
|
||||||
|
LastGenerated = DateTime.Now,
|
||||||
|
};
|
||||||
|
_lastGeneratedTime = DateTime.Now;
|
||||||
|
await SavePDFReportDataToDisk(report);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetReportSavedDataFileName()
|
||||||
|
{
|
||||||
|
return "report_data.json";
|
||||||
|
}
|
||||||
|
|
||||||
public byte[]? GetFont(string faceName)
|
public byte[]? GetFont(string faceName)
|
||||||
{
|
{
|
||||||
LogInfo(string.Format("Loading font {0}", faceName));
|
LogInfo(string.Format("Loading font {0}", faceName));
|
||||||
if (faceName == "Noto Sans JP")
|
if (faceName == "Noto Sans JP")
|
||||||
{
|
{
|
||||||
var path = Path.Combine(_baseDir, "Assets/Fonts/Noto_Sans_JP/static/NotoSansJP-Regular.ttf");
|
var path = Path.Combine(_processDir, "Assets/Fonts/Noto_Sans_JP/static/NotoSansJP-Regular.ttf");
|
||||||
if (!File.Exists(path))
|
if (!File.Exists(path))
|
||||||
{
|
{
|
||||||
path = Path.Combine(_baseDir, "../Resources/Assets/Fonts/Noto_Sans_JP/static/NotoSansJP-Regular.ttf");
|
path = Path.Combine(_processDir, "../Resources/Assets/Fonts/Noto_Sans_JP/static/NotoSansJP-Regular.ttf");
|
||||||
}
|
}
|
||||||
return File.ReadAllBytes(path);
|
return File.ReadAllBytes(path);
|
||||||
}
|
}
|
||||||
if (faceName == "Noto Sans JP Bold")
|
if (faceName == "Noto Sans JP Bold")
|
||||||
{
|
{
|
||||||
var path = Path.Combine(_baseDir, "Assets/Fonts/Noto_Sans_JP/static/NotoSansJP-SemiBold.ttf");
|
var path = Path.Combine(_processDir, "Assets/Fonts/Noto_Sans_JP/static/NotoSansJP-SemiBold.ttf");
|
||||||
if (!File.Exists(path))
|
if (!File.Exists(path))
|
||||||
{
|
{
|
||||||
path = Path.Combine(_baseDir, "../Resources/Assets/Fonts/Noto_Sans_JP/static/NotoSansJP-SemiBold.ttf");
|
path = Path.Combine(_processDir, "../Resources/Assets/Fonts/Noto_Sans_JP/static/NotoSansJP-SemiBold.ttf");
|
||||||
}
|
}
|
||||||
return File.ReadAllBytes(Path.Combine(_baseDir, "Assets/Fonts/Noto_Sans_JP/static/NotoSansJP-SemiBold.ttf"));
|
return File.ReadAllBytes(Path.Combine(_processDir, "Assets/Fonts/Noto_Sans_JP/static/NotoSansJP-SemiBold.ttf"));
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -399,6 +470,7 @@ class MainViewModel : BaseViewModel, IFontResolver
|
|||||||
LogInfo("Saving document to disk...");
|
LogInfo("Saving document to disk...");
|
||||||
pdfRenderer.PdfDocument.Save(filename);
|
pdfRenderer.PdfDocument.Save(filename);
|
||||||
LogInfo("Saved PDF output to: " + filename);
|
LogInfo("Saved PDF output to: " + filename);
|
||||||
|
await CreateAndSaveReportObjectAfterReportCreation();
|
||||||
IsCreatingPDF = false;
|
IsCreatingPDF = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,6 +129,10 @@
|
|||||||
IsEnabled="{Binding IsTitleBoxVisible}">
|
IsEnabled="{Binding IsTitleBoxVisible}">
|
||||||
<TextBlock><Run Text="+" FontFamily="{StaticResource FontAwesomeSolid}"/> Add Item</TextBlock>
|
<TextBlock><Run Text="+" FontFamily="{StaticResource FontAwesomeSolid}"/> Add Item</TextBlock>
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button Command="{Binding SaveInterimReportInfo}"
|
||||||
|
IsEnabled="{Binding IsTitleBoxVisible}">
|
||||||
|
<TextBlock><Run Text="" FontFamily="{StaticResource FontAwesomeSolid}"/> Save Report Info</TextBlock>
|
||||||
|
</Button>
|
||||||
<Button Content="Create Report PDF"
|
<Button Content="Create Report PDF"
|
||||||
Command="{Binding BuildPDF}"
|
Command="{Binding BuildPDF}"
|
||||||
Classes="accent"
|
Classes="accent"
|
||||||
|
|||||||
Reference in New Issue
Block a user