Merge branch 'develop' of https://gitlab.steamware.net/steamware/mapo-core into develop
This commit is contained in:
@@ -724,9 +724,10 @@ namespace MP.Data.Controllers
|
||||
/// <returns></returns>
|
||||
public async Task<bool> ForceDbMaint(bool doExec, bool doUpdStat, bool doSave, int minPgCnt, int minAvgFrag, int maxAvgFragReb)
|
||||
{
|
||||
Log.Info($"Inizio ForceDbMaint");
|
||||
Log.Info($"Inizio ForceDbMaint on MoonProAdminContext");
|
||||
bool fatto = false;
|
||||
using (var dbCtx = new MoonProContext(_configuration))
|
||||
// uso context admin x query lunghe
|
||||
using (var dbCtx = new MoonProAdminContext(_configuration))
|
||||
{
|
||||
var pFlgExec = new SqlParameter("@FlgExec", doExec ? "Y" : "N");
|
||||
var pFlgUpdStat = new SqlParameter("@FlgUpdStat", doUpdStat ? "Y" : "N");
|
||||
@@ -741,7 +742,7 @@ namespace MP.Data.Controllers
|
||||
//.ExecuteSqlRaw("EXEC man.stp_Utility_Maintanance @FlgExec, @FlgUpdStat, @FlgSave, @min_page_count, @min_avg_fragmentation_in_percent, @max_avg_fragmentation_per_rebuild", pFlgExec, pFlgUpdStat, pFlgSave, pMinPgCnt, pMinAvgFrag, pMaxAvgFrag);
|
||||
fatto = true;
|
||||
}
|
||||
Log.Info($"FINE ForceDbMaint");
|
||||
Log.Info($"FINE ForceDbMaint on MoonProAdminContext");
|
||||
return fatto;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Blazored.LocalStorage" Version="4.3.0" />
|
||||
<PackageReference Include="Blazored.SessionStorage" Version="2.4.0" />
|
||||
<PackageReference Include="EgwCoreLib.Utils" Version="1.4.2310.1312" />
|
||||
<PackageReference Include="EgwCoreLib.Utils" Version="1.4.2310.2409" />
|
||||
<PackageReference Include="MailKit" Version="4.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="5.0.17" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.9" />
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using MP.Data.DatabaseModels;
|
||||
using MP.Data.DTO;
|
||||
using NLog;
|
||||
|
||||
#nullable disable
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
namespace MP.Data
|
||||
{
|
||||
public partial class MoonProAdminContext : DbContext
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private IConfiguration _configuration;
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Public Constructors
|
||||
|
||||
public MoonProAdminContext(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
// timeout esecuzione a 5 min (std: 30 sec)...
|
||||
Database.SetCommandTimeout(TimeSpan.FromSeconds(300));
|
||||
}
|
||||
|
||||
public MoonProAdminContext(DbContextOptions<MoonProAdminContext> options) : base(options)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion Public Constructors
|
||||
|
||||
#region Private Methods
|
||||
|
||||
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
|
||||
|
||||
#endregion Private Methods
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
if (!optionsBuilder.IsConfigured)
|
||||
{
|
||||
string connString = _configuration.GetConnectionString("Mp.Data");
|
||||
if (string.IsNullOrEmpty(connString))
|
||||
{
|
||||
connString = _configuration.GetConnectionString("Mp.Mon");
|
||||
}
|
||||
if (string.IsNullOrEmpty(connString))
|
||||
{
|
||||
connString = _configuration.GetConnectionString("Mp.STATS");
|
||||
}
|
||||
|
||||
optionsBuilder.UseSqlServer(connString);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.HasAnnotation("Relational:Collation", "SQL_Latin1_General_CP1_CI_AS");
|
||||
|
||||
OnModelCreatingPartial(modelBuilder);
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
}
|
||||
}
|
||||
@@ -233,6 +233,7 @@ namespace MP.Data
|
||||
public const string redisAKVKey = redisBaseAddr + "Cache:AKV";
|
||||
public const string redisParetoFLKey = redisBaseAddr + "Cache:ParetoFL";
|
||||
public const string redisStatsProcFL = redisBaseAddr + "Stats:ProcessFL";
|
||||
public const string redisStatsDbMaint = redisBaseAddr + "Stats:DbMaint";
|
||||
public const string redisDossByMac = redisBaseAddr + "Cache:DossByMac";
|
||||
public const string redisFluxByMac = redisBaseAddr + "Cache:FluxByMac";
|
||||
public const string redisFluxLogFilt = redisBaseAddr + "Cache:FluxLogFilt";
|
||||
|
||||
@@ -453,6 +453,27 @@ namespace MP.SPEC.Data
|
||||
return await Task.FromResult(dbController.ConfigUpdate(updRec));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restituisce le statistiche di DB maintenance eseguite
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Dictionary<DateTime, double> DbDedupStats()
|
||||
{
|
||||
Dictionary<DateTime, double> actStats = new Dictionary<DateTime, double>();
|
||||
string currKey = $"{Utils.redisStatsDbMaint}";
|
||||
// recupero i record statistiche correnti
|
||||
RedisValue rawData = redisDb.StringGet(currKey);
|
||||
if (rawData.HasValue)
|
||||
{
|
||||
var rawStats = JsonConvert.DeserializeObject<Dictionary<DateTime, double>>($"{rawData}");
|
||||
if (rawStats != null)
|
||||
{
|
||||
actStats = rawStats;
|
||||
}
|
||||
}
|
||||
return actStats;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose del connettore ai dati
|
||||
/// </summary>
|
||||
@@ -705,7 +726,8 @@ namespace MP.SPEC.Data
|
||||
{
|
||||
List<StatDedupDTO> procStats = await dbController.FluxLogDataRedux(idxMaccSel, fluxList, currPeriodo, valMode, intReq, maxItem);
|
||||
// effettuo merge statistiche...
|
||||
ProcStatMerge(procStats);
|
||||
ProcDedupStatMerge(procStats);
|
||||
// svuoto cache
|
||||
await FlushCacheFluxLog();
|
||||
}
|
||||
|
||||
@@ -790,7 +812,12 @@ namespace MP.SPEC.Data
|
||||
/// <returns></returns>
|
||||
public async Task ForceDbMaint(bool doExec = true, bool doUpdStat = true, bool doSave = true, int minPgCnt = 1000, int minAvgFrag = 10, int maxAvgFragReb = 50)
|
||||
{
|
||||
Stopwatch sw = Stopwatch.StartNew();
|
||||
await dbController.ForceDbMaint(doExec, doUpdStat, doSave, minPgCnt, minAvgFrag, maxAvgFragReb);
|
||||
sw.Stop();
|
||||
// registro statistiche esecuzione
|
||||
RecDbMaintStat(sw.Elapsed);
|
||||
// svuoto cache
|
||||
await FlushCacheFluxLog();
|
||||
}
|
||||
|
||||
@@ -1766,7 +1793,12 @@ namespace MP.SPEC.Data
|
||||
return TimeSpan.FromMinutes(rndValue);
|
||||
}
|
||||
|
||||
protected bool ProcStatMerge(List<StatDedupDTO> procStats)
|
||||
/// <summary>
|
||||
/// Merge statistiche Dedup
|
||||
/// </summary>
|
||||
/// <param name="procStats"></param>
|
||||
/// <returns></returns>
|
||||
protected bool ProcDedupStatMerge(List<StatDedupDTO> procStats)
|
||||
{
|
||||
bool answ = false;
|
||||
List<StatDedupDTO> actStats = ProcFLStats();
|
||||
@@ -1805,6 +1837,24 @@ namespace MP.SPEC.Data
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Merge statistiche DB Maintenance
|
||||
/// </summary>
|
||||
/// <param name="procStats"></param>
|
||||
/// <returns></returns>
|
||||
protected bool RecDbMaintStat(TimeSpan duration)
|
||||
{
|
||||
bool answ = false;
|
||||
Dictionary<DateTime, double> actStats = DbDedupStats();
|
||||
// aggiungo record!
|
||||
actStats.Add(DateTime.Now, duration.TotalSeconds);
|
||||
// salvo NUOVO record statistiche
|
||||
string currKey = $"{Utils.redisStatsDbMaint}";
|
||||
var rawData = JsonConvert.SerializeObject(actStats);
|
||||
redisDb.StringSet(currKey, rawData);
|
||||
return answ;
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<RootNamespace>MP.SPEC</RootNamespace>
|
||||
<Version>6.16.2310.2320</Version>
|
||||
<Version>6.16.2310.2409</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -39,8 +39,8 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Blazored.LocalStorage" Version="4.3.0" />
|
||||
<PackageReference Include="Blazored.SessionStorage" Version="2.4.0" />
|
||||
<PackageReference Include="EgwCoreLib.Razor" Version="1.4.2310.1312" />
|
||||
<PackageReference Include="EgwCoreLib.Utils" Version="1.4.2310.1312" />
|
||||
<PackageReference Include="EgwCoreLib.Razor" Version="1.4.2310.2409" />
|
||||
<PackageReference Include="EgwCoreLib.Utils" Version="1.4.2310.2409" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.Negotiate" Version="6.0.9" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -35,11 +35,11 @@
|
||||
@if (isProcessing)
|
||||
{
|
||||
<ProgressDisplay RefreshInterval="200" Title="Data Maintenance" MaxVal="@MaxVal" CurrVal="@currVal" NextVal="@nextVal" ExpTimeMSec="@expTimeMsec"></ProgressDisplay>
|
||||
<LoadingData DisplaySize="LoadingData.CtrlSize.Large" DisplayMode="LoadingData.SpinMode.Growl"></LoadingData>
|
||||
<LoadingData Title="Cleaning Up Data" DisplaySize="LoadingData.CtrlSize.Large" DisplayMode="LoadingData.SpinMode.Growl"></LoadingData>
|
||||
}
|
||||
else if (isReindexing)
|
||||
{
|
||||
<LoadingData DisplaySize="LoadingData.CtrlSize.Large" DisplayMode="LoadingData.SpinMode.BounceLine"></LoadingData>
|
||||
<LoadingData Title="DB Maintenance running" DisplaySize="LoadingData.CtrlSize.Large" DisplayMode="LoadingData.SpinMode.BounceLine"></LoadingData>
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -49,11 +49,16 @@
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<div class="row">
|
||||
<div class="col-4">
|
||||
<div class="col-2">
|
||||
<div>
|
||||
Cleanup: <b>@strPrTimeExp</b> <small>(stimato)</small>
|
||||
Cleanup: <b>@strPrTimeExp</b> <small>(stimato)</small>
|
||||
</div>
|
||||
<div class="small">Ultima: @lastDedupExecTime</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<div class="btn-group w-100">
|
||||
<button class="btn btn-danger w-100" title="Data Cleanup" @onclick="DoCleanup"><i class="fa-solid fa-broom"></i> Data Cleanup</button>
|
||||
</div>
|
||||
<div class="small">last exec: @lastExecTime</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<div class="input-group">
|
||||
@@ -78,12 +83,17 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<div class="col-2">
|
||||
<div class="btn-group w-100">
|
||||
<button class="btn btn-danger w-100" title="Data Cleanup" @onclick="DoCleanup"><i class="fa-solid fa-broom"></i> Data Cleanup</button>
|
||||
<button class="btn btn-warning w-100" title="Data Cleanup" @onclick="IdxRebuild"><i class="fa-solid fa-database"></i> Maint</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<div>
|
||||
Db Maint: <b>@strDbMaintTimeExp</b> <small>(stimato)</small>
|
||||
</div>
|
||||
<div class="small">Ultima: @lastDbMaintTime</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -12,7 +12,9 @@ namespace MP.SPEC.Pages
|
||||
{
|
||||
#region Protected Fields
|
||||
|
||||
protected double currVal = 0;
|
||||
protected DataInterval IntReq = DataInterval.hour;
|
||||
protected double nextVal = 0;
|
||||
protected int numRecPage = 10;
|
||||
protected int pageNum = 1;
|
||||
protected int totalCount = 0;
|
||||
@@ -24,6 +26,8 @@ namespace MP.SPEC.Pages
|
||||
|
||||
#region Protected Properties
|
||||
|
||||
protected Dictionary<DateTime, double> actDbMaintStats { get; set; } = new Dictionary<DateTime, double>();
|
||||
protected List<MP.Data.DTO.StatDedupDTO> actProcDedupStats { get; set; } = new List<MP.Data.DTO.StatDedupDTO>();
|
||||
protected List<string> fluxList { get; set; } = new List<string>();
|
||||
|
||||
[Inject]
|
||||
@@ -31,6 +35,11 @@ namespace MP.SPEC.Pages
|
||||
|
||||
protected Dictionary<string, string> ListMacchineAll { get; set; } = new Dictionary<string, string>();
|
||||
|
||||
protected int MaxVal
|
||||
{
|
||||
get => fluxList.Count;
|
||||
}
|
||||
|
||||
[Inject]
|
||||
protected MpDataService MDataServ { get; set; } = null!;
|
||||
|
||||
@@ -49,6 +58,9 @@ namespace MP.SPEC.Pages
|
||||
}
|
||||
}
|
||||
|
||||
protected string strDbMaintTimeExp { get; set; } = "-";
|
||||
protected string strPrTimeExp { get; set; } = "-";
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Protected Methods
|
||||
@@ -62,9 +74,8 @@ namespace MP.SPEC.Pages
|
||||
if (!await JSRuntime.InvokeAsync<bool>("confirm", "Attenzione! il task di Data Cleanup eliminerà in modo definitivo i dati in eccesso secondo lo schema impostato, sei sicuro di voler procedere?"))
|
||||
return;
|
||||
|
||||
|
||||
isProcessing = true;
|
||||
lastExecTime = "...";
|
||||
lastDedupExecTime = "...";
|
||||
Stopwatch sw = Stopwatch.StartNew();
|
||||
int currStep = 1;
|
||||
int stepVal = 1;
|
||||
@@ -80,12 +91,10 @@ namespace MP.SPEC.Pages
|
||||
}
|
||||
//await MDataServ.FluxLogDataRedux(idxMaccSel, fluxList, CurrPeriodo, ValMode, IntReq, maxItem);
|
||||
sw.Stop();
|
||||
lastExecTime = $"{sw.Elapsed.Minutes}m {sw.Elapsed.Seconds}s";
|
||||
lastDedupExecTime = $"{sw.Elapsed.Minutes}m {sw.Elapsed.Seconds}s";
|
||||
isProcessing = false;
|
||||
}
|
||||
|
||||
protected string lastExecTime = "";
|
||||
|
||||
/// <summary>
|
||||
/// Esegue cleanup dati
|
||||
/// </summary>
|
||||
@@ -96,10 +105,13 @@ namespace MP.SPEC.Pages
|
||||
return;
|
||||
|
||||
isReindexing = true;
|
||||
Stopwatch sw = Stopwatch.StartNew();
|
||||
lastDbMaintTime = "...";
|
||||
await InvokeAsync(StateHasChanged);
|
||||
await MDataServ.ForceDbMaint(true, true, true, 1000, 10, 50);
|
||||
sw.Stop();
|
||||
lastDbMaintTime = $"{sw.Elapsed.Minutes}m {sw.Elapsed.Seconds}s";
|
||||
isReindexing = false;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
@@ -108,13 +120,6 @@ namespace MP.SPEC.Pages
|
||||
await ReloadData();
|
||||
}
|
||||
|
||||
private void ReloadStats()
|
||||
{
|
||||
actStats = MDataServ.ProcFLStats();
|
||||
}
|
||||
|
||||
protected List<MP.Data.DTO.StatDedupDTO> actStats { get; set; } = new List<MP.Data.DTO.StatDedupDTO>();
|
||||
|
||||
protected async Task ReloadMacchine()
|
||||
{
|
||||
if (ListMacchineAll == null || ListMacchineAll.Count == 0)
|
||||
@@ -164,6 +169,7 @@ namespace MP.SPEC.Pages
|
||||
totalCount = numRec;
|
||||
await Task.Delay(1);
|
||||
}
|
||||
|
||||
protected async Task SetTotRec(int numRec)
|
||||
{
|
||||
totRecords = numRec;
|
||||
@@ -171,12 +177,61 @@ namespace MP.SPEC.Pages
|
||||
updateExpTime();
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
/// <summary>
|
||||
/// Tempo atteso processing
|
||||
/// - da calcolare in base al num eventi e alla tab logProcessing...
|
||||
/// </summary>
|
||||
private int expTimeMsec = 3000;
|
||||
|
||||
private string lastDbMaintTime = "";
|
||||
private string lastDedupExecTime = "";
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Private Properties
|
||||
|
||||
private Periodo CurrPeriodo { get; set; } = new Periodo();
|
||||
|
||||
private string idxMaccSel { get; set; } = "";
|
||||
|
||||
private bool isProcessing { get; set; } = false;
|
||||
|
||||
private bool isReindexing { get; set; } = false;
|
||||
|
||||
private double msProcEst { get; set; } = 0.2;
|
||||
|
||||
private int numItem { get; set; } = 1;
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private async Task ReloadData()
|
||||
{
|
||||
await ReloadMacchine();
|
||||
DateTime dtEnd = DateTime.Today.AddDays(1);
|
||||
DateTime dtStart = dtEnd.AddMonths(-1);
|
||||
CurrPeriodo = new Periodo(dtStart, dtEnd);
|
||||
}
|
||||
|
||||
private void ReloadStats()
|
||||
{
|
||||
actProcDedupStats = MDataServ.ProcFLStats();
|
||||
actDbMaintStats = MDataServ.DbDedupStats();
|
||||
}
|
||||
|
||||
private void updateExpTime()
|
||||
{
|
||||
// calcolo tempo stimato e mostro...
|
||||
double msProcEst = 0.15 * numItem;
|
||||
// recupero statistiche x tipoInt e num eventi...
|
||||
var calcStats = actStats.Where(x => x.Interval == IntReq && x.Num4Int == numItem);
|
||||
var calcStats = actProcDedupStats.Where(x => x.Interval == IntReq && x.Num4Int == numItem);
|
||||
//var calcStats = actStats.Where(x => x.IdxMacchina == idxMaccSel && x.Interval == IntReq && x.Num4Int == numItem);
|
||||
if (calcStats != null && calcStats.Count() > 0)
|
||||
{
|
||||
@@ -199,59 +254,25 @@ namespace MP.SPEC.Pages
|
||||
strPrTimeExp = $"{TotalTime.Minutes}m {TotalTime.Seconds}s";
|
||||
}
|
||||
}
|
||||
// ora sistemo le statistiche DB maintenance
|
||||
double estimDbMaintSec = 150;
|
||||
var dbTotSec = actDbMaintStats.Sum(x => x.Value);
|
||||
var dbNumItem = actDbMaintStats.Count();
|
||||
if (dbNumItem > 0)
|
||||
{
|
||||
estimDbMaintSec = dbTotSec / dbNumItem;
|
||||
}
|
||||
var TotalTimeDb = TimeSpan.FromSeconds(estimDbMaintSec);
|
||||
if (TotalTimeDb.TotalMinutes > 60)
|
||||
{
|
||||
strDbMaintTimeExp = $"{TotalTimeDb.Hours}h {TotalTimeDb.Minutes}m";
|
||||
}
|
||||
else
|
||||
{
|
||||
strDbMaintTimeExp = $"{TotalTimeDb.Minutes}m {TotalTimeDb.Seconds}s";
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Tempo atteso processing
|
||||
/// - da calcolare in base al num eventi e alla tab logProcessing...
|
||||
/// </summary>
|
||||
private int expTimeMsec = 3000;
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Private Properties
|
||||
|
||||
private Periodo CurrPeriodo { get; set; } = new Periodo();
|
||||
|
||||
private string idxMaccSel { get; set; } = "";
|
||||
private bool isProcessing { get; set; } = false;
|
||||
private bool isReindexing { get; set; } = false;
|
||||
|
||||
|
||||
protected double currVal = 0;
|
||||
protected double nextVal = 0;
|
||||
protected int MaxVal
|
||||
{
|
||||
get => fluxList.Count;
|
||||
}
|
||||
|
||||
private int numItem { get; set; } = 1;
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private async Task ReloadData()
|
||||
{
|
||||
await ReloadMacchine();
|
||||
DateTime dtEnd = DateTime.Today.AddDays(1);
|
||||
DateTime dtStart = dtEnd.AddMonths(-1);
|
||||
CurrPeriodo = new Periodo(dtStart, dtEnd);
|
||||
|
||||
}
|
||||
|
||||
private double msProcEst { get; set; } = 0.2;
|
||||
|
||||
protected string strPrTimeExp { get; set; } = "-";
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<body>
|
||||
<i>Modulo MAPOSPEC </i>
|
||||
<h4>Versione: 6.16.2310.2320</h4>
|
||||
<h4>Versione: 6.16.2310.2409</h4>
|
||||
<br /> Note di rilascio:
|
||||
<ul>
|
||||
<li>
|
||||
|
||||
@@ -1 +1 @@
|
||||
6.16.2310.2320
|
||||
6.16.2310.2409
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<item>
|
||||
<version>6.16.2310.2320</version>
|
||||
<version>6.16.2310.2409</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>
|
||||
|
||||
Reference in New Issue
Block a user