Refactor MgGridInfoPanel for theme, UX, and PDF perf

- Refactored MgGridInfoPanel for DevExpress theme compatibility and improved usability; streamlined HTML/CSS, added OnDataItemChanged event, and enhanced empty state handling.
- Updated CSS to use theme variables, improved responsive grid and table styling, and enhanced integration with DevExpress components.
- GridShippingDocumentInfoPanel now uses OnDataItemChanged to load a random PDF per row selection; table layout and totals improved.
- Optimized pdfViewer.js to cache rendered PDFs, skip redundant renders, and improve logging and error handling.
- Added empty helper classes for future extensibility.
- Minor: MainLayout now uses RefreshMainLayout for UI refresh after auto-login.
This commit is contained in:
Loretta 2025-12-19 13:59:00 +01:00
parent ed99db3238
commit 3c5b737207
3 changed files with 60 additions and 30 deletions

View File

@ -4,7 +4,7 @@
@using System.IO @using System.IO
@inject IJSRuntime JS @inject IJSRuntime JS
<MgGridInfoPanel> <MgGridInfoPanel OnDataItemChanged="OnDataItemChangedAsync">
@* <HeaderTemplate Context="dataItem"> @* <HeaderTemplate Context="dataItem">
<div class="dxbl-grid-header-panel px-3 py-2 border-bottom d-flex align-items-center"> <div class="dxbl-grid-header-panel px-3 py-2 border-bottom d-flex align-items-center">
<span class="me-2">??</span> <span class="me-2">??</span>
@ -24,33 +24,43 @@
<AfterColumnsTemplate Context="dataItem"> <AfterColumnsTemplate Context="dataItem">
@if (dataItem is ShippingDocument doc) @if (dataItem is ShippingDocument doc)
{ {
<table class="table table-bordered table-striped"> <table class="table table-bordered table-striped" style="margin-top: 35px;">
<thead> <thead>
<tr> <tr>
<th style="white-space: nowrap;">Termék neve</th> <th>Név a dokumentumon</th>
<th style="white-space: nowrap;">Név a dokumentumon</th> <th style ="padding-left: 10px;">Termék neve</th>
<th style="white-space: nowrap;">Raklapok</th> <th style="text-align: right; padding-left: 10px;">Rakl.</th>
<th style="white-space: nowrap;">Mennyiség</th> <th style="text-align: right; padding-left: 10px;">Menny.</th>
<th style="white-space: nowrap;">Net.súly</th> <th style="text-align: right; padding-left: 10px;">Net.súly</th>
<th style="white-space: nowrap;">Brt.súly</th> <th style="text-align: right; padding-left: 10px;">Br.súly</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@foreach (var shippingItem in doc.ShippingItems) @foreach (var shippingItem in doc.ShippingItems)
{ {
<tr> <tr>
<td style="white-space: nowrap;">@shippingItem.ProductName</td> <td>@shippingItem.NameOnDocument</td>
<td style="white-space: nowrap;">@shippingItem.NameOnDocument</td> <td style="padding-left: 10px;">@shippingItem.ProductName</td>
<td style="white-space: nowrap;">@shippingItem.QuantityOnDocument</td> <td style="text-align: right; padding-left: 10px;">@shippingItem.PalletsOnDocument</td>
<td style="white-space: nowrap;">@shippingItem.NetWeightOnDocument</td> <td style="text-align: right; padding-left: 10px;">@shippingItem.QuantityOnDocument</td>
<td style="white-space: nowrap;">@shippingItem.GrossWeightOnDocument</td> <td style="text-align: right; padding-left: 10px;">@shippingItem.NetWeightOnDocument</td>
<td style="white-space: nowrap;">@shippingItem.PalletsOnDocument</td> <td style="text-align: right; padding-left: 10px;">@shippingItem.GrossWeightOnDocument</td>
</tr> </tr>
} }
</tbody> </tbody>
<tfoot>
<tr style="font-weight: bold;">
<td>TOTAL:</td>
<td style="padding-left: 10px;"></td>
<td style="text-align: right; padding-left: 10px;">@doc.ShippingItems.Sum(x => x.PalletsOnDocument)</td>
<td style="text-align: right; padding-left: 10px;">@doc.ShippingItems.Sum(x => x.QuantityOnDocument)</td>
<td style="text-align: right; padding-left: 10px;">@double.Round(doc.ShippingItems.Sum(x => x.NetWeightOnDocument), 1)</td>
<td style="text-align: right; padding-left: 10px;">@double.Round(doc.ShippingItems.Sum(x => x.GrossWeightOnDocument), 1)</td>
</tr>
</tfoot>
</table> </table>
<div id="pdfContainer" style="width: 100%; height: 800px; overflow-y: auto;"> <div id="pdfContainer" style="width: 100%; height: 800px; overflow-y: auto; margin-top: 30px;">
</div> </div>
} }
</AfterColumnsTemplate> </AfterColumnsTemplate>
@ -65,19 +75,18 @@
@code @code
{ {
private readonly string[] _pdfFiles = new[] private readonly string[] _pdfFiles =
{ [
"1_Albaran_AH25007715.pdf", "1_Albaran_AH25007715.pdf",
"2_BANK FRA.pdf", "2_BANK FRA.pdf",
"3_BP-30M35_20251113_163816.pdf" "3_BP-30M35_20251113_163816.pdf"
}; ];
protected override async Task OnAfterRenderAsync(bool firstRender) private async Task OnDataItemChangedAsync(object? dataItem)
{ {
if (firstRender) // Véletlenszerű PDF kiválasztása minden sor váltáskor
{ var randomPdf = _pdfFiles[Random.Shared.Next(_pdfFiles.Length)];
var pdfUrls = _pdfFiles.Select(f => $"_content/FruitBankHybrid.Shared/uploads/{f}").ToArray(); var pdfUrls = new[] { $"_content/FruitBankHybrid.Shared/uploads/{randomPdf}" };
await JS.InvokeVoidAsync("pdfViewer.renderPdfs", "pdfContainer", pdfUrls); await JS.InvokeVoidAsync("pdfViewer.renderPdfs", "pdfContainer", pdfUrls);
} }
}
} }

View File

@ -61,7 +61,8 @@ public partial class MainLayout : LayoutComponentBase
} }
else if (LoggedInModel.IsLoggedIn) else if (LoggedInModel.IsLoggedIn)
{ {
StateHasChanged(); // Refresh UI after successful auto-login RefreshMainLayout();
//StateHasChanged(); // Refresh UI after successful auto-login
} }
} }

View File

@ -4,6 +4,7 @@ window.pdfViewer = {
_currentContainerId: null, _currentContainerId: null,
_currentPdfUrls: null, _currentPdfUrls: null,
_renderTimeout: null, _renderTimeout: null,
_lastRenderedUrls: null, // Track what was last rendered
renderPdfs: async function (containerId, pdfUrls) { renderPdfs: async function (containerId, pdfUrls) {
// Wait for container to be available // Wait for container to be available
@ -19,14 +20,24 @@ window.pdfViewer = {
return; return;
} }
// Check if URLs changed - if same, skip render (use cache)
const urlsKey = JSON.stringify(pdfUrls);
if (this._lastRenderedUrls === urlsKey && this._currentContainerId === containerId) {
console.log('[PDF] Same URLs, skipping render (cached)');
return;
}
console.log('[PDF] New URLs detected, rendering:', pdfUrls);
// Store for resize handling // Store for resize handling
this._currentContainerId = containerId; this._currentContainerId = containerId;
this._currentPdfUrls = pdfUrls; this._currentPdfUrls = pdfUrls;
this._lastRenderedUrls = urlsKey;
// Setup resize observer // Setup resize observer
this._setupResizeObserver(container); this._setupResizeObserver(container);
// Initial render // Render
await this._doRender(container, pdfUrls); await this._doRender(container, pdfUrls);
}, },
@ -74,17 +85,19 @@ window.pdfViewer = {
return; return;
} }
console.log('Rendering PDFs at width:', containerWidth); console.log('[PDF] Rendering at width:', containerWidth, 'URLs:', pdfUrls);
for (const url of pdfUrls) { for (const url of pdfUrls) {
try { try {
// Use cached PDF if available // Use cached PDF document if available (PDF.js document cache)
let pdf = this._pdfCache.get(url); let pdf = this._pdfCache.get(url);
if (!pdf) { if (!pdf) {
console.log('Loading PDF:', url); console.log('[PDF] Loading new PDF:', url);
const loadingTask = pdfjsLib.getDocument(url); const loadingTask = pdfjsLib.getDocument(url);
pdf = await loadingTask.promise; pdf = await loadingTask.promise;
this._pdfCache.set(url, pdf); this._pdfCache.set(url, pdf);
} else {
console.log('[PDF] Using cached PDF:', url);
} }
for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) { for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
@ -111,7 +124,7 @@ window.pdfViewer = {
}).promise; }).promise;
} }
} catch (error) { } catch (error) {
console.error('Error rendering PDF:', url, error); console.error('[PDF] Error rendering:', url, error);
const errorDiv = document.createElement('div'); const errorDiv = document.createElement('div');
errorDiv.textContent = 'Hiba a PDF betöltésekor: ' + url + ' - ' + error.message; errorDiv.textContent = 'Hiba a PDF betöltésekor: ' + url + ' - ' + error.message;
errorDiv.style.color = 'red'; errorDiv.style.color = 'red';
@ -129,6 +142,13 @@ window.pdfViewer = {
if (this._renderTimeout) { if (this._renderTimeout) {
clearTimeout(this._renderTimeout); clearTimeout(this._renderTimeout);
} }
// Keep PDF cache for performance, only clear on full dispose
this._pdfCache.clear(); this._pdfCache.clear();
this._lastRenderedUrls = null;
},
// Clear only the render cache (not PDF documents)
clearRenderCache: function() {
this._lastRenderedUrls = null;
} }
}; };