Compare commits

...

4 Commits

Author SHA1 Message Date
Loretta 920bc299aa Add grid sync state tracking and robust login redirection
Introduce IsSyncing and OnSyncingStateChanged to IMgGridBase and MgGridBase for real-time sync state tracking and event notification. Update FruitBankToolbarTemplate to enable/disable the reload button based on grid sync and reload state, subscribing to sync events and cleaning up on disposal. Implement IAsyncDisposable in MgGridBase to prevent memory leaks. Update login navigation to use forceLoad for reliability. These changes improve UI responsiveness and resource management.
2025-12-09 11:27:21 +01:00
Loretta 06f397e285 Refactor, enhance, and improve test coverage
Refactored `OnDataSourceLoaded` to be asynchronous for better state handling. Downgraded `Newtonsoft.Json` to version `13.0.3` across multiple projects for compatibility. Enhanced `MeasuringItemPalletBase` with `SetParentPropToNull` and `SetForeignKey` methods. Refactored `OrderItemPallet`, `ShippingItemPallet`, and `StockTakingItemPallet` to simplify table attributes and improve parent-child relationship handling.

Added `IsReadyForClose` to `StockTaking` for better closure validation. Updated SignalR tag constants to reflect new functionality. Improved Razor components (`PalletItemComponent`, `StockTakingTemplate`, `MeasuringIn`, `MeasuringOut`) to streamline logic and maintain proper references.

Introduced `JsonExtensionTests` for comprehensive validation of JSON serialization/deserialization, including deep hierarchies, circular references, and hybrid references. Added `test_debug.ps1` for streamlined test debugging. Performed general code cleanup and improved test coverage.
2025-12-08 15:50:57 +01:00
Loretta 0e2d31aa4b .Net10, VS2026; StockTaking in progress... 2025-12-01 16:18:47 +01:00
Loretta 687b745b4d Upgrade to .net10 and Visual Studio 2026; StockTaking in progress... 2025-11-28 08:15:58 +01:00
8 changed files with 99 additions and 81 deletions

View File

@ -1,6 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk.Razor"> <Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup> <PropertyGroup>
<RunAOTCompilation>true</RunAOTCompilation>
<WasmStripILAfterAOT>true</WasmStripILAfterAOT>
</PropertyGroup> </PropertyGroup>
<Import Project="..//AyCode.Blazor.targets" /> <Import Project="..//AyCode.Blazor.targets" />
@ -13,12 +15,14 @@
<PackageReference Include="DevExpress.Blazor" Version="25.1.3" /> <PackageReference Include="DevExpress.Blazor" Version="25.1.3" />
<PackageReference Include="DevExpress.Data" Version="25.1.3" /> <PackageReference Include="DevExpress.Data" Version="25.1.3" />
<PackageReference Include="MessagePack" Version="3.1.4" /> <PackageReference Include="MessagePack" Version="3.1.4" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="9.0.10" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.10" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="9.0.10" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Core" Version="1.2.0" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Core" Version="1.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.10" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.11" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="9.0.8" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="9.0.11" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Identity.Core" Version="10.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,53 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<SupportedPlatform Include="browser" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="DevExpress.Blazor" Version="23.2.3" />
<PackageReference Include="DevExpress.Blazor.Dashboard" Version="23.2.3" />
<PackageReference Include="MessagePack" Version="2.5.168" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="8.0.6" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.6" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="8.0.6" />
</ItemGroup>
<ItemGroup>
<Reference Include="AyCode.Core">
<HintPath>..\..\AyCode.Core\AyCode.Services.Server\bin\TIAM\Debug\net9.0\AyCode.Core.dll</HintPath>
</Reference>
<Reference Include="AyCode.Entities">
<HintPath>..\..\AyCode.Core\AyCode.Services.Server\bin\TIAM\Debug\net9.0\AyCode.Entities.dll</HintPath>
</Reference>
<Reference Include="AyCode.Interfaces">
<HintPath>..\..\AyCode.Core\AyCode.Services.Server\bin\TIAM\Debug\net9.0\AyCode.Interfaces.dll</HintPath>
</Reference>
<Reference Include="AyCode.Models">
<HintPath>..\..\AyCode.Core\AyCode.Services.Server\bin\TIAM\Debug\net9.0\AyCode.Models.dll</HintPath>
</Reference>
<Reference Include="AyCode.Services">
<HintPath>..\..\AyCode.Core\AyCode.Services.Server\bin\TIAM\Debug\net9.0\AyCode.Services.dll</HintPath>
</Reference>
<Reference Include="AyCode.Utils">
<HintPath>..\..\AyCode.Core\AyCode.Services.Server\bin\TIAM\Debug\net9.0\AyCode.Utils.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Folder Include="Layouts\" />
<Folder Include="Pages\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AyCode.Blazor.Models\AyCode.Blazor.Models.csproj" />
</ItemGroup>
</Project>

View File

@ -15,10 +15,18 @@ namespace AyCode.Blazor.Components.Components.Grids;
public interface IMgGridBase : IGrid public interface IMgGridBase : IGrid
{ {
/// <summary>
/// Indicates whether any synchronization operation is in progress
/// </summary>
bool IsSyncing { get; }
/// <summary>
/// Event fired when synchronization state changes (true = syncing started, false = syncing ended)
/// </summary>
event Action<bool>? OnSyncingStateChanged;
} }
public abstract class MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClient> : DxGrid, IMgGridBase public abstract class MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClient> : DxGrid, IMgGridBase, IAsyncDisposable
where TSignalRDataSource : AcSignalRDataSource<TDataItem, TId, AcObservableCollection<TDataItem>> where TSignalRDataSource : AcSignalRDataSource<TDataItem, TId, AcObservableCollection<TDataItem>>
where TDataItem : class, IId<TId> where TDataItem : class, IId<TId>
where TId : struct where TId : struct
@ -29,11 +37,18 @@ public abstract class MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClie
protected bool IsFirstInitializeParameters; protected bool IsFirstInitializeParameters;
protected bool IsFirstInitializeParameterCore; protected bool IsFirstInitializeParameterCore;
private bool _isDisposed;
private TSignalRDataSource? _dataSource = null!; private TSignalRDataSource? _dataSource = null!;
private AcObservableCollection<TDataItem>? _dataSourceParam = []; private AcObservableCollection<TDataItem>? _dataSourceParam = [];
private string _gridLogName; private string _gridLogName;
/// <inheritdoc />
public bool IsSyncing => _dataSource?.IsSyncing ?? false;
/// <inheritdoc />
public event Action<bool>? OnSyncingStateChanged;
public MgGridBase() : base() public MgGridBase() : base()
{ {
} }
@ -133,6 +148,7 @@ public abstract class MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClie
public void SetGridData(object? data) public void SetGridData(object? data)
{ {
if (_isDisposed) return;
if (ReferenceEquals(Data, data)) return; if (ReferenceEquals(Data, data)) return;
BeginUpdate(); BeginUpdate();
@ -161,12 +177,25 @@ public abstract class MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClie
_dataSource.OnDataSourceLoaded += OnDataSourceLoaded; _dataSource.OnDataSourceLoaded += OnDataSourceLoaded;
_dataSource.OnDataSourceItemChanged += OnDataSourceItemChanged; _dataSource.OnDataSourceItemChanged += OnDataSourceItemChanged;
_dataSource.OnSyncingStateChanged += OnDataSourceSyncingStateChanged;
await base.OnInitializedAsync(); await base.OnInitializedAsync();
} }
private void OnDataSourceSyncingStateChanged(bool isSyncing)
{
if (_isDisposed) return;
// Forward the event to external subscribers
OnSyncingStateChanged?.Invoke(isSyncing);
// Trigger UI update
InvokeAsync(StateHasChanged);
}
private async Task OnDataSourceItemChanged(ItemChangedEventArgs<TDataItem> args) private async Task OnDataSourceItemChanged(ItemChangedEventArgs<TDataItem> args)
{ {
if (_isDisposed) return;
if (args.TrackingState is TrackingState.GetAll or TrackingState.None) return; if (args.TrackingState is TrackingState.GetAll or TrackingState.None) return;
Logger.Debug($"{_gridLogName} OnDataSourceItemChanged; trackingState: {args.TrackingState}"); Logger.Debug($"{_gridLogName} OnDataSourceItemChanged; trackingState: {args.TrackingState}");
@ -174,7 +203,7 @@ public abstract class MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClie
var changedEventArgs = new GridDataItemChangedEventArgs<TDataItem>(this, args.Item, args.TrackingState); var changedEventArgs = new GridDataItemChangedEventArgs<TDataItem>(this, args.Item, args.TrackingState);
await OnGridItemChanged.InvokeAsync(changedEventArgs); await OnGridItemChanged.InvokeAsync(changedEventArgs);
if (!changedEventArgs.CancelStateChangeInvoke) if (!changedEventArgs.CancelStateChangeInvoke && !_isDisposed)
{ {
//BeginUpdate(); //BeginUpdate();
await InvokeAsync(StateHasChanged); //TODO: bezárja a DetailRow-t! pl: az email-nél IsReaded=true update... - J. await InvokeAsync(StateHasChanged); //TODO: bezárja a DetailRow-t! pl: az email-nél IsReaded=true update... - J.
@ -182,8 +211,10 @@ public abstract class MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClie
} }
} }
private Task OnDataSourceLoaded() private async Task OnDataSourceLoaded()
{ {
if (_isDisposed) return;
Logger.Debug($"{_gridLogName} OnDataSourceLoaded; Count: {_dataSource?.Count}"); Logger.Debug($"{_gridLogName} OnDataSourceLoaded; Count: {_dataSource?.Count}");
//if(_dataSourceParam.GetType() == typeof()AcObservableCollection<TDataItem>) //if(_dataSourceParam.GetType() == typeof()AcObservableCollection<TDataItem>)
@ -192,7 +223,11 @@ public abstract class MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClie
//else Reload(); //else Reload();
//_dataSource.LoadItem(_dataSource.First().Id).Forget(); //_dataSource.LoadItem(_dataSource.First().Id).Forget();
return OnDataSourceChanged.InvokeAsync(_dataSource); if (!_isDisposed)
{
await OnDataSourceChanged.InvokeAsync(_dataSource);
await InvokeAsync(StateHasChanged);
}
} }
protected override async Task OnAfterRenderAsync(bool firstRender) protected override async Task OnAfterRenderAsync(bool firstRender)
@ -410,6 +445,7 @@ public abstract class MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClie
base.DataItemDeleting = EventCallback.Factory.Create<GridDataItemDeletingEventArgs>(this, OnItemDeleting); base.DataItemDeleting = EventCallback.Factory.Create<GridDataItemDeletingEventArgs>(this, OnItemDeleting);
base.EditModelSaving = EventCallback.Factory.Create<GridEditModelSavingEventArgs>(this, OnItemSaving); base.EditModelSaving = EventCallback.Factory.Create<GridEditModelSavingEventArgs>(this, OnItemSaving);
base.CustomizeEditModel = EventCallback.Factory.Create<GridCustomizeEditModelEventArgs>(this, OnCustomizeEditModel); base.CustomizeEditModel = EventCallback.Factory.Create<GridCustomizeEditModelEventArgs>(this, OnCustomizeEditModel);
//base.customizecel= EventCallback.Factory.Create<GridCustomizeEditModelEventArgs>(this, OnCustomizeEditModel);
base.EditStart = EventCallback.Factory.Create<GridEditStartEventArgs>(this, OnEditStart); base.EditStart = EventCallback.Factory.Create<GridEditStartEventArgs>(this, OnEditStart);
CustomizeElement += OnCustomizeElement; CustomizeElement += OnCustomizeElement;
@ -480,6 +516,30 @@ public abstract class MgGridBase<TSignalRDataSource, TDataItem, TId, TLoggerClie
{ {
return _dataSource.LoadDataSourceAsync(false); return _dataSource.LoadDataSourceAsync(false);
} }
public async ValueTask DisposeAsync()
{
if (_isDisposed) return;
_isDisposed = true;
// Unsubscribe from events to prevent callbacks to disposed component
if (_dataSource != null)
{
_dataSource.OnDataSourceLoaded -= OnDataSourceLoaded;
_dataSource.OnDataSourceItemChanged -= OnDataSourceItemChanged;
_dataSource.OnSyncingStateChanged -= OnDataSourceSyncingStateChanged;
}
CustomizeElement -= OnCustomizeElement;
// Dispose base if it implements IAsyncDisposable
if (this is IAsyncDisposable asyncDisposable && asyncDisposable != this)
{
await asyncDisposable.DisposeAsync();
}
GC.SuppressFinalize(this);
}
} }
public class GridDataItemChangingEventArgs<TDataItem> : GridDataItemChangedEventArgs<TDataItem> where TDataItem : class public class GridDataItemChangingEventArgs<TDataItem> : GridDataItemChangedEventArgs<TDataItem> where TDataItem : class

View File

@ -1,6 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<RunAOTCompilation>true</RunAOTCompilation>
<WasmStripILAfterAOT>true</WasmStripILAfterAOT>
</PropertyGroup> </PropertyGroup>
<Import Project="..//AyCode.Blazor.targets" /> <Import Project="..//AyCode.Blazor.targets" />
@ -55,8 +57,8 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="MessagePack" Version="3.1.4" /> <PackageReference Include="MessagePack" Version="3.1.4" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.10" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.11" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="9.0.10" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="9.0.11" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,6 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<RunAOTCompilation>true</RunAOTCompilation>
<WasmStripILAfterAOT>true</WasmStripILAfterAOT>
</PropertyGroup> </PropertyGroup>
<Import Project="..//AyCode.Blazor.targets" /> <Import Project="..//AyCode.Blazor.targets" />

View File

@ -1,6 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<RunAOTCompilation>true</RunAOTCompilation>
<WasmStripILAfterAOT>true</WasmStripILAfterAOT>
</PropertyGroup> </PropertyGroup>
<Import Project="..//AyCode.Blazor.targets" /> <Import Project="..//AyCode.Blazor.targets" />

View File

@ -3,25 +3,28 @@
<Import Project="..//AyCode.Maui.targets" /> <Import Project="..//AyCode.Maui.targets" />
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net9.0;net9.0-maccatalyst;net9.0-ios;net9.0-android35.0</TargetFrameworks> <TargetFrameworks>net10.0-android;net10.0-ios</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net10.0-windows10.0.26100.0</TargetFrameworks>
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET --> <!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
<!-- <TargetFrameworks>$(TargetFrameworks);net9.0-tizen</TargetFrameworks> --> <!-- <TargetFrameworks>$(TargetFrameworks);net9.0-tizen</TargetFrameworks> -->
<UseMaui>true</UseMaui> <UseMaui>true</UseMaui>
<SingleProject>true</SingleProject> <SingleProject>true</SingleProject>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">14.2</SupportedOSPlatformVersion> <RunAOTCompilation>true</RunAOTCompilation>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">14.0</SupportedOSPlatformVersion> <WasmStripILAfterAOT>true</WasmStripILAfterAOT>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">31.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.0</SupportedOSPlatformVersion>
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">15.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">33.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.19041.0</SupportedOSPlatformVersion>
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.19041.0</TargetPlatformMinVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="MessagePack" Version="3.1.4" /> <PackageReference Include="MessagePack" Version="3.1.4" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.10" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.11" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="9.0.10" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="9.0.11" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -46,11 +49,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Update="Microsoft.AspNetCore.Components.WebView.Maui" Version="9.0.120" /> <PackageReference Include="Microsoft.Maui.Controls" Version="10.0.11" />
</ItemGroup> <PackageReference Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="10.0.11" />
<ItemGroup>
<PackageReference Update="Microsoft.Maui.Controls" Version="9.0.120" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -3,7 +3,8 @@
<Name>AyCode.Project.targets</Name> <Name>AyCode.Project.targets</Name>
<_ProjectName>FruitBank</_ProjectName> <_ProjectName>FruitBank</_ProjectName>
<_TargetFramework>net9.0</_TargetFramework> <_TargetFramework>net10.0</_TargetFramework>
<_TargetFrameworkAyCodeCore>net9.0</_TargetFrameworkAyCodeCore>
<!--<GitBranch>$([System.IO.File]::ReadAlltext('$(MsBuildThisFileDirectory)\.git\HEAD').Replace('ref: refs/heads/', '').Trim())</GitBranch> <!--<GitBranch>$([System.IO.File]::ReadAlltext('$(MsBuildThisFileDirectory)\.git\HEAD').Replace('ref: refs/heads/', '').Trim())</GitBranch>
<_ProjectName>$(GitBranch)</_ProjectName>--> <_ProjectName>$(GitBranch)</_ProjectName>-->
@ -13,7 +14,7 @@
<Configurations>Debug;Release;Product</Configurations> <Configurations>Debug;Release;Product</Configurations>
<BaseOutputPath>bin\$(_ProjectName)</BaseOutputPath> <BaseOutputPath>bin\$(_ProjectName)</BaseOutputPath>
<_AyCodeCoresReferenceBuildSubPath>$(_ProjectName)\$(Configuration)\$(_TargetFramework)</_AyCodeCoresReferenceBuildSubPath> <_AyCodeCoresReferenceBuildSubPath>$(_ProjectName)\$(Configuration)\$(_TargetFrameworkAyCodeCore)</_AyCodeCoresReferenceBuildSubPath>
</PropertyGroup> </PropertyGroup>
<Target Name="Test" AfterTargets="AfterBuild"> <Target Name="Test" AfterTargets="AfterBuild">