Compare commits

..

51 Commits

Author SHA1 Message Date
Samuele Locatelli 4644646fa4 Merge branch 'Release/220921_FixAndNugetUpdate' 2022-09-21 14:53:05 +02:00
Samuele Locatelli c3c5300830 Nuget Update:
- nlog
- newtonsoft json
2022-09-21 14:52:25 +02:00
Samuele Locatelli ebeeab69e1 Nuget Update: dotNet framework 2022-09-21 14:50:56 +02:00
Samuele Locatelli 2a41e8070b CodeMaid
- fix componenti UI
- lasciati invariati in area wwwroot
2022-09-21 14:49:45 +02:00
Samuele Locatelli 3a5b77314a CodeMaid:
- DTO e MOdelli NON riorganizzabili
- refresh globale ordinamenti
- test rebuild
2022-09-21 14:45:57 +02:00
zaccaria.majid 16c7b0bc6b modifiche grafiche + fix paginazione 2022-09-21 14:21:22 +02:00
Samuele Locatelli 46f284ae0c Merge tag 'FirstSpecStableRelease' into develop
Prima release master con fix vari grafici + tutte le funzionalità
2022-09-21 10:36:57 +02:00
Samuele Locatelli e945aad224 Merge branch 'Release/FirstSpecStableRelease' 2022-09-21 10:36:40 +02:00
Samuele Locatelli 8510731366 Update home page 2022-09-21 10:36:29 +02:00
Samuele Locatelli 5df4195e6c Completato salvataggio snapshot + refresh 2022-09-21 10:26:09 +02:00
Samuele Locatelli a3dc1e1657 Start ver 6.16 2022-09-21 09:52:54 +02:00
Samuele Locatelli 27149e2131 Fix grafici minori 2022-09-21 09:46:44 +02:00
Samuele Locatelli 91be755781 Fix conf key redis cache:
- era overlapping parametri/dossiers
2022-09-21 09:27:00 +02:00
Samuele Locatelli 84f6730023 Merge remote-tracking branch 'origin/develop' into develop 2022-09-21 09:22:12 +02:00
zaccaria.majid b51c2679e4 aggiunta cache redis 2022-09-21 09:17:28 +02:00
zaccaria.majid 9d7502d1a4 modifiche grafiche e round orario datetime 2022-09-21 09:13:39 +02:00
zaccaria.majid d3b8160634 fix deserializzazione oggetto fluxlog 2022-09-20 17:35:45 +02:00
zaccaria.majid 601c817aa2 Modifiche grafiche 2022-09-20 17:16:42 +02:00
zaccaria.majid d0d30bd1c3 Modifiche per permettere la deserializzazione dei
valori in dossier
2022-09-20 17:16:21 +02:00
zaccaria.majid 0e9e7f3dda Creazione pagina per la visualizzazione Dossier
con relativi filtri
2022-09-20 12:54:46 +02:00
Samuele Locatelli e518c17db2 Aggiunta traccia x pagina dossiers 2022-09-20 09:03:22 +02:00
Samuele Locatelli 0a281827f9 Refresh 2022-09-19 20:01:24 +02:00
Samuele Locatelli 141473ce28 Aggiunta metodi gestione lettura dossiers da DB + refresh 2022-09-19 20:01:13 +02:00
Samuele Locatelli 45af089e3f Aggiunta preliminare modello Dossiers 2022-09-19 20:00:56 +02:00
Samuele Locatelli 4e4387620b Merge branch 'develop' of https://gitlab.steamware.net/steamware/mapo-core into develop 2022-09-19 09:58:28 +02:00
Samuele Locatelli 8c2c48a63f Fix procedura di flux dati:
- aggiunta conn tipo admin
- tolta cancellazione intero DB
- ricerca x pattern delle sole chaivi interessate
2022-09-19 09:54:30 +02:00
zaccaria.majid 534a668496 tentativo fix redis Flush 2022-09-19 09:22:29 +02:00
zaccaria.majid eed45695e8 continuo flushCache 2022-09-19 08:43:48 +02:00
zaccaria.majid ff2fbe0c34 modifiche grafiche
inizio pagina utils
2022-09-16 17:37:39 +02:00
Samuele Locatelli 3324c736c6 Minor fix 2022-09-16 16:49:19 +02:00
zaccaria.majid 0a6a0bc5cb modifiche grafiche varie 2022-09-16 16:00:13 +02:00
Samuele Locatelli e18e0ddff3 Fix last update da pagina main 2022-09-16 15:18:56 +02:00
zaccaria.majid 580a498238 tentativo fix lastUpdate 2022-09-16 14:47:31 +02:00
zaccaria.majid c97557722e Modifiche grafiche 2022-09-16 14:22:23 +02:00
zaccaria.majid c17fa17d76 fix filtri aggiunta titles 2022-09-16 12:40:18 +02:00
zaccaria.majid 5b054ee2ec fix last snapshot che non veniva
scritto al primo giro
2022-09-16 11:55:23 +02:00
zaccaria.majid 2771d9957d Merge branch 'develop' of https://gitlab.steamware.net/steamware/mapo-core into develop 2022-09-16 11:47:43 +02:00
zaccaria.majid 5893152761 aggiornamento grafico filtri 2022-09-16 11:47:35 +02:00
Samuele Locatelli b7d57e935a COmpletato fix version number 2022-09-16 11:21:03 +02:00
Samuele Locatelli 61b613a8fb Fix proj config x calcolo versione 2022-09-16 11:19:26 +02:00
Samuele Locatelli d2fef81f55 Merge remote-tracking branch 'origin/develop' into develop 2022-09-16 11:17:33 +02:00
Samuele Locatelli cd7a8ccad8 Fix x display numero versione 2022-09-16 11:17:28 +02:00
zaccaria.majid 08079d3e0e Merge branch 'develop' of https://gitlab.steamware.net/steamware/mapo-core into develop 2022-09-16 10:51:19 +02:00
zaccaria.majid 8156828ec3 fix bottone filtri avanzati 2022-09-16 10:44:45 +02:00
Samuele Locatelli 9bb95c5a49 Merge tag 'FixMasterDeploy' into develop
Fix deploy IIS x icone, errore cancellazione, log
2022-09-16 10:37:26 +02:00
Samuele Locatelli 7ba3aeb65d Merge branch 'Release/FixMasterDeploy' 2022-09-16 10:37:10 +02:00
Samuele Locatelli 6ea938a91a Aggiunta web.config x windows auth 2022-09-16 10:36:25 +02:00
Samuele Locatelli 92c196023d fix posizione img home page 2022-09-16 10:33:13 +02:00
Samuele Locatelli 10d9625b6d fix articoli:
- tolto refuso cancellazione csv temp appoggio
2022-09-16 10:33:03 +02:00
Samuele Locatelli 5f955499e2 Fix file favicon e logfolder 2022-09-16 10:32:47 +02:00
Samuele Locatelli 716813abe1 Merge tag 'AddSpecInstaller' into develop
Aggiornamento x generazione installer SPEC su nexus
2022-09-16 09:13:19 +02:00
84 changed files with 1470 additions and 735 deletions
+6 -6
View File
@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
namespace MP.Data.Conf
{
@@ -11,9 +7,13 @@ namespace MP.Data.Conf
/// </summary>
public class IobTags
{
#region Public Fields
/// <summary>
/// Oggetto dizionario di configurazione x IOB
/// </summary>
public Dictionary<string, List<TagData>> IobSetup = new Dictionary<string, List<TagData>>();
#endregion Public Fields
}
}
}
+18 -12
View File
@@ -1,37 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MP.Data.Conf
namespace MP.Data.Conf
{
/// <summary>
/// Item da mostrare nei blocchi MON degli impianti come override ai dati MSE
/// </summary>
public class TagData
{
#region Public Properties
/// <summary>
/// Indice della colonna (ordine) del dato
/// </summary>
public int ColNum { get; set; } = 0;
/// <summary>
/// Indice della riga del dato
/// </summary>
public int RowNum { get; set; } = 0;
/// <summary>
/// Override CSS (es fontSmall)
/// </summary>
public string TagCss { get; set; } = "";
/// <summary>
/// Etichetta da mostrare
/// </summary>
public string TagName { get; set; } = "";
/// <summary>
/// Indicazione della chiave REDIS dove recuperare il tag indicato (già in formato string)
/// </summary>
public string TagLocation { get; set; } = "";
/// <summary>
/// Etichetta da mostrare
/// </summary>
public string TagName { get; set; } = "";
#endregion Public Properties
#region Public Methods
/// <summary>
/// Clone dell'oggetto
/// </summary>
@@ -40,5 +44,7 @@ namespace MP.Data.Conf
{
return (TagData)this.MemberwiseClone();
}
#endregion Public Methods
}
}
}
+10 -12
View File
@@ -1,21 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MP.Data
namespace MP.Data
{
public class Constants
public class Constants
{
#region Public Fields
public static readonly string ACT_BLINK_KEY = $"{BASE_HASH}:Current:Blink";
public static readonly string ACT_MSE_DATA_KEY = $"{BASE_HASH}:Current:MSE";
// dati conf REDIS Cache
public static readonly string BASE_HASH = "MAPO";
// REDIS KEY Dati correnti
public static readonly string CONF_MON_KEY = $"{BASE_HASH}:Conf:MonDispData";
public static readonly string ACT_MSE_DATA_KEY = $"{BASE_HASH}:Current:MSE";
public static readonly string ACT_BLINK_KEY = $"{BASE_HASH}:Current:Blink";
#endregion Public Fields
}
}
}
+40
View File
@@ -277,6 +277,46 @@ namespace MP.Data.Controllers
{
}
/// <summary>
/// Elenco ultimi n record DOssiers (che contengono ad esempio "salvataggi" di FLuxLog) dato
/// macchina (ordinato x data registrazione)
/// </summary>
/// <param name="IdxMacchina">* = tutte, altrimenti solo x una data macchina</param>
/// <param name="DtRef">Data di riferimento (Massima) per estrazioen records</param>
/// <param name="MaxRec">numero massimo record da restituire</param>
/// <returns></returns>
public List<DatabaseModels.Dossiers> DossiersGetLastFilt(string IdxMacchina, DateTime DtRef, int MaxRec)
{
List<DatabaseModels.Dossiers> dbResult = new List<DatabaseModels.Dossiers>();
using (var dbCtx = new MoonProContext(_configuration))
{
dbResult = dbCtx
.DbSetDossiers
.AsNoTracking()
.Where(x => (IdxMacchina == "*" || x.IdxMacchina == IdxMacchina) && x.DtRif <= DtRef)
.OrderByDescending(x => x.DtRif)
.Take(MaxRec)
.ToList();
}
return dbResult;
}
public bool DossiersTakeParamsSnapshot(string idxMacchina, int maxSec)
{
bool answ = false;
using (var dbCtx = new MoonProContext(_configuration))
{
var pIdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina);
var pMaxSec = new SqlParameter("@MaxSec", maxSec);
var dbResult = dbCtx
.Database
.ExecuteSqlRaw("EXEC stp_FL_TakeSnapshot @IdxMacchina,@MaxSec", pIdxMacchina, pMaxSec);
answ = true;
}
return answ;
}
/// <summary>
/// Elenco valori link (x home e navMenu laterale)
/// </summary>
+8 -8
View File
@@ -10,14 +10,6 @@ namespace MP.Data.Controllers
{
public class MpStatsController : IDisposable
{
#region Private Fields
private static IConfiguration _configuration;
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
#endregion Private Fields
#region Public Constructors
public MpStatsController(IConfiguration configuration)
@@ -326,5 +318,13 @@ namespace MP.Data.Controllers
}
#endregion Public Methods
#region Private Fields
private static IConfiguration _configuration;
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
#endregion Private Fields
}
}
+18
View File
@@ -0,0 +1,18 @@
using MP.Data.DatabaseModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data.DTO
{
public class DossierFluxLogDTO
{
public List<FluxLog> ODL { get; set; } = new List<FluxLog>();
}
}
+3 -1
View File
@@ -3,7 +3,9 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data.DatabaseModels
{
[Table("AnagArticoli")]
+3 -1
View File
@@ -4,7 +4,9 @@ using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data.DatabaseModels
{
[Table("AnagraficaGruppi")]
+3 -1
View File
@@ -2,7 +2,9 @@
using System.Collections.Generic;
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data.DatabaseModels
{
public partial class AzioniUL
+4
View File
@@ -2,6 +2,10 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data.DatabaseModels
{
[Table("Config")]
+3
View File
@@ -4,6 +4,9 @@ using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data.DatabaseModels
{
+30
View File
@@ -0,0 +1,30 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data.DatabaseModels
{
[Table("Dossiers")]
public partial class Dossiers
{
#region Public Properties
[MaxLength(50)]
public string DataType { get; set; }
public DateTime DtRif { get; set; }
[MaxLength(50)]
public string IdxMacchina { get; set; }
public int IdxODL { get; set; }
public string Valore { get; set; }
#endregion Public Properties
}
}
+4 -1
View File
@@ -2,8 +2,11 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
#nullable disable
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data.DatabaseModels
{
[Table("FluxLog")]
+4 -1
View File
@@ -3,8 +3,11 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
#nullable disable
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data.DatabaseModels
{
[Table("LinkMenuJQM")]
+4 -1
View File
@@ -1,8 +1,11 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
#nullable disable
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data.DatabaseModels
{
[Table("ListValues")]
+4 -1
View File
@@ -1,8 +1,11 @@
using System;
using System.Collections.Generic;
#nullable disable
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data.DatabaseModels
{
public partial class Macchine
+4
View File
@@ -1,6 +1,10 @@
using System;
using System.Collections.Generic;
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data.DatabaseModels
{
public partial class MappaStatoExpl
+4 -1
View File
@@ -3,8 +3,11 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
#nullable disable
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data.DatabaseModels
{
[Table("ODL")]
+4 -1
View File
@@ -3,8 +3,11 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
#nullable disable
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data.DatabaseModels
{
[Table("PromesseODL")]
+4 -1
View File
@@ -1,8 +1,11 @@
using System;
using System.Collections.Generic;
#nullable disable
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data.DatabaseModels
{
public partial class ResControlli
+4 -1
View File
@@ -1,8 +1,11 @@
using System;
using System.Collections.Generic;
#nullable disable
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data.DatabaseModels
{
public partial class ResScarti
+4 -1
View File
@@ -1,8 +1,11 @@
using System;
using System.Collections.Generic;
#nullable disable
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data.DatabaseModels
{
public partial class StatsAnagArticoli
+4 -1
View File
@@ -1,8 +1,11 @@
using System;
using System.Collections.Generic;
#nullable disable
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data.DatabaseModels
{
public partial class StatsODL
+4 -1
View File
@@ -3,8 +3,11 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
#nullable disable
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data.DatabaseModels
{
public partial class TurniOee
+4 -1
View File
@@ -1,8 +1,11 @@
using System;
using System.Collections.Generic;
#nullable disable
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data.DatabaseModels
{
public partial class UserActionLog
+6 -6
View File
@@ -12,14 +12,14 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.7">
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="6.0.7" />
<PackageReference Include="NLog" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="6.0.9" />
<PackageReference Include="NLog" Version="5.0.4" />
</ItemGroup>
</Project>
+46 -50
View File
@@ -1,29 +1,11 @@
using NLog;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MP.Data
{
public class MessagePipe
{
#region Private Fields
private bool enableLog = false;
private IConnectionMultiplexer redis;
private IDatabase? redisDb;
#endregion Private Fields
#region Protected Fields
protected static Logger Log = LogManager.GetCurrentClassLogger();
#endregion Protected Fields
#region Public Constructors
public MessagePipe(IConnectionMultiplexer redisConn, string channelName, bool enableLog = false)
@@ -44,37 +26,6 @@ namespace MP.Data
#endregion Public Events
#region Private Properties
/// <summary>
/// Canale associato al gestore pipeline messaggi
/// </summary>
private string _channel { get; set; } = "";
#endregion Private Properties
#region Private Methods
private void setupSubscriber()
{
ISubscriber sub = redis.GetSubscriber();
//Subscribe to the channel named messages
sub.Subscribe(_channel, (channel, message) =>
{
Log.Trace($"ch {channel} | {message}");
// messaggio
PubSubEventArgs mea = new PubSubEventArgs(message);
// se qualcuno ascolta sollevo evento nuovo valore...
if (EA_NewMessage != null)
{
EA_NewMessage(this, mea);
}
});
Log.Info($"Subscribed {_channel}");
}
#endregion Private Methods
#region Public Methods
public bool saveAndSendMessage(string memKey, string message)
@@ -108,6 +59,51 @@ namespace MP.Data
#endregion Public Methods
#region Protected Fields
protected static Logger Log = LogManager.GetCurrentClassLogger();
#endregion Protected Fields
#region Private Fields
private bool enableLog = false;
private IConnectionMultiplexer redis;
private IDatabase? redisDb;
#endregion Private Fields
#region Private Properties
/// <summary>
/// Canale associato al gestore pipeline messaggi
/// </summary>
private string _channel { get; set; } = "";
#endregion Private Properties
#region Private Methods
private void setupSubscriber()
{
ISubscriber sub = redis.GetSubscriber();
//Subscribe to the channel named messages
sub.Subscribe(_channel, (channel, message) =>
{
Log.Trace($"ch {channel} | {message}");
// messaggio
PubSubEventArgs mea = new PubSubEventArgs(message);
// se qualcuno ascolta sollevo evento nuovo valore...
if (EA_NewMessage != null)
{
EA_NewMessage(this, mea);
}
});
Log.Info($"Subscribed {_channel}");
}
#endregion Private Methods
/// <summary>
/// Invio messaggio sul canale + salvataggio in cache REDIS
/// </summary>
@@ -132,4 +128,4 @@ namespace MP.Data
#endregion Public Properties
}
}
}
+10 -2
View File
@@ -6,7 +6,9 @@ using MP.Data.DatabaseModels;
using NLog;
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data
{
public partial class MoonProContext : DbContext
@@ -45,6 +47,7 @@ namespace MP.Data
public virtual DbSet<ODLModel> DbSetODL { get; set; }
public virtual DbSet<PODLModel> DbSetPODL { get; set; }
public virtual DbSet<FluxLog> DbSetFluxLog { get; set; }
public virtual DbSet<Dossiers> DbSetDossiers { get; set; }
#endregion Public Properties
@@ -291,7 +294,12 @@ namespace MP.Data
});
modelBuilder.Entity<FluxLog>(entity =>
{
entity.HasKey(e => new { e.IdxMacchina, e.dtEvento, e.CodFlux});
entity.HasKey(e => new { e.IdxMacchina, e.dtEvento, e.CodFlux });
});
modelBuilder.Entity<Dossiers>(entity =>
{
entity.HasKey(e => new { e.IdxMacchina, e.DtRif });
});
+3 -1
View File
@@ -6,7 +6,9 @@ using MP.Data.DatabaseModels;
using NLog;
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data
{
public partial class MoonPro_STATSContext : DbContext
+30 -25
View File
@@ -3,13 +3,26 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MP.Data
{
public class Utils
{
#region Public Properties
public static string redKeyArtUsed
{
get => RedHash($"CACHE:CheckArtUsed");
}
public static string redKeyTabCheckArt
{
get => RedHash($"CACHE:TabCheckArt");
}
#endregion Public Properties
#region Public Methods
public static string ConvMinToTime(double minutes)
@@ -28,6 +41,22 @@ namespace MP.Data
return answ;
}
/// <summary>
/// Nome della variabile HASH da utilizzare (dato CodModulo / Server / DB impiegato da
/// funzionalita' DbConfig) + keyName richiesto...
/// </summary>
public static string RedHash(string keyName)
{
string answ = keyName;
try
{
answ = $"MP:Data:{keyName}";
}
catch
{ }
return answ;
}
public static async Task SaveToCsv<T>(List<T> reportData, string path)
{
var lines = new List<string>();
@@ -39,30 +68,6 @@ namespace MP.Data
await Task.Run(() => File.WriteAllLines(path, lines.ToArray()));
}
public static string redKeyArtUsed
{
get => RedHash($"CACHE:CheckArtUsed");
}
public static string redKeyTabCheckArt
{
get => RedHash($"CACHE:TabCheckArt");
}
/// <summary>
/// Nome della variabile HASH da utilizzare (dato CodModulo / Server / DB impiegato da funzionalita' DbConfig) + keyName richiesto...
/// </summary>
public static string RedHash(string keyName)
{
string answ = keyName;
try
{
answ =$"MP:Data:{keyName}";
}
catch
{ }
return answ;
}
#endregion Public Methods
}
}
+1 -1
View File
@@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>MP.Prog</RootNamespace>
<Version>6.15.2202.2715</Version>
<Version>6.15.2209.1609</Version>
</PropertyGroup>
<ItemGroup>
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>Modulo gestione Programmi MAPO</i>
<h4>Versione: 6.15.2202.2715</h4>
<h4>Versione: 6.15.2209.1609</h4>
<br />
Note di rilascio:
<ul>
+1 -1
View File
@@ -1 +1 @@
6.15.2202.2715
6.15.2209.1609
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>6.15.2202.2715</version>
<version>6.15.2209.1609</version>
<url>https://nexus.steamware.net/repository/SWS/MP-PROG/stable/LAST/MP.Prog.zip</url>
<changelog>https://nexus.steamware.net/repository/SWS/MP-PROG/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>
+6 -2
View File
@@ -8,7 +8,7 @@ namespace MP.SPEC.Components
public void Dispose()
{
//aTimer.Elapsed -= ElapsedTimer;
aTimer.Elapsed -= ElapsedTimer;
aTimer.Stop();
aTimer.Dispose();
}
@@ -21,7 +21,6 @@ namespace MP.SPEC.Components
await InvokeAsync(() => StateHasChanged());
});
pUpd.Wait();
//Log.Trace($"Elapsed Timer Footer");
}
public void StartTimer()
@@ -38,6 +37,11 @@ namespace MP.SPEC.Components
#region Protected Methods
protected override void OnInitialized()
{
version = typeof(Program).Assembly.GetName().Version;
}
#endregion Protected Methods
#region Private Fields
+1 -2
View File
@@ -43,7 +43,6 @@
}
private async void MService_EA_ShowSearch()
{
//await forceReload();
await Task.Delay(1);
await InvokeAsync(() => StateHasChanged());
}
@@ -54,7 +53,7 @@
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
var user = authState.User;
if (user.Identity.IsAuthenticated)
if (user.Identity != null&& user.Identity.IsAuthenticated)
{
userName = $"{user.Identity.Name}";
}
+10 -6
View File
@@ -23,12 +23,6 @@ namespace MP.SPEC.Components
}
}
}
public async Task resetCurrPage()
{
await Task.Delay(1);
currPage = 1;
}
[Parameter]
public EventCallback<int> numPageChanged { get; set; }
@@ -82,6 +76,16 @@ namespace MP.SPEC.Components
#endregion Public Properties
#region Public Methods
public async Task resetCurrPage()
{
await Task.Delay(1);
currPage = 1;
}
#endregion Public Methods
#region Protected Fields
protected bool _showLoading = false;
+30
View File
@@ -0,0 +1,30 @@
<div class="d-flex justify-content-between">
<div class="px-0 py-1">
</div>
<div class="px-0 col-6">
<div class="">
<div class="px-0 py-1">
<div class="px-2 input-group" id="basic-addon1">
<label class="input-group-text" for="macchina" title="Selezionare la macchina"><i class="fa-solid fa-hard-drive"></i></label>
<select @bind="@selMacchina" class="form-select" id="macchina" title="Selezionare la macchina">
<option value="*">--- Tutti ---</option>
@if (ListMacchine != null)
{
foreach (var item in ListMacchine)
{
<option value="@item">@item</option>
}
}
</select>
<label class="input-group-text" for="DtRef" title="Selezionare la data da visualizzare"><i class="fa-solid fa-calendar-check"></i></label>
<input @bind="@selDtRef" id="DtRef" class="form-control" type="datetime-local" title="Selezionare la data da visualizzare" />
</div>
</div>
</div>
</div>
</div>
+118
View File
@@ -0,0 +1,118 @@
using Microsoft.AspNetCore.Components;
using MP.Data.DatabaseModels;
using MP.SPEC.Data;
namespace MP.SPEC.Components
{
public partial class DossiersFilter
{
#region Public Properties
[Parameter]
public EventCallback<SelectDossierParams> FilterChanged { get; set; }
[Parameter]
public SelectDossierParams SelFilterDossier { get; set; } = null!;
#endregion Public Properties
#region Protected Properties
[Inject]
protected MpDataService MDService { get; set; } = null!;
protected DateTime selDtRef
{
get
{
return SelFilterDossier.DtRef;
}
set
{
if (!SelFilterDossier.DtRef.Equals(value))
{
SelFilterDossier.DtRef = value;
reportChange();
}
}
}
protected string selMacchina
{
get
{
return SelFilterDossier.IdxMacchina;
}
set
{
if (!SelFilterDossier.IdxMacchina.Equals(value))
{
SelFilterDossier.CurrPage = 1;
SelFilterDossier.IdxMacchina = value;
StateHasChanged();
Task.Delay(1);
reportChange();
}
}
}
protected int selMaxRecord
{
get
{
return SelFilterDossier.MaxRecord;
}
set
{
if (!SelFilterDossier.MaxRecord.Equals(value))
{
SelFilterDossier.MaxRecord = value;
reportChange();
}
}
}
#endregion Protected Properties
#region Protected Methods
protected override async Task OnInitializedAsync()
{
SelFilterDossier = new SelectDossierParams();
ListMacchine = await MDService.MacchineWithFlux();
ListDossier = await MDService.DossiersGetLastFilt(selMacchina, selDtRef, selMaxRecord);
await FilterChanged.InvokeAsync(SelFilterDossier);
}
protected void toggleParams()
{
showEditPar = !showEditPar;
}
#endregion Protected Methods
#region Private Fields
private List<Dossiers>? ListDossier = null;
private List<string>? ListMacchine = null;
#endregion Private Fields
#region Private Properties
private bool showEditPar { get; set; } = false;
#endregion Private Properties
#region Private Methods
private void reportChange()
{
FilterChanged.InvokeAsync(SelFilterDossier);
}
#endregion Private Methods
}
}
+100
View File
@@ -0,0 +1,100 @@
@using MP.SPEC.Components
@using MP.SPEC.Data
@if (ListRecords == null)
{
<LoadingData></LoadingData>
}
else if (totalCount == 0)
{
<div class="alert alert-warning text-center display-4">Nessun record trovato</div>
}
else
{
<div class="row">
<div class="d-flex justify justify-content-between">
<table class="table table-sm table-striped small">
<thead>
<tr>
<th>
<button @onclick="() => unToggleTableFlux()" class="btn btn-primary btn-sm"><i class="bi bi-arrow-counterclockwise"></i></button>
</th>
<th><i class="fa-solid fa-hard-drive"></i> Macchina</th>
<th><i class="fa-regular fa-calendar-days"></i> Data</th>
<th><i class="fa-solid fa-sliders"></i> ODL</th>
<th><i class="fa-solid fa-circle-info"></i> DATA TYPE</th>
</tr>
</thead>
<tbody>
@foreach (var record in ListRecords)
{
<tr class="@checkSelect(@record)">
<td>
<button class="btn btn-primary btn-sm" @onclick="() => selRecord(record)"><i class="fa-solid fa-magnifying-glass"></i></button>
</td>
<td>
@record.IdxMacchina
</td>
<td>
@record.DtRif
</td>
<td>
@record.IdxODL
</td>
<td>
@record.DataType
</td>
</tr>
}
</tbody>
</table>
@if (!visualizzaFlux)
{
if (listaFlux == null)
{
<div class="alert alert-warning text-center display-4">Nessun record trovato</div>
}
else
{
<div class="table selBlock p-2">
<table class="table table-light table-sm table-striped small mb-0">
<thead>
<tr>
<th><i class="fa-solid fa-hard-drive"></i> Macchina</th>
<th><i class="fa-regular fa-calendar-days"></i> Data</th>
<th><i class="fa-solid fa-sliders"></i> ODL</th>
<th class="d-flex justify-content-between"> Valore <button class="btn btn-primary btn-sm py-0" @onclick="() => unToggleTableFlux()"><i class="fa-solid fa-xmark"></i></button></th>
</tr>
</thead>
<tbody>
@foreach (var record in listaFlux)
{
<tr>
<td>
@record.IdxMacchina
</td>
<td>
@record.dtEvento
</td>
<td>
@record.CodFlux
</td>
<td style="text-align: right;">
<b>@record.Valore</b>
</td>
</tr>
}
</tbody>
</table>
</div>
}
}
</div>
</div>
}
+197
View File
@@ -0,0 +1,197 @@
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using MP.Data.DatabaseModels;
using MP.SPEC.Data;
namespace MP.SPEC.Components
{
public partial class ListDossiers
{
#region Public Properties
[Parameter]
public EventCallback<Dossiers> RecordSel { get; set; }
[Parameter]
public SelectDossierParams SelFilter { get; set; } = null!;
[Parameter]
public EventCallback<int> TotRecordChanged { get; set; }
#endregion Public Properties
#region Public Methods
public string checkSelect(Dossiers recordSel)
{
string answ = "";
if (currRecord != null)
{
try
{
answ = (currRecord.IdxMacchina == recordSel.IdxMacchina && currRecord.DtRif == recordSel.DtRif) ? "table-info" : "";
}
catch
{ }
}
return answ;
}
public async Task reloadData(bool setChanged)
{
isLoading = true;
SearchRecords = await MDService.DossiersGetLastFilt(SelMacchina, SelDtRef, MaxRecord);
totalCount = SearchRecords.Count;
ListRecords = SearchRecords.Skip(numRecord * (currPage - 1)).Take(numRecord).ToList();
await Task.Delay(1);
if (setChanged)
{
await InvokeAsync(() => StateHasChanged());
}
isLoading = false;
}
#endregion Public Methods
#region Protected Properties
[Inject]
protected IJSRuntime JSRuntime { get; set; } = null!;
[Inject]
protected MpDataService MDService { get; set; } = null!;
[Inject]
protected MessageService MessageService { get; set; } = null!;
#endregion Protected Properties
#region Protected Methods
protected override async Task OnInitializedAsync()
{
MessageService.EA_PageUpdated += MessageService_EA_PageUpdated;
MessageService.EA_SearchUpdated += OnSeachUpdated;
ListRecords = await MDService.DossiersGetLastFilt(SelMacchina, SelDtRef, MaxRecord);
await reloadData();
}
protected async void OnSeachUpdated()
{
await InvokeAsync(() =>
{
currPage = 1;
StateHasChanged();
});
}
protected async Task selRecord(Dossiers selRec)
{
currRecord = selRec;
await RecordSel.InvokeAsync(selRec);
listaFlux = MDService.convertToFluxLog(selRec.Valore);
await toggleTableFlux();
}
protected async Task UpdateData()
{
currRecord = null;
await reloadData(true);
}
#endregion Protected Methods
#region Private Fields
private int _totalCount = 0;
private Dossiers? currRecord = null;
private List<Dossiers>? ListRecords;
private List<Dossiers>? SearchRecords;
#endregion Private Fields
#region Private Properties
private int currPage
{
get => MessageService.currPage;
set => MessageService.currPage = value;
}
private bool isLoading { get; set; } = false;
private List<FluxLog>? listaFlux { get; set; } = null;
private int MaxRecord
{
get => SelFilter.MaxRecord;
}
private int numRecord
{
get => MessageService.numRecord;
set => MessageService.numRecord = value;
}
private DateTime SelDtRef
{
get => SelFilter.DtRef;
}
private string SelMacchina
{
get => SelFilter.IdxMacchina;
}
private int totalCount
{
get => _totalCount;
set
{
if (_totalCount != value)
{
_totalCount = value;
TotRecordChanged.InvokeAsync(value);
}
}
}
private bool visualizzaFlux { get; set; } = true;
#endregion Private Properties
#region Private Methods
private async void MessageService_EA_PageUpdated()
{
await reloadData();
}
private async Task reloadData()
{
isLoading = true;
SearchRecords = await MDService.DossiersGetLastFilt(SelMacchina, SelDtRef, MaxRecord);
totalCount = SearchRecords.Count;
ListRecords = SearchRecords.Skip(numRecord * (currPage - 1)).Take(numRecord).ToList();
await Task.Delay(1);
await InvokeAsync(() => StateHasChanged());
isLoading = false;
}
private async Task toggleTableFlux()
{
visualizzaFlux = false;
await Task.Delay(1);
}
private async Task unToggleTableFlux()
{
currRecord = null;
visualizzaFlux = true;
await Task.Delay(1);
}
#endregion Private Methods
}
}
+6 -6
View File
@@ -19,13 +19,13 @@ else
<th>
@*<button @onclick="() => resetSel()" class="btn btn-primary btn-sm"><i class="bi bi-arrow-counterclockwise"></i></button>*@
</th>
<th>Articolo</th>
<th>Macchina</th>
<th><i class="fa-solid fa-file"></i> Articolo</th>
<th><i class="fa-solid fa-hard-drive"></i> Macchina</th>
<th># pz</th>
<th>T.Ciclo</th>
<th>Inizio</th>
<th>Note</th>
<th>Richiesta</th>
<th><i class="fa-solid fa-clock"></i> T.Ciclo</th>
<th><i class="fa-solid fa-play"></i> Inizio</th>
<th><i class="fa-solid fa-pen-to-square"></i> Note</th>
<th><i class="fa-solid fa-code-pull-request"></i> Richiesta</th>
<th></th>
</tr>
</thead>
+3 -3
View File
@@ -19,9 +19,9 @@ else
<th>
@*<button @onclick="() => resetSel()" class="btn btn-primary btn-sm"><i class="bi bi-arrow-counterclockwise"></i></button>*@
</th>
<th>Data</th>
<th>Macchina</th>
<th>Parametro</th>
<th><i class="fa-regular fa-calendar-days"></i> Data</th>
<th><i class="fa-solid fa-hard-drive"></i> Macchina</th>
<th><i class="fa-solid fa-sliders"></i> Parametro</th>
<th style="text-align: right">Valore</th>
<th></th>
</tr>
+2 -1
View File
@@ -111,10 +111,11 @@ namespace MP.SPEC.Components
{
get => SelFilter.TempoAgg;
}
//protected int RefreshPeriod { get; set; } = 5000;
#endregion Protected Properties
//protected int RefreshPeriod { get; set; } = 5000;
#region Protected Methods
protected override async Task OnInitializedAsync()
+5 -5
View File
@@ -19,12 +19,12 @@ else
<th>
<button @onclick="() => resetSel()" class="btn btn-primary btn-sm"><i class="bi bi-arrow-counterclockwise"></i></button>
</th>
<th>Articolo</th>
<th>Fase</th>
<th>Macchina</th>
<th><i class="fa-solid fa-file"></i> Articolo</th>
<th><i class="fa-solid fa-screwdriver-wrench"></i> Fase</th>
<th><i class="fa-solid fa-hard-drive"></i> Macchina</th>
<th># pz</th>
<th>T.Ciclo</th>
<th>Note</th>
<th><i class="fa-solid fa-clock"></i> T.Ciclo</th>
<th><i class="fa-solid fa-pen-to-square"></i> Note</th>
<th></th>
</tr>
</thead>
+43 -47
View File
@@ -12,7 +12,6 @@ namespace MP.SPEC.Components
[Parameter]
public EventCallback<bool> PagerResetReq { get; set; }
[Parameter]
public EventCallback<PODLModel> RecordSel { get; set; }
@@ -35,38 +34,6 @@ namespace MP.SPEC.Components
return answ;
}
protected async Task resetSel()
{
await RecordSel.InvokeAsync(null);
}
protected bool POdlDelEnabled(int idxOdl)
{
return idxOdl == 0;
}
protected async Task selRecord(PODLModel selRec)
{
await RecordSel.InvokeAsync(selRec);
}
/// <summary>
/// Eliminazione record selezioanto (previa conferma)
/// </summary>
/// <param name="selRec"></param>
/// <returns></returns>
protected async Task deleteRecord(PODLModel selRec)
{
if (!await JSRuntime.InvokeAsync<bool>("confirm", "Eliminazione Record: sei sicuro di voler procedere?"))
return;
await Task.Delay(1);
var done = await MDService.PODLDeleteRecord(selRec);
currRecord = null;
await reloadData();
await Task.Delay(1);
}
#endregion Public Methods
#region Protected Properties
@@ -84,6 +51,22 @@ namespace MP.SPEC.Components
#region Protected Methods
/// <summary>
/// Eliminazione record selezioanto (previa conferma)
/// </summary>
/// <param name="selRec"></param>
/// <returns></returns>
protected async Task deleteRecord(PODLModel selRec)
{
if (!await JSRuntime.InvokeAsync<bool>("confirm", "Eliminazione Record: sei sicuro di voler procedere?"))
return;
await Task.Delay(1);
var done = await MDService.PODLDeleteRecord(selRec);
currRecord = null;
await reloadData();
await Task.Delay(1);
}
protected override async Task OnInitializedAsync()
{
MsgService.EA_PageUpdated += MessageService_EA_PageUpdated;
@@ -104,6 +87,21 @@ namespace MP.SPEC.Components
});
}
protected bool POdlDelEnabled(int idxOdl)
{
return idxOdl == 0;
}
protected async Task resetSel()
{
await RecordSel.InvokeAsync(null);
}
protected async Task selRecord(PODLModel selRec)
{
await RecordSel.InvokeAsync(selRec);
}
protected async Task UpdateData()
{
currRecord = null;
@@ -118,6 +116,7 @@ namespace MP.SPEC.Components
private List<PODLModel>? ListRecords;
private List<ListValues>? ListStati;
private List<PODLModel>? SearchRecords;
#endregion Private Fields
@@ -175,6 +174,17 @@ namespace MP.SPEC.Components
});
}
private async Task reloadData()
{
isLoading = true;
SearchRecords = await MDService.ListPODLFilt(SearchVal, StatoSel);
totalCount = SearchRecords.Count;
ListRecords = SearchRecords.Skip(numRecord * (currPage - 1)).Take(numRecord).ToList();
await Task.Delay(1);
await InvokeAsync(() => StateHasChanged());
isLoading = false;
}
private string tradFase(string codFase)
{
string answ = codFase;
@@ -189,20 +199,6 @@ namespace MP.SPEC.Components
return answ;
}
private List<ListValues>? ListStati;
private async Task reloadData()
{
isLoading = true;
SearchRecords = await MDService.ListPODLFilt(SearchVal, StatoSel);
totalCount = SearchRecords.Count;
ListRecords = SearchRecords.Skip(numRecord * (currPage - 1)).Take(numRecord).ToList();
await Task.Delay(1);
await InvokeAsync(() => StateHasChanged());
isLoading = false;
}
#endregion Private Methods
}
}
+59 -42
View File
@@ -1,29 +1,44 @@
<div class="d-flex justify-content-between">
<div class="px-0">
@if (!liveUpdate)
{
<button class="btn btn-secondary" type="button" @onclick="() => toggleUpdate()">
<small>@lastUpdate</small>
</button>
}
else
{
<button class="btn btn-primary" type="button" @onclick="() => toggleUpdate()">
<span class="spinner-grow spinner-grow-sm" role="status" aria-hidden="true"></span>
Valori live
</button>
}
<div class="px-0 py-1">
<div class="d-flex justify-content-between">
<div class="px-2">
@if (!liveUpdate)
{
<button class="btn btn-secondary" type="button" @onclick="() => toggleUpdate()">
<small>@lastUpdate</small>
</button>
}
else
{
<button class="btn btn-primary" type="button" @onclick="() => toggleUpdate()">
<span class="spinner-grow spinner-grow-sm" role="status" aria-hidden="true"></span>
Valori live
</button>
}
</div>
<div class="px-2">
@if (selMacchina != "*")
{
<button class="btn btn-warning" type="button" @onclick="() => takeSnapshot()">
<i class="fa-solid fa-camera"></i>
Registra
</button>
}
</div>
</div>
</div>
<div class="px-0">
<div class="d-flex justify-content-end">
@if (showEditPar)
{
<div class="px-2">
<div class="px-0 input-group py-1" id="basic-addon1">
<button class="btn btn-primary" @onclick="() => toggleParams()"> <i class="fa-solid fa-arrow-right"></i></button>
</div>
<div class="px-2">
<select @bind="@selTempoAgg" class="form-select">
<label class="input-group-text" for="tempoAgg" title="Selezionare il tempo di aggiornamento dei dati"><i class="fa-solid fa-clock"></i></label>
<select @bind="@selTempoAgg" class="form-select" id="tempoAgg" title="Selezionare il tempo di aggiornamento dei dati" style="width: 3em;">
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
@@ -44,9 +59,8 @@
<option value="19">19</option>
<option value="20">20</option>
</select>
</div>
<div class="px-2">
<select @bind="@selMaxRecord" class="form-select">
<label class="input-group-text" for="maxRecord" title="Selezionare il numero massimo di record da visualizzare"><i class="fa-solid fa-list-ol"></i></label>
<select @bind="@selMaxRecord" class="form-select" id="maxRecord" title="Selezionare il numero massimo di record da visualizzare">
<option value="50">50</option>
<option value="100">100</option>
<option value="150">150</option>
@@ -62,34 +76,37 @@
}
else
{
<div class="px-2">
<div class="px-2 py-1">
<button class="btn btn-primary" @onclick="() => toggleParams()"><i class="fa-solid fa-arrow-left"></i></button>
</div>
}
<div class="px-2">
<select @bind="@selMacchina" class="form-select">
<option value="*">--- Tutti ---</option>
@if (ListMacchine != null)
{
foreach (var item in ListMacchine)
<div class="px-0 py-1">
<div class="px-2 input-group" id="basic-addon1">
<label class="input-group-text" for="macchina" title="Selezionare la macchina"><i class="fa-solid fa-hard-drive"></i></label>
<select @bind="@selMacchina" class="form-select" id="macchina" title="Selezionare la macchina">
<option value="*">--- Tutti ---</option>
@if (ListMacchine != null)
{
<option value="@item">@item</option>
foreach (var item in ListMacchine)
{
<option value="@item">@item</option>
}
}
}
</select>
</div>
<div class="px-2">
<select @bind="@selFlux" class="form-select">
<option value="*">--- Tutti ---</option>
@if (ListFlux != null)
{
foreach (var item in ListFlux)
</select>
<label class="input-group-text" for="flusso" title="Selezionare il tipo di flusso"><i class="fa-solid fa-sliders"></i></label>
<select @bind="@selFlux" class="form-select" id="flusso" title="Selezionare il tipo di flusso">
<option value="*">--- Tutti ---</option>
@if (ListFlux != null)
{
<option value="@item">@item</option>
foreach (var item in ListFlux)
{
<option value="@item">@item</option>
}
}
}
</select>
</select>
</div>
</div>
</div>
</div>
</div>
+14 -6
View File
@@ -15,14 +15,14 @@ namespace MP.SPEC.Components
#endregion Public Properties
#region Protected Fields
protected string lastUpdate = "-";
#endregion Protected Fields
#region Protected Properties
protected string lastUpdate
{
get => SelFilter.lastUpdate;
set => SelFilter.lastUpdate = value;
}
protected bool liveUpdate
{
get => SelFilter.LiveUpdate;
@@ -130,6 +130,14 @@ namespace MP.SPEC.Components
await FilterChanged.InvokeAsync(SelFilter);
}
protected async Task takeSnapshot()
{
// fermo udpate
liveUpdate = false;
await MDService.DossiersTakeParamsSnapshot(selMacchina, 10);
lastUpdate = $"Last Snapshot: {DateTime.Now:yyyy/MM/dd HH:mm:ss}";
}
protected void toggleParams()
{
showEditPar = !showEditPar;
+1 -1
View File
@@ -150,7 +150,7 @@
private string searchVal = "";
private bool showSearch;
private string stateSel = "*";
private string tipoSearch = "*";
private string tipoSearch = "";
#endregion Private Fields
+114 -23
View File
@@ -1,6 +1,7 @@
using MP.Data;
using MP.Data.Conf;
using MP.Data.DatabaseModels;
using MP.Data.DTO;
using Newtonsoft.Json;
using NLog;
using StackExchange.Redis;
@@ -20,8 +21,12 @@ namespace MP.SPEC.Data
// setup compoenti REDIS
redisConn = ConnectionMultiplexer.Connect(_configuration.GetConnectionString("Redis"));
redisConnAdmin = ConnectionMultiplexer.Connect(_configuration.GetConnectionString("RedisAdmin"));
redisDb = redisConn.GetDatabase();
// leggo cache lungo periodo
int.TryParse(_configuration.GetValue<string>("ServerConf:redisLongTimeCache"), out redisLongTimeCache);
_logger.LogInformation("Redis INIT");
// setup canali pub/sub
@@ -62,7 +67,6 @@ namespace MP.SPEC.Data
public async Task<List<ListValues>> AnagStatiComm()
{
int maxAgeConfig = 5;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
List<ListValues>? result = new List<ListValues>();
@@ -80,7 +84,7 @@ namespace MP.SPEC.Data
result = await Task.FromResult(dbController.AnagStatiComm());
// serializzp e salvo...
rawData = JsonConvert.SerializeObject(result);
await redisDb.StringSetAsync(redisStatoCom, rawData, getRandTOut(maxAgeConfig));
await redisDb.StringSetAsync(redisStatoCom, rawData, getRandTOut(redisLongTimeCache));
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"AnagStatiComm Read from DB: {ts.TotalMilliseconds}ms");
@@ -94,7 +98,6 @@ namespace MP.SPEC.Data
public async Task<List<ListValues>> AnagTipoArtLV()
{
int maxAgeConfig = 5;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
List<ListValues>? result = new List<ListValues>();
@@ -112,7 +115,7 @@ namespace MP.SPEC.Data
result = await Task.FromResult(dbController.AnagTipoArtLV());
// serializzp e salvo...
rawData = JsonConvert.SerializeObject(result);
await redisDb.StringSetAsync(redisTipoArt, rawData, getRandTOut(maxAgeConfig));
await redisDb.StringSetAsync(redisTipoArt, rawData, getRandTOut(redisLongTimeCache));
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"AnagTipoArtLV Read from DB: {ts.TotalMilliseconds}ms");
@@ -224,7 +227,6 @@ namespace MP.SPEC.Data
public async Task<List<ConfigModel>> ConfigGetAll()
{
int maxAgeConfig = 5;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
List<ConfigModel>? result = new List<ConfigModel>();
@@ -242,7 +244,7 @@ namespace MP.SPEC.Data
result = await Task.FromResult(dbController.ConfigGetAll());
// serializzp e salvo...
rawData = JsonConvert.SerializeObject(result);
await redisDb.StringSetAsync(redisConfKey, rawData, getRandTOut(maxAgeConfig));
await redisDb.StringSetAsync(redisConfKey, rawData, getRandTOut(redisLongTimeCache));
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"ConfigGetAll Read from DB: {ts.TotalMilliseconds}ms");
@@ -272,6 +274,14 @@ namespace MP.SPEC.Data
return await Task.FromResult(dbController.ConfigUpdate(updRec));
}
public List<FluxLog> convertToFluxLog(string Valore)
{
//string valStriped = Valore.Substring(7, Valore.Length - 8);
//var result = JsonConvert.DeserializeObject<List<FluxLog>>(valStriped);
var result = JsonConvert.DeserializeObject<DossierFluxLogDTO>(Valore);
return result.ODL;
}
public void Dispose()
{
// Clear database controller
@@ -279,6 +289,65 @@ namespace MP.SPEC.Data
redisConn.Dispose();
}
/// <summary>
/// Elenco ultimi n record DOssiers (che contengono ad esempio "salvataggi" di FLuxLog) dato
/// macchina (ordinato x data registrazione)
/// </summary>
/// <param name="IdxMacchina">* = tutte, altrimenti solo x una data macchina</param>
/// <param name="DtRef">Data di riferimento (Massima) per estrazione records</param>
/// <param name="MaxRec">numero massimo record da restituire</param>
/// <returns></returns>
public async Task<List<Dossiers>> DossiersGetLastFilt(string IdxMacchina, DateTime DtRef, int MaxRec)
{
List<Dossiers>? result = new List<Dossiers>();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string readType = "DB";
string currKey = $"{redisDossByMac}:{IdxMacchina}";
// cerco in redis dato valore sel macchina...
RedisValue rawData = redisDb.StringGet(currKey);
if (rawData.HasValue)
{
result = JsonConvert.DeserializeObject<List<Dossiers>>($"{rawData}");
readType = "REDIS";
}
else
{
result = await Task.FromResult(dbController.DossiersGetLastFilt(IdxMacchina, DtRef, MaxRec));
// serializzp e salvo...
rawData = JsonConvert.SerializeObject(result);
redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache / 5));
}
if (result == null)
{
result = new List<Dossiers>();
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"DossiersGetLastFilt | Read from {readType}: {ts.TotalMilliseconds}ms");
return result;
}
/// <summary>
/// Effettua salvataggio snapshot parametri (con stored) + svuota eventuale cache redis
/// </summary>
/// <param name="IdxMacchina">macchina</param>
/// <param name="maxSec">NUm massimo secondi per recuperare dati correnti</param>
/// <returns></returns>
public async Task<bool> DossiersTakeParamsSnapshot(string IdxMacchina, int MaxSec)
{
bool answ = false;
await Task.Delay(1);
// chiamo stored x salvare parametri
dbController.DossiersTakeParamsSnapshot(IdxMacchina, MaxSec);
// svuoto cache redis x macchina
string currKey = $"{redisDossByMac}:{IdxMacchina}";
redisDb.StringSet(currKey, "", TimeSpan.FromSeconds(1));
currKey = $"{redisDossByMac}:*";
redisDb.StringSet(currKey, "", TimeSpan.FromSeconds(1));
return answ;
}
/// <summary>
/// Restitusice elenco aziende
/// </summary>
@@ -302,6 +371,27 @@ namespace MP.SPEC.Data
return Task.FromResult(dbController.ElencoLink());
}
public async Task<bool> FlushRedisCache()
{
await Task.Delay(1);
bool answ = false;
var listEndpoints = redisConnAdmin.GetEndPoints();
var server = redisConnAdmin.GetServer(listEndpoints[0]);
RedisValue pattern = new RedisValue($"{redisBaseAddr}*");
if (server != null)
{
var keyList = server.Keys(redisDb.Database, pattern);
foreach (var item in keyList)
{
await redisDb.KeyDeleteAsync(item);
}
// brutalmente rimuovo intero contenuto DB... DANGER
//await server.FlushDatabaseAsync();
answ = true;
}
return answ;
}
/// <summary>
/// Elenco ultimi n record flux log dato macchina e flusso (ordinato x data registrazione)
/// </summary>
@@ -379,8 +469,6 @@ namespace MP.SPEC.Data
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string readType = "DB";
// 5 minuti valore cache
int maxAgeMin = 5;
string currKey = redisMacList;
// cerco in redis dato valore sel macchina...
RedisValue rawData = redisDb.StringGet(currKey);
@@ -394,7 +482,7 @@ namespace MP.SPEC.Data
result = await Task.FromResult(dbController.MacchineGetAll());
// serializzp e salvo...
rawData = JsonConvert.SerializeObject(result);
redisDb.StringSet(currKey, rawData, getRandTOut(maxAgeMin));
redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache));
}
if (result == null)
{
@@ -416,8 +504,6 @@ namespace MP.SPEC.Data
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string readType = "DB";
// 5 minuti valore cache
int maxAgeMin = 5;
string currKey = redisMacByFlux;
// cerco in redis dato valore sel macchina...
RedisValue rawData = redisDb.StringGet(currKey);
@@ -431,7 +517,7 @@ namespace MP.SPEC.Data
result = await Task.FromResult(dbController.MacchineWithFlux());
// serializzp e salvo...
rawData = JsonConvert.SerializeObject(result);
redisDb.StringSet(currKey, rawData, getRandTOut(maxAgeMin));
redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache));
}
if (result == null)
{
@@ -454,8 +540,6 @@ namespace MP.SPEC.Data
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string readType = "DB";
// 5 minuti valore cache
int maxAgeMin = 5;
string currKey = $"{redisFluxByMac}:{IdxMacchina}";
// cerco in redis dato valore sel macchina...
RedisValue rawData = redisDb.StringGet(currKey);
@@ -469,7 +553,7 @@ namespace MP.SPEC.Data
result = await Task.FromResult(dbController.ParametriGetFilt(IdxMacchina));
// serializzp e salvo...
rawData = JsonConvert.SerializeObject(result);
redisDb.StringSet(currKey, rawData, getRandTOut(maxAgeMin));
redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache));
}
if (result == null)
{
@@ -526,16 +610,16 @@ namespace MP.SPEC.Data
#region Private Fields
private const string redisConfKey = "MP:SPEC:Cache:Config";
private const string redisFluxByMac = "MP:SPEC:Cache:FluxByMac";
private const string redisMacByFlux = "MP:SPEC:Cache:MacByFlux";
private const string redisMacList = "MP:SPEC:Cache:MacList";
private const string redisStatoCom = "MP:SPEC:Cache:StatoCom";
private const string redisTipoArt = "MP:SPEC:Cache:TipoArt";
private const string redisBaseAddr = "MP:";
private const string redisConfKey = redisBaseAddr + "SPEC:Cache:Config";
private const string redisDossByMac = redisBaseAddr + "SPEC:Cache:DossByMac";
private const string redisFluxByMac = redisBaseAddr + "SPEC:Cache:FluxByMac";
private const string redisMacByFlux = redisBaseAddr + "SPEC:Cache:MacByFlux";
private const string redisMacList = redisBaseAddr + "SPEC:Cache:MacList";
private const string redisStatoCom = redisBaseAddr + "SPEC:Cache:StatoCom";
private const string redisTipoArt = redisBaseAddr + "SPEC:Cache:TipoArt";
private static IConfiguration _configuration = null!;
private static ILogger<MpDataService> _logger = null!;
private static Logger Log = LogManager.GetCurrentClassLogger();
/// <summary>
@@ -543,11 +627,18 @@ namespace MP.SPEC.Data
/// </summary>
private ConnectionMultiplexer redisConn = null!;
/// <summary>
/// Oggetto per connessione a REDIS modalità admin (ex flux dati)
/// </summary>
private ConnectionMultiplexer redisConnAdmin = null!;
/// <summary>
/// Oggetto DB redis da impiegare x chiamate R/W
/// </summary>
private IDatabase redisDb = null!;
private int redisLongTimeCache = 5;
#endregion Private Fields
}
}
+70
View File
@@ -0,0 +1,70 @@
namespace MP.SPEC.Data
{
public class SelectDossierParams
{
#region Public Constructors
public SelectDossierParams()
{ }
#endregion Public Constructors
#region Public Properties
public int CurrPage { get; set; } = 1;
public DateTime DtRef { get; set; } = Init(5);
public string IdxMacchina { get; set; } = "*";
public int MaxRecord { get; set; } = 100;
#endregion Public Properties
#region Public Methods
/// <summary>
        /// Inizializzazione con periodo e arrotondamento
        /// </summary>
        /// <param name="minRound"></param>
        /// <param name="numDayPrev"></param>
        /// <returns></returns>
public static DateTime Init(int minRound)
{
TimeSpan DayElapsed = DateTime.Now.Subtract(DateTime.Today);
int minDay = (int)Math.Ceiling((double)(DayElapsed.TotalMinutes / minRound)) * minRound;
DateTime endRounded = DateTime.Today.AddMinutes(minDay);
return endRounded;
}
public override bool Equals(object obj)
{
if (!(obj is SelectDossierParams item))
return false;
if (IdxMacchina != item.IdxMacchina)
return false;
if (MaxRecord != item.MaxRecord)
return false;
if (DtRef != item.DtRef)
return false;
if (CurrPage != item.CurrPage)
return false;
//if (lastUpdate != item.lastUpdate)
// return false;
return true;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
#endregion Public Methods
}
}
+5 -1
View File
@@ -12,12 +12,13 @@
#region Public Properties
public string CodFlux { get; set; } = "*";
public int CurrPage { get; set; } = 1;
public string IdxMacchina { get; set; } = "*";
public string lastUpdate { get; set; } = "-";
public bool LiveUpdate { get; set; } = true;
public int MaxRecord { get; set; } = 100;
public int TempoAgg { get; set; } = 2000;
public int CurrPage { get; set; } = 1;
#endregion Public Properties
@@ -46,6 +47,9 @@
if (CurrPage != item.CurrPage)
return false;
if (lastUpdate != item.lastUpdate)
return false;
return true;
}
+21 -2
View File
@@ -5,6 +5,7 @@
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>MP.SPEC</RootNamespace>
<Version>6.16.2209.2114</Version>
</PropertyGroup>
<ItemGroup>
@@ -16,8 +17,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.Negotiate" Version="6.0.6" />
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Negotiate" Version="6.0.9" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
<ItemGroup>
@@ -28,4 +29,22 @@
<ProjectReference Include="..\MP.Data\MP.Data.csproj" />
</ItemGroup>
<ItemGroup>
<Content Update="wwwroot\favicon.ico">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<None Update="logs\.placeholder">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="post-build.ps1">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="powershell.exe -ExecutionPolicy Unrestricted -NoProfile -NonInteractive -File $(ProjectDir)\post-build.ps1 -ProjectDir $(ProjectDir) -ProjectPath $(ProjectPath)" />
</Target>
</Project>
+15 -12
View File
@@ -17,15 +17,18 @@
</div>
</div>
<div class="px-0 align-content-center">
<select @bind="@selAzienda" class="form-select">
@if (ListAziende != null)
{
foreach (var item in ListAziende)
<div class="input-group input-group">
<label class="input-group-text" for="maxRecord" title="Selezionare l'azienda da visualizzare"><i class="fa-solid fa-industry"></i></label>
<select @bind="@selAzienda" class="form-select" title="Selezionare l'azienda da visualizzare">
@if (ListAziende != null)
{
<option value="@item.CodGruppo">@item.DescrGruppo</option>
foreach (var item in ListAziende)
{
<option value="@item.CodGruppo">@item.DescrGruppo</option>
}
}
}
</select>
</select>
</div>
</div>
</div>
@if (currRecord != null)
@@ -119,11 +122,11 @@
<th>
<button @onclick="() => resetSel()" class="btn btn-primary btn-sm"><i class="bi bi-arrow-counterclockwise"></i></button>
</th>
<th>Articolo</th>
<th>Disegno</th>
<th>Descrizione</th>
<th>Tipo</th>
<th>Azienda</th>
<th><i class="fa-solid fa-file"></i> Articolo</th>
<th><i class="fa-solid fa-compass-drafting"></i> Disegno</th>
<th><i class="fa-solid fa-file-word"></i> Descrizione</th>
<th><i class="fa-solid fa-rectangle-list"></i> Tipo</th>
<th><i class="fa-solid fa-industry"></i> Azienda</th>
<th></th>
</tr>
</thead>
+12 -33
View File
@@ -44,13 +44,13 @@ namespace MP.SPEC.Pages
#region Protected Properties
[Inject]
protected IJSRuntime JSRuntime { get; set; }
protected IJSRuntime JSRuntime { get; set; } = null!;
[Inject]
protected MpDataService MDService { get; set; }
protected MpDataService MDService { get; set; } = null!;
[Inject]
protected MessageService MessageService { get; set; }
protected MessageService MessageService { get; set; } = null!;
[Inject]
protected NavigationManager NavManager { get; set; }
@@ -78,7 +78,7 @@ namespace MP.SPEC.Pages
/// <returns></returns>
protected async Task addNew()
{
currRecord = new MP.Data.DatabaseModels.AnagArticoli()
currRecord = new AnagArticoli()
{
CodArticolo = $"_NEW_{DateTime.Now:yyyyMMdd.HHmmss}",
DescArticolo = "Nuovo articolo",
@@ -101,7 +101,7 @@ namespace MP.SPEC.Pages
/// </summary>
/// <param name="selRec"></param>
/// <returns></returns>
protected async Task deleteRecord(MP.Data.DatabaseModels.AnagArticoli selRec)
protected async Task deleteRecord(AnagArticoli selRec)
{
if (!await JSRuntime.InvokeAsync<bool>("confirm", "Eliminazione Articolo: sei sicuro di voler procedere?"))
return;
@@ -124,7 +124,6 @@ namespace MP.SPEC.Pages
protected override async Task OnInitializedAsync()
{
clearFile();
numRecord = 10;
// mostro ricerca
MessageService.ShowSearch = true;
@@ -142,7 +141,6 @@ namespace MP.SPEC.Pages
protected void ResetData()
{
clearFile();
currRecord = null;
}
@@ -152,13 +150,13 @@ namespace MP.SPEC.Pages
await Task.Delay(1);
}
protected async Task selRecord(MP.Data.DatabaseModels.AnagArticoli selRec)
protected async Task selRecord(AnagArticoli selRec)
{
currRecord = selRec;
await Task.Delay(1);
}
protected async Task update(MP.Data.DatabaseModels.AnagArticoli selRec)
protected async Task update(AnagArticoli selRec)
{
if (!await JSRuntime.InvokeAsync<bool>("confirm", "Confermi di voler salvare le modifiche?"))
return;
@@ -180,12 +178,11 @@ namespace MP.SPEC.Pages
#region Private Fields
private string _selAzienda = "*";
private MP.Data.DatabaseModels.AnagArticoli? currRecord = null;
private string fileName = "Controlli.csv";
private List<MP.Data.DatabaseModels.AnagGruppi>? ListAziende;
private List<MP.Data.DatabaseModels.AnagArticoli>? ListRecords;
private List<MP.Data.DatabaseModels.ListValues>? ListTipoArt;
private List<MP.Data.DatabaseModels.AnagArticoli>? SearchRecords;
private AnagArticoli? currRecord = null;
private List<AnagGruppi>? ListAziende;
private List<AnagArticoli>? ListRecords;
private List<ListValues>? ListTipoArt;
private List<AnagArticoli>? SearchRecords;
#endregion Private Fields
@@ -209,11 +206,6 @@ namespace MP.SPEC.Pages
}
}
private string fullPath
{
get => $"{Directory.GetCurrentDirectory()}\\temp\\{fileName}";
}
private bool isLoading { get; set; } = false;
private int numRecord
@@ -274,19 +266,6 @@ namespace MP.SPEC.Pages
return answ;
}
private async void clearFile()
{
await Task.Run(() => File.Delete(fullPath));
}
private async Task ExportCsv()
{
isLoading = true;
// salvo davvero!
await MP.Data.Utils.SaveToCsv(SearchRecords, fullPath);
isLoading = false;
}
private async Task reloadData()
{
isLoading = true;
+37
View File
@@ -0,0 +1,37 @@
@page "/DOSS"
<div class="card">
<div class="card-header table-primary">
<div class="d-flex">
<div class="px-0 py-1">
<h3><b>DOSSIERS</b></h3>
</div>
<div class="px-2 flex-fill">
@if (isFiltering)
{
<LoadingDataSmall></LoadingDataSmall>
<i>filtro x macchina / periodo</i>
}
else
{
<DossiersFilter FilterChanged="updateFilter"></DossiersFilter>
}
</div>
</div>
</div>
<div class="card-body">
@if (isLoading)
{
<LoadingData></LoadingData>
}
else
{
<ListDossiers SelFilter="@currFilter" TotRecordChanged="updateTotal"></ListDossiers>
}
</div>
<div class="card-footer py-1">
<DataPager @ref="pagerODL" PageSize="numRecord" currPage="currPage" numRecordChanged="ForceReload" numPageChanged="ForceReloadPage" totalCount="totalCount" showLoading="isLoading" />
</div>
</div>
+97
View File
@@ -0,0 +1,97 @@
using Microsoft.AspNetCore.Components;
using MP.SPEC.Components;
using MP.SPEC.Data;
namespace MP.SPEC.Pages
{
public partial class DOSS
{
#region Protected Fields
protected DataPager pagerODL = null!;
#endregion Protected Fields
#region Protected Properties
[Inject]
protected MessageService MsgService { get; set; } = null!;
#endregion Protected Properties
#region Protected Methods
protected void ForceReload(int newNum)
{
numRecord = newNum;
}
protected void ForceReloadPage(int newNum)
{
currPage = newNum;
StateHasChanged();
}
protected override async Task OnInitializedAsync()
{
isLoading = true;
isFiltering = true;
// disabilito ricerca...
MsgService.SearchVal = "";
MsgService.ShowSearch = false;
// fix pagina
await Task.Delay(1);
var modFilter = currFilter;
modFilter.CurrPage = 1;
currFilter = modFilter;
await Task.Delay(1);
isFiltering = false;
}
protected void updateTotal(int newTotCount)
{
totalCount = newTotCount;
}
#endregion Protected Methods
#region Private Properties
private SelectDossierParams currFilter { get; set; } = new SelectDossierParams();
private int currPage
{
get => MsgService.currPage;
set => MsgService.currPage = value;
}
private bool isFiltering { get; set; } = false;
private bool isLoading { get; set; } = true;
private int numRecord
{
get => MsgService.numRecord;
set => MsgService.numRecord = value;
}
private int totalCount { get; set; } = 0;
#endregion Private Properties
#region Private Methods
private async Task updateFilter(SelectDossierParams newParams)
{
isFiltering = false;
isLoading = true;
await Task.Delay(1);
currPage = 1;
await Task.Delay(1);
await InvokeAsync(() => StateHasChanged());
currFilter = newParams;
isLoading = false;
}
#endregion Private Methods
}
}
+21 -5
View File
@@ -8,20 +8,36 @@ namespace MP.SPEC.Pages
[IgnoreAntiforgeryToken]
public class ErrorModel : PageModel
{
public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
private readonly ILogger<ErrorModel> _logger;
#region Public Constructors
public ErrorModel(ILogger<ErrorModel> logger)
{
_logger = logger;
}
#endregion Public Constructors
#region Public Properties
public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
#endregion Public Properties
#region Public Methods
public void OnGet()
{
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
}
#endregion Public Methods
#region Private Fields
private readonly ILogger<ErrorModel> _logger;
#endregion Private Fields
}
}
+13 -6
View File
@@ -6,21 +6,19 @@
<div class="card-header bg-dark text-light">
<div class="d-flex justify-content-between">
<div class="p-2">
<img src="/images/LogoMapo.png" class="image-fluid" height="64" />
<img src="images/LogoMapo.png" class="image-fluid" height="64" />
</div>
<div class="p-2 align-content-center fs-1">
<b>MAPO SPEC</b>
</div>
<div class="p-2 bg-light">
<img src="/images/LogoEgw.png" class="image-fluid" height="64" />
<img src="images/LogoEgw.png" class="image-fluid" height="64" />
</div>
</div>
</div>
<div class="card-body text-center">
<h5 class="card-title">MAPO MES Custom Pages</h5>
<div class="shortcuts">
<div class="shortcuts my-5 py-5">
<div class="row">
<div class="col-12">
@if (ElencoLink == null)
@@ -46,7 +44,16 @@
</div>
</div>
</div>
<p class="card-text">Custom pages azienda <b>@currAzienda</b></p>
</div>
<dic class="card-footer bg-primary">
<div class="d-flex text-white justify-content-between">
<div class="px-2">
<h1>@currAzienda</h1>
</div>
<div class="px-2">
<h3 class="my-2">MAPO MES Custom Pages</h3>
</div>
</div>
</dic>
</div>
+15 -209
View File
@@ -2,223 +2,29 @@
<div class="card">
<div class="card-header table-primary">
<div class="row">
<div class="col-5">
<div class="d-flex justify-content-between">
<div class="px-2">
<h3><b>ODL</b></h3>
</div>
<div class="px-2">
<button class="btn btn-success" disabled="!@addEnabled" @onclick="() => reqNewPODL()">Nuovo ODL <i class="bi bi-plus-square"></i></button>
</div><div class="px-2">
</div>
</div>
<div class="d-flex justify-content-between">
<div class="px-1">
<h3><b>ODL</b></h3>
</div>
<div class="col-2">
</div>
<div class="col-5">
<div class="d-flex justify-content-between">
<div class="px-2">
<div class="form-check form-switch" title="Visualizzazione ODL Programmati / In Corso" style="padding-top: 3px">
@*<input class="form-check-input" type="checkbox" id="flexSwitchCheckDefault" @onclick="() => toggleCurrent()">*@
<button type="button" class="btn btn-primary btn-sm" @onclick="() => navToPODL()">PODL</button>
<label class="form-check-label" for="flexSwitchCheckDefault">Visualizza programmati</label>
</div>
</div>
<div class="px-2">
<select @bind="@selStato" class="form-select">
<option value="*">--- Tutti ---</option>
@if (ListStati != null)
<div class="px-2">
<div class="input-group input-group">
<label class="input-group-text" for="maxRecord" title="Selezionare la fase da visualizzare"><i class="fa-solid fa-screwdriver-wrench"></i></label>
<select @bind="@selStato" class="form-select"title="Selezionare la fase da visualizzare">
<option value="*">--- Tutti ---</option>
@if (ListStati != null)
{
foreach (var item in ListStati)
{
foreach (var item in ListStati)
{
<option value="@item.value">@item.label</option>
}
<option value="@item.value">@item.label</option>
}
</select>
</div>
}
</select>
</div>
</div>
</div>
@if (reqNew)
{
<div class="d-flex justify-content-around">
<div class="px-2">
<div class="input-group input-group-sm">
<span class="input-group-text" id="inputGroup-sizing-sm">Azienda</span>
<select @bind="@currAzienda" class="form-select">
@if (ListAziende != null)
{
foreach (var item in ListAziende.Where(x => x.CodGruppo != "*").ToList())
{
<option value="@item.CodGruppo">@item.DescrGruppo</option>
}
}
</select>
<span class="input-group-text" id="inputGroup-sizing-sm">Art Search</span>
<input type="text" class="form-control" aria-label="Art search" aria-describedby="inputGroup-sizing-sm">
</div>
</div>
</div>
<div class="d-flex justify-content-around">
<div class="px-2">
<div class="input-group input-group-sm">
<span class="input-group-text" id="inputGroup-sizing-sm">Articolo</span>
<select @bind="@currAzienda" class="form-select">
@if (ListAziende != null)
{
foreach (var item in ListAziende.Where(x => x.CodGruppo != "*").ToList())
{
<option value="@item.CodGruppo">@item.DescrGruppo</option>
}
}
</select>
</div>
</div>
</div>
}
else if (currRecordOdl != null)
{
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header bg-primary text-light">Modifica ODL</div>
<div class="card-body">
@*<div class="row">
<div class="col-4">
<div class="input-group">
<span class="input-group-text">Codice</span>
<input type="text" class="form-control" placeholder="Articolo" @bind-value="@currRecord.CodArticolo">
</div>
</div>
<div class="col-4">
<div class="input-group">
<span class="input-group-text">Disegno</span>
<input type="text" class="form-control" placeholder="Disegno" @bind-value="@currRecord.Disegno">
</div>
</div>
<div class="col-1">
<div class="input-group" title="Tipo">
<select @bind="@currRecord.Tipo" class="form-select text-end">
@if (ListTipoArt != null)
{
foreach (var item in ListTipoArt)
{
<option value="@item.value">@item.label</option>
}
}
</select>
</div>
</div>
<div class="col-3">
<div class="input-group" title="Azienda">
<select @bind="@currRecord.Azienda" class="form-select text-end">
@if (ListAziende != null)
{
foreach (var item in ListAziende.Where(x => x.CodGruppo != "*").ToList())
{
<option value="@item.CodGruppo">@item.DescrGruppo</option>
}
}
</select>
</div>
</div>
</div>
<div class="row mt-2">
<div class="col-8">
<input type="text" class="form-control" placeholder="Descrizione Articolo" @bind-value="@currRecord.DescArticolo">
</div>
<div class="col-2">
<div class="d-grid gap-2">
<button class="btn btn-warning" @onclick="() => cancel()">Annulla <i class="bi bi-x-circle"></i></button>
</div>
</div>
<div class="col-2">
<div class="d-grid gap-2">
<button class="btn btn-success" @onclick="() => update(currRecord)">Salva <i class="bi bi-save"></i></button>
</div>
</div>
</div>*@
</div>
</div>
</div>
</div>
}
else if (currRecordPOdl != null)
{
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header bg-primary text-light">Modifica PODL</div>
<div class="card-body">
@*<div class="row">
<div class="col-4">
<div class="input-group">
<span class="input-group-text">Codice</span>
<input type="text" class="form-control" placeholder="Articolo" @bind-value="@currRecord.CodArticolo">
</div>
</div>
<div class="col-4">
<div class="input-group">
<span class="input-group-text">Disegno</span>
<input type="text" class="form-control" placeholder="Disegno" @bind-value="@currRecord.Disegno">
</div>
</div>
<div class="col-1">
<div class="input-group" title="Tipo">
<select @bind="@currRecord.Tipo" class="form-select text-end">
@if (ListTipoArt != null)
{
foreach (var item in ListTipoArt)
{
<option value="@item.value">@item.label</option>
}
}
</select>
</div>
</div>
<div class="col-3">
<div class="input-group" title="Azienda">
<select @bind="@currRecord.Azienda" class="form-select text-end">
@if (ListAziende != null)
{
foreach (var item in ListAziende.Where(x => x.CodGruppo != "*").ToList())
{
<option value="@item.CodGruppo">@item.DescrGruppo</option>
}
}
</select>
</div>
</div>
</div>
<div class="row mt-2">
<div class="col-8">
<input type="text" class="form-control" placeholder="Descrizione Articolo" @bind-value="@currRecord.DescArticolo">
</div>
<div class="col-2">
<div class="d-grid gap-2">
<button class="btn btn-warning" @onclick="() => cancel()">Annulla <i class="bi bi-x-circle"></i></button>
</div>
</div>
<div class="col-2">
<div class="d-grid gap-2">
<button class="btn btn-success" @onclick="() => update(currRecord)">Salva <i class="bi bi-save"></i></button>
</div>
</div>
</div>*@
</div>
</div>
</div>
</div>
}
</div>
<div class="card-body">
<ListODL StatoSel="@selStato" PagerResetReq="pgResetReq"></ListODL>
<ListODL StatoSel="@selStato" PagerResetReq="pgResetReq"></ListODL>
</div>
<div class="card-footer py-1">
<DataPager @ref="pagerODL" PageSize="numRecord" currPage="currPage" numRecordChanged="ForceReload" numPageChanged="ForceReloadPage" totalCount="totalCount" showLoading="isLoading" />
+21 -101
View File
@@ -7,19 +7,22 @@ namespace MP.SPEC.Pages
{
public partial class ODL
{
#region Protected Fields
protected DataPager pagerODL;
#endregion Protected Fields
#region Protected Properties
[Inject]
protected IJSRuntime JSRuntime { get; set; }
protected IJSRuntime JSRuntime { get; set; } = null!;
[Inject]
protected MpDataService MDService { get; set; }
protected MpDataService MDService { get; set; } = null!;
[Inject]
protected MessageService MsgService { get; set; }
[Inject]
protected NavigationManager NavManager { get; set; }
protected MessageService MsgService { get; set; } = null!;
#endregion Protected Properties
@@ -35,54 +38,6 @@ namespace MP.SPEC.Pages
currPage = newNum;
}
protected async Task pgResetReq(bool doReset)
{
if (doReset)
{
await pagerODL.resetCurrPage();
}
}
private MP.Data.DatabaseModels.ODLModel? currRecordOdl = null;
private MP.Data.DatabaseModels.PODLModel? currRecordPOdl = null;
/// <summary>
/// Crea nuovo record e va in editing...
/// </summary>
/// <returns></returns>
protected async Task addNew()
{
currRecordPOdl = new MP.Data.DatabaseModels.PODLModel()
{
CodArticolo = $"_NEW_{DateTime.Now:yyyyMMdd.HHmmss}"
};
await Task.Delay(1);
}
protected async Task cancel()
{
currRecordOdl = null;
currRecordPOdl = null;
await reloadData();
await Task.Delay(1);
}
protected DataPager pagerODL;
protected bool reqNew = false;
/// <summary>
/// Crea nuovo record e va in editing...
/// </summary>
/// <returns></returns>
protected async Task reqNewPODL()
{
reqNew = !reqNew;
await Task.Delay(1);
}
protected override async Task OnInitializedAsync()
{
// abilito ricerca...
@@ -95,20 +50,29 @@ namespace MP.SPEC.Pages
await reloadData();
}
private string currAzienda { get; set; } = "*";
private List<MP.Data.DatabaseModels.AnagGruppi>? ListAziende;
protected async Task pgResetReq(bool doReset)
{
if (doReset)
{
await pagerODL.resetCurrPage();
}
}
#endregion Protected Methods
#region Private Fields
private MP.Data.DatabaseModels.ODLModel? currRecordOdl = null;
private MP.Data.DatabaseModels.PODLModel? currRecordPOdl = null;
private List<MP.Data.DatabaseModels.AnagGruppi>? ListAziende;
private List<MP.Data.DatabaseModels.ListValues>? ListStati;
#endregion Private Fields
#region Private Properties
private string currAzienda { get; set; } = "*";
private int currPage
{
get => MsgService.currPage;
@@ -124,37 +88,6 @@ namespace MP.SPEC.Pages
}
private string selStato { get; set; } = "*";
#if false
private string selStato
{
get => _selStato;
set
{
if (!_selStato.Equals(value))
{
_selStato = value;
addEnabled = selStato != "*";
////StateHasChanged();
//var pUpd = Task.Run(async () =>
//{
// //await reloadData();
// await Task.Delay(1);
// await InvokeAsync(() => StateHasChanged());
//});
//pUpd.Wait();
}
}
}
#endif
//private bool showODL { get; set; } = false;
private bool addEnabled = false;
//private string textToggle
//{
// get => showODL ? "In Corso" : "Programmati";
//}
private int totalCount
{
@@ -173,19 +106,6 @@ namespace MP.SPEC.Pages
isLoading = false;
}
//private async Task toggleCurrent()
//{
// //NavManager.NavigateTo("/PODL");
// showODL = !showODL;
// await Task.Delay(1);
//}
private async Task navToPODL()
{
NavManager.NavigateTo("/PODL");
//showODL = !showODL;
await Task.Delay(1);
}
#endregion Private Methods
}
}
+1 -1
View File
@@ -3,7 +3,7 @@
<div class="card">
<div class="card-header table-primary">
<div class="d-flex">
<div class="px-0">
<div class="px-0 py-1">
<h3><b>PARAMETERS</b></h3>
</div>
<div class="px-2 flex-fill">
+2 -6
View File
@@ -29,6 +29,7 @@ namespace MP.SPEC.Pages
protected void ForceReloadPage(int newNum)
{
currPage = newNum;
currFilter.lastUpdate = $"Last Snapshot: {DateTime.Now:yyyy/MM/dd HH:mm:ss}";
currFilter.LiveUpdate = (currPage == 1);
StateHasChanged();
}
@@ -65,11 +66,6 @@ namespace MP.SPEC.Pages
#endregion Protected Methods
#region Private Fields
#endregion Private Fields
#region Private Properties
private SelectFluxParams currFilter { get; set; } = new SelectFluxParams();
@@ -80,8 +76,8 @@ namespace MP.SPEC.Pages
set => MsgService.currPage = value;
}
private bool isLoading { get; set; } = true;
private bool isFiltering { get; set; } = false;
private bool isLoading { get; set; } = true;
private int numRecord
{
+14 -19
View File
@@ -3,7 +3,7 @@
<div class="card">
<div class="card-header table-primary">
<div class="row">
<div class="d-flex justify-content-between">
<div class="col-6">
<div class="d-flex">
<div class="px-2">
@@ -17,10 +17,10 @@
</div>
</div>
</div>
<div class="col-3">
<div class="col-6">
<div class="input-group input-group-sm">
<span class="input-group-text" id="inputGroup-sizing-sm">Azienda</span>
<select @bind="@currAzienda" class="form-select">
<label class="input-group-text" for="maxRecord" title="Selezionare l'azienda da visualizzare"><i class="fa-solid fa-industry"></i></label>
<select @bind="@currAzienda" class="form-select" title="Selezionare l'azienda da visualizzare">
@if (ListAziende != null)
{
foreach (var item in ListAziende)
@@ -29,25 +29,20 @@
}
}
</select>
</div>
</div>
<div class="col-3">
<div class="d-flex text-end">
<div class="input-group input-group-sm">
<span class="input-group-text" id="inputGroup-sizing-sm">Fase</span>
<select @bind="@selStato" class="form-select">
<option value="*">--- Tutti ---</option>
@if (ListStati != null)
<label class="input-group-text" for="maxRecord" title="Selezionare la fase da visualizzare"><i class="fa-solid fa-screwdriver-wrench"></i></label>
<select @bind="@selStato" class="form-select" title="Selezionare la fase da visualizzare">
<option value="*">--- Tutti ---</option>
@if (ListStati != null)
{
foreach (var item in ListStati)
{
foreach (var item in ListStati)
{
<option value="@item.value">@item.label</option>
}
<option value="@item.value">@item.label</option>
}
</select>
</div>
}
</select>
</div>
</div>
</div>
@if (currRecord != null)
{
+10
View File
@@ -0,0 +1,10 @@
@page "/Utils"
@using MP.SPEC.Components
@using MP.SPEC.Data
<h3>Utils</h3>
<div class="px-2">
<button class="btn btn-primary" @onclick="() => flushCache()"> Flush Cache </button>
</div>
+25
View File
@@ -0,0 +1,25 @@
using Microsoft.AspNetCore.Components;
using MP.SPEC.Data;
namespace MP.SPEC.Pages
{
public partial class Utils
{
#region Public Methods
public async Task flushCache()
{
await Task.Delay(1);
await MDService.FlushRedisCache();
}
#endregion Public Methods
#region Protected Properties
[Inject]
protected MpDataService MDService { get; set; }
#endregion Protected Properties
}
}
+25 -25
View File
@@ -1,28 +1,28 @@
{
"iisSettings": {
"windowsAuthentication": true,
"anonymousAuthentication": false,
"iisExpress": {
"applicationUrl": "http://localhost:46815",
"sslPort": 44370
}
},
"profiles": {
"MP.SPEC": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7212;http://localhost:5212",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
"iisSettings": {
"windowsAuthentication": true,
"anonymousAuthentication": false,
"iisExpress": {
"applicationUrl": "http://localhost:46815",
"sslPort": 44370
}
},
"profiles": {
"MP.SPEC": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7212;http://localhost:5212",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
+2 -2
View File
@@ -1,5 +1,5 @@
<body>
<i>Modulo MON MAPO</i>
<i>Modulo MAPOSPEC </i>
<h4>Versione: {{CURRENT-REL}}</h4>
<br /> Note di rilascio:
<ul>
@@ -19,7 +19,7 @@
<img src="logoSteamware.png" />
</div>
<div style="float: right;">
<a href="https://www.steamware.net/IOT" target="_blank">&copy; Steamware 2006-2021</a>
<a href="https://www.steamware.net/IOT" target="_blank">&copy; Steamware 2006-2022</a>
</div>
</div>
</body>
+3 -3
View File
@@ -1,6 +1,6 @@
<body>
<i>Modulo MON MAPO</i>
<h4>Versione: 6.15.2207.2109</h4>
<i>Modulo MAPOSPEC </i>
<h4>Versione: 6.16.2209.2114</h4>
<br /> Note di rilascio:
<ul>
<li>
@@ -19,7 +19,7 @@
<img src="logoSteamware.png" />
</div>
<div style="float: right;">
<a href="https://www.steamware.net/IOT" target="_blank">&copy; Steamware 2006-2021</a>
<a href="https://www.steamware.net/IOT" target="_blank">&copy; Steamware 2006-2022</a>
</div>
</div>
</body>
+1 -1
View File
@@ -1 +1 @@
6.15.2207.2109
6.16.2209.2114
+3 -3
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>6.15.2207.2109</version>
<url>https://nexus.steamware.net/repository/SWS/MP-MON/stable/LAST/MP.Mon.zip</url>
<changelog>https://nexus.steamware.net/repository/SWS/MP-MON/stable/LAST/ChangeLog.html</changelog>
<version>6.16.2209.2114</version>
<url>https://nexus.steamware.net/repository/SWS/MP-SPEC/stable/LAST/MP.SPEC.zip</url>
<changelog>https://nexus.steamware.net/repository/SWS/MP-SPEC/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>
</item>
+18 -10
View File
@@ -24,16 +24,16 @@ main {
display: flex;*/
}
.top-row ::deep a,
.top-row .btn-link {
white-space: nowrap;
margin-left: 1.5rem;
}
.top-row ::deep a,
.top-row .btn-link {
white-space: nowrap;
margin-left: 1.5rem;
}
.top-row a:first-child {
overflow: hidden;
text-overflow: ellipsis;
}
.top-row a:first-child {
overflow: hidden;
text-overflow: ellipsis;
}
.bottom-row {
color: #dedede;
@@ -46,9 +46,11 @@ main {
.top-row:not(.auth) {
display: none;
}
.top-row.auth {
justify-content: space-between;
}
.top-row a,
.top-row .btn-link {
margin-left: 0;
@@ -59,34 +61,40 @@ main {
.page {
flex-direction: row;
}
.sidebar {
width: 15rem;
height: 100vh;
position: sticky;
top: 0;
}
.sidebarSmall {
width: 5rem;
height: 100vh;
position: sticky;
top: 0;
}
.top-row {
position: sticky;
top: 0;
z-index: 1;
}
.top-row,
article {
padding-left: 0.5rem !important;
padding-right: 0.5rem !important;
}
.bottom-row {
position: fixed;
bottom: 0;
z-index: 1;
}
.main>div {
.main > div {
padding-left: 0.5rem !important;
padding-right: 0.5rem !important;
/*padding-left: 2rem !important;
+1 -1
View File
@@ -59,4 +59,4 @@
/* Never collapse the sidebar for wide screens */
display: block;
}
}
}
+4 -2
View File
@@ -9,10 +9,12 @@
"CodApp": "MP.SPEC",
"ConnectionStrings": {
"Mp.Data": "Server=SQL2016DEV;Database=MoonPro; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=MP.SPEC;",
"Redis": "localhost:6379,DefaultDatabase=1,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false"
"Redis": "localhost:6379,DefaultDatabase=1,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false",
"RedisAdmin": "localhost:6379,DefaultDatabase=1,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false,allowAdmin=true"
},
"ServerConf": {
"maxAge": "2000",
"cacheCheckArtUsato": 2
"cacheCheckArtUsato": 2,
"redisLongTimeCache": 15
}
}
+2 -2
View File
@@ -21,9 +21,9 @@ Set-Content -Path $FileVers -Value $currRelNum
# replace x manifest
$manData = Get-Content $FileManIn
$manData = $manData -replace "1.0.0.0", $currRelNum
$manData = $manData -replace "{{DIRNAME}}", "MP-MON"
$manData = $manData -replace "{{DIRNAME}}", "MP-SPEC"
$manData = $manData -replace "{{BRANCHNAME}}", "stable/LAST"
$manData = $manData -replace "{{PACKNAME}}", "MP.Mon"
$manData = $manData -replace "{{PACKNAME}}", "MP.SPEC"
Set-Content -Path $FileManOut -Value $manData
# replace x ChangeLog
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<security>
<authentication>
<!--<anonymousAuthentication enabled="false" />
<windowsAuthentication enabled="true" />-->
</authentication>
</security>
</system.webServer>
</location>
</configuration>
+3
View File
@@ -46,6 +46,9 @@ a,
.validation-message {
color: red;
}
.selBlock {
background-color: #CFF4FC;
}
.watermark {
position: absolute;
top: 250px;
+4
View File
@@ -45,6 +45,10 @@ a, .btn-link {
color: red;
}
.selBlock {
background-color: #CFF4FC;
}
.watermark {
position: absolute;
top: 250px;
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -4,7 +4,7 @@
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>MP.Stats</RootNamespace>
<UserSecretsId>826e877c-ba70-4253-84cb-d0b1cafd4440</UserSecretsId>
<Version>6.15.2209.0917</Version>
<Version>6.15.2209.1609</Version>
</PropertyGroup>
<ItemGroup>
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>Modulo statistiche MAPO</i>
<h4>Versione: 6.15.2209.0917</h4>
<h4>Versione: 6.15.2209.1609</h4>
<br />
Note di rilascio:
<ul>
+1 -1
View File
@@ -1 +1 @@
6.15.2209.0917
6.15.2209.1609
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>6.15.2209.0917</version>
<version>6.15.2209.1609</version>
<url>https://nexus.steamware.net/repository/SWS/MP-STATS/stable/LAST/MP.Stats.zip</url>
<changelog>https://nexus.steamware.net/repository/SWS/MP-STATS/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>
+1 -1
View File
@@ -1 +1 @@
6.15.
6.16.