From 8b02b0da12fd887d7e5e9554d72b7a8d50e5cc9e Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Mon, 4 May 2026 12:36:09 +0200 Subject: [PATCH] Update display STATS x situazione acquisitori + update conf MON/TAB3 x MP.Data in json conf --- AGENTS.md | 94 +++++++++++++ Directory.Packages.props | 5 +- MP.Data/Controllers/MpStatsController.cs | 4 +- ...yCheckModel.cs => MaccEnergyCheckModel.cs} | 4 +- MP.Data/MoonPro_STATSContext.cs | 6 +- MP.Land/MP.Land.csproj | 2 +- MP.Land/Resources/ChangeLog.html | 2 +- MP.Land/Resources/VersNum.txt | 2 +- MP.Land/Resources/manifest.xml | 2 +- MP.Stats/Data/MpStatsService.cs | 12 +- MP.Stats/MP.Stats.csproj | 3 +- MP.Stats/Pages/StatusChecks.razor | 21 +-- MP.Stats/Pages/StatusChecks.razor.cs | 133 ++++++++++++++++-- MP.Stats/Resources/ChangeLog.html | 2 +- MP.Stats/Resources/VersNum.txt | 2 +- MP.Stats/Resources/manifest.xml | 2 +- MP.Stats/_Imports.razor | 6 +- 17 files changed, 257 insertions(+), 45 deletions(-) create mode 100644 AGENTS.md rename MP.Data/DbModels/Energy/{MacchineEnergyCheckModel.cs => MaccEnergyCheckModel.cs} (86%) diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..9c089229 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,94 @@ +# CI to Local Workflow Guide + +This document describes how the GitLab CI pipeline in this repository translates to local commands that can be run on your machine. It also contains helper scripts and environment variables used by the CI. + +## Environment Variables +All variables listed below are interpolated in the CI templates. When running locally you can set them in a PowerShell profile or via `dotnet` arguments. + +| Variable | Description | Typical value | +|----------|--------------|---------------| +| `SOL_NAME` | Solution name to restore | **MP-STATS.sln** | +| `PROJ_PATH` | Directory containing the main project | **MP.Stats** | +| `APP_NAME` | Main project file name (without `.csproj`) | **MP.Stats** | +| `NUGET_PATH` | NuGet credential file | **`C:\\Users\\samuele.steamw\AppData\Roaming\NuGet\Credentials.config`** | +| `NEXUS_PATH` | Nexus host URL | **https://nexus.steamware.net** | +| `DEST` | Artifacts output folder | **bin\publish** | +| `VERS_MAIN`, `VERS_MAIN_APP`, `VERSSUB` | Version strings used in packaging | **1.0.0** / +| `NEXUS_PASSWD` | Nexus password (secure via CI secret) | *Secret* | + +## Build Pipeline (`buildjob`) – Local Equivalent + +The CI first restores NuGet packages and then builds the solution for the selected `APP_NAME`. + +```powershell +# 1. Restore +#$env:SOL_NAME.sln is resolved by the .nuget-fix script +# In PowerShell: dotnet restore "MP-STATS.sln" + +# 2. Build +# $env:APP_NAME/$env:APP_NAME.csproj points to the project file +# In PowerShell: dotnet build "MP.Stats/MP.Stats.csproj" +``` + +### Helper: `.nuget-fix` +The `.nuget-fix` PowerShell script removes any stale NuGet sources that conflict with the Nexus proxy and re‑adds the latest proxy source with credentials. Ensure this script runs *before* `dotnet restore`. + +## Deploy Pipeline (`deployjob`) – Local Equivalent + +Deployment in CI rebuilds the project, publishes it, hashes the output, and uploads it to Nexus. The same steps can be executed locally. + +```powershell +# 1. Rebuild (same as Build) +# dotnet build "MP.Stats/MP.Stats.csproj" + +# 2. Publish to a local folder +# The `dotnet publish` command mimics the CI publish step. The `-c Release` ensures a Release build. +# In PowerShell: +# dotnet publish "MP.Stats/MP.Stats.csproj" -c Release -o publish + +# 3. Create hashes (MD5 & SHA1) +# The .hashBuild template generates .md5 and .sha1 files alongside the ZIP. A simple replacement can be +# 1. Zip the folder: `Compress-Archive -Path publish -DestinationPath $(APP_NAME).zip` +# 2. Generate hashes: +# (Get-FileHash -Algorithm MD5 "$(APP_NAME).zip").Hash | Out-File "$(APP_NAME).md5" +# (Get-FileHash -Algorithm SHA1 "$(APP_NAME).zip").Hash | Out-File "$(APP_NAME).sha1" + +# 4. Upload to Nexus (requires `curl`) +# Example curl command (CI uses `nexus-curl` script): +# $curl -u $(NUGET_USER):$(NEXUS_PASSWD) "$(NEXUS_PATH)/repository/$(APP_NAME)" -T "$(APP_NAME).zip" +``` + +## Installer & Release +The **installer** template copies the published artifacts to a staging folder and optionally creates installers. The **release** template bumps version numbers, updates the `nuspec`, generates a changelog, and pushes the packages to Nexus. + +Generally these steps are CI‑only, but you can repeat the same `dotnet pack` / `nuget push` commands locally if needed. + +## Common Issues & Fixes + +* _NuGet authentication errors_: Run `.nuget-fix` to reset the sources. +* _Missing SDK_: Verify `dotnet --list-sdks` includes at least one SDK. +* _Hashes not matching_: Ensure the ZIP file is identical to the one CI produced (same path, no hidden files). + +## Quick Start +```powershell +# Restore +.\.nuget-fix + +# Build + +dotnet restore "MP-STATS.sln" +dotnet build "MP.Stats/MP.Stats.csproj" + +# Publish & run + +dotnet publish "MP.Stats/MP.Stats.csproj" -c Release -o publish +dotnet run --project "MP.Stats/MP.Stats.csproj" + +# For hot‑reload during development + +dotnet watch run --project "MP.Stats/MP.Stats.csproj" +``` + +--- + +Feel free to adjust paths or environment variable names if your local setup differs. diff --git a/Directory.Packages.props b/Directory.Packages.props index 91034140..de7d50f2 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,8 +7,8 @@ - - + + @@ -48,6 +48,5 @@ - \ No newline at end of file diff --git a/MP.Data/Controllers/MpStatsController.cs b/MP.Data/Controllers/MpStatsController.cs index cb6dd8a6..046d5549 100644 --- a/MP.Data/Controllers/MpStatsController.cs +++ b/MP.Data/Controllers/MpStatsController.cs @@ -201,9 +201,9 @@ namespace MP.Data.Controllers /// Elenco controllo stato Macchine Energy x check /// /// - public async Task> MacchineEnergyCheckGetAllAsync() + public async Task> MacchineEnergyCheckGetAllAsync() { - List dbResult = new List(); + List dbResult = new List(); using (var dbCtx = new MoonPro_STATSContext(_configuration)) { dbResult = await dbCtx diff --git a/MP.Data/DbModels/Energy/MacchineEnergyCheckModel.cs b/MP.Data/DbModels/Energy/MaccEnergyCheckModel.cs similarity index 86% rename from MP.Data/DbModels/Energy/MacchineEnergyCheckModel.cs rename to MP.Data/DbModels/Energy/MaccEnergyCheckModel.cs index 04cedc23..b75ffd22 100644 --- a/MP.Data/DbModels/Energy/MacchineEnergyCheckModel.cs +++ b/MP.Data/DbModels/Energy/MaccEnergyCheckModel.cs @@ -1,16 +1,14 @@ using System; -using System.ComponentModel.DataAnnotations; namespace MP.Data.DbModels.Energy { - public class MacchineEnergyCheckModel + public class MaccEnergyCheckModel { public string IdxMacchina { get; set; } = ""; /// /// Nome macchina /// - [MaxLength(50)] public string Nome { get; set; } = ""; /// /// Descrizione macchina diff --git a/MP.Data/MoonPro_STATSContext.cs b/MP.Data/MoonPro_STATSContext.cs index 9baca2e2..11ba7efd 100644 --- a/MP.Data/MoonPro_STATSContext.cs +++ b/MP.Data/MoonPro_STATSContext.cs @@ -44,7 +44,7 @@ namespace MP.Data public virtual DbSet DbSetDdbTurni { get; set; } public virtual DbSet DbSetFL { get; set; } public virtual DbSet DbSetMacchine { get; set; } - public virtual DbSet DbSetMacchineCheck { get; set; } + public virtual DbSet DbSetMacchineCheck { get; set; } public virtual DbSet DbSetODL { get; set; } public virtual DbSet DbSetOdlEnergy { get; set; } @@ -139,11 +139,11 @@ namespace MP.Data .HasMaxLength(5); }); - modelBuilder.Entity(entity => + modelBuilder.Entity(entity => { entity.HasNoKey(); - entity.ToView("v_UI_MacchineEnergyCheck"); + entity.ToView("v_UI_MaccEnergyCheck"); }); modelBuilder.Entity(entity => diff --git a/MP.Land/MP.Land.csproj b/MP.Land/MP.Land.csproj index edb05ea5..4b406421 100644 --- a/MP.Land/MP.Land.csproj +++ b/MP.Land/MP.Land.csproj @@ -3,7 +3,7 @@ net8.0 MP.Land - 8.16.2604.2718 + 8.16.2605.0411 Debug;Release;Debug_LiManDebug en True diff --git a/MP.Land/Resources/ChangeLog.html b/MP.Land/Resources/ChangeLog.html index 552a2531..01aed9ae 100644 --- a/MP.Land/Resources/ChangeLog.html +++ b/MP.Land/Resources/ChangeLog.html @@ -1,6 +1,6 @@ Modulo Tablet MAPO - DotNet6 -

Versione: 8.16.2604.2718

+

Versione: 8.16.2605.0411


Note di rilascio:
    diff --git a/MP.Land/Resources/VersNum.txt b/MP.Land/Resources/VersNum.txt index 87ec763e..af1dc925 100644 --- a/MP.Land/Resources/VersNum.txt +++ b/MP.Land/Resources/VersNum.txt @@ -1 +1 @@ -8.16.2604.2718 +8.16.2605.0411 diff --git a/MP.Land/Resources/manifest.xml b/MP.Land/Resources/manifest.xml index e38827ea..d230416a 100644 --- a/MP.Land/Resources/manifest.xml +++ b/MP.Land/Resources/manifest.xml @@ -1,6 +1,6 @@ - 8.16.2604.2718 + 8.16.2605.0411 https://nexus.steamware.net/repository/SWS/MP-LAND/stable/LAST/MP.Land.zip https://nexus.steamware.net/repository/SWS/MP-LAND/stable/LAST/ChangeLog.html false diff --git a/MP.Stats/Data/MpStatsService.cs b/MP.Stats/Data/MpStatsService.cs index 35c6cfbb..54e4803b 100644 --- a/MP.Stats/Data/MpStatsService.cs +++ b/MP.Stats/Data/MpStatsService.cs @@ -378,20 +378,20 @@ namespace MP.Stats.Data /// Elenco check stato Macchine Energy ///
/// - public async Task> MacchineEnergyCheckGetAll() + public async Task> MacchineEnergyCheckGetAll() { // setup parametri costanti string source = "DB"; Stopwatch sw = new Stopwatch(); sw.Start(); - List result = new List(); + List result = new List(); // cerco in redis... DateTime adesso = DateTime.Now; string currKey = $"{redisBaseKey}:Cache:MacchineEnegyCheck"; RedisValue rawData = await _redisDb.StringGetAsync(currKey); - if (rawData.HasValue) + if (rawData.HasValue && rawData.Length() > 2) { - result = JsonConvert.DeserializeObject>($"{rawData}"); + result = JsonConvert.DeserializeObject>($"{rawData}"); source = "REDIS"; } else @@ -399,11 +399,11 @@ namespace MP.Stats.Data result = await dbController.MacchineEnergyCheckGetAllAsync(); // serializzp e salvo... rawData = JsonConvert.SerializeObject(result); - await _redisDb.StringSetAsync(currKey, rawData, FastCache); + await _redisDb.StringSetAsync(currKey, rawData, TimeSpan.FromSeconds(60)); } if (result == null) { - result = new List(); + result = new List(); } sw.Stop(); Log.Debug($"MacchineEnergyCheckGetAllAsync | {source} | {sw.Elapsed.TotalMilliseconds}ms"); diff --git a/MP.Stats/MP.Stats.csproj b/MP.Stats/MP.Stats.csproj index f55ebae2..b17391ea 100644 --- a/MP.Stats/MP.Stats.csproj +++ b/MP.Stats/MP.Stats.csproj @@ -4,7 +4,7 @@ net8.0 MP.Stats 826e877c-ba70-4253-84cb-d0b1cafd4440 - 8.16.2605.0409 + 8.16.2605.0412 true en @@ -50,6 +50,7 @@ + diff --git a/MP.Stats/Pages/StatusChecks.razor b/MP.Stats/Pages/StatusChecks.razor index 1aee7299..dd70a135 100644 --- a/MP.Stats/Pages/StatusChecks.razor +++ b/MP.Stats/Pages/StatusChecks.razor @@ -4,12 +4,15 @@
- Status Checks + Status Checks +
+
+
- Scdenza (minuti) - + Scadenza (minuti) +
@@ -17,12 +20,12 @@ - - - - - - + + + + + + diff --git a/MP.Stats/Pages/StatusChecks.razor.cs b/MP.Stats/Pages/StatusChecks.razor.cs index 1b44db4b..c827abd8 100644 --- a/MP.Stats/Pages/StatusChecks.razor.cs +++ b/MP.Stats/Pages/StatusChecks.razor.cs @@ -1,3 +1,4 @@ +using EgwCoreLib.Razor; using Microsoft.AspNetCore.Components; using Microsoft.Extensions.Configuration; using MP.Data.DbModels.Energy; @@ -25,6 +26,7 @@ namespace MP.Stats.Pages protected override void OnInitialized() { + sortField = "dtEvento"; timeoutMin = ConfMan.GetValue("SpecialConf:TimeoutEnergyFlux"); } @@ -38,9 +40,10 @@ namespace MP.Stats.Pages #region Private Fields - private List AllRecord = new(); + private List AllRecord = new(); + private List SortRecord = new(); - private List ListPaged = new(); + private List ListPaged = new(); private int numRecPage = 10; @@ -58,11 +61,11 @@ namespace MP.Stats.Pages /// /// /// - private string CheckScadute(MacchineEnergyCheckModel item) + private string CheckScadute(MaccEnergyCheckModel item) { DateTime adesso = DateTime.Now; var dataAge = adesso.Subtract(item.dtEvento).TotalMinutes; - string status = ""; + string status = "table-success"; // se supero limite if (dataAge >= timeoutMin) { @@ -83,6 +86,18 @@ namespace MP.Stats.Pages numRecPage = newNum; UpdateTable(); } + protected void SortRequested(Sorter.SortCallBack e) + { + if (sortField == e.ParamName) + { + sortAsc = e.IsAscending; + } + sortField = e.ParamName; + UpdateTable(); + } + private bool sortAsc = true; + private string sortField = ""; + private void SavePage(int newNum) { @@ -92,17 +107,119 @@ namespace MP.Stats.Pages private void UpdateTable() { - // esegue paginazione - if (totalCount > numRecPage) + // se ho ordinamento riordino... + if (!string.IsNullOrEmpty(sortField)) { - ListPaged = AllRecord.Skip((pageNum - 1) * numRecPage).Take(numRecPage).ToList(); + switch (sortField) + { + case "IdxMacc": + if (sortAsc) + { + SortRecord = AllRecord.OrderBy(x => x.IdxMacchina).ToList(); + } + else + { + SortRecord = AllRecord.OrderByDescending(x => x.IdxMacchina).ToList(); + } + break; + + case "Nome": + if (sortAsc) + { + SortRecord = AllRecord.OrderBy(x => x.Nome).ToList(); + } + else + { + SortRecord = AllRecord.OrderByDescending(x => x.Nome).ToList(); + } + break; + + case "CodFlux": + if (sortAsc) + { + SortRecord = AllRecord.OrderBy(x => x.CodFlux).ToList(); + } + else + { + SortRecord = AllRecord.OrderByDescending(x => x.CodFlux).ToList(); + } + break; + + case "Descr": + if (sortAsc) + { + SortRecord = AllRecord.OrderBy(x => x.Descrizione).ToList(); + } + else + { + SortRecord = AllRecord.OrderByDescending(x => x.Descrizione).ToList(); + } + break; + + case "dtEvento": + if (sortAsc) + { + SortRecord = AllRecord.OrderBy(x => x.dtEvento).ToList(); + } + else + { + SortRecord = AllRecord.OrderByDescending(x => x.dtEvento).ToList(); + } + break; + + case "Valore": + if (sortAsc) + { + SortRecord = AllRecord.OrderBy(x => x.Valore).ToList(); + } + else + { + SortRecord = AllRecord.OrderByDescending(x => x.Valore).ToList(); + } + break; + + + default: + SortRecord = AllRecord.OrderBy(x => x.IdxMacchina).ToList(); + break; + } } else { - ListPaged = AllRecord; + SortRecord = AllRecord.OrderBy(x => x.IdxMacchina).ToList(); } + + // esegue paginazione + if (totalCount > numRecPage) + { + ListPaged = SortRecord.Skip((pageNum - 1) * numRecPage).Take(numRecPage).ToList(); + } + else + { + ListPaged = SortRecord; + } + + // calcolo pareto x scadenze... + DateTime adesso = DateTime.Now; + ParetoTime = AllRecord + .GroupBy(x => + { + double dataAge = (adesso - x.dtEvento).TotalMinutes; + return dataAge < timeoutMin ? "success" : dataAge < timeoutMin * 2 ? "warning" : "danger"; + }) + .ToDictionary(g => g.Key, g => g.Count()); + + // Fallback per le categorie con 0 elementi (opzionale ma consigliato) + ParetoTime["success"] = ParetoTime.GetValueOrDefault("success", 0); + ParetoTime["warning"] = ParetoTime.GetValueOrDefault("warning", 0); + ParetoTime["danger"] = ParetoTime.GetValueOrDefault("danger", 0); } + /// + /// Pareto dei tempi secondo scadenza + /// + private Dictionary ParetoTime = new(); + #endregion Private Methods } } \ No newline at end of file diff --git a/MP.Stats/Resources/ChangeLog.html b/MP.Stats/Resources/ChangeLog.html index 5a3ceecc..c5efb8b9 100644 --- a/MP.Stats/Resources/ChangeLog.html +++ b/MP.Stats/Resources/ChangeLog.html @@ -1,6 +1,6 @@ Modulo statistiche MAPO -

Versione: 8.16.2605.0409

+

Versione: 8.16.2605.0412


Note di rilascio:
    diff --git a/MP.Stats/Resources/VersNum.txt b/MP.Stats/Resources/VersNum.txt index 8cdf9194..63e48186 100644 --- a/MP.Stats/Resources/VersNum.txt +++ b/MP.Stats/Resources/VersNum.txt @@ -1 +1 @@ -8.16.2605.0409 +8.16.2605.0412 diff --git a/MP.Stats/Resources/manifest.xml b/MP.Stats/Resources/manifest.xml index bbf1a5bd..0a1aae75 100644 --- a/MP.Stats/Resources/manifest.xml +++ b/MP.Stats/Resources/manifest.xml @@ -1,6 +1,6 @@ - 8.16.2605.0409 + 8.16.2605.0412 https://nexus.steamware.net/repository/SWS/MP-STATS/stable/LAST/MP.Stats.zip https://nexus.steamware.net/repository/SWS/MP-STATS/stable/LAST/ChangeLog.html false diff --git a/MP.Stats/_Imports.razor b/MP.Stats/_Imports.razor index a9c2785e..c73030b5 100644 --- a/MP.Stats/_Imports.razor +++ b/MP.Stats/_Imports.razor @@ -1,4 +1,5 @@ -@using System.Net.Http +@using EgwCoreLib.Razor +@using System.Net.Http @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.AspNetCore.Components.Forms @@ -11,5 +12,4 @@ @using MP.Stats.Components @using MP.Stats.Components.ChartJs @using MP.TaskMan -@using MP.TaskMan.Models -@using EgwCoreLib.Razor \ No newline at end of file +@using MP.TaskMan.Models \ No newline at end of file
IdxMacchinadescrFluxLast EventValoreIdx Macchina descr Flux Last Event Valore