Improve toolbar controls and async UX in stock taking

- Added EnableNew and EnableEdit parameters to MgGridToolbarTemplate for finer control of toolbar button states.
- Disabled "New", "Edit", and "Delete" actions in history and item grids by passing explicit parameters.
- Introduced DxLoadingPanel in StockTakingTemplate for better async feedback.
- Disabled "New" and "Close" buttons during async operations to prevent duplicates.
- Enhanced combo boxes with search/filter and usability features.
- Updated new/close stock taking logic to show loading, handle errors, and prevent duplicate actions.
- Set focus to item combo box after saving a StockTakingItemPallet.
- Removed global loading panel from StockTaking.razor; loading is now handled locally.
- Performed minor code cleanups and removed obsolete code.
This commit is contained in:
Loretta 2026-02-07 08:55:00 +01:00
parent 0343f7b677
commit 5604f1e338
4 changed files with 88 additions and 33 deletions

View File

@ -48,7 +48,7 @@
<ToolbarTemplate> <ToolbarTemplate>
@if (IsMasterGrid) @if (IsMasterGrid)
{ {
<MgGridToolbarTemplate Grid="Grid" OnReloadDataClick="() => ReloadDataFromDb(true)" /> <MgGridToolbarTemplate Grid="Grid" OnReloadDataClick="() => ReloadDataFromDb(true)" EnableDelete="false" EnableEdit="false" EnableNew="false" />
} }
</ToolbarTemplate> </ToolbarTemplate>
@* <GroupSummary> @* <GroupSummary>

View File

@ -48,7 +48,7 @@
<ToolbarTemplate> <ToolbarTemplate>
@if (IsMasterGrid) @if (IsMasterGrid)
{ {
<MgGridToolbarTemplate Grid="Grid" OnReloadDataClick="() => ReloadDataFromDb(true)" /> <MgGridToolbarTemplate Grid="Grid" OnReloadDataClick="() => ReloadDataFromDb(true)" EnableDelete="false" EnableEdit="false" EnableNew="false" />
} }
</ToolbarTemplate> </ToolbarTemplate>
</GridStockTakingItemBase> </GridStockTakingItemBase>

View File

@ -12,10 +12,19 @@
@using FruitBankHybrid.Shared.Services.SignalRs @using FruitBankHybrid.Shared.Services.SignalRs
@using Mango.Nop.Core.Entities @using Mango.Nop.Core.Entities
<DxLoadingPanel @bind-Visible="LoadingPanelVisible"
IsContentBlocked="true"
ApplyBackgroundShading="true"
IndicatorAreaVisible="true"
IsContentVisible="true"
IndicatorAnimationType="WaitIndicatorAnimationType.Spin"
Text="Adatok szinkronizálása folyamatban...">
<DxFormLayout CaptionPosition="CaptionPosition.Vertical" CssClass="w-100"> <DxFormLayout CaptionPosition="CaptionPosition.Vertical" CssClass="w-100">
<DxFormLayoutItem Caption="Termék:" ColSpanMd="2"> <DxFormLayoutItem Caption="Termék:" ColSpanMd="2">
@* CaptionCssClass="@(SelectedProductDto?.IsMeasured == true ? "text-success" : "")"> *@ @* CaptionCssClass="@(SelectedProductDto?.IsMeasured == true ? "text-success" : "")"> *@
<DxComboBox Data="@_stockTakings" <DxComboBox @ref="cbStockTakings"
Data="@_stockTakings"
TextFieldName="@nameof(StockTaking.StartDateTime)" TextFieldName="@nameof(StockTaking.StartDateTime)"
CssClass="cw-480" CssClass="cw-480"
DropDownBodyCssClass="dd-body-class" DropDownBodyCssClass="dd-body-class"
@ -32,18 +41,24 @@
CssClass="cw-480" CssClass="cw-480"
DropDownBodyCssClass="dd-body-class" DropDownBodyCssClass="dd-body-class"
Context="ctxProduct2" Context="ctxProduct2"
InputId="cbProduct2"> InputId="cbProduct2"
SearchMode="ListSearchMode.AutoSearch"
SearchFilterCondition="ListSearchFilterCondition.Contains"
SearchTextParseMode="ListSearchTextParseMode.Default"
ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto"
DropDownTriggerMode="DropDownTriggerMode.Click"
@ref="cbStockTakingItems">
</DxComboBox> </DxComboBox>
</DxFormLayoutItem> </DxFormLayoutItem>
@* TextFieldName="StockTakingItem.Product.Name" *@ @* TextFieldName="StockTakingItem.Product.Name" *@
<DxFormLayoutItem ColSpanMd="1"> <DxFormLayoutItem ColSpanMd="1">
<DxButton Text="Új" Enabled="@(_stockTakings.All(x => x.IsClosed))" Click="() => NewStockTakingClick()"></DxButton> <DxButton Text="Új" Enabled="@(!_btnDisabled && _stockTakings.All(x => x.IsClosed))" Click="() => NewStockTakingClick()"></DxButton>
</DxFormLayoutItem> </DxFormLayoutItem>
<DxFormLayoutItem ColSpanMd="1"> @* <DxFormLayoutItem ColSpanMd="1">
<DxButton Text="Módosít" Enabled="@((SelectedStockTaking?.IsClosed ?? false) && false)" Click="() => UpdateStockTakingClick()"></DxButton> <DxButton Text="Módosít" Enabled="@((SelectedStockTaking?.IsClosed ?? false) && false)" Click="() => UpdateStockTakingClick()"></DxButton>
</DxFormLayoutItem> </DxFormLayoutItem>
<DxFormLayoutItem ColSpanMd="1"> *@ <DxFormLayoutItem ColSpanMd="1">
<DxButton Text="Lezárás" Enabled="@((!SelectedStockTaking?.IsClosed ?? false) && (SelectedStockTaking?.IsReadyForClose() ?? false))" Click="() => StockTakingCloseClick(SelectedStockTaking!.Id)"></DxButton> <DxButton Text="Lezárás" Enabled="@(!_btnDisabled && (!SelectedStockTaking?.IsClosed ?? false) && (SelectedStockTaking?.IsReadyForClose() ?? false))" Click="() => StockTakingCloseClick(SelectedStockTaking!.Id)"></DxButton>
</DxFormLayoutItem> </DxFormLayoutItem>
</DxFormLayout> </DxFormLayout>
@ -95,6 +110,7 @@
</DxFormLayout> </DxFormLayout>
} }
</div> </div>
</DxLoadingPanel>
@code @code
{ {
@ -103,6 +119,12 @@
[Inject] public required IDialogService DialogService { get; set; } = null!; [Inject] public required IDialogService DialogService { get; set; } = null!;
[Inject] public required FruitBankSignalRClient FruitBankSignalRClient { get; set; } [Inject] public required FruitBankSignalRClient FruitBankSignalRClient { get; set; }
bool _btnDisabled = false;
bool LoadingPanelVisible = false;
DxComboBox<StockTaking, StockTaking> cbStockTakings;
DxComboBox<StockTakingItem, StockTakingItem> cbStockTakingItems;
List<StockTaking> _stockTakings { get; set; } = []; List<StockTaking> _stockTakings { get; set; } = [];
List<StockTakingItem> _stockTakingItems { get; set; } = []; List<StockTakingItem> _stockTakingItems { get; set; } = [];
List<StockTakingItemPallet> _stockTakingItemPallets { get; set; } = []; List<StockTakingItemPallet> _stockTakingItemPallets { get; set; } = [];
@ -116,25 +138,44 @@
public async Task ReloadDataFromDb(bool forceReload) public async Task ReloadDataFromDb(bool forceReload)
{ {
LoadingPanelVisibility.Visible = true; LoadingPanelVisible = true;
_stockTakings = await FruitBankSignalRClient.GetStockTakings(false) ?? []; _stockTakings = await FruitBankSignalRClient.GetStockTakings(false) ?? [];
await StockTakingComboValueChanged(_stockTakings.FirstOrDefault()); await StockTakingComboValueChanged(_stockTakings.FirstOrDefault());
LoadingPanelVisibility.Visible = false; LoadingPanelVisible = false;
} }
private async Task NewStockTakingClick() private async Task NewStockTakingClick()
{ {
var stockTaking = new StockTaking(); _btnDisabled = true;
stockTaking.StartDateTime = DateTime.Now;
stockTaking.Creator = LoggedInModel.CustomerDto!.Id;
var resultStockTakings = await FruitBankSignalRClient.AddStockTaking(stockTaking); try
if (resultStockTakings == null) return; {
LoadingPanelVisible = true;
_stockTakings.UpdateCollection(resultStockTakings, false); var stockTaking = new StockTaking();
await StockTakingComboValueChanged(_stockTakings.FirstOrDefault(x => x.Id == stockTaking.Id)); stockTaking.StartDateTime = DateTime.Now;
stockTaking.Creator = LoggedInModel.CustomerDto!.Id;
var resultStockTakings = await FruitBankSignalRClient.AddStockTaking(stockTaking);
if (resultStockTakings == null)
{
await DialogService.ShowMessageBoxAsync("Hiba", "Új leltár létrehozása sikertelen volt!", MessageBoxRenderStyle.Danger);
return;
}
_stockTakings.UpdateCollection(resultStockTakings, false);
await StockTakingComboValueChanged(_stockTakings.FirstOrDefault(x => x.Id == resultStockTakings.Id));
}
finally
{
_btnDisabled = false;
LoadingPanelVisible = false;
}
//cbStockTakings.Reload();
await InvokeAsync(StateHasChanged);
} }
private async Task UpdateStockTakingClick() private async Task UpdateStockTakingClick()
@ -148,11 +189,27 @@
private async Task StockTakingCloseClick(int stockTakingId) private async Task StockTakingCloseClick(int stockTakingId)
{ {
var resultStockTaking = await FruitBankSignalRClient.CloseStockTaking(stockTakingId); _btnDisabled = true;
if (resultStockTaking == null) return;
_stockTakings.UpdateCollection(resultStockTaking, false); try
await StockTakingComboValueChanged(_stockTakings.FirstOrDefault(x => x.Id == resultStockTaking.Id)); {
LoadingPanelVisible = true;
var resultStockTaking = await FruitBankSignalRClient.CloseStockTaking(stockTakingId);
if (resultStockTaking == null)
{
await DialogService.ShowMessageBoxAsync("Hiba", "A leltár lezárása sikertelen volt, ellenőrizze a leltár adatait!", MessageBoxRenderStyle.Danger);
return;
}
_stockTakings.UpdateCollection(resultStockTaking, false);
await StockTakingComboValueChanged(_stockTakings.FirstOrDefault(x => x.Id == resultStockTaking.Id));
}
finally
{
_btnDisabled = false;
LoadingPanelVisible = false;
}
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);
} }
@ -161,7 +218,7 @@
{ {
SelectedStockTaking = newValue; SelectedStockTaking = newValue;
SelectedStockTaking?.StockTakingItems = await FruitBankSignalRClient.GetStockTakingItemsByStockTakingId(SelectedStockTaking.Id); SelectedStockTaking?.StockTakingItems = await FruitBankSignalRClient.GetStockTakingItemsByStockTakingId(SelectedStockTaking.Id);
PrepareStockTakingItems(SelectedStockTaking); PrepareStockTakingItems(SelectedStockTaking);
SelectedStockTakingItem = _stockTakingItems.FirstOrDefault(); SelectedStockTakingItem = _stockTakingItems.FirstOrDefault();
@ -194,19 +251,22 @@
} }
} }
private Task OnStockTakingItemPalletValueChanged(StockTakingItemPallet stockTakingItemPallet, StockTakingItem stockTakingItem) private async Task OnStockTakingItemPalletValueChanged(StockTakingItemPallet stockTakingItemPallet, StockTakingItem stockTakingItem)
{ {
// MeasuringValuesHelper.SetShippingItemTotalMeasuringValues(stockTakingItem); // MeasuringValuesHelper.SetShippingItemTotalMeasuringValues(stockTakingItem);
// BtnSaveEnabled = stockTakingItem.IsValidMeasuringValues() && stockTakingItemPallet.IsValidMeasuringValues(stockTakingItem.IsMeasurable); // BtnSaveEnabled = stockTakingItem.IsValidMeasuringValues() && stockTakingItemPallet.IsValidMeasuringValues(stockTakingItem.IsMeasurable);
StateHasChanged(); //cbStockTakingItems.Reload();
return Task.CompletedTask; await InvokeAsync(StateHasChanged);
//return Task.CompletedTask;
} }
private async Task OnStockTakingItemPalletSaved(StockTakingItemPallet? responseStockTakingItemPallet) private async Task OnStockTakingItemPalletSaved(StockTakingItemPallet? responseStockTakingItemPallet)
{ {
if (responseStockTakingItemPallet != null) if (responseStockTakingItemPallet != null)
{ {
//responseStockTakingItemPallet.IsMeasured = true;
responseStockTakingItemPallet.StockTakingItem = SelectedStockTakingItem; responseStockTakingItemPallet.StockTakingItem = SelectedStockTakingItem;
SelectedStockTakingItem!.MeasuredStockQuantity = responseStockTakingItemPallet.TrayQuantity; SelectedStockTakingItem!.MeasuredStockQuantity = responseStockTakingItemPallet.TrayQuantity;
@ -219,7 +279,10 @@
} }
else await DialogService.ShowMessageBoxAsync("Hiba", "Adatok mentése sikertelen volt, ellenőrizze a mérés adatait!", MessageBoxRenderStyle.Danger); else await DialogService.ShowMessageBoxAsync("Hiba", "Adatok mentése sikertelen volt, ellenőrizze a mérés adatait!", MessageBoxRenderStyle.Danger);
//cbStockTakingItems.Reload();
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);
await cbStockTakingItems.FocusAsync();
} }
} }

View File

@ -10,12 +10,6 @@
<div style="margin-top: 30px;"> <div style="margin-top: 30px;">
<DxLoadingPanel @bind-Visible="LoadingPanelVisibility.Visible"
IsContentBlocked="true"
ApplyBackgroundShading="true"
IndicatorAreaVisible="false"
Text="Adatok szinkronizálása folyamatban...">
<DxTabs RenderMode="TabsRenderMode.OnDemand"> <DxTabs RenderMode="TabsRenderMode.OnDemand">
<DxTabPage Text="Leltározás"> <DxTabPage Text="Leltározás">
<StockTakingTemplate></StockTakingTemplate> <StockTakingTemplate></StockTakingTemplate>
@ -31,6 +25,4 @@
} }
</DxTabPage> </DxTabPage>
</DxTabs> </DxTabs>
</DxLoadingPanel>
</div> </div>