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

View File

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