improvements, fixes, etc...

This commit is contained in:
Loretta 2025-11-12 17:19:03 +01:00
parent 0e8ab18ca4
commit cfe9c2c3fd
35 changed files with 1131 additions and 286 deletions

View File

@ -75,6 +75,9 @@ public class OrderDto : MgOrderDto<OrderItemDto, ProductDto>, IOrderDto
[NotColumn, JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
public bool IsAllOrderItemAudited => OrderItemDtos.Count > 0 && OrderItemDtos.All(oi => oi.IsAudited);
[NotColumn, JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
public bool IsAllOrderItemAvgWeightValid => OrderItemDtos.All(oi => oi.AverageWeightIsValid);
[NotColumn, JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
public MeasuringStatus MeasuringStatus
{

View File

@ -84,6 +84,16 @@ public class OrderItemDto : MgOrderItemDto<ProductDto>, IOrderItemDto
}
}
[NotColumn, JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
public double AverageWeight => IsMeasurable && OrderItemPallets.Count > 0 ? double.Round(OrderItemPallets.Sum(oip => oip.AverageWeight) / OrderItemPallets.Count, 1) : 0d;
[NotColumn, JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
public double AverageWeightDifference => IsMeasurable ? double.Round(ProductDto!.AverageWeight - AverageWeight, 1) : 0;
[NotColumn, JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
public bool AverageWeightIsValid => !IsMeasurable ||
(ProductDto!.AverageWeight > 0 && ((AverageWeightDifference / ProductDto!.AverageWeight) * 100) < ProductDto!.AverageWeightTreshold);
[NotColumn, JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
public bool IsAudited => OrderItemPallets.Count > 0 && OrderItemPallets.All(oip => oip.IsAudited);

View File

@ -70,5 +70,11 @@ public class ProductDto : MgProductDto, IProductDto
[NotColumn, JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
public int AvailableQuantity => StockQuantity + IncomingQuantity;
[NotColumn, JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
public double AverageWeight => GenericAttributes.GetValueOrDefault<double>(nameof(IProductDto.AverageWeight));
[NotColumn, JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
public double AverageWeightTreshold => GenericAttributes.GetValueOrDefault<double>(nameof(IProductDto.AverageWeightTreshold));
public bool HasMeasuringValues() => Id > 0 && NetWeight != 0 && IsMeasurable;
}

View File

@ -2,6 +2,7 @@
using FruitBank.Common.Enums;
using FruitBank.Common.Interfaces;
using LinqToDB.Mapping;
using Newtonsoft.Json;
using Nop.Core.Domain.Orders;
namespace FruitBank.Common.Entities;
@ -30,6 +31,8 @@ public class OrderItemPallet : MeasuringItemPalletBase, IOrderItemPallet
return OrderItemId > 0 && base.IsValidSafeMeasuringValues();
}
[NotColumn, JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
public double AverageWeight => double.Round(NetWeight / TrayQuantity, 1);
/// <summary>
/// "Szigorúbb" mint az IsValidSafeMeasuringValues()
/// </summary>

View File

@ -0,0 +1,127 @@
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
namespace FruitBank.Common
{
public interface IFastObservableCollection
{
public void AddRange(IEnumerable other);
public void Replace(IEnumerable other);
public void RemoveRange(IEnumerable other);
public void Synchronize(NotifyCollectionChangedEventArgs args);
}
public interface IFastObservableCollection<T>: IFastObservableCollection
{
public void Replace(IEnumerable<T> other);
public void Sort(IComparer<T> comparer);
public void SortAndReplace(IEnumerable<T> other, IComparer<T> comparer);
}
public class FastObservableCollection<T> : ObservableCollection<T>, IFastObservableCollection<T>
{
private bool suppressChangedEvent = false;
public void Replace(IEnumerable<T> other)
{
suppressChangedEvent = true;
Clear();
AddRange(other);
}
public void Replace(IEnumerable other)
{
suppressChangedEvent = true;
Clear();
foreach (T item in other) Add(item);
suppressChangedEvent = false;
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
OnPropertyChanged(new(nameof(Count)));
}
public void AddRange(IEnumerable other)
{
suppressChangedEvent = true;
foreach (object item in other)
{
if (item is T tItem) Add(tItem);
}
suppressChangedEvent = false;
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
OnPropertyChanged(new(nameof(Count)));
}
public void RemoveRange(IEnumerable other)
{
suppressChangedEvent = true;
foreach (object item in other)
{
if (item is T tItem) Remove(tItem);
}
suppressChangedEvent = false;
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
OnPropertyChanged(new(nameof(Count)));
}
public void SortAndReplace(IEnumerable<T> other, IComparer<T> comparer)
{
List<T> values = new(other);
values.Sort(comparer);
Replace(values);
}
public void Sort(IComparer<T> comparer)
{
List<T> values = new(this);
values.Sort(comparer);
Replace(values);
}
public void Synchronize(NotifyCollectionChangedEventArgs args)
{
if (args.Action == NotifyCollectionChangedAction.Add && args.NewItems != null)
{
AddRange(args.NewItems);
}
else if (args.Action == NotifyCollectionChangedAction.Remove && args.OldItems != null)
{
RemoveRange(args.OldItems);
}
else if (args.Action == NotifyCollectionChangedAction.Reset)
{
Clear();
}
}
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (suppressChangedEvent)
return;
base.OnPropertyChanged(e);
}
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (suppressChangedEvent)
return;
base.OnCollectionChanged(e);
}
}
}

View File

@ -8,7 +8,7 @@ public interface ICustomOrderSignalREndpointCommon
{
Task<List<OrderDto>?> GetAllOrderDtos();
Task<List<OrderDto>?> GetPendingOrderDtos();
Task<List<OrderDto>?> GetPendingOrderDtosForMeasuring();
Task<List<OrderDto>?> GetPendingOrderDtosForMeasuring(int lastDaysCount);
Task<List<OrderDto>?> GetAllOrderDtoByIds(int[] orderIds);
Task<OrderDto?> GetOrderDtoById(int orderId);

View File

@ -4,4 +4,7 @@ namespace FruitBank.Common.Interfaces;
public interface IProductDto : IMgProductDto, ITare, IIncomingQuantity, IAvailableQuantity, IMeasuringAttributeValues
{
public double AverageWeight { get; }
public double AverageWeightTreshold { get; }
}

View File

@ -53,8 +53,9 @@ public class SignalRTags : AcSignalRTags
public const int GetPendingOrderDtos = 114;
public const int GetAllOrderDtoByProductId = 115;
public const int GetPendingOrderDtosForMeasuring = 116;
public const int StartMeasuring = 117;
public const int SetOrderStatusToComplete = 118;
public const int GetOrderDatesForMeasuring = 117;
public const int StartMeasuring = 118;
public const int SetOrderStatusToComplete = 119;
public const int GetOrderItemDtoById = 120;
public const int GetAllOrderItemDtos = 121;

View File

@ -1,11 +1,17 @@
@using FruitBank.Common.Dtos
@using AyCode.Utils.Extensions
@using FruitBank.Common.Dtos
@using FruitBank.Common.Models
@using FruitBankHybrid.Shared.Components.Toolbars
@using FruitBankHybrid.Shared.Databases
@using FruitBankHybrid.Shared.Services.SignalRs
@inject LoggedInModel LoggedInModel;
@inject FruitBankSignalRClient FruitBankSignalRClient
<MgGridBase Data="OrderDtos" IsMasterGrid="IsMasterGrid" AutoSaveLayoutName="GridDetailOrderDto"
<MgGridBase @ref="@Grid" Data="OrderDtos" IsMasterGrid="IsMasterGrid" AutoSaveLayoutName="GridDetailOrderDto"
ShowFilterRow="IsMasterGrid" ShowGroupPanel="IsMasterGrid"
AutoExpandAllGroupRows="false"
AutoExpandAllGroupRows="false"
CssClass="@GridCss"
ColumnResizeMode="GridColumnResizeMode.NextColumn" VirtualScrollingEnabled="IsMasterGrid"
FilterMenuButtonDisplayMode="@(IsMasterGrid ? GridFilterMenuButtonDisplayMode.Never : GridFilterMenuButtonDisplayMode.Always)">
<Columns>
@ -14,9 +20,12 @@
<DxGridDataColumn FieldName="OrderTotal" />
<DxGridDataColumn FieldName="OrderStatus" />
<DxGridDataColumn FieldName="IsMeasured" ReadOnly="true" />
<DxGridDataColumn FieldName="IsMeasurable" ReadOnly="true" />
<DxGridDataColumn FieldName="MeasuringStatus" ReadOnly="true" />
@* <DxGridDataColumn FieldName="IsMeasured" ReadOnly="true" /> *@
<DxGridDataColumn FieldName="IsAllOrderItemAvgWeightValid" ReadOnly="true" Caption="AvgWeightValid" />
<DxGridDataColumn FieldName="RevisorId" ReadOnly="true" />
<DxGridDataColumn FieldName="MeasurementOwnerId" ReadOnly="true" />
<DxGridDataColumn FieldName="DateOfReceipt" />
@ -24,7 +33,7 @@
<DxGridCommandColumn Visible="!IsMasterGrid" Width="120"></DxGridCommandColumn>
</Columns>
<DetailRowTemplate>
@if (IsMasterGrid)
@if (IsMasterGrid && LoggedInModel.IsDeveloper)
{
var orderDto = ((OrderDto)context.DataItem);
@ -35,13 +44,19 @@
<DxTabPage Text="Mérések">
@{
var orderItemPalletDtos = orderDto?.OrderItemDtos.SelectMany(oi => oi.OrderItemPallets).ToList() ?? [];
<GridDetailOrderItemPallets OrderItemPallets="orderItemPalletDtos" IsMasterGrid="false"/>
<GridDetailOrderItemPallets OrderItemPallets="orderItemPalletDtos" IsMasterGrid="false"/>
}
</DxTabPage>
</DxTabs>
}
</DetailRowTemplate>
<ToolbarTemplate>
@if (IsMasterGrid)
{
<FruitBankToolbarTemplate Grid="Grid" OnReloadDataClick="() => ReloadDataFromDb(true)"/>
}
</ToolbarTemplate>
<GroupSummary>
<DxGridSummaryItem SummaryType="GridSummaryItemType.Sum"
FieldName="Quantity"
@ -60,11 +75,35 @@
//[Parameter] public OrderDto? OrderDto { get; set; }
[Parameter] public List<OrderDto>? OrderDtos { get; set; }
private int _activeTabIndex;
protected override void OnInitialized()
string GridCss => !IsMasterGrid ? "hide-toolbar" : string.Empty;
MgGridBase Grid;
int _activeTabIndex;
protected override async Task OnInitializedAsync()
{
// if (OrderDto != null)
// OrderItemDtos = OrderDto.OrderItemDtos;
await ReloadDataFromDb(false);
}
private async Task ReloadDataFromDb(bool forceReload = false)
{
LoadingPanelVisibility.Visible = true;
using (await ObjectLock.GetSemaphore<OrderDto>().UseWaitAsync())
{
if (OrderDtos == null) OrderDtos = await FruitBankSignalRClient.GetAllOrderDtos() ?? [];
else if (OrderDtos.Count == 0 || forceReload)
{
OrderDtos.Clear();
OrderDtos.AddRange(await FruitBankSignalRClient.GetAllOrderDtos() ?? []);
}
}
//if (forceReload)
Grid?.Reload();
LoadingPanelVisibility.Visible = false;
}
protected async Task OnActiveTabChanged(int activeTabIndex)

View File

@ -1,16 +1,19 @@
@using FruitBank.Common.Dtos
@using AyCode.Core.Helpers
@using AyCode.Utils.Extensions
@using FruitBank.Common.Dtos
@using FruitBank.Common.Models
@using FruitBankHybrid.Shared.Components.Toolbars
@using FruitBankHybrid.Shared.Databases
@using FruitBankHybrid.Shared.Services.SignalRs
@inject LoggedInModel LoggedInModel;
@inject FruitBankSignalRClient FruitBankSignalRClient
@* <div class="mb-2">
Contact Phone: @OrderDto.Email
</div> *@
<MgGridBase Data="OrderItemDtos" IsMasterGrid="IsMasterGrid"
<MgGridBase @ref="Grid" Data="OrderItemDtos" IsMasterGrid="IsMasterGrid"
PageSize="@(IsMasterGrid ? 15 : 50)" ShowFilterRow="IsMasterGrid" ShowGroupPanel="IsMasterGrid"
AutoExpandAllGroupRows="false" AutoSaveLayoutName="GridDetailOrderItemDto"
ColumnResizeMode="GridColumnResizeMode.NextColumn"
CssClass="@GridCss"
FilterMenuButtonDisplayMode="@(IsMasterGrid ? GridFilterMenuButtonDisplayMode.Never : GridFilterMenuButtonDisplayMode.Always)">
<Columns>
<DxGridDataColumn FieldName="Id" />
@ -34,15 +37,29 @@
<DxGridDataColumn FieldName="Quantity" />
<DxGridDataColumn FieldName="NetWeight" />
<DxGridDataColumn FieldName="IsMeasurable" ReadOnly="true" />
<DxGridDataColumn FieldName="IsMeasured" ReadOnly="true" />
<DxGridDataColumn FieldName="MeasuringStatus" ReadOnly="true" />
@* <DxGridDataColumn FieldName="IsMeasured" ReadOnly="true" /> *@
<DxGridDataColumn FieldName="AverageWeight" ReadOnly="true" Visible="false" Caption="AvgWeight" />
<DxGridDataColumn FieldName="AverageWeightDifference" ReadOnly="true" Visible="false" Caption="AvgWeightDiff" />
<DxGridDataColumn FieldName="AverageWeightIsValid" ReadOnly="true" Caption="AvgWeightValid" />
<DxGridDataColumn FieldName="IsAudited" ReadOnly="true" />
<DxGridCommandColumn Visible="!IsMasterGrid" Width="120"></DxGridCommandColumn>
</Columns>
<DetailRowTemplate>
<GridDetailOrderItemPallets OrderItemPallets="((OrderItemDto)context.DataItem).OrderItemPallets" />
@if (IsMasterGrid && LoggedInModel.IsDeveloper)
{
<GridDetailOrderItemPallets OrderItemPallets="((OrderItemDto)context.DataItem).OrderItemPallets" />
}
</DetailRowTemplate>
<ToolbarTemplate>
@if (IsMasterGrid)
{
<FruitBankToolbarTemplate Grid="Grid" OnReloadDataClick="() => ReloadDataFromDb(true)"/>
}
</ToolbarTemplate>
<GroupSummary>
<DxGridSummaryItem SummaryType="GridSummaryItemType.Sum"
FieldName="Quantity"
@ -57,15 +74,62 @@
</MgGridBase>
@code {
[Inject] public required DatabaseClient Database { get; set; }
[Parameter] public bool IsMasterGrid { get; set; } = false;
//[Parameter] public OrderDto? OrderDto { get; set; }
[Parameter] public List<OrderItemDto>? OrderItemDtos { get; set; }
[Parameter] public List<ProductDto>? ProductDtos { get; set; }
[Parameter] public IEnumerable<ProductDto>? ProductDtos { get; set; }
string GridCss => !IsMasterGrid ? "hide-toolbar" : string.Empty;
public MgGridBase Grid;
protected override async Task OnInitializedAsync()
{
ProductDtos ??= await FruitBankSignalRClient.GetProductDtos();
// if (OrderDto != null)
// OrderItemDtos = OrderDto.OrderItemDtos;
await ReloadDataFromDb();
}
private async Task ReloadDataFromDb(bool forceReload = false)
{
LoadingPanelVisibility.Visible = true;
//using (await ObjectLock.GetSemaphore<ProductDto>().UseWaitAsync())
{
// if (ProductDtos == null || !ProductDtos.Any())
// {
// ProductDtos = await Database.ProductDtoTable.LoadDataAsync(!forceReload);
// // Database.ProductDtoTable.LoadDataAsync(!forceReload).ContinueWith(x =>
// // {
// // ProductDtos = x.Result;
// // }).Forget();
// }
}
if (!IsMasterGrid) return;
using (await ObjectLock.GetSemaphore<OrderItemDto>().UseWaitAsync())
{
if (OrderItemDtos == null) OrderItemDtos = await FruitBankSignalRClient.GetAllOrderItemDtos() ?? [];
else if (OrderItemDtos.Count == 0 || forceReload)
{
OrderItemDtos.Clear();
OrderItemDtos.AddRange(await FruitBankSignalRClient.GetAllOrderItemDtos() ?? []);
}
}
//if (forceReload)
Grid?.Reload();
if (ProductDtos == null || !ProductDtos.Any() || forceReload)
{
//ProductDtos = await Database.ProductDtoTable.LoadDataAsync(!forceReload);
Database.ProductDtoTable.LoadDataAsync(!forceReload).ContinueWith(x =>
{
ProductDtos = x.Result;
}).Forget();
}
LoadingPanelVisibility.Visible = false;
}
}

View File

@ -1,12 +1,18 @@
@using FruitBank.Common.Dtos
@using AyCode.Utils.Extensions
@using FruitBank.Common.Dtos
@using FruitBank.Common.Entities
@using FruitBank.Common.Models
@using FruitBankHybrid.Shared.Components.Toolbars
@using FruitBankHybrid.Shared.Databases
@using FruitBankHybrid.Shared.Services.SignalRs
@inject LoggedInModel LoggedInModel;
@inject FruitBankSignalRClient FruitBankSignalRClient
<MgGridBase @ref="gridOrderItemPallet" Data="OrderItemPallets" IsMasterGrid="IsMasterGrid" AutoSaveLayoutName="GridDetailOrderItemPallets"
PageSize="@(IsMasterGrid ? 15 : 50)" ShowFilterRow="IsMasterGrid" ShowGroupPanel="IsMasterGrid"
AutoExpandAllGroupRows="false"
CssClass="@GridCss"
ColumnResizeMode="GridColumnResizeMode.NextColumn"
FilterMenuButtonDisplayMode="@(IsMasterGrid ? GridFilterMenuButtonDisplayMode.Never : GridFilterMenuButtonDisplayMode.Always)">
<Columns>
@ -22,11 +28,18 @@
<DxGridDataColumn FieldName="TrayQuantity" />
<DxGridDataColumn FieldName="GrossWeight" />
<DxGridDataColumn FieldName="NetWeight" />
<DxGridDataColumn FieldName="AverageWeight" ReadOnly="true" Caption="AvgWeight" />
<DxGridDataColumn FieldName="IsMeasured" ReadOnly="true" />
<DxGridDataColumn FieldName="IsAudited" ReadOnly="true" />
<DxGridCommandColumn Visible="!IsMasterGrid" Width="120"></DxGridCommandColumn>
</Columns>
<ToolbarTemplate>
@if (IsMasterGrid)
{
<FruitBankToolbarTemplate Grid="gridOrderItemPallet" OnReloadDataClick="() => ReloadDataFromDb(true)" />
}
</ToolbarTemplate>
<GroupSummary>
<DxGridSummaryItem SummaryType="GridSummaryItemType.Sum"
FieldName="TrayQuantity"
@ -38,28 +51,47 @@
</MgGridBase>
@code {
IGrid gridOrderItemPallet;
MgGridBase gridOrderItemPallet;
[Parameter] public bool IsMasterGrid { get; set; } = false;
[Parameter] public List<OrderItemPallet>? OrderItemPallets { get; set; }
string GridCss => !IsMasterGrid ? "hide-toolbar" : string.Empty;
protected override async Task OnInitializedAsync()
{
if (OrderItemPallets == null)
await ReloadDataFromDb(false);
}
public async Task ReloadDataFromDb(bool forceReload)
{
if (!IsMasterGrid) return;
LoadingPanelVisibility.Visible = true;
using (await ObjectLock.GetSemaphore<OrderItemPallet>().UseWaitAsync())
{
OrderItemPallets = await FruitBankSignalRClient.GetAllOrderItemPallets();
if (OrderItemPallets != null && OrderItemPallets.Any(oip => oip.OrderItemDto?.ProductDto != null))
if (OrderItemPallets == null) OrderItemPallets = await FruitBankSignalRClient.GetAllOrderItemPallets() ?? [];
else if (OrderItemPallets.Count == 0 || forceReload)
{
gridOrderItemPallet.BeginUpdate();
gridOrderItemPallet.GetColumns().FirstOrDefault(x => x.Name == "ProductId")!.Visible = true;
gridOrderItemPallet.GetColumns().FirstOrDefault(x => x.Name == "ProductName")!.Visible = true;
gridOrderItemPallet.EndUpdate();
OrderItemPallets.Clear();
OrderItemPallets.AddRange(await FruitBankSignalRClient.GetAllOrderItemPallets() ?? []);
}
}
if (OrderItemPallets != null && OrderItemPallets.Any(oip => oip.OrderItemDto?.ProductDto != null))
{
gridOrderItemPallet.BeginUpdate();
gridOrderItemPallet.GetColumns().FirstOrDefault(x => x.Name == "ProductId")!.Visible = true;
gridOrderItemPallet.GetColumns().FirstOrDefault(x => x.Name == "ProductName")!.Visible = true;
gridOrderItemPallet.EndUpdate();
}
if (forceReload)
gridOrderItemPallet?.Reload();
LoadingPanelVisibility.Visible = false;
}
protected override Task OnAfterRenderAsync(bool firstRender)
@ -69,10 +101,10 @@
// if (OrderItemPallets != null && OrderItemPallets.Any(oip => oip.OrderItemDto?.ProductDto != null))
// {
// gridOrderItemPallet.BeginUpdate();
// gridOrderItemPallet.GetColumns().FirstOrDefault(x => x.Name == "ProductId")!.Visible = true;
// gridOrderItemPallet.GetColumns().FirstOrDefault(x => x.Name == "ProductName")!.Visible = true;
// gridOrderItemPallet.EndUpdate();
// }
}

View File

@ -1,12 +1,17 @@
@using AyCode.Core.Helpers
@using AyCode.Utils.Extensions
@using DevExpress.Internal.About
@using FruitBank.Common.Dtos
@using FruitBank.Common.Models
@using FruitBankHybrid.Shared.Components.Toolbars
@using FruitBankHybrid.Shared.Databases
@using FruitBankHybrid.Shared.Services.SignalRs
@inject LoggedInModel LoggedInModel;
@inject FruitBankSignalRClient FruitBankSignalRClient
<GridProductDto Data="ProductDtos" IsMasterGrid="IsMasterGrid" FocusedRowChanged="OnFocusedRowChanged" AutoSaveLayoutName="GridProductDtoTemplate">
<GridProductDto @ref="Grid" Data="ProductDtos" IsMasterGrid="IsMasterGrid" FocusedRowChanged="OnFocusedRowChanged"
CssClass="@GridCss" AutoSaveLayoutName="GridProductDtoTemplate">
<Columns>
<DxGridDataColumn FieldName="Id" SortIndex="0" SortOrder="GridColumnSortOrder.Ascending" />
<DxGridDataColumn FieldName="Name" />
@ -16,10 +21,12 @@
<DxGridDataColumn FieldName="IncomingQuantity" ReadOnly="true" />
<DxGridDataColumn FieldName="NetWeight" ReadOnly="true" />
<DxGridDataColumn FieldName="IsMeasurable" />
<DxGridDataColumn FieldName="AverageWeight" ReadOnly="true" />
<DxGridDataColumn FieldName="AverageWeightTreshold" ReadOnly="true" />
<DxGridCommandColumn Visible="!IsMasterGrid" Width="120"></DxGridCommandColumn>
</Columns>
<DetailRowTemplate>
@if (IsMasterGrid)
@if (IsMasterGrid && LoggedInModel.IsDeveloper)
{
var productId = ((ProductDto)context.DataItem).Id;
@ -42,13 +49,20 @@
</DxTabs>
}
</DetailRowTemplate>
<ToolbarTemplate>
@if (IsMasterGrid)
{
<FruitBankToolbarTemplate Grid="Grid" OnReloadDataClick="() => ReloadDataFromDb(true)" />
}
</ToolbarTemplate>
</GridProductDto>
@code {
[Inject] public required DatabaseClient Database { get; set; }
string GridCss => !IsMasterGrid ? "hide-toolbar" : string.Empty;
private int _activeTabIndex;
private List<OrderDto>? _currentOrderDtos;
@ -56,6 +70,7 @@
private readonly Dictionary<int, List<OrderDto>> _orderDtosByProductId = new();
private readonly Dictionary<int, List<OrderItemDto>> _orderItemDtosByProductId = new();
public GridProductDto Grid { get; set; }
[Parameter] public bool IsMasterGrid { get; set; } = false;
[Parameter] public IEnumerable<ProductDto>? ProductDtos { get; set; }
@ -64,12 +79,38 @@
protected override async Task OnInitializedAsync()
{
ProductDtos ??= await Database.ProductDtoTable.LoadDataAsync(true);
// if (IsMasterGrid)
// {
// using (await ObjectLock.GetSemaphore<ProductDto>().UseWaitAsync())
// {
// ProductDtos ??= await Database.ProductDtoTable.LoadDataAsync(true);
// }
// //ProductDtos ??= await FruitBankSignalRClient.GetProductDtos();
//ProductDtos ??= await FruitBankSignalRClient.GetProductDtos();
// // if (ProductDtos is { Count: > 0 })
// // _currentOrderDtos = await GetOrderDtosFromDbAsync(ProductDtos[0].Id);
// }
// if (ProductDtos is { Count: > 0 })
// _currentOrderDtos = await GetOrderDtosFromDbAsync(ProductDtos[0].Id);
await ReloadDataFromDb(false);
}
public async Task ReloadDataFromDb(bool forceReload)
{
if (!IsMasterGrid) return;
LoadingPanelVisibility.Visible = true;
using (await ObjectLock.GetSemaphore<ProductDto>().UseWaitAsync())
{
if (ProductDtos == null || !ProductDtos.Any() || forceReload) ProductDtos = await Database.ProductDtoTable.LoadDataAsync(!forceReload);
}
_orderDtosByProductId.Clear();
_orderItemDtosByProductId.Clear();
// if (forceReload)
// Grid?.Reload();
LoadingPanelVisibility.Visible = false;
}
private async Task<List<OrderDto>> GetOrderDtosFromDbAsync(int productId)

View File

@ -1,5 +1,7 @@
@using FruitBank.Common.Dtos
@using AyCode.Utils.Extensions
@using FruitBank.Common.Dtos
@using FruitBank.Common.Entities
@using FruitBankHybrid.Shared.Databases
@using FruitBankHybrid.Shared.Services.SignalRs
@inject FruitBankSignalRClient FruitBankSignalRClient
@ -34,7 +36,7 @@
</DxTabPage>
<DxTabPage Text="Szállítmány tételek">
<GridShippingItem ShippingItems="shippingDocuments?.SelectMany(sd => sd.ShippingItems ?? [])?.ToList() ?? []" IsMasterGrid="false" />
<GridShippingItemTemplate ShippingItems="shippingDocuments?.SelectMany(sd => sd.ShippingItems ?? [])?.ToList() ?? []" IsMasterGrid="false" />
</DxTabPage>
</DxTabs>
}
@ -77,6 +79,9 @@
</MgGridBase>
@code {
//[Inject] public required ObjectLock ObjectLock { get; set; }
[Inject] public required DatabaseClient Database { get; set; }
[Parameter] public bool IsMasterGrid { get; set; } = false;
//[Parameter] public OrderDto? OrderDto { get; set; }
[Parameter] public List<Shipping>? Shippings{ get; set; }
@ -85,13 +90,32 @@
string GridSearchText = "";
bool EditItemsEnabled { get; set; }
int FocusedRowVisibleIndex { get; set; }
IGrid Grid { get; set; }
public MgGridBase Grid { get; set; }
private int _activeTabIndex;
protected override async Task OnInitializedAsync()
{
Shippings ??= (await FruitBankSignalRClient.GetShippings()) ?? [];
// OrderItemDtos = OrderDto.OrderItemDtos;
await ReloadDataFromDb(false);
}
private async Task ReloadDataFromDb(bool forceReload = false)
{
if (!IsMasterGrid) return;
//ProductDtos ??= await FruitBankSignalRClient.GetProductDtos() ?? [];
//ProductDtos ??= await Database.ProductDtoTable.LoadDataAsync(true);
using (await ObjectLock.GetSemaphore<Shipping>().UseWaitAsync())
{
if (Shippings == null) Shippings = await FruitBankSignalRClient.GetShippings() ?? [];
else if (Shippings.Count == 0 || forceReload)
{
Shippings.Clear();
Shippings.AddRange(await FruitBankSignalRClient.GetShippings() ?? []);
}
}
if (forceReload) Grid?.Reload();
}
async Task Grid_DataItemDeleting(GridDataItemDeletingEventArgs e) {

View File

@ -1,4 +1,5 @@
@using FruitBank.Common.Dtos
@using AyCode.Utils.Extensions
@using FruitBank.Common.Dtos
@using FruitBank.Common.Entities
@using FruitBankHybrid.Shared.Components.FileUploads
@using FruitBankHybrid.Shared.Databases
@ -71,12 +72,12 @@
<DxTabs ActiveTabIndexChanged="(i) => OnActiveTabChanged(i)">
<DxTabPage Text="Szállítmány tételek">
<GridShippingItem ShippingItems="shippingDocument.ShippingItems" IsMasterGrid="false" />
<GridShippingItemTemplate ShippingItems="shippingDocument.ShippingItems" IsMasterGrid="false" />
</DxTabPage>
<DxTabPage Text="Mérések">
@{
var shippingItemPallets = shippingDocument?.ShippingItems?.SelectMany(oi => oi.ShippingItemPallets ?? []).ToList() ?? [];
// <GridDetailOrderItemPallets OrderItemPallets="orderItemPalletDtos" IsMasterGrid="false"/>
<GridShippingItemPallets OrderItemPallets="shippingItemPallets" IsMasterGrid="false" />
}
</DxTabPage>
@ -135,13 +136,14 @@
</MgGridBase>
@code {
//[Inject] public required ObjectLock ObjectLock { get; set; }
[Inject] public required DatabaseClient Database { get; set; }
[Inject] public required LoggedInModel LoggedInModel { get; set; }
[Parameter] public bool IsMasterGrid { get; set; } = false;
[Parameter] public List<Shipping>? Shippings { get; set; }
[Parameter] public IEnumerable<Partner>? Partners { get; set; }
[Parameter] public List<Partner>? Partners { get; set; }
[Parameter] public List<ShippingDocument>? ShippingDocuments { get; set; }
[Parameter] public Func<List<Partner>?, Task>? OnUploadedFileParsed { get; set; }
@ -154,20 +156,54 @@
string GridSearchText = "";
bool EditItemsEnabled { get; set; } = true;
int FocusedRowVisibleIndex { get; set; }
IGrid Grid { get; set; }
public MgGridBase Grid { get; set; }
private int _activeTabIndex;
protected override async Task OnInitializedAsync()
{
_localStorageKey += LoggedInModel.CustomerDto!.Id;
await ReloadDataFromDb();
}
private async Task ReloadDataFromDb(bool forceReload = false)
{
if (!IsMasterGrid) return;
//ProductDtos ??= await Database.ProductDtoTable.LoadDataAsync(true);
Partners ??= await FruitBankSignalRClient.GetPartners() ?? [];
Shippings ??= await FruitBankSignalRClient.GetShippings() ?? [];
//ProductDtos ??= await FruitBankSignalRClient.GetProductDtos() ?? [];
ShippingDocuments ??= await FruitBankSignalRClient.GetShippingDocuments() ?? [];
// if (OrderDto != null)
// OrderItemDtos = OrderDto.OrderItemDtos;
//ProductDtos ??= await Database.ProductDtoTable.LoadDataAsync(true);
using (await ObjectLock.GetSemaphore<Partner>().UseWaitAsync())
{
if (Partners == null) Partners = await FruitBankSignalRClient.GetPartners() ?? [];
else if (Partners.Count == 0 || forceReload)
{
Partners.Clear();
Partners.AddRange(await FruitBankSignalRClient.GetPartners() ?? []);
}
}
using (await ObjectLock.GetSemaphore<Shipping>().UseWaitAsync())
{
if (Shippings == null) Shippings = await FruitBankSignalRClient.GetShippings() ?? [];
else if (Shippings.Count == 0 || forceReload)
{
Shippings.Clear();
Shippings.AddRange(await FruitBankSignalRClient.GetShippings() ?? []);
}
}
using (await ObjectLock.GetSemaphore<ShippingDocument>().UseWaitAsync())
{
if (ShippingDocuments == null) ShippingDocuments = await FruitBankSignalRClient.GetShippingDocuments() ?? [];
else if (ShippingDocuments.Count == 0 || forceReload)
{
ShippingDocuments.Clear();
ShippingDocuments.AddRange(await FruitBankSignalRClient.GetShippingDocuments() ?? []);
}
}
if (forceReload) Grid?.Reload();
}
private async Task OnFileUploaded(byte[] arg)

View File

@ -1,5 +1,7 @@
@using FruitBank.Common.Dtos
@using AyCode.Utils.Extensions
@using FruitBank.Common.Dtos
@using FruitBank.Common.Entities
@using FruitBankHybrid.Shared.Databases
@using FruitBankHybrid.Shared.Services.SignalRs
@inject FruitBankSignalRClient FruitBankSignalRClient
@ -37,29 +39,48 @@
</MgGridBase>
@code {
IGrid gridOrderItemPallet;
public MgGridBase gridOrderItemPallet;
[Inject] public required DatabaseClient Database { get; set; }
//[Inject] public required ObjectLock ObjectLock{ get; set; }
[Parameter] public bool IsMasterGrid { get; set; } = false;
[Parameter] public List<ShippingItemPallet>? ShippingItemPallets { get; set; }
protected override async Task OnInitializedAsync()
{
if (ShippingItemPallets == null)
await ReloadDataFromDb(false);
}
private async Task ReloadDataFromDb(bool forceReload = false)
{
if (!IsMasterGrid) return;
using (await ObjectLock.GetSemaphore<ShippingItemPallet>().UseWaitAsync())
{
//TODO: A ShippingItemPallet-eknek SignalR Endpoint! - J.
ShippingItemPallets = (await FruitBankSignalRClient.GetShippingItems())!.SelectMany(si => si.ShippingItemPallets!).ToList();
ShippingItemPallets ??= [];
if (ShippingItemPallets != null && ShippingItemPallets.Any(sip => sip.ShippingItem?.ProductDto != null))
if (ShippingItemPallets.Count == 0 || forceReload)
{
gridOrderItemPallet.BeginUpdate();
gridOrderItemPallet.GetColumns().FirstOrDefault(x => x.Name == "ProductId")!.Visible = true;
gridOrderItemPallet.GetColumns().FirstOrDefault(x => x.Name == "ProductName")!.Visible = true;
gridOrderItemPallet.EndUpdate();
}
ShippingItemPallets.Clear();
//TODO: A ShippingItemPallet-eknek SignalR Endpoint! - J.
ShippingItemPallets.AddRange((await FruitBankSignalRClient.GetShippingItems())?.SelectMany(si => si.ShippingItemPallets ?? []) ?? []);
if (ShippingItemPallets.Any(sip => sip.ShippingItem?.ProductDto != null))
{
gridOrderItemPallet.BeginUpdate();
gridOrderItemPallet.GetColumns().FirstOrDefault(x => x.Name == "ProductId")!.Visible = true;
gridOrderItemPallet.GetColumns().FirstOrDefault(x => x.Name == "ProductName")!.Visible = true;
gridOrderItemPallet.EndUpdate();
}
}
}
if (forceReload)
gridOrderItemPallet?.Reload();
}
protected override Task OnAfterRenderAsync(bool firstRender)

View File

@ -1,26 +1,38 @@
@using AyCode.Core.Extensions
@using AyCode.Core.Loggers;
@using AyCode.Core.Extensions
@using AyCode.Core.Helpers
@using AyCode.Utils.Extensions
@using FruitBank.Common.Dtos
@using FruitBank.Common.Entities
@using FruitBankHybrid.Shared.Components.Grids.ShippingItems
@using FruitBankHybrid.Shared.Components.Toolbars
@using FruitBankHybrid.Shared.Databases
@using FruitBankHybrid.Shared.Services.Loggers;
@using FruitBankHybrid.Shared.Services.SignalRs
@inject IEnumerable<IAcLogWriterClientBase> LogWriters
@inject FruitBankSignalRClient FruitBankSignalRClient
@* <div class="mb-2">
Contact Phone: @OrderDto.Email
</div> *@
@* Data="ShippingItems" IsMasterGrid="IsMasterGrid" CssClass="@GridCss" AutoSaveLayoutName="GridShippingItem"
ValidationEnabled="false" EditMode="GridEditMode.EditRow"
EditModelSaving="Grid_EditModelSaving"
FocusedRowChanged="Grid_FocusedRowChanged" *@
<MgGridBase @ref="Grid" Data="ShippingItems" IsMasterGrid="IsMasterGrid" CssClass="@GridCss" AutoSaveLayoutName="GridShippingItem"
<GridShippingItemBase @ref="Grid" IsMasterGrid="IsMasterGrid" DataSource="ShippingItems" AutoSaveLayoutName="GridShippingItem"
SignalRClient="FruitBankSignalRClient" Logger="_logger"
CssClass="@GridCss" ValidationEnabled="false" EditMode="GridEditMode.EditRow"
FocusedRowChanged="Grid_FocusedRowChanged">
@* <MgGridBase Data="ShippingItems" IsMasterGrid="IsMasterGrid" CssClass="@GridCss" AutoSaveLayoutName="GridShippingItem"
ValidationEnabled="false" EditMode="GridEditMode.EditRow"
EditModelSaving="Grid_EditModelSaving"
FocusedRowChanged="Grid_FocusedRowChanged">
FocusedRowChanged="Grid_FocusedRowChanged"> *@
<Columns>
<DxGridDataColumn FieldName="Id" Caption="oiId" Width="125" />
<DxGridDataColumn FieldName="ShippingDocumentId" Caption="ShippingDocument">
<EditSettings>
<DxComboBoxSettings Data="ShippingDocuments"
ValueFieldName="Id"
TextFieldName="DocumentIdNumber"
TextFieldName="@("Partner.Name")"
DropDownBodyCssClass="dd-body-class"
ListRenderMode="ListRenderMode.Entire"
SearchMode="ListSearchMode.AutoSearch"
@ -40,13 +52,13 @@
<DxGridDataColumn FieldName="ProductId" Caption="Product">
<EditSettings>
<DxComboBoxSettings Data="ProductDtos"
ValueFieldName="Id"
TextFieldName="Name"
DropDownBodyCssClass="dd-body-class"
ListRenderMode="ListRenderMode.Entire"
SearchMode="ListSearchMode.AutoSearch"
SearchFilterCondition="ListSearchFilterCondition.Contains"
ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto" >
ValueFieldName="Id"
TextFieldName="Name"
DropDownBodyCssClass="dd-body-class"
ListRenderMode="ListRenderMode.Entire"
SearchMode="ListSearchMode.AutoSearch"
SearchFilterCondition="ListSearchFilterCondition.Contains"
ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto">
<Columns>
<DxListEditorColumn FieldName="@nameof(ProductDto.Id)" />
<DxListEditorColumn FieldName="@nameof(ProductDto.Name)" />
@ -73,7 +85,7 @@
<DxGridDataColumn FieldName="MeasuredGrossWeight" Caption="Mért br.súly(kg)" ReadOnly="true" />
<DxGridDataColumn FieldName="IsMeasurable" ReadOnly="true" />
<DxGridDataColumn FieldName="IsMeasured" ReadOnly="true"/>
<DxGridDataColumn FieldName="IsMeasured" ReadOnly="true" />
<DxGridDataColumn FieldName="Created" ReadOnly="true" />
<DxGridDataColumn FieldName="Modified" ReadOnly="true" />
@ -88,28 +100,7 @@
<ToolbarTemplate>
@if (IsMasterGrid)
{
<DxToolbar ItemRenderStyleMode="ToolbarRenderStyleMode.Plain">
<DxToolbarItem Text="New" Click="NewItem_Click" IconCssClass="grid-toolbar-new" />
<DxToolbarItem Text="Edit" Click="EditItem_Click" IconCssClass="grid-toolbar-edit" Enabled="EditItemsEnabled" />
<DxToolbarItem Text="Delete" Click="DeleteItem_Click" IconCssClass="grid-toolbar-delete" Enabled="EditItemsEnabled" />
<DxToolbarItem Text="Column Chooser" BeginGroup="true" Click="ColumnChooserItem_Click" IconCssClass="grid-toolbar-column-chooser" />
<DxToolbarItem Text="Export" IconCssClass="grid-toolbar-export">
<Items>
<DxToolbarItem Text="To CSV" Click="ExportCsvItem_Click" />
<DxToolbarItem Text="To XLSX" Click="ExportXlsxItem_Click" />
<DxToolbarItem Text="To XLS" Click="ExportXlsItem_Click" />
<DxToolbarItem Text="To PDF" Click="ExportPdfItem_Click" />
</Items>
</DxToolbarItem>
@* <DxToolbarItem BeginGroup="true">
<Template Context="toolbar_item_context">
<DxSearchBox @bind-Text="GridSearchText"
BindValueMode="BindValueMode.OnInput"
ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto"
aria-label="Search" />
</Template>
</DxToolbarItem>*@
</DxToolbar>
<FruitBankToolbarTemplate Grid="Grid" OnReloadDataClick="() => ReloadDataFromDb(true)"/>
}
</ToolbarTemplate>
<GroupSummary>
@ -123,16 +114,18 @@
FieldName="MeasuredNetWeight"
FooterColumnName="NetWeight" />
</GroupSummary>
</MgGridBase>
</GridShippingItemBase>
@* </MgGridBase> *@
@code {
//[Inject] public required ObjectLock ObjectLock { get; set; }
[Inject] public required DatabaseClient Database { get; set; }
[Parameter] public bool IsMasterGrid { get; set; } = false;
[Parameter] public IEnumerable<ProductDto>? ProductDtos { get; set; }
[Parameter] public List<ShippingItem>? ShippingItems { get; set; }
[Parameter] public IEnumerable<ShippingDocument>? ShippingDocuments { get; set; }
[Parameter] public List<ShippingDocument>? ShippingDocuments { get; set; }
string GridCss => !IsMasterGrid ? "hide-toolbar" : string.Empty;
@ -142,15 +135,43 @@
string GridSearchText = "";
bool EditItemsEnabled { get; set; } = true;
int FocusedRowVisibleIndex { get; set; }
IGrid Grid { get; set; }
public GridShippingItemBase Grid { get; set; }
private LoggerClient<GridShippingItemTemplate> _logger;
protected override async Task OnInitializedAsync()
{
ProductDtos ??= await Database.ProductDtoTable.LoadDataAsync(true);
_logger = new LoggerClient<GridShippingItemTemplate>(LogWriters.ToArray());
//ProductDtos ??= await FruitBankSignalRClient.GetProductDtos() ?? [];
ShippingItems ??= await FruitBankSignalRClient.GetShippingItems() ?? [];
ShippingDocuments ??= await FruitBankSignalRClient.GetShippingDocuments() ?? [];
await ReloadDataFromDb(false);
}
public async Task ReloadDataFromDb(bool forceReload = false)
{
if (!IsMasterGrid) return;
using (await ObjectLock.GetSemaphore<ProductDto>().UseWaitAsync())
{
if (ProductDtos == null || !ProductDtos.Any() || forceReload) ProductDtos = await Database.ProductDtoTable.LoadDataAsync(!forceReload);
}
using (await ObjectLock.GetSemaphore<ShippingDocument>().UseWaitAsync())
{
if (ShippingDocuments == null) ShippingDocuments = await FruitBankSignalRClient.GetShippingDocuments() ?? [];
else if (ShippingDocuments.Count == 0 || forceReload)
{
ShippingDocuments.Clear();
ShippingDocuments.AddRange(await FruitBankSignalRClient.GetShippingDocuments() ?? []);
}
}
if (Grid == null) return;
using (await ObjectLock.GetSemaphore<ShippingItem>().UseWaitAsync())
if (forceReload) await Grid.ReloadDataSourceAsync();
if (forceReload)
Grid.Reload();
}
async Task Grid_FocusedRowChanged(GridFocusedRowChangedEventArgs args)
@ -180,46 +201,9 @@
EditItemsEnabled = true;
}
if (resultShippingItem != null)
ShippingItems!.UpdateCollection(resultShippingItem, false);
// if (resultShippingItem != null)
// ShippingItems!.UpdateCollection(resultShippingItem, false);
EditItemsEnabled = true;
}
async Task NewItem_Click()
{
EditItemsEnabled = false;
await Grid.StartEditNewRowAsync();
}
async Task EditItem_Click()
{
EditItemsEnabled = false;
await Grid.StartEditRowAsync(FocusedRowVisibleIndex);
}
void DeleteItem_Click()
{
EditItemsEnabled = false;
Grid.ShowRowDeleteConfirmation(FocusedRowVisibleIndex);
}
void ColumnChooserItem_Click(ToolbarItemClickEventArgs e)
{
Grid.ShowColumnChooser();
}
async Task ExportXlsxItem_Click()
{
await Grid.ExportToXlsxAsync(ExportFileName);
}
async Task ExportXlsItem_Click()
{
await Grid.ExportToXlsAsync(ExportFileName);
}
async Task ExportCsvItem_Click()
{
await Grid.ExportToCsvAsync(ExportFileName);
}
async Task ExportPdfItem_Click()
{
await Grid.ExportToPdfAsync(ExportFileName);
}
}

View File

@ -1,13 +1,170 @@
using AyCode.Blazor.Components.Components.Grids;
using AyCode.Core.Extensions;
using AyCode.Core.Interfaces;
using AyCode.Interfaces.Entities;
using AyCode.Utils.Extensions;
using DevExpress.Blazor;
using FruitBank.Common.Models;
using FruitBankHybrid.Shared.Services.Loggers;
using FruitBankHybrid.Shared.Services.SignalRs;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
namespace FruitBankHybrid.Shared.Components.Grids;
//var a = new GridDevExtremeDataSource(DataSource.AsQueryable().Where(x=>x.IsMeasurable));
public class FruitBankListGridBase<TDataItem> : MgGridBase<SignalRDataSourceList<TDataItem>, TDataItem, int, LoggerClient> where TDataItem : class, IId<int>
{ }
{
[Inject] public required LoggedInModel LoggedInModel { get; set; }
[Inject] public required IJSRuntime JSRuntime { get; set; }
[Parameter] public bool IsMasterGrid { get; set; } = false;
[Parameter] public string AutoSaveLayoutName { get; set; }
private bool _isFirstInitializeParameterCore;
private bool _isFirstInitializeParameters;
public bool PreRendered { get; set; }
//public virtual Task ReloadDataFromDb(bool forceReload = false)
//{
// throw new NotImplementedException();
//}
protected void OnCustomizeElement(GridCustomizeElementEventArgs e)
{
//if (!IsMasterGrid) e.CssClass = "hideDetailButton";
if (IsMasterGrid && e.ElementType == GridElementType.DataRow && e.VisibleIndex % 2 == 1 && !e.Grid.IsRowSelected(e.VisibleIndex) && !e.Grid.IsRowFocused(e.VisibleIndex))
{
e.CssClass = " alt-item";
}
if(e.ElementType == GridElementType.DataRow && !LoggedInModel.IsDeveloper)
{
e.CssClass = "hideDetailButton";
}
if (e.ElementType == GridElementType.HeaderCell)
{
e.Style = "background-color: #E6E6E6;";
//e.CssClass = "header-bold";
}
}
protected override async Task SetParametersAsyncCore(ParameterView parameters)
{
await base.SetParametersAsyncCore(parameters);
if (!_isFirstInitializeParameterCore)
{
//if (typeof(TDataItem) is IId<Guid> || typeof(TDataItem) is IId<int>)
KeyFieldName = "Id";
//base.DataItemDeleting = EventCallback.Factory.Create<GridDataItemDeletingEventArgs>(this, OnItemDeleting);
//base.EditModelSaving = EventCallback.Factory.Create<GridEditModelSavingEventArgs>(this, OnItemSaving);
CustomizeElement += OnCustomizeElement;
_isFirstInitializeParameterCore = true;
}
}
protected override void OnParametersSet()
{
base.OnParametersSet();
if (!_isFirstInitializeParameters)
{
SizeMode = DevExpress.Blazor.SizeMode.Small;
ShowGroupPanel = IsMasterGrid;
ShowSearchBox = IsMasterGrid;
ShowFilterRow = IsMasterGrid;
FilterMenuButtonDisplayMode = (IsMasterGrid ? GridFilterMenuButtonDisplayMode.Never : GridFilterMenuButtonDisplayMode.Always);
DetailRowDisplayMode = IsMasterGrid ? GridDetailRowDisplayMode.Auto : GridDetailRowDisplayMode.Never;
DetailExpandButtonDisplayMode = IsMasterGrid ? GridDetailExpandButtonDisplayMode.Auto : GridDetailExpandButtonDisplayMode.Never;
TextWrapEnabled = false;
AllowSelectRowByClick = true;
HighlightRowOnHover = true;
AutoCollapseDetailRow = true;
AutoExpandAllGroupRows = false;
PagerVisible = IsMasterGrid;
PageSize = IsMasterGrid ? (SizeMode == DevExpress.Blazor.SizeMode.Small ? 23 : 15) : 50;
AllowColumnReorder = true;
AllowGroup = IsMasterGrid;
AllowSort = true;
EditMode = GridEditMode.EditRow;
FocusedRowEnabled = true;
ColumnResizeMode = GridColumnResizeMode.NextColumn;
//VirtualScrollingEnabled = IsMasterGrid;
PageSizeSelectorVisible = true;
if (IsMasterGrid && !AutoSaveLayoutName.IsNullOrWhiteSpace())
{
LayoutAutoLoading = Grid_LayoutAutoLoading;
LayoutAutoSaving = Grid_LayoutAutoSaving;
}
_isFirstInitializeParameters = true;
}
}
protected override void OnAfterRender(bool firstRender)
{
base.OnAfterRender(firstRender);
if (firstRender)
{
//PreRendered = true;
//StateHasChanged();
}
}
async Task Grid_LayoutAutoLoading(GridPersistentLayoutEventArgs e)
{
e.Layout = await LoadLayoutFromLocalStorageAsync($"{AutoSaveLayoutName}_AutoSave_{LoggedInModel.CustomerDto?.Id ?? 0}");
}
private async Task Grid_LayoutAutoSaving(GridPersistentLayoutEventArgs e)
{
await SaveLayoutToLocalStorageAsync(e.Layout, $"{AutoSaveLayoutName}_AutoSave_{LoggedInModel.CustomerDto?.Id ?? 0}");
}
async Task<GridPersistentLayout?> LoadLayoutFromLocalStorageAsync(string localStorageKey)
{
try
{
var json = await JSRuntime.InvokeAsync<string>("localStorage.getItem", localStorageKey);
if (!json.IsNullOrWhiteSpace()) return json.JsonTo<GridPersistentLayout>();
}
catch
{
// Mute exceptions for the server prerender stage
}
return null;
}
async Task SaveLayoutToLocalStorageAsync(GridPersistentLayout layout, string localStorageKey)
{
try
{
var json = layout.ToJson();
await JSRuntime.InvokeVoidAsync("localStorage.setItem", localStorageKey, json);
}
catch
{
// Mute exceptions for the server prerender stage
}
}
}
//public abstract class FruitBankObservableGridBase<TDataItem> : MgGridBase<SignalRDataSourceObservable<TDataItem>, TDataItem, int, LoggerClient> where TDataItem : class, IId<int>
//{ }

View File

@ -7,9 +7,9 @@ using Microsoft.AspNetCore.Components;
namespace FruitBankHybrid.Shared.Components.Grids.ShippingItems;
public class GridShippingItem : FruitBankListGridBase<ShippingItem>, IGrid
public class GridShippingItemBase : FruitBankListGridBase<ShippingItem>, IGrid
{
public GridShippingItem() : base()
public GridShippingItemBase() : base()
{
GetAllMessageTag = SignalRTags.GetShippingItems;
AddMessageTag = SignalRTags.AddShippingItem;

View File

@ -50,6 +50,11 @@ public class MgGridBase : DxGrid
e.CssClass = " alt-item";
}
if(e.ElementType == GridElementType.DataRow && !LoggedInModel.IsDeveloper)
{
e.CssClass = "hideDetailButton";
}
if (e.ElementType == GridElementType.HeaderCell)
{
e.Style = "background-color: #E6E6E6;";
@ -104,7 +109,7 @@ public class MgGridBase : DxGrid
EditMode = GridEditMode.EditRow;
FocusedRowEnabled = true;
ColumnResizeMode = GridColumnResizeMode.ColumnsContainer;
ColumnResizeMode = GridColumnResizeMode.NextColumn;
//VirtualScrollingEnabled = IsMasterGrid;
PageSizeSelectorVisible = true;

View File

@ -0,0 +1,98 @@
@using AyCode.Core.Loggers;
@using AyCode.Core.Extensions
@using AyCode.Core.Helpers
@using AyCode.Utils.Extensions
@using FruitBank.Common.Dtos
@using FruitBank.Common.Entities
@using FruitBank.Common.Models
@using FruitBankHybrid.Shared.Components.Grids.ShippingItems
@using FruitBankHybrid.Shared.Databases
@using FruitBankHybrid.Shared.Services.Loggers;
@using FruitBankHybrid.Shared.Services.SignalRs
@inject IEnumerable<IAcLogWriterClientBase> LogWriters
@inject FruitBankSignalRClient FruitBankSignalRClient
@inject LoggedInModel LoggedInModel;
<ToolbarBase @ref="Toolbar" Grid="Grid" ItemRenderStyleMode="ToolbarRenderStyleMode.Plain">
<DxToolbarItem Text="New" Click="NewItem_Click" IconCssClass="grid-toolbar-new" Enabled="LoggedInModel.IsDeveloper" />
<DxToolbarItem Text="Edit" Click="EditItem_Click" IconCssClass="grid-toolbar-edit" Enabled="@(LoggedInModel.IsDeveloper && EditItemsEnabled)" />
<DxToolbarItem Text="Delete" Click="DeleteItem_Click" IconCssClass="grid-toolbar-delete" Enabled="@(LoggedInModel.IsDeveloper && EditItemsEnabled)" />
<DxToolbarItem Text="Column Chooser" BeginGroup="true" Click="ColumnChooserItem_Click" IconCssClass="grid-toolbar-column-chooser" />
<DxToolbarItem Text="Export" IconCssClass="grid-toolbar-export" Enabled="@(LoggedInModel.IsDeveloper && EditItemsEnabled)">
<Items>
<DxToolbarItem Text="To CSV" Click="ExportCsvItem_Click" />
<DxToolbarItem Text="To XLSX" Click="ExportXlsxItem_Click" />
<DxToolbarItem Text="To XLS" Click="ExportXlsItem_Click" />
<DxToolbarItem Text="To PDF" Click="ExportPdfItem_Click" />
</Items>
</DxToolbarItem>
<DxToolbarItem Text="Reload data" BeginGroup="true" Click="ReloadData_Click" />
<DxToolbarItem BeginGroup="true">
</DxToolbarItem>
@* <DxToolbarItem BeginGroup="true">
<Template Context="toolbar_item_context">
<DxSearchBox @bind-Text="GridSearchText"
BindValueMode="BindValueMode.OnInput"
ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto"
aria-label="Search" />
</Template>
</DxToolbarItem>*@
</ToolbarBase>
@code {
[Parameter] public IGrid Grid{ get; set; }
[Parameter] public EventCallback<ToolbarItemClickEventArgs> OnReloadDataClick { get; set; }
public ToolbarBase Toolbar { get; set; }
const string ExportFileName = "ExportResult";
public bool EditItemsEnabled { get; set; } = true;
private LoggerClient<GridShippingItemTemplate> _logger;
protected override async Task OnInitializedAsync()
{
_logger = new LoggerClient<GridShippingItemTemplate>(LogWriters.ToArray());
}
async Task ReloadData_Click(ToolbarItemClickEventArgs e)
{
await OnReloadDataClick.InvokeAsync();
}
async Task NewItem_Click()
{
EditItemsEnabled = false;
await Grid.StartEditNewRowAsync();
}
async Task EditItem_Click()
{
EditItemsEnabled = false;
await Grid.StartEditRowAsync(Grid.GetFocusedRowIndex());
}
void DeleteItem_Click()
{
EditItemsEnabled = false;
Grid.ShowRowDeleteConfirmation(Grid.GetFocusedRowIndex());
}
void ColumnChooserItem_Click(ToolbarItemClickEventArgs e)
{
Grid.ShowColumnChooser();
}
async Task ExportXlsxItem_Click()
{
await Grid.ExportToXlsxAsync(ExportFileName);
}
async Task ExportXlsItem_Click()
{
await Grid.ExportToXlsAsync(ExportFileName);
}
async Task ExportCsvItem_Click()
{
await Grid.ExportToCsvAsync(ExportFileName);
}
async Task ExportPdfItem_Click()
{
await Grid.ExportToPdfAsync(ExportFileName);
}
}

View File

@ -0,0 +1,17 @@
using DevExpress.Blazor;
using DevExpress.Blazor.Navigation.Internal;
using Microsoft.AspNetCore.Components;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FruitBankHybrid.Shared.Components.Toolbars
{
public class ToolbarBase : DxToolbar
{
[Parameter] public IGrid Grid { get; set; }
[Parameter] public Func<ToolbarItemClickEventArgs, Task> RefreshClick { get; set; }
}
}

View File

@ -1,16 +1,31 @@
using AyCode.Core.Extensions;
using AyCode.Core.Interfaces;
using AyCode.Interfaces.Entities;
using AyCode.Services.SignalRs;
using AyCode.Utils.Extensions;
using AyCode.Utils.Wrappers;
using DevExpress.Blazor.Scheduler.Internal;
using FruitBank.Common;
using FruitBank.Common.Dtos;
using FruitBank.Common.Entities;
using FruitBank.Common.SignalRs;
using FruitBankHybrid.Shared.Services.SignalRs;
using Nop.Core.Domain.Common;
using Nop.Core.Domain.Orders;
using System.Collections.Concurrent;
using System.Collections.ObjectModel;
using AyCode.Utils.Extensions;
using System.Threading;
namespace FruitBankHybrid.Shared.Databases;
public class ShippingTableItem : Shipping
{ }
public class ShippingDocumentTableItem : ShippingDocument
{ }
public class ShippingItemTableItem : ShippingItem
{ }
public class ShippingItemPalletTableItem : ShippingItemPallet
{ }
public class ProductDtoTableItem : ProductDto
{
//[Newtonsoft.Json.JsonProperty]
@ -25,7 +40,22 @@ public class OrderDtoTableItem : OrderDto
//public new ObservableCollection<GenericAttribute>? OrderItemDtos { get; set; }
}
public class ProductDtoTable(FruitBankSignalRClient fruitBankSignalRClient) : ObservableCollection<ProductDtoTableItem>
public class ShippingItemTable : SignalRDataSourceList<ShippingItemTableItem>
{
private static readonly SignalRCrudTags SignalRCrudTags = new(SignalRTags.GetShippingItems, 0, SignalRTags.AddShippingItem, SignalRTags.UpdateShippingItem, 0);
public ShippingItemTable(AcSignalRClientBase signalRClient, params object[]? contextIds)
: this(signalRClient, SignalRCrudTags, contextIds)
{
}
public ShippingItemTable(AcSignalRClientBase signalRClient, SignalRCrudTags signalRCrudTags, params object[]? contextIds) : base(signalRClient, signalRCrudTags, contextIds)
{
}
}
public class ProductDtoTable(FruitBankSignalRClient fruitBankSignalRClient) : FastObservableCollection<ProductDtoTableItem>
{
private readonly SemaphoreSlim _semaphoreSlim = new(1);
public async Task<ProductDtoTable> LoadDataAsync(bool onlyIfEmpty = true)
@ -34,21 +64,23 @@ public class ProductDtoTable(FruitBankSignalRClient fruitBankSignalRClient) : Ob
using (await _semaphoreSlim.UseWaitAsync())
{
if (Count != 0) return this;
//Előfordulhat, h egy másik szálban már megtörtént a refresh... - J.
if (onlyIfEmpty && Count != 0) return this;
var items = (await fruitBankSignalRClient.GetProductDtoTableItems() ?? []);
Clear();
foreach (var productDto in items)
{
this.Add(productDto);
}
//Clear();
this.Replace(items);
//foreach (var productDto in items)
//{
// this.UpdateCollection(productDto, false);
//}
}
return this;
}
}
public class OrderDtoTable(FruitBankSignalRClient fruitBankSignalRClient) : ObservableCollection<OrderDtoTableItem>
public class OrderDtoTable(FruitBankSignalRClient fruitBankSignalRClient) : FastObservableCollection<OrderDtoTableItem>
{
private readonly SemaphoreSlim _semaphoreSlim = new(1);
@ -62,26 +94,81 @@ public class OrderDtoTable(FruitBankSignalRClient fruitBankSignalRClient) : Obse
var items = (await fruitBankSignalRClient.GetAllOrderDtoTableItems() ?? []);
Clear();
foreach (var orderDto in items)
{
this.Add(orderDto);
}
//Clear();
this.Replace(items);
//foreach (var orderDto in items)
//{
// this.UpdateCollection(orderDto, false);
//}
}
return this;
}
}
public abstract class DatabaseTableBase<TDataItem> : SignalRDataSourceObservable<TDataItem> where TDataItem : class, IId<int>
{
protected DatabaseTableBase(AcSignalRClientBase signalRClient, SignalRCrudTags signalRCrudTags, params object[]? contextIds) : base(signalRClient, signalRCrudTags, contextIds)
{
}
//protected readonly SemaphoreSlim _semaphoreSlim = new(1);
//public async Task<OrderDtoTable> LoadDataAsync(bool onlyIfEmpty = true)
//{
// if (onlyIfEmpty && Count != 0) return this;
// using (await _semaphoreSlim.UseWaitAsync())
// {
// if (Count != 0) return this;
// var items = (await fruitBankSignalRClient.GetAllOrderDtoTableItems() ?? []);
// Clear();
// foreach (var orderDto in items)
// {
// this.Add(orderDto);
// }
// }
// return this;
//}
}
public static class LoadingPanelVisibility
{
public static bool Visible =false;
}
public static class ObjectLock
{
private static readonly Dictionary<Type, SemaphoreSlim> SemaphoresByType = new();
public static SemaphoreSlim GetSemaphore<TObject>()
{
lock (SemaphoresByType)
{
if (!SemaphoresByType.TryGetValue(typeof(TObject), out var semaphore))
{
semaphore = new SemaphoreSlim(1);
SemaphoresByType[typeof(TObject)] = semaphore;
}
return semaphore;
}
}
}
public class DatabaseClient : DatabaseClientBase
{
private FruitBankSignalRClient _fruitBankSignalRClient;
private readonly FruitBankSignalRClient _fruitBankSignalRClient;
public DatabaseClient(FruitBankSignalRClient fruitBankSignalRClient)
{
_fruitBankSignalRClient = fruitBankSignalRClient;
AddTable(new ProductDtoTable(_fruitBankSignalRClient));
AddTable(new ShippingItemTable(_fruitBankSignalRClient));
AddTable(new OrderDtoTable(_fruitBankSignalRClient));
}

View File

@ -2,6 +2,7 @@
using AyCode.Core.Extensions;
using AyCode.Core.Loggers;
using AyCode.Services.SignalRs;
using AyCode.Utils.Extensions;
using DevExpress.Blazor;
using FruitBank.Common.Dtos;
using FruitBank.Common.Models;
@ -31,7 +32,7 @@ public partial class MainLayout : LayoutComponentBase
// Toast fields
private DxToast orderNotificationToast;
private string toastTitle = "Értesítő!";
private string toastMessage = "";
private string? toastMessage;
private string? toastOrderNumber;
private DateTime? toastDateOfReceipt;
@ -59,21 +60,29 @@ public partial class MainLayout : LayoutComponentBase
return;
}
toastOrderNumber = null;
toastDateOfReceipt = null;
toastMessage = notificationMessage.Message;
var orderDto = notificationMessage.Content;
if ((orderDto?.HasMeasuringAccess(LoggedInModel.CustomerDto!.Id, LoggedInModel.IsRevisor) ?? LoggedInModel.IsRevisor) || orderDto?.MeasurementOwnerId == 0)
var hasPermission = orderDto == null || (orderDto.HasMeasuringAccess(LoggedInModel.CustomerDto!.Id, LoggedInModel.IsRevisor) || orderDto.MeasurementOwnerId == 0);
if (orderDto != null && hasPermission)
{
toastMessage = notificationMessage.Message;
toastOrderNumber = orderDto?.CustomOrderNumber;
toastDateOfReceipt = orderDto?.DateOfReceipt;
_logger.Debug($"NotificationMessage received. {toastMessage}");
await InvokeAsync(() =>
{
orderNotificationToast?.Show();
StateHasChanged();
});
toastOrderNumber = orderDto.CustomOrderNumber;
toastDateOfReceipt = orderDto.DateOfReceipt;
}
if (!hasPermission) return;
_logger.Debug($"NotificationMessage received. {toastMessage}");
await InvokeAsync(() =>
{
orderNotificationToast?.Show();
StateHasChanged();
});
}
private void OnLogoutClick()

View File

@ -37,14 +37,16 @@
</NavLink>
</div>
@if (LoggedInModel.IsDeveloper)
@if (LoggedInModel.IsAdministrator)
{
<div class="nav-item px-3">
<NavLink class="nav-link" href="OrdersAdmin">
<span class="icon counter-icon" aria-hidden="true"></span> Rendelések - Adminisztrátor
</NavLink>
</div>
}
@if (LoggedInModel.IsDeveloper)
{
<div class="nav-item px-3">
<NavLink class="nav-link" href="ShippingsAdmin">
<span class="icon counter-icon" aria-hidden="true"></span> Szállítmányok - Adminisztrátor

View File

@ -3,6 +3,7 @@
@using FruitBank.Common
@using FruitBank.Common.Dtos
@using FruitBank.Common.Entities
@using FruitBank.Common.Enums
@using FruitBank.Common.SignalRs
@using FruitBankHybrid.Shared.Components
@using FruitBankHybrid.Shared.Services
@ -22,35 +23,43 @@
Text="Adatok szinkronizálása folyamatban...">
<DxFormLayout CaptionPosition="CaptionPosition.Vertical" CssClass="w-100">
<DxFormLayoutItem Caption="Dátum" ColSpanMd="2"
<DxFormLayoutItem Caption="Dátum" ColSpanMd="3"
CaptionCssClass="@(SelectedOrder != null && _measuringDates.Where(x => MeasurementService.DaysEqual(x.DateTime, SelectedOrder.DateOfReceiptOrCreated)).All(x => x.IsMeasured) ? "text-success" : "")">
<DxDateEdit CssClass="cw-320"
DisplayFormat="m"
Format="m"
Context="ctxOrderDate"
Date="@(SelectedOrder?.DateOfReceiptOrCreated.Date ?? DateTime.Now.Date)"
CustomDisabledDate="@OnCustomDisabledMeasuringDate"
DateChanged="@((DateTime newValue) => OnMeasuringDateChanged(newValue))"
InputId="deDisabledDates"
PickerDisplayMode="DatePickerDisplayMode.Calendar">
<DayCellTemplate>
@{
var cssClass = GetMeasuringDateCssClassNames(ctxOrderDate);
if (!cssClass.IsNullOrWhiteSpace())
{
<a class="@GetMeasuringDateCssClassNames(ctxOrderDate)">@ctxOrderDate.Day.ToString()</a>
}
else
{
<a>@ctxOrderDate.Day.ToString()</a>
}
}
</DayCellTemplate>
</DxDateEdit>
<div class="container-fluid p-0">
<div class="row">
<div class="col-9 p-0">
<DxDateEdit DisplayFormat="m"
Format="m"
Context="ctxOrderDate"
Date="@(SelectedOrder?.DateOfReceiptOrCreated.Date ?? DateTime.Now.Date)"
CustomDisabledDate="@OnCustomDisabledMeasuringDate"
DateChanged="@((DateTime newValue) => OnMeasuringDateChanged(newValue))"
InputId="deDisabledDates"
PickerDisplayMode="DatePickerDisplayMode.Calendar">
<DayCellTemplate>
@{
var cssClass = GetMeasuringDateCssClassNames(ctxOrderDate);
if (!cssClass.IsNullOrWhiteSpace())
{
<a class="@GetMeasuringDateCssClassNames(ctxOrderDate)">@ctxOrderDate.Day.ToString()</a>
}
else
{
<a>@ctxOrderDate.Day.ToString()</a>
}
}
or
</DayCellTemplate>
</DxDateEdit>
</div>
<div class="col-3 p-0">
<DxSpinEdit T="int" Value="1" Increment="1" MinValue="1" ValueChanged="async i => await RefreshOrdersFromDb(DateTime.Now, i)"></DxSpinEdit>
</div>
</div>
</div>
</DxFormLayoutItem>
<DxFormLayoutItem Caption="Átvétel időpontja:" ColSpanMd="6" CaptionCssClass="@(SelectedOrder?.IsMeasured == true ? "text-success" : "")">
<DxFormLayoutItem Caption="Átvétel időpontja:" ColSpanMd="5" CaptionCssClass="@(SelectedOrder?.IsMeasured == true ? "text-success" : "")">
<DxComboBox Data="@SelectedDayOrders"
@bind-Value="@SelectedOrder"
Text="Válasszon időpontot..."
@ -80,15 +89,15 @@
if (SelectedOrder is { MeasurementOwnerId: 0, IsComplete: false } && HasMeasuringAccess)
{
<DxFormLayoutItem ColSpanMd="2">
<DxButton Enabled="@(HasMeasuringAccess && SelectedOrder?.MeasurementOwnerId == 0)" Visible="(SelectedOrder != null)"
CssClass="w-100"
<DxButton Enabled="@(HasMeasuringAccess && SelectedOrder?.MeasurementOwnerId == 0)" Visible="(SelectedOrder != null)"
CssClass="w-100"
Text="@(HasMeasuringAccess && SelectedOrder?.MeasurementOwnerId == 0 ? " Indítás" : "Folyamatban...")"
Click="() => OnStartMeasuringClick()" />
</DxFormLayoutItem>
}
else
{
<DxFormLayoutItem ColSpanMd="2" Caption="Indította" CaptionCssClass="@(SelectedOrder?.IsMeasured == true ? " text-success" : "" )">
<DxFormLayoutItem ColSpanMd="2" Caption="Indította" CaptionCssClass="@(SelectedOrder?.IsMeasured == true ? " text-success" : "")">
<DxTextBox Enabled="false" Text="@(LoggedInModel.MeasuringUsers.FirstOrDefault(x => x.Id == SelectedOrder?.MeasurementOwnerId)?.LastName)" />
</DxFormLayoutItem>
}
@ -112,15 +121,21 @@
}
else if (!HasMeasuringAccess)
{
<div style="margin-top: 50px;">
<div style="margin-top: 30px;">
<H3>Mások végzik a mérést!</H3>
</div>
}
else
{
//Átvétel dátuma október 23. [AUDITED] 15:51 - Vegetable Kft. Rendelés azonosító: #8
string? orderNote;
if (!(orderNote = SelectedOrder?.OrderNotes.FirstOrDefault()?.Note).IsNullOrWhiteSpace())
{
<div class="container-fluid p-0" style="margin-top: 20px">
<b> Megjegyzés: </b><span>@(orderNote) </span>
</div>
}
<div style="margin-top: 50px;">
<div style="margin-top: 30px;">
<h4 style="margin-bottom: 30px;" class="@(SelectedOrder?.IsMeasured == true ? "text-success" : "")">
Rendelés azonosító: #@(SelectedOrder?.CustomOrderNumber)
</h4>
@ -130,7 +145,7 @@
ExpandCollapseAction="AccordionExpandCollapseAction.ExpandButtonClick"
AnimationType="LayoutAnimationType.Slide">
<DataMappings>
<DxAccordionDataMapping Text="ProductName"></DxAccordionDataMapping>
<DxAccordionDataMapping Text=ProductName></DxAccordionDataMapping>
@* <DxAccordionDataMapping Text="OrderItemId" Level="1"></DxAccordionDataMapping> *@
</DataMappings>
<ItemHeaderTextTemplate>
@ -148,7 +163,10 @@
if (isValidAndMeasured) cssClass = "text-success";
else if (isValid) cssClass = string.Empty;
<h5 class="@cssClass">@($"{selectedOrderItemDto.ProductName} - [{trayQuantity}/{selectedOrderItemDto.Quantity} rekesz, {(selectedOrderItemDto.IsMeasurable ? "net.súly: " + selectedOrderItemDto.NetWeight + "kg." : "nem mérendő!")}]")</h5>
var displayText = $"{selectedOrderItemDto.ProductName} - [{trayQuantity}/{selectedOrderItemDto.Quantity} rekesz, {(selectedOrderItemDto.IsMeasurable ? "net.súly: " + selectedOrderItemDto.NetWeight + "kg." : "nem mérendő!")}]";
if (selectedOrderItemDto.MeasuringStatus == MeasuringStatus.Audited) displayText = $"[{selectedOrderItemDto.MeasuringStatus}] " + displayText;
<h5 class="@cssClass">@(displayText)</h5>
}
}
</ItemHeaderTextTemplate>
@ -181,7 +199,7 @@
<DxFormLayoutItem Context="ctxFromLayoutNewPallet" ColSpanMd="2" BeginRow="true">
<DxButton Text="Új sor" Click="() => AddNewPalletItemClick(selectedOrderItem)" CssClass="w-100"
Visible="@(!(SelectedOrder?.IsComplete ?? false))"
Visible="@(!(SelectedOrder?.IsComplete ?? false))"
Enabled="@(selectedOrderItem.OrderItemPallets[^1].Id > 0)" />
</DxFormLayoutItem>
<DxFormLayoutItem Context="ctxFromLayoutNewPallet" ColSpanMd="3">

View File

@ -28,6 +28,7 @@ namespace FruitBankHybrid.Shared.Pages
private LoggerClient _logger = null!;
private string _errorText;
private int _lastDaysCount = 1;
public bool HasMeasuringAccess;
public bool LoadingPanelVisible { get; set; } = true;
public bool IsAllOrderItemPalletAudited => SelectedOrder?.IsAllOrderItemAudited ?? false;
@ -48,7 +49,7 @@ namespace FruitBankHybrid.Shared.Pages
FruitBankSignalRClient.OnMessageReceived += SignalRClientOnMessageReceived;
await RefreshOrdersFromDb(DateTime.Now);
await RefreshOrdersFromDb(DateTime.Now, _lastDaysCount);
await base.OnInitializedAsync();
}
@ -145,12 +146,14 @@ namespace FruitBankHybrid.Shared.Pages
_logger.Error($"SignalRClientOnMessageReceived message == null");
}
private async Task RefreshOrdersFromDb(DateTime dateTime)
private async Task RefreshOrdersFromDb(DateTime dateTime, int lastDaysCount)
{
SelectedDate = dateTime;
LoadingPanelVisible = true;
_lastDaysCount = lastDaysCount;
SelectedDate = dateTime;
var orders = (await FruitBankSignalRClient.GetPendingOrderDtosForMeasuring() ?? []).Where(o => o.HasMeasuringAccess(LoggedInModel.CustomerDto?.Id, LoggedInModel.IsRevisor)).OrderBy(o => o.DateOfReceipt).ToList();
var orders = (await FruitBankSignalRClient.GetPendingOrderDtosForMeasuring(_lastDaysCount) ?? []).Where(o => o.HasMeasuringAccess(LoggedInModel.CustomerDto?.Id, LoggedInModel.IsRevisor)).OrderBy(o => o.DateOfReceipt).ToList();
lock (_lock)
{
@ -170,7 +173,7 @@ namespace FruitBankHybrid.Shared.Pages
LoadingPanelVisible = SelectedOrder != null; //Lefut a change és ott lesz false! - J.
}
private async Task OnMeasuringDateChanged(DateTime selectedDateTime) => await RefreshOrdersFromDb(selectedDateTime);
private async Task OnMeasuringDateChanged(DateTime selectedDateTime) => await RefreshOrdersFromDb(selectedDateTime, _lastDaysCount);
private void OnCustomDisabledMeasuringDate(CalendarCustomDisabledDateEventArgs args)
=> MeasurementService.OnCustomDisabledDate(args, _measuringDates);
@ -274,7 +277,7 @@ namespace FruitBankHybrid.Shared.Pages
private async Task OnOrdersRefreshClick()
{
await RefreshOrdersFromDb(SelectedDayOrders.FirstOrDefault()?.DateOfReceiptOrCreated ?? DateTime.Now);
await RefreshOrdersFromDb(SelectedDayOrders.FirstOrDefault()?.DateOfReceiptOrCreated ?? DateTime.Now, _lastDaysCount);
StateHasChanged();
}

View File

@ -1,18 +1,17 @@
@page "/OrdersAdmin"
@using FruitBank.Common.Dtos
@using FruitBankHybrid.Shared.Components
@using FruitBankHybrid.Shared.Databases
<h3>Rendelések - Adminisztrátor</h3>
<DxDialogProvider />
<div style="margin-top: 30px;">
<DxLoadingPanel @bind-Visible="LoadingPanelVisible"
<DxLoadingPanel @bind-Visible="LoadingPanelVisibility.Visible"
IsContentBlocked="true"
ApplyBackgroundShading="true"
IndicatorAreaVisible="true"
IsContentVisible="true"
IndicatorAnimationType="WaitIndicatorAnimationType.Spin"
IndicatorAreaVisible="false"
Text="Adatok szinkronizálása folyamatban...">
@* @bind-ActiveTabIndex="@ActiveTabIndex" *@

View File

@ -2,10 +2,12 @@
using AyCode.Core.Loggers;
using AyCode.Services.Server.SignalRs;
using AyCode.Services.SignalRs;
using AyCode.Utils.Extensions;
using DevExpress.Blazor;
using FruitBank.Common.Dtos;
using FruitBank.Common.Models;
using FruitBank.Common.SignalRs;
using FruitBankHybrid.Shared.Databases;
using FruitBankHybrid.Shared.Services.Loggers;
using FruitBankHybrid.Shared.Services.SignalRs;
using Mango.Nop.Core.Loggers;
@ -16,6 +18,7 @@ namespace FruitBankHybrid.Shared.Pages;
public partial class OrdersAdmin : ComponentBase
{
[Inject] public required DatabaseClient Database { get; set; }
[Inject] public required IEnumerable<IAcLogWriterClientBase> LogWriters { get; set; }
[Inject] public required FruitBankSignalRClient FruitBankSignalRClient { get; set; }
[Inject] public required NavigationManager NavManager { get; set; }
@ -23,12 +26,11 @@ public partial class OrdersAdmin : ComponentBase
[Inject] public required LoggedInModel LoggedInModel { get; set; }
public required IGrid gridOrder;
private List<ProductDto>? ProductDtos { get; set; } = null!;
private List<OrderDto>? OrderDtos { get; set; } = null!;
private List<OrderItemDto>? OrderItemDtos { get; set; } = null!;
private IEnumerable<ProductDto>? ProductDtos { get; set; } = [];
private List<OrderDto>? OrderDtos { get; set; } = [];
private List<OrderItemDto>? OrderItemDtos { get; set; } = [];
public bool AutoCollapseDetailRow { get; set; }
public bool LoadingPanelVisible { get; set; } = true;
private ILogger _logger = null!;
public int ActiveTabIndex;
@ -37,42 +39,52 @@ public partial class OrdersAdmin : ComponentBase
{
if (!LoggedInModel.IsRevisor) NavManager.NavigateTo("/Login");
LoadingPanelVisible = true;
_logger = new LoggerClient<OrdersAdmin>(LogWriters.ToArray());
_logger.Info("OnInitializedAsync");
await RefreshOrdersFromDb(DateTime.Now);
await ReloadDataFromDb(false);
await base.OnInitializedAsync();
}
private async Task RefreshOrdersFromDb(DateTime dateTime)
private async Task ReloadDataFromDb(bool forceReload = false)
{
LoadingPanelVisible = true;
OrderDtos = (await FruitBankSignalRClient.GetAllOrderDtos() ?? []).OrderByDescending(o=>o.Id).ToList();//.Where(o => o.HasMeasuringAccess(LoggedInModel.CustomerDto?.Id, LoggedInModel.IsRevisor)).OrderBy(o => o.DateOfReceipt).ToList();
LoadingPanelVisibility.Visible = true;
using (await ObjectLock.GetSemaphore<ProductDto>().UseWaitAsync())
{
if (ProductDtos == null || !ProductDtos.Any() || forceReload) ProductDtos = await Database.ProductDtoTable.LoadDataAsync(!forceReload);
}
LoadingPanelVisible = false;
//using (await ObjectLock.GetSemaphore<OrderItemDto>().UseWaitAsync())
//{
// if (OrderItemDtos == null) OrderItemDtos = await FruitBankSignalRClient.GetAllOrderItemDtos() ?? [];
// else if (OrderItemDtos.Count == 0 || forceReload)
// {
// OrderItemDtos.Clear();
// OrderItemDtos.AddRange(await FruitBankSignalRClient.GetAllOrderItemDtos() ?? []);
// }
//}
LoadingPanelVisibility.Visible = false;
}
protected async Task OnActiveTabChanged(int activeTabIndex)
{
ActiveTabIndex = activeTabIndex;
LoadingPanelVisible = true;
//LoadingPanelVisibility.Visible = true;
switch (ActiveTabIndex)
{
case 0:
ProductDtos ??= (await FruitBankSignalRClient.GetProductDtos() ?? []); //.Where(o => o.HasMeasuringAccess(LoggedInModel.CustomerDto?.Id, LoggedInModel.IsRevisor)).OrderBy(o => o.DateOfReceipt).ToList();
//ProductDtos ??= (await FruitBankSignalRClient.GetProductDtos() ?? []); //.Where(o => o.HasMeasuringAccess(LoggedInModel.CustomerDto?.Id, LoggedInModel.IsRevisor)).OrderBy(o => o.DateOfReceipt).ToList();
break;
case 1:
OrderDtos ??= (await FruitBankSignalRClient.GetAllOrderDtos() ?? []).OrderByDescending(o => o.Id).ToList(); //.Where(o => o.HasMeasuringAccess(LoggedInModel.CustomerDto?.Id, LoggedInModel.IsRevisor)).OrderBy(o => o.DateOfReceipt).ToList();
//OrderDtos ??= (await FruitBankSignalRClient.GetAllOrderDtos() ?? []).OrderByDescending(o => o.Id).ToList(); //.Where(o => o.HasMeasuringAccess(LoggedInModel.CustomerDto?.Id, LoggedInModel.IsRevisor)).OrderBy(o => o.DateOfReceipt).ToList();
break;
case 2:
OrderItemDtos ??= (await FruitBankSignalRClient.GetAllOrderItemDtos() ?? []).OrderByDescending(o => o.Id).ToList(); //.Where(o => o.HasMeasuringAccess(LoggedInModel.CustomerDto?.Id, LoggedInModel.IsRevisor)).OrderBy(o => o.DateOfReceipt).ToList();
//OrderItemDtos ??= (await FruitBankSignalRClient.GetAllOrderItemDtos() ?? []).OrderByDescending(o => o.Id).ToList(); //.Where(o => o.HasMeasuringAccess(LoggedInModel.CustomerDto?.Id, LoggedInModel.IsRevisor)).OrderBy(o => o.DateOfReceipt).ToList();
break;
}
LoadingPanelVisible = false;
//LoadingPanelVisibility.Visible = false;
}
}

View File

@ -1,36 +1,35 @@
@page "/ShippingsAdmin"
@using FruitBank.Common.Dtos
@using FruitBankHybrid.Shared.Components
@using FruitBankHybrid.Shared.Databases
<h3>Szállítmányok - Adminisztrátor</h3>
<DxDialogProvider />
<div style="margin-top: 30px;">
<DxLoadingPanel @bind-Visible="LoadingPanelVisible"
<DxLoadingPanel @bind-Visible="LoadingPanelVisibility.Visible"
IsContentBlocked="true"
ApplyBackgroundShading="true"
IndicatorAreaVisible="true"
IsContentVisible="true"
IndicatorAnimationType="WaitIndicatorAnimationType.Spin"
IndicatorAreaVisible="false"
Text="Adatok szinkronizálása folyamatban...">
@* @bind-ActiveTabIndex="@ActiveTabIndex" *@
<DxTabs ActiveTabIndexChanged="(i) => OnActiveTabChanged(i)" RenderMode="TabsRenderMode.AllTabs" AllowTabReorder="true">
<DxTabPage Text="Termékek">
<GridProductDtoTemplate IsMasterGrid="true"></GridProductDtoTemplate>
<GridProductDtoTemplate @ref="gridProductDtoTemplate" IsMasterGrid="true"></GridProductDtoTemplate>
</DxTabPage>
<DxTabPage Text="Szállítmányok">
<GridShipping Shippings="Shippings" IsMasterGrid="true"></GridShipping>
<GridShipping @ref="gridShipping" Shippings="Shippings" IsMasterGrid="true"></GridShipping>
</DxTabPage>
<DxTabPage Text="Szállítólevelek">
<GridShippingDocument ShippingDocuments="ShippingDocuments" Shippings="Shippings" IsMasterGrid="true"></GridShippingDocument>
<GridShippingDocument @ref="gridShippingDocument" ShippingDocuments="ShippingDocuments" Shippings="Shippings" IsMasterGrid="true"></GridShippingDocument>
</DxTabPage>
<DxTabPage Text="Szállítólevél tételek">
<GridShippingItem ShippingItems="ShippingItems" ShippingDocuments="ShippingDocuments" IsMasterGrid="true"></GridShippingItem>
<GridShippingItemTemplate @ref="gridShippingItemTemplate" ShippingItems="ShippingItems" ShippingDocuments="ShippingDocuments" IsMasterGrid="true"></GridShippingItemTemplate>
</DxTabPage>
<DxTabPage Text="Mérések">
<GridShippingItemPallets IsMasterGrid="true"></GridShippingItemPallets>
<GridShippingItemPallets @ref="gridShippingItemPallet" IsMasterGrid="true" ShippingItemPallets="ShippingItemPallets"></GridShippingItemPallets>
</DxTabPage>
</DxTabs>
</DxLoadingPanel>

View File

@ -3,7 +3,10 @@ using DevExpress.Blazor;
using DevExpress.ClipboardSource.SpreadsheetML;
using FruitBank.Common.Dtos;
using FruitBank.Common.Entities;
using FruitBank.Common.Interfaces;
using FruitBank.Common.Models;
using FruitBankHybrid.Shared.Components;
using FruitBankHybrid.Shared.Components.Grids.ShippingItems;
using FruitBankHybrid.Shared.Databases;
using FruitBankHybrid.Shared.Services.Loggers;
using FruitBankHybrid.Shared.Services.SignalRs;
@ -21,14 +24,18 @@ public partial class ShippingsAdmin : ComponentBase
[Inject] public required LoggedInModel LoggedInModel { get; set; }
[Inject] public required DatabaseClient Database { get; set; }
public IGrid gridShipping;
//private List<ProductDto>? ProductDtos { get; set; } = null!;
private List<Shipping>? Shippings { get; set; } = null!;
private List<ShippingDocument>? ShippingDocuments { get; set; } = null!;
private List<ShippingItem>? ShippingItems { get; set; } = null!;
private GridProductDtoTemplate gridProductDtoTemplate;
private GridShipping gridShipping;
private GridShippingDocument gridShippingDocument;
private GridShippingItemTemplate gridShippingItemTemplate;
private GridShippingItemPallets gridShippingItemPallet;
public List<Shipping> Shippings { get; set; } = [];
public List<ShippingDocument> ShippingDocuments { get; set; } = [];
public List<ShippingItem> ShippingItems { get; set; } = [];
public List<ShippingItemPallet> ShippingItemPallets { get; set; } = [];
public bool AutoCollapseDetailRow { get; set; }
public bool LoadingPanelVisible { get; set; } = true;
private ILogger _logger = null!;
public int ActiveTabIndex;
@ -37,7 +44,7 @@ public partial class ShippingsAdmin : ComponentBase
{
if (!LoggedInModel.IsRevisor) NavManager.NavigateTo("/Login");
LoadingPanelVisible = true;
LoadingPanelVisibility.Visible = true;
_logger = new LoggerClient<ShippingsAdmin>(LogWriters.ToArray());
_logger.Info("OnInitializedAsync");
@ -48,35 +55,51 @@ public partial class ShippingsAdmin : ComponentBase
private async Task RefreshOrdersFromDb(DateTime dateTime)
{
LoadingPanelVisible = true;
Shippings = (await FruitBankSignalRClient.GetShippings() ?? []).OrderByDescending(o=>o.Id).ToList();//.Where(o => o.HasMeasuringAccess(LoggedInModel.CustomerDto?.Id, LoggedInModel.IsRevisor)).OrderBy(o => o.DateOfReceipt).ToList();
LoadingPanelVisibility.Visible = true;
LoadingPanelVisible = false;
//Shippings.Clear();
//Shippings.AddRange((await FruitBankSignalRClient.GetShippings() ?? []).OrderByDescending(o => o.Id));//.Where(o => o.HasMeasuringAccess(LoggedInModel.CustomerDto?.Id, LoggedInModel.IsRevisor)).OrderBy(o => o.DateOfReceipt).ToList();
LoadingPanelVisibility.Visible = false;
}
protected async Task OnActiveTabChanged(int activeTabIndex)
{
ActiveTabIndex = activeTabIndex;
LoadingPanelVisible = true;
LoadingPanelVisibility.Visible = true;
switch (ActiveTabIndex)
{
case 0:
await Database.ProductDtoTable.LoadDataAsync(true);
//await Database.ProductDtoTable.LoadDataAsync(true);
gridProductDtoTemplate.Grid.Reload();
break;
case 1:
Shippings ??= (await FruitBankSignalRClient.GetShippings() ?? []).OrderByDescending(o => o.Id).ToList(); //.Where(o => o.HasMeasuringAccess(LoggedInModel.CustomerDto?.Id, LoggedInModel.IsRevisor)).OrderBy(o => o.DateOfReceipt).ToList();
break;
case 2:
ShippingDocuments ??= (await FruitBankSignalRClient.GetShippingDocuments() ?? []).OrderByDescending(o => o.Id).ToList(); //.Where(o => o.HasMeasuringAccess(LoggedInModel.CustomerDto?.Id, LoggedInModel.IsRevisor)).OrderBy(o => o.DateOfReceipt).ToList();
if (Shippings.Count == 0)
{
//Shippings.AddRange((await FruitBankSignalRClient.GetShippings() ?? []).OrderByDescending(o => o.Id)); //.Where(o => o.HasMeasuringAccess(LoggedInModel.CustomerDto?.Id, LoggedInModel.IsRevisor)).OrderBy(o => o.DateOfReceipt).ToList();}
}
gridShipping.Grid.Reload();
break;
case 2:
if (ShippingDocuments.Count == 0)
{
//ShippingDocuments.AddRange((await FruitBankSignalRClient.GetShippingDocuments() ?? []).OrderByDescending(o => o.Id)); //.Where(o => o.HasMeasuringAccess(LoggedInModel.CustomerDto?.Id, LoggedInModel.IsRevisor)).OrderBy(o => o.DateOfReceipt).ToList();
}
gridShippingDocument.Grid.Reload();
break;
case 3:
ShippingItems ??= (await FruitBankSignalRClient.GetShippingItems() ?? []).OrderByDescending(o => o.Id).ToList(); //.Where(o => o.HasMeasuringAccess(LoggedInModel.CustomerDto?.Id, LoggedInModel.IsRevisor)).OrderBy(o => o.DateOfReceipt).ToList();
gridShippingItemTemplate.Grid.Reload();
//if(ShippingItems.Count=0) ShippingItems.AddRange((await FruitBankSignalRClient.GetShippingItems() ?? []).OrderByDescending(o => o.Id)); //.Where(o => o.HasMeasuringAccess(LoggedInModel.CustomerDto?.Id, LoggedInModel.IsRevisor)).OrderBy(o => o.DateOfReceipt).ToList();
break;
case 4:
gridShippingItemPallet.gridOrderItemPallet.Reload();
break;
}
LoadingPanelVisible = false;
LoadingPanelVisibility.Visible = false;
}
}

View File

@ -177,8 +177,8 @@ namespace FruitBankHybrid.Shared.Services.SignalRs
public Task<List<OrderDto>?> GetPendingOrderDtos()
=> GetAllAsync<List<OrderDto>>(SignalRTags.GetPendingOrderDtos);
public Task<List<OrderDto>?> GetPendingOrderDtosForMeasuring()
=> GetAllAsync<List<OrderDto>>(SignalRTags.GetPendingOrderDtosForMeasuring);
public Task<List<OrderDto>?> GetPendingOrderDtosForMeasuring(int lastDaysCount)
=> GetAllAsync<List<OrderDto>>(SignalRTags.GetPendingOrderDtosForMeasuring, [lastDaysCount]);
public Task<List<OrderDto>?> GetAllOrderDtoByIds(int[] orderIds)
=> GetAllAsync<List<OrderDto>>(SignalRTags.GetAllOrderDtoByIds, [orderIds]);

View File

@ -9,7 +9,7 @@ namespace FruitBankHybrid.Shared.Services.SignalRs;
[Serializable]
[DebuggerDisplay("Count = {Count}")]
public class SignalRDataSourceList<TDataItem>(AcSignalRClientBase signalRClient, SignalRCrudTags signalRCrudTags, params object[]? contextIds)
: AcSignalRDataSource<TDataItem, int, IList<TDataItem>>(signalRClient, signalRCrudTags, contextIds) where TDataItem : class, IId<int>;
: AcSignalRDataSource<TDataItem, int, List<TDataItem>>(signalRClient, signalRCrudTags, contextIds) where TDataItem : class, IId<int>;
[Serializable]
[DebuggerDisplay("Count = {Count}")]

View File

@ -24,18 +24,33 @@
<Reference Include="AyCode.Core">
<HintPath>..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server\bin\FruitBank\Debug\net9.0\AyCode.Core.dll</HintPath>
</Reference>
<Reference Include="AyCode.Core.Server">
<HintPath>..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server\bin\FruitBank\Debug\net9.0\AyCode.Core.Server.dll</HintPath>
</Reference>
<Reference Include="AyCode.Entities">
<HintPath>..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server\bin\FruitBank\Debug\net9.0\AyCode.Entities.dll</HintPath>
</Reference>
<Reference Include="AyCode.Entities.Server">
<HintPath>..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server\bin\FruitBank\Debug\net9.0\AyCode.Entities.Server.dll</HintPath>
</Reference>
<Reference Include="AyCode.Interfaces">
<HintPath>..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server\bin\FruitBank\Debug\net9.0\AyCode.Interfaces.dll</HintPath>
</Reference>
<Reference Include="AyCode.Interfaces.Server">
<HintPath>..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server\bin\FruitBank\Debug\net9.0\AyCode.Interfaces.Server.dll</HintPath>
</Reference>
<Reference Include="AyCode.Models">
<HintPath>..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server\bin\FruitBank\Debug\net9.0\AyCode.Models.dll</HintPath>
</Reference>
<Reference Include="AyCode.Models.Server">
<HintPath>..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server\bin\FruitBank\Debug\net9.0\AyCode.Models.Server.dll</HintPath>
</Reference>
<Reference Include="AyCode.Services">
<HintPath>..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server\bin\FruitBank\Debug\net9.0\AyCode.Services.dll</HintPath>
</Reference>
<Reference Include="AyCode.Services.Server">
<HintPath>..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server\bin\FruitBank\Debug\net9.0\AyCode.Services.Server.dll</HintPath>
</Reference>
<Reference Include="AyCode.Utils">
<HintPath>..\..\..\..\Aycode\Source\AyCode.Core\AyCode.Services.Server\bin\FruitBank\Debug\net9.0\AyCode.Utils.dll</HintPath>
</Reference>
@ -44,6 +59,9 @@
<Reference Include="DevExpress.Blazor.v25.1.Viewer"></Reference>
<Reference Include="DevExpress.Data.v25.1"></Reference>
<Reference Include="DevExpress.Utils.v25.1"></Reference>
<Reference Include="Mango.Nop.Core">
<HintPath>..\..\NopCommerce.Common\4.70\Libraries\Mango.Nop.Core\bin\FruitBank\Debug\net9.0\Mango.Nop.Core.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View File

@ -71,6 +71,9 @@
<Reference Include="DevExpress.Utils.v25.1">
</Reference>
<Reference Include="Mango.Nop.Core">
<HintPath>..\..\NopCommerce.Common\4.70\Libraries\Mango.Nop.Core\bin\FruitBank\Debug\net9.0\Mango.Nop.Core.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>

View File

@ -33,6 +33,7 @@ namespace FruitBankHybrid
builder.Services.AddSingleton<IAcLogWriterClientBase, BrowserConsoleLogWriter>();
#endif
builder.Services.AddSingleton<ObjectLock>();
builder.Services.AddSingleton<LoggedInModel>();
builder.Services.AddScoped<FruitBankSignalRClient>();
builder.Services.AddSingleton<DatabaseClient>();