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:
parent
ed99db3238
commit
3c5b737207
|
|
@ -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);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue