From 9007a4df8506e049b6324e67aee53e540f3e1981 Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Tue, 15 Oct 2024 10:12:50 +0200 Subject: [PATCH] SPEC: - inizio gestione display folder ODL - browse directory locale x documenti - da verificare metodo refresh modulo browse --- MP-TAB3/Components/IobInfoMan.razor.cs | 2 +- MP.Data/MeasureUtils.cs | 53 +++++++ MP.SPEC/Components/FolderBrowser.razor | 34 +++++ MP.SPEC/Components/FolderBrowser.razor.cs | 66 ++++++++ MP.SPEC/Components/ListODL.razor | 65 ++++++-- MP.SPEC/Components/ListODL.razor.cs | 59 +++++++ MP.SPEC/Data/MpDataService.cs | 178 +++++++++++++++++++++- MP.SPEC/MP.SPEC.csproj | 2 +- MP.SPEC/Program.cs | 21 ++- MP.SPEC/Resources/ChangeLog.html | 2 +- MP.SPEC/Resources/VersNum.txt | 2 +- MP.SPEC/Resources/manifest.xml | 2 +- MP.SPEC/appsettings.Production.json | 4 +- MP.SPEC/appsettings.json | 4 +- 14 files changed, 473 insertions(+), 21 deletions(-) create mode 100644 MP.Data/MeasureUtils.cs create mode 100644 MP.SPEC/Components/FolderBrowser.razor create mode 100644 MP.SPEC/Components/FolderBrowser.razor.cs diff --git a/MP-TAB3/Components/IobInfoMan.razor.cs b/MP-TAB3/Components/IobInfoMan.razor.cs index 0a4cacdf..c1b75b6f 100644 --- a/MP-TAB3/Components/IobInfoMan.razor.cs +++ b/MP-TAB3/Components/IobInfoMan.razor.cs @@ -34,7 +34,7 @@ namespace MP_TAB3.Components public string MacIobConf(string kReq) { - string answ = ""; + string answ = "-"; if (MachineData.ContainsKey(kReq)) { answ = MachineData[kReq]; diff --git a/MP.Data/MeasureUtils.cs b/MP.Data/MeasureUtils.cs new file mode 100644 index 00000000..e930a623 --- /dev/null +++ b/MP.Data/MeasureUtils.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MP.Data +{ + public class MeasureUtils + { + #region Public Fields + + public static readonly string[] SizeSuffixes = { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; + + #endregion Public Fields + + #region Public Methods + + /// + /// Calcola dimensione file automaticamwente secondo dimensione + /// + /// + /// + /// + /// + public static string SizeSuffix(Int64 value, int decimalPlaces = 1) + { + if (decimalPlaces < 0) { throw new ArgumentOutOfRangeException("decimalPlaces"); } + if (value < 0) { return "-" + SizeSuffix(-value, decimalPlaces); } + if (value == 0) { return string.Format("{0:n" + decimalPlaces + "} bytes", 0); } + + // mag is 0 for bytes, 1 for KB, 2, for MB, etc. + int mag = (int)Math.Log(value, 1024); + + // 1L << (mag * 10) == 2 ^ (10 * mag) [i.e. the number of bytes in the unit + // corresponding to mag] + decimal adjustedSize = (decimal)value / (1L << (mag * 10)); + + // make adjustment when the value is large enough that it would round up to 1000 or more + if (Math.Round(adjustedSize, decimalPlaces) >= 1000) + { + mag += 1; + adjustedSize /= 1024; + } + + return string.Format("{0:n" + decimalPlaces + "} {1}", + adjustedSize, + SizeSuffixes[mag]); + } + + #endregion Public Methods + } +} diff --git a/MP.SPEC/Components/FolderBrowser.razor b/MP.SPEC/Components/FolderBrowser.razor new file mode 100644 index 00000000..2aafaac3 --- /dev/null +++ b/MP.SPEC/Components/FolderBrowser.razor @@ -0,0 +1,34 @@ + + + + + + + + + + + @if (ListFiles == null || ListFiles.Count == 0) + { + + + + } + else + { + @foreach (var record in ListFiles) + { + + + + + + } + } + +
NameTypeSize
+
Attenzione: nessun file trovato per ODL richiesto.
+
+ @record.Name + + @record.Extension@CalcSize(record.Length)
\ No newline at end of file diff --git a/MP.SPEC/Components/FolderBrowser.razor.cs b/MP.SPEC/Components/FolderBrowser.razor.cs new file mode 100644 index 00000000..05eb2df4 --- /dev/null +++ b/MP.SPEC/Components/FolderBrowser.razor.cs @@ -0,0 +1,66 @@ +using Microsoft.AspNetCore.Components; +using MP.Data; + +namespace MP.SPEC.Components +{ + public partial class FolderBrowser + { + #region Public Properties + + [Parameter] + public string LogicalPath { get; set; } = ""; + + #endregion Public Properties + + #region Protected Properties + + [Inject] + protected IConfiguration ConfMan { get; set; } = null!; + + #endregion Protected Properties + + #region Protected Methods + + /// + /// Restituisce size calcolata + /// + /// + /// + protected string CalcSize(long origSize) + { + return MeasureUtils.SizeSuffix(origSize, 1); + } + + protected string FileLink(string fName) + { + return $"RET_DATA/{LogicalPath}/{fName}"; + } + + /// + /// Eseguo browsing directory... + /// + /// + protected override void OnParametersSet() + { + // calcolo phisical path... + string BasePathOdlReturn = ConfMan.GetValue("ServerConf:BasePathOdlReturn") ?? ConfMan.GetValue("OptConf:BasePathOdlReturn") ?? ""; + PhysicalPath = Path.Combine(BasePathOdlReturn, LogicalPath); + // controllo esista + if (Directory.Exists(PhysicalPath)) + { + // recupero come DirectoryInfo x avere tutte le informazioni su nome, tipo, size... + DirectoryInfo dirInfo = new DirectoryInfo(PhysicalPath); + ListFiles = dirInfo.GetFiles().ToList(); + } + } + + #endregion Protected Methods + + #region Private Properties + + private List ListFiles { get; set; } = new List(); + private string PhysicalPath { get; set; } = ""; + + #endregion Private Properties + } +} \ No newline at end of file diff --git a/MP.SPEC/Components/ListODL.razor b/MP.SPEC/Components/ListODL.razor index 83b35f54..f6db2ba4 100644 --- a/MP.SPEC/Components/ListODL.razor +++ b/MP.SPEC/Components/ListODL.razor @@ -15,7 +15,7 @@ else @if (currRecord != null && !showStats && isCurrOdl) {
- @if(enableForceSync) + @if (enableForceSync) { } @@ -25,7 +25,7 @@ else }
- @if(enableStopODL) + @if (enableStopODL) { } @@ -61,7 +61,16 @@ else @if (isCurrOdl) { - +
+ +
+ @if (HasFolderMan(record.IdxMacchina)) + { +
+ + @* *@ +
+ } } else { @@ -147,10 +156,12 @@ else
- @record.DurataMinuti -
-
- +
@@ -159,8 +170,7 @@ else - - } diff --git a/MP.SPEC/Components/ListODL.razor.cs b/MP.SPEC/Components/ListODL.razor.cs index 9f633f5a..829448c2 100644 --- a/MP.SPEC/Components/ListODL.razor.cs +++ b/MP.SPEC/Components/ListODL.razor.cs @@ -76,6 +76,8 @@ namespace MP.SPEC.Components [Inject] protected IJSRuntime JSRuntime { get; set; } = null!; + protected Dictionary MachHasFolderLut { get; set; } = new Dictionary(); + [Inject] protected MpDataService MDService { get; set; } = null!; @@ -146,6 +148,32 @@ namespace MP.SPEC.Components return answ; } + /// + /// Determina se abbia gestione folder dati in ritorno + /// + /// + /// + protected bool HasFolderMan(string idxMacc) + { + bool answ = true; + // cerco nella LUT + if (MachHasFolderLut.ContainsKey(idxMacc)) + { + answ = MachHasFolderLut[idxMacc]; + } + // se non trovo cerco nella cache... + else + { + var rawVal = MDService.MachIobConfVal(idxMacc, KeyFolderMan); + if (rawVal != null) + { + bool.TryParse((string)rawVal, out answ); + MachHasFolderLut.Add(idxMacc, answ); + } + } + return answ; + } + protected override async Task OnInitializedAsync() { ListStati = await MDService.AnagStatiComm(); @@ -189,6 +217,7 @@ namespace MP.SPEC.Components protected async Task selectStatRecord(ODLExpModel? currRec) { + showBrowse = false; showStats = true; await Task.Delay(1); statRecord = currRec; @@ -202,6 +231,24 @@ namespace MP.SPEC.Components ListOdlStats = null; } } + protected async Task selBrowseRecord(ODLExpModel? currRec) + { + showBrowse = true; + showStats = false; + await Task.Delay(1); + browseRecord = currRec; +#if false + if (currRec != null) + { + await reloadStatsData(currRec); + } + else + { + showBrowse = false; + ListOdlStats = null; + } +#endif + } protected async Task selRecord(ODLExpModel? currRec) { @@ -237,6 +284,16 @@ namespace MP.SPEC.Components private ODLExpModel? currRecord = null; + /// + /// Chiave gestione folder (hard coded, da IOB OptPar) + /// + private string KeyFolderMan = "OP_ODL_FOLDER"; + + protected string OdlLink(int idxOdl) + { + return $"RET_DATA/ODL{idxOdl:00000000}"; + } + private List? ListOdlStats; private List? ListOdlStatsNetto; @@ -248,6 +305,7 @@ namespace MP.SPEC.Components private List? SearchRecords; private ODLExpModel? statRecord = null; + private ODLExpModel? browseRecord = null; #endregion Private Fields @@ -340,6 +398,7 @@ namespace MP.SPEC.Components private DateTime selDtFine { get; set; } = DateTime.Now; private bool showStats { get; set; } = false; + private bool showBrowse { get; set; } = false; private int totalCount { diff --git a/MP.SPEC/Data/MpDataService.cs b/MP.SPEC/Data/MpDataService.cs index 8a971750..f6aa8374 100644 --- a/MP.SPEC/Data/MpDataService.cs +++ b/MP.SPEC/Data/MpDataService.cs @@ -1,10 +1,12 @@ using EgwCoreLib.Utils; +using Microsoft.Extensions.Options; using MP.Data; using MP.Data.Conf; using MP.Data.DatabaseModels; using MP.Data.DTO; using MP.Data.MgModels; using MP.Data.Objects; +using MP.Data.Services; using Newtonsoft.Json; using NLog; using StackExchange.Redis; @@ -45,6 +47,9 @@ namespace MP.SPEC.Data _logger.LogInformation("DbController OK"); } + // conf x lettura dati da area REDIS di MP-IO + MpIoNS = _configuration.GetValue("ServerConf:MpIoNS"); + // conf mongo... connStr = _configuration.GetConnectionString("mdbConnString"); if (string.IsNullOrEmpty(connStr)) @@ -60,6 +65,15 @@ namespace MP.SPEC.Data #endregion Public Constructors + #region Public Events + + /// + /// Evento richiesta rilettura dati pagina (x refresh pagine aperte) + /// + public event EventHandler ReloadRequest = delegate { }; + + #endregion Public Events + #region Public Properties public static MP.Data.Controllers.MpSpecController dbController { get; set; } = null!; @@ -443,7 +457,7 @@ namespace MP.SPEC.Data return answ; } - + /// /// Update chiave config /// @@ -868,6 +882,42 @@ namespace MP.SPEC.Data return mongoController.InitRecipe(confPath, idxPODL, CalcArgs); } + /// + /// Recupero info IOB x TAB (da info registrate IOB-WIN--> MP-IO) + /// + /// + /// + public async Task IobInfo(string IdxMacchina) + { + string source = "DB"; + Stopwatch sw = new Stopwatch(); + sw.Start(); + IOB_data? result = new IOB_data(); + // cerco in redis... + string currKey = redHashMpIO($"hM2IOB:{IdxMacchina}"); + RedisValue rawData = await redisDb.StringGetAsync(currKey); + //if (!string.IsNullOrEmpty($"{rawData}")) + if (rawData.HasValue) + { + result = JsonConvert.DeserializeObject($"{rawData}"); + source = "REDIS"; + } + else + { + Log.Error($"Errore: non trovato valore valido in REDIS | key: {currKey}"); + Log.Info($"REDIS | conf: {redisConn.Configuration}"); + Log.Info($" --> Valore trovato:{Environment.NewLine}{rawData}"); + } + if (result == null) + { + result = new IOB_data(); + Log.Debug($"Init valore default | IdxMacchina: {IdxMacchina}"); + } + sw.Stop(); + Log.Debug($"IobInfo per {IdxMacchina} | {source} | {sw.Elapsed.TotalMilliseconds}ms"); + return result; + } + /// /// /// id odl da cercare @@ -1047,6 +1097,69 @@ namespace MP.SPEC.Data return result; } + /// + /// Recupero info Machine-IOB x TAB (da info registrate IOB-WIN --> MP-IO) + /// + /// + /// + public Dictionary MachIobConf(string IdxMacchina) + { + string source = "NA"; + Stopwatch sw = new Stopwatch(); + sw.Start(); + Dictionary result = new Dictionary(); + // cerco in redis... + string currKey = redHashMpIO($"IOB:{IdxMacchina}:MachIobConf"); + try + { + result = redisDb + .HashGetAll(currKey) + .ToDictionary(x => $"{x.Name}", x => $"{x.Value}"); + source = "REDIS"; + } + catch (Exception exc) + { + Log.Error($"Errore in MachIobConf{Environment.NewLine}{exc}"); + } + if (result == null) + { + result = new Dictionary(); + Log.Debug($"Init valore default MachIobConf | IdxMacchina: {IdxMacchina}"); + } + sw.Stop(); + Log.Debug($"MachIobConf per {IdxMacchina} | {source} | {sw.Elapsed.TotalMilliseconds}ms"); + return result; + } + /// + /// Recupero singolo recordo info Machine-IOB x TAB (da info registrate IOB-WIN --> MP-IO) + /// + /// + /// + public string MachIobConfVal(string IdxMacchina, string Key) + { + string answ = ""; + var currList = MachIobConf(IdxMacchina); + if (currList.ContainsKey(Key)) + { + answ = currList[Key]; + } + return answ; + } + + /// + /// Invio notifica rilettura (con parametro) + /// + /// + public void NotifyReloadRequest(string message) + { + if (ReloadRequest != null) + { + // messaggio + ReloadEventArgs rea = new ReloadEventArgs(message); + ReloadRequest.Invoke(this, rea); + } + } + /// /// Elenco ODL dato batch selezionato /// @@ -1634,6 +1747,23 @@ namespace MP.SPEC.Data return answ; } + /// + /// Reset della cache IO post operazioni come setup ODL... + /// + /// Indirizzo base da cui rimuovere memoria cache + /// + public async Task ResetIoCache(string baseMem) + { + // patterna a partire da cache IO... + RedisValue pattern = new RedisValue($"{MpIoNS}:*"); + if (!string.IsNullOrEmpty(baseMem)) + { + pattern = new RedisValue($"{MpIoNS}:{baseMem}:*"); + } + bool answ = await ExecFlushRedisPattern(pattern); + return answ; + } + /// /// Statistiche ODL calcolate (da stored stp_STAT_ODL) /// @@ -1860,10 +1990,9 @@ namespace MP.SPEC.Data #region Private Fields private static IConfiguration _configuration = null!; - private static ILogger _logger = null!; - private static Logger Log = LogManager.GetCurrentClassLogger(); + private string MpIoNS = ""; /// /// Oggetto vocabolario x uso continuo traduzione @@ -1893,6 +2022,34 @@ namespace MP.SPEC.Data #region Private Methods + /// + /// Esegue flush memoria redis dato pattern + /// + /// + /// + private async Task ExecFlushRedisPattern(RedisValue pattern) + { + bool answ = false; + var listEndpoints = redisConn.GetEndPoints(); + foreach (var endPoint in listEndpoints) + { + //var server = redisConnAdmin.GetServer(listEndpoints[0]); + var server = redisConn.GetServer(endPoint); + if (server != null) + { + var keyList = server.Keys(redisDb.Database, pattern); + foreach (var item in keyList) + { + await redisDb.KeyDeleteAsync(item); + } + answ = true; + } + } + // notifico update ai client in ascolto x reset cache + NotifyReloadRequest($"FlushRedisCache | {pattern}"); + return answ; + } + private async Task POdlFlushCache() { bool answ = false; @@ -1908,6 +2065,21 @@ namespace MP.SPEC.Data return answ; } + private string redHashMpIO(string keyName) + { + string result = keyName; + try + { + result = $"{MpIoNS}:{keyName}".Replace("\\", "_"); + } + catch (Exception exc) + { + Log.Error($"Errore in redHashMpIO{Environment.NewLine}{exc}"); + } + + return result; + } + private async Task resetCacheArticoli() { RedisValue pattern = new RedisValue($"{Utils.redisArtByDossier}:*"); diff --git a/MP.SPEC/MP.SPEC.csproj b/MP.SPEC/MP.SPEC.csproj index b99fdc7b..30e59216 100644 --- a/MP.SPEC/MP.SPEC.csproj +++ b/MP.SPEC/MP.SPEC.csproj @@ -5,7 +5,7 @@ enable enable MP.SPEC - 6.16.2410.1411 + 6.16.2410.1509 1800a78a-6ff1-40f9-b490-87fb8bfc1394 diff --git a/MP.SPEC/Program.cs b/MP.SPEC/Program.cs index af583595..b03f99b4 100644 --- a/MP.SPEC/Program.cs +++ b/MP.SPEC/Program.cs @@ -3,6 +3,7 @@ using Blazored.SessionStorage; using Microsoft.AspNetCore.Authentication.Negotiate; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; +using Microsoft.Extensions.FileProviders; using MP.SPEC.Components; using MP.SPEC.Data; using MP.SPEC.Services; @@ -15,7 +16,7 @@ var builder = WebApplication.CreateBuilder(args); /*-------------------- * Note migrazione startup.cs --> program.cs: * - * - https://stackoverflow.com/questions/69722872/asp-net-core-6-how-to-access-configuration-during-startup + * - https://stackoverflow.com/questions/69722872/asp-net-core-6-how-to-access-ConfMan-during-startup * - https://docs.microsoft.com/en-us/aspnet/core/migration/50-to-60?view=aspnetcore-5.0&tabs=visual-studio#where-do-i-put-state-that-was-stored-as-fields-in-my-program-or-startup-class * * */ @@ -32,7 +33,7 @@ ConfigurationManager configuration = builder.Configuration; // REDIS setup logger.Info("Setup REDIS"); string connStringRedis = configuration.GetConnectionString("Redis"); -//string connStringRedis = configuration.GetConnectionString("RedisAdmin"); +//string connStringRedis = ConfMan.GetConnectionString("RedisAdmin"); string redisSrvAddr = connStringRedis.Substring(0, connStringRedis.IndexOf(":")); // avvio oggetto shared x redis... var redisMultiplexer = ConnectionMultiplexer.Connect(connStringRedis); @@ -77,6 +78,22 @@ app.UseHttpsRedirection(); app.UseStaticFiles(); +// gestione static files: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/static-files?view=aspnetcore-8.0 +string BasePathOdlReturn = configuration.GetValue("ServerConf:BasePathOdlReturn") ?? configuration.GetValue("OptConf:BasePathOdlReturn") ?? ""; +if (!string.IsNullOrEmpty(BasePathOdlReturn)) +{ + // verifico esista folder + if (Directory.Exists(BasePathOdlReturn)) + { + // gestione cartella x file ritornati x ODL + app.UseStaticFiles(new StaticFileOptions + { + FileProvider = new PhysicalFileProvider(BasePathOdlReturn), + RequestPath = "/RET_DATA", + }); + } +} + app.UseRouting(); app.UseAuthentication(); diff --git a/MP.SPEC/Resources/ChangeLog.html b/MP.SPEC/Resources/ChangeLog.html index 8781b674..b588075b 100644 --- a/MP.SPEC/Resources/ChangeLog.html +++ b/MP.SPEC/Resources/ChangeLog.html @@ -1,6 +1,6 @@ Modulo MAPOSPEC -

Versione: 6.16.2410.1411

+

Versione: 6.16.2410.1509


Note di rilascio:
  • diff --git a/MP.SPEC/Resources/VersNum.txt b/MP.SPEC/Resources/VersNum.txt index ad35aa1a..a2ec8bcf 100644 --- a/MP.SPEC/Resources/VersNum.txt +++ b/MP.SPEC/Resources/VersNum.txt @@ -1 +1 @@ -6.16.2410.1411 +6.16.2410.1509 diff --git a/MP.SPEC/Resources/manifest.xml b/MP.SPEC/Resources/manifest.xml index 492b1f18..af9049bb 100644 --- a/MP.SPEC/Resources/manifest.xml +++ b/MP.SPEC/Resources/manifest.xml @@ -1,6 +1,6 @@ - 6.16.2410.1411 + 6.16.2410.1509 https://nexus.steamware.net/repository/SWS/MP-SPEC/stable/LAST/MP.SPEC.zip https://nexus.steamware.net/repository/SWS/MP-SPEC/stable/LAST/ChangeLog.html false diff --git a/MP.SPEC/appsettings.Production.json b/MP.SPEC/appsettings.Production.json index a2c661f0..3fda7d5b 100644 --- a/MP.SPEC/appsettings.Production.json +++ b/MP.SPEC/appsettings.Production.json @@ -19,6 +19,8 @@ "maxAge": "2000", "cacheCheckArtUsato": 2, "redisLongTimeCache": 15, - "MpIoBaseUrl": "http://localhost/MP/IO/" + "MpIoBaseUrl": "http://localhost/MP/IO/", + "MpIoNS": "MoonPro:SQL2016DEV:MoonPro", + "BasePathOdlReturn": "\\\\iis01\\W$\\Files\\ODL" } } diff --git a/MP.SPEC/appsettings.json b/MP.SPEC/appsettings.json index 9e519fb5..ca53c247 100644 --- a/MP.SPEC/appsettings.json +++ b/MP.SPEC/appsettings.json @@ -61,6 +61,8 @@ "maxAge": "2000", "cacheCheckArtUsato": "2", "redisLongTimeCache": "15", - "MpIoBaseUrl": "http://localhost:20967/" + "MpIoBaseUrl": "http://localhost:20967/", + "MpIoNS": "MoonPro:SQL2016DEV:MoonPro", + "BasePathOdlReturn": "\\\\iis01\\W$\\Files\\ODL" } }