From 7efc649d0b1043fb0bb99cf56cfe9ba386a95ccb Mon Sep 17 00:00:00 2001 From: Loretta Date: Tue, 23 Dec 2025 15:22:52 +0100 Subject: [PATCH] Add AI process modal to shipping grid with toolbar button Added an "AI process" toolbar button to the shipping document grid, styled with a new magic/sparkles icon. Clicking the button opens a large modal (DxWindow) containing an iframe-based AI processing form (AiProcessFormTemplate). The modal reloads grid data on close. Also includes related CSS for the icon, minor grid layout logic improvements, and retains commented file upload code for reference. --- .../Components/GridShippingDocument.razor | 49 +++++++++++++++++-- .../AiProcessFormTemplate.razor | 4 ++ FruitBankHybrid.Shared/wwwroot/app.css | 12 ++++- 3 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 FruitBankHybrid.Shared/Components/Grids/ShippingDocuments/AiProcessFormTemplate.razor diff --git a/FruitBankHybrid.Shared/Components/GridShippingDocument.razor b/FruitBankHybrid.Shared/Components/GridShippingDocument.razor index 950d0d4..80b4e98 100644 --- a/FruitBankHybrid.Shared/Components/GridShippingDocument.razor +++ b/FruitBankHybrid.Shared/Components/GridShippingDocument.razor @@ -2,6 +2,7 @@ @using AyCode.Utils.Extensions @using FruitBank.Common.Dtos @using FruitBank.Common.Entities +@* @using FruitBankHybrid.Shared.Components.FileUploads *@ @using FruitBankHybrid.Shared.Components.Grids.ShippingDocuments @using FruitBankHybrid.Shared.Databases @using FruitBankHybrid.Shared.Services.SignalRs @@ -99,11 +100,15 @@ { - +@* + *@ + + + } @@ -126,6 +131,25 @@ + +@* + + + *@ + + + @code { [Inject] public required DatabaseClient Database { get; set; } [Inject] public required LoggedInModel LoggedInModel { get; set; } @@ -148,6 +172,10 @@ string GridSearchText = ""; bool EditItemsEnabled { get; set; } = true; int FocusedRowVisibleIndex { get; set; } + + private DxWindow windowRef; + private bool windowVisible; + public GridShippingDocumentBase Grid { get; set; } private LoggerClient _logger = null!; private int _activeTabIndex; @@ -196,7 +224,8 @@ if (Grid == null) return; using (await ObjectLock.GetSemaphore().UseWaitAsync()) - if (forceReload) await Grid.ReloadDataSourceAsync(); + if (forceReload) + await Grid.ReloadDataSourceAsync(); if (forceReload) Grid.Reload(); } @@ -233,4 +262,18 @@ { _activeTabIndex = activeTabIndex; } -} \ No newline at end of file + + private async Task Callback(ToolbarItemClickEventArgs obj) + { + if (windowVisible) + await windowRef.CloseAsync(); + else + await windowRef.ShowAsync(); + } + + private void Callback2(WindowClosingEventArgs obj) + { + ReloadDataFromDb(true).Forget(); + } + +} diff --git a/FruitBankHybrid.Shared/Components/Grids/ShippingDocuments/AiProcessFormTemplate.razor b/FruitBankHybrid.Shared/Components/Grids/ShippingDocuments/AiProcessFormTemplate.razor new file mode 100644 index 0000000..8f2fb07 --- /dev/null +++ b/FruitBankHybrid.Shared/Components/Grids/ShippingDocuments/AiProcessFormTemplate.razor @@ -0,0 +1,4 @@ + +@code { + +} diff --git a/FruitBankHybrid.Shared/wwwroot/app.css b/FruitBankHybrid.Shared/wwwroot/app.css index 1bbebda..64bf028 100644 --- a/FruitBankHybrid.Shared/wwwroot/app.css +++ b/FruitBankHybrid.Shared/wwwroot/app.css @@ -170,7 +170,8 @@ h1:focus { .grid-export-pdf, .grid-refresh, .grid-fullscreen, -.grid-fullscreen-exit { +.grid-fullscreen-exit, +.grid-ai { display: inline-flex; align-items: center; justify-content: center; @@ -193,7 +194,8 @@ h1:focus { .grid-export-pdf::before, .grid-refresh::before, .grid-fullscreen::before, - .grid-fullscreen-exit::before { + .grid-fullscreen-exit::before, + .grid-ai::before { content: ""; display: inline-block; width: 1.25rem; @@ -316,6 +318,12 @@ h1:focus { -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Cpolyline points='4 14 10 14 10 20'/%3E%3Cpolyline points='20 10 14 10 14 4'/%3E%3Cline x1='14' y1='10' x2='21' y2='3'/%3E%3Cline x1='3' y1='21' x2='10' y2='14'/%3E%3C/svg%3E"); } + /* AI icon (sparkles/magic) */ + .grid-ai::before { + mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Cpath d='M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3z'/%3E%3Cpath d='M5 19l1 3 1-3 3-1-3-1-1-3-1 3-3 1 3 1z'/%3E%3Cpath d='M19 11l.5 1.5 1.5.5-1.5.5-.5 1.5-.5-1.5L17 13l1.5-.5.5-1.5z'/%3E%3C/svg%3E"); + -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Cpath d='M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3z'/%3E%3Cpath d='M5 19l1 3 1-3 3-1-3-1-1-3-1 3-3 1 3 1z'/%3E%3Cpath d='M19 11l.5 1.5 1.5.5-1.5.5-.5 1.5-.5-1.5L17 13l1.5-.5.5-1.5z'/%3E%3C/svg%3E"); + } + /* ======================================== MgGrid Splitter with InfoPanel InfoPanel sticky via JavaScript