diff --git a/EpsonTest.Templates/Templates/KitcheReceipt.json b/EpsonTest.Templates/Templates/KitcheReceipt.json new file mode 100644 index 0000000..ed103e4 --- /dev/null +++ b/EpsonTest.Templates/Templates/KitcheReceipt.json @@ -0,0 +1,78 @@ +{ + "Title": "Warme K\u00FCche", + "TransactionDateTime": "2025-10-23T12:18:00", + "ReceiptNumber": "132018166", + "WaiterName": "Mariano Amato", + "WaiterId": "32 (VK Restaurant)", + "TableNumber": "22", + "SpecialInstruction": null, + "Gangs": [ + { + "Id": 1, + "Name": "Gang", + "Dishes": [ + { + "Number": 1, + "Name": "Avocado Sashimi", + "GuestId": 1, + "Modifications": { + "Removed": [ + "Wasabi" + ], + "Added": [ + "Extra Ginger" + ], + "HasModifications": true + }, + "Comment": "No soy sauce", + "GuestPrefix": "1 " + }, + { + "Number": 1, + "Name": "Baby Spinach Salad with Truffl", + "GuestId": 2, + "Modifications": { + "Removed": [], + "Added": [], + "HasModifications": false + }, + "Comment": null, + "GuestPrefix": "2 " + } + ] + }, + { + "Id": 2, + "Name": "Gang", + "Dishes": [ + { + "Number": 1, + "Name": "Avocado Sashimi", + "GuestId": 1, + "Modifications": { + "Removed": [], + "Added": [], + "HasModifications": false + }, + "Comment": null, + "GuestPrefix": "1 " + }, + { + "Number": 1, + "Name": "Baby Spinach Salad with Truffl", + "GuestId": 2, + "Modifications": { + "Removed": [], + "Added": [], + "HasModifications": false + }, + "Comment": null, + "GuestPrefix": "2 " + } + ] + } + ], + "Dishes": [], + "HasGangs": true, + "HasDishes": false +} \ No newline at end of file diff --git a/EpsonTest.Templates/Templates/KitchenReceipt.xml b/EpsonTest.Templates/Templates/KitchenReceipt.xml index 201933d..6f7bd8f 100644 --- a/EpsonTest.Templates/Templates/KitchenReceipt.xml +++ b/EpsonTest.Templates/Templates/KitchenReceipt.xml @@ -21,14 +21,14 @@ {{dish.GuestPrefix}}{{dish.Number}}x {{dish.Name}} - - {{removed}} + - {{removed}} - + {{added}} + + {{added}} - Comment: {{dish.Comment}} + Comment: {{dish.Comment}} diff --git a/Inspectron.PrintServer.TemplateEditor/Components/Pages/Home.razor b/Inspectron.PrintServer.TemplateEditor/Components/Pages/Home.razor index 31672f7..da68049 100644 --- a/Inspectron.PrintServer.TemplateEditor/Components/Pages/Home.razor +++ b/Inspectron.PrintServer.TemplateEditor/Components/Pages/Home.razor @@ -7,18 +7,19 @@ @using Inspectron.Epson.PrintServer.Printers @using Inspectron.Epson.TemplateEngine @using Inspectron.PrintServer.TemplateEditor.Services +@implements IDisposable @inject IJSRuntime JSRuntime
- - - + + + @FileDisplayName@(HasUnsavedChanges ? " *" : "")
- + @if (!string.IsNullOrEmpty(_loadedJsonFile)) { @_loadedJsonFile @@ -66,6 +67,7 @@ private string? _previewError; private string _selectedPrinterModel = "TM-T30III"; private CancellationTokenSource? _debounceCts; + private DotNetObjectReference? _dotNetRef; private bool HasUnsavedChanges => _editorContent != _savedContent; @@ -101,6 +103,30 @@ "receipt-xml", _completionProvider.ProvideCompletionItems, _completionProvider.ResolveCompletionItem); + + // Register global hotkeys + _dotNetRef = DotNetObjectReference.Create(this); + await JSRuntime.InvokeVoidAsync("registerHotkeys", _dotNetRef); + } + + [JSInvokable] + public async Task OnHotkeyAsync(string action) + { + switch (action) + { + case "New": await NewFileAsync(); break; + case "Open": await OpenFileAsync(); break; + case "Save": await SaveFileAsync(); break; + case "LoadJson": await LoadJsonAsync(); break; + } + StateHasChanged(); + } + + public void Dispose() + { + _debounceCts?.Cancel(); + _debounceCts?.Dispose(); + _dotNetRef?.Dispose(); } private async Task OnContentChanged(ModelContentChangedEvent e) diff --git a/Inspectron.PrintServer.TemplateEditor/wwwroot/receiptLanguage.js b/Inspectron.PrintServer.TemplateEditor/wwwroot/receiptLanguage.js index 08c66ac..c86fbfb 100644 --- a/Inspectron.PrintServer.TemplateEditor/wwwroot/receiptLanguage.js +++ b/Inspectron.PrintServer.TemplateEditor/wwwroot/receiptLanguage.js @@ -161,3 +161,23 @@ window.setPreviewContent = function(html) { var iframe = document.getElementById('preview-iframe'); if (iframe) iframe.srcdoc = html; }; + +window.registerHotkeys = function(dotNetRef) { + document.addEventListener('keydown', function(e) { + if (!(e.ctrlKey || e.metaKey)) return; + + var action = null; + switch (e.key.toLowerCase()) { + case 'n': action = 'New'; break; + case 'o': action = 'Open'; break; + case 's': action = 'Save'; break; + case 'j': action = 'LoadJson'; break; + } + + if (action) { + e.preventDefault(); + e.stopPropagation(); + dotNetRef.invokeMethodAsync('OnHotkeyAsync', action); + } + }, true); +};