Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c418812ba2 | |||
| 6169d8cfcc | |||
| 75596c61bc | |||
| b51e164c18 | |||
| c35d625c36 | |||
| c893ce4d44 | |||
| c47fb1787c | |||
| aca61c24dc | |||
| 167c9d89d4 | |||
| 2295f12958 | |||
| 9762628abc | |||
| a7918e1a89 | |||
| 7a8e05462c | |||
| aaeae6e99e | |||
| 533f3f4f8f | |||
| 5135987f1b | |||
| 458d788a13 | |||
| e842228baf | |||
| 25d2ada96e | |||
| f22933f925 | |||
| 009b5f6452 | |||
| 94c72b7e11 | |||
| 11a1925660 | |||
| 6ce8386248 | |||
| 1739dcf38a | |||
| 1a42d581d4 | |||
| 625433a3af | |||
| 782a01a4b0 | |||
| e65105b305 | |||
| 0429ad398a | |||
| 268ee1e2e0 | |||
| d19dc0edb5 |
+1
-1
@@ -311,7 +311,7 @@ MON:IIS02:deploy:
|
|||||||
- dotnet restore "$env:SOL_NAME.sln"
|
- dotnet restore "$env:SOL_NAME.sln"
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
needs: ["MON:test"]
|
needs: ["MON:build"]
|
||||||
script:
|
script:
|
||||||
- dotnet publish -p:PublishProfile=IIS02.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=viadante16 -p:AllowUntrustedCertificate=true $env:APP_NAME/$env:APP_NAME.csproj
|
- dotnet publish -p:PublishProfile=IIS02.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=viadante16 -p:AllowUntrustedCertificate=true $env:APP_NAME/$env:APP_NAME.csproj
|
||||||
- dotnet publish -p:PublishProfile=IIS03.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=viadante16 -p:AllowUntrustedCertificate=true $env:APP_NAME/$env:APP_NAME.csproj
|
- dotnet publish -p:PublishProfile=IIS03.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=viadante16 -p:AllowUntrustedCertificate=true $env:APP_NAME/$env:APP_NAME.csproj
|
||||||
|
|||||||
@@ -54,7 +54,9 @@ namespace MP.AppAuth
|
|||||||
|
|
||||||
#region Public Properties
|
#region Public Properties
|
||||||
|
|
||||||
|
public virtual DbSet<AnagraficaGruppi> DbSetAnagraficaGruppi { get; set; }
|
||||||
public virtual DbSet<AnagraficaOperatori> DbSetAnagOpr { get; set; }
|
public virtual DbSet<AnagraficaOperatori> DbSetAnagOpr { get; set; }
|
||||||
|
public virtual DbSet<Gruppi2Operatori> DbSetGruppi2Oper { get; set; }
|
||||||
public virtual DbSet<UpdMan> DbSetUpdMan { get; set; }
|
public virtual DbSet<UpdMan> DbSetUpdMan { get; set; }
|
||||||
public virtual DbSet<Vocabolario> DbSetVocabolario { get; set; }
|
public virtual DbSet<Vocabolario> DbSetVocabolario { get; set; }
|
||||||
|
|
||||||
@@ -103,6 +105,37 @@ namespace MP.AppAuth
|
|||||||
.HasMaxLength(500);
|
.HasMaxLength(500);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<AnagraficaGruppi>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasKey(e => e.CodGruppo);
|
||||||
|
|
||||||
|
entity.ToTable("AnagraficaGruppi");
|
||||||
|
|
||||||
|
entity.Property(e => e.CodGruppo).HasMaxLength(50);
|
||||||
|
|
||||||
|
entity.Property(e => e.DescrGruppo)
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(250)
|
||||||
|
.HasDefaultValueSql("('')");
|
||||||
|
|
||||||
|
entity.Property(e => e.SelEnabled).HasComment("Indica se sia selezionabile a livello di tendina x inserimento BCode");
|
||||||
|
|
||||||
|
entity.Property(e => e.TipoGruppo)
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasDefaultValueSql("('REPARTO')")
|
||||||
|
.HasComment("tipo gruppo: reparto (es x gestione operatori assegnati), GRUPPO FASE (es macchien che fanno lo stesso tipo di lavoro), ...");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<Gruppi2Operatori>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasKey(e => new { e.MatrOpr, e.CodGruppo });
|
||||||
|
|
||||||
|
entity.ToTable("Gruppi2Operatori");
|
||||||
|
|
||||||
|
entity.Property(e => e.CodGruppo).HasMaxLength(50);
|
||||||
|
});
|
||||||
|
|
||||||
//
|
//
|
||||||
modelBuilder.Seed();
|
modelBuilder.Seed();
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,38 @@ namespace MP.AppAuth.Controllers
|
|||||||
|
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Elenco Record x Gruppi
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public List<Models.AnagraficaGruppi> AnagGruppiFilt(string codTipo)
|
||||||
|
{
|
||||||
|
List<Models.AnagraficaGruppi> dbResult = new List<Models.AnagraficaGruppi>();
|
||||||
|
using (AppAuthContext localDbCtx = new AppAuthContext(_configuration))
|
||||||
|
{
|
||||||
|
dbResult = localDbCtx
|
||||||
|
.DbSetAnagraficaGruppi
|
||||||
|
.Where(x => x.TipoGruppo == codTipo || x.SelEnabled)
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
return dbResult;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Elenco Record x Gruppi
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public List<Models.AnagraficaGruppi> AnagGruppiGetAll()
|
||||||
|
{
|
||||||
|
List<Models.AnagraficaGruppi> dbResult = new List<Models.AnagraficaGruppi>();
|
||||||
|
using (AppAuthContext localDbCtx = new AppAuthContext(_configuration))
|
||||||
|
{
|
||||||
|
dbResult = localDbCtx
|
||||||
|
.DbSetAnagraficaGruppi
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
return dbResult;
|
||||||
|
}
|
||||||
|
|
||||||
public List<Models.AnagraficaOperatori> AnagOpGetAll(string searchVal)
|
public List<Models.AnagraficaOperatori> AnagOpGetAll(string searchVal)
|
||||||
{
|
{
|
||||||
List<Models.AnagraficaOperatori> dbResult = new List<Models.AnagraficaOperatori>();
|
List<Models.AnagraficaOperatori> dbResult = new List<Models.AnagraficaOperatori>();
|
||||||
@@ -53,6 +85,41 @@ namespace MP.AppAuth.Controllers
|
|||||||
// ritorno
|
// ritorno
|
||||||
return dbResult;
|
return dbResult;
|
||||||
}
|
}
|
||||||
|
public List<Models.AnagraficaOperatori> AnagOpByGruppoGetFilt(string codGruppo, string searchVal)
|
||||||
|
{
|
||||||
|
List<Models.AnagraficaOperatori> dbResult = new List<Models.AnagraficaOperatori>();
|
||||||
|
using (AppAuthContext localDbCtx = new AppAuthContext(_configuration))
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(searchVal))
|
||||||
|
{
|
||||||
|
dbResult = localDbCtx
|
||||||
|
.DbSetGruppi2Oper
|
||||||
|
.Where(x => x.CodGruppo == codGruppo || string.IsNullOrEmpty(codGruppo))
|
||||||
|
.Join(
|
||||||
|
localDbCtx.DbSetAnagOpr.Where(x => x.Cognome.Contains(searchVal) || x.Nome.Contains(searchVal)),
|
||||||
|
gruppo => gruppo.MatrOpr,
|
||||||
|
operatore => operatore.MatrOpr,
|
||||||
|
(gruppo, operatore) => operatore
|
||||||
|
)
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dbResult = localDbCtx
|
||||||
|
.DbSetGruppi2Oper
|
||||||
|
.Where(x => x.CodGruppo == codGruppo || string.IsNullOrEmpty(codGruppo))
|
||||||
|
.Join(
|
||||||
|
localDbCtx.DbSetAnagOpr,
|
||||||
|
gruppo => gruppo.MatrOpr,
|
||||||
|
operatore => operatore.MatrOpr,
|
||||||
|
(gruppo, operatore) => operatore
|
||||||
|
)
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ritorno
|
||||||
|
return dbResult;
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,22 +2,17 @@
|
|||||||
using NLog;
|
using NLog;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MP.AppAuth.Controllers
|
namespace MP.AppAuth.Controllers
|
||||||
{
|
{
|
||||||
public class MPController : IDisposable
|
public class MPController : IDisposable
|
||||||
{
|
{
|
||||||
#region Private Fields
|
#region Public Fields
|
||||||
|
|
||||||
private static IConfiguration _configuration;
|
|
||||||
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
|
|
||||||
public static AppAuth.Controllers.MPController dbController;
|
public static AppAuth.Controllers.MPController dbController;
|
||||||
|
|
||||||
#endregion Private Fields
|
#endregion Public Fields
|
||||||
|
|
||||||
#region Public Constructors
|
#region Public Constructors
|
||||||
|
|
||||||
@@ -31,12 +26,6 @@ namespace MP.AppAuth.Controllers
|
|||||||
|
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
// Clear database controller
|
|
||||||
dbController.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Elenco Record x AnagKeyValue
|
/// Elenco Record x AnagKeyValue
|
||||||
@@ -54,7 +43,19 @@ namespace MP.AppAuth.Controllers
|
|||||||
return dbResult;
|
return dbResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
// Clear database controller
|
||||||
|
dbController.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
#endregion Public Methods
|
#endregion Public Methods
|
||||||
|
|
||||||
|
#region Private Fields
|
||||||
|
|
||||||
|
private static IConfiguration _configuration;
|
||||||
|
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
#endregion Private Fields
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MP.AppAuth.Models
|
||||||
|
{
|
||||||
|
public partial class AnagraficaGruppi
|
||||||
|
{
|
||||||
|
public string CodGruppo { get; set; }
|
||||||
|
public string TipoGruppo { get; set; }
|
||||||
|
public string DescrGruppo { get; set; }
|
||||||
|
public bool SelEnabled { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace MP.AppAuth.Models
|
||||||
|
{
|
||||||
|
public partial class Gruppi2Operatori
|
||||||
|
{
|
||||||
|
public int MatrOpr { get; set; }
|
||||||
|
public string CodGruppo { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -71,7 +71,7 @@ namespace MP.AppAuth
|
|||||||
public virtual DbSet<ListValue> ListValues { get; set; }
|
public virtual DbSet<ListValue> ListValues { get; set; }
|
||||||
public virtual DbSet<Macchine> Macchines { get; set; }
|
public virtual DbSet<Macchine> Macchines { get; set; }
|
||||||
public virtual DbSet<UpdMan> UpdMan { get; set; }
|
public virtual DbSet<UpdMan> UpdMan { get; set; }
|
||||||
public virtual DbSet<Vocabolario> Vocabolario { get; set; }
|
public virtual DbSet<Vocabolario> DbSetVocabolario { get; set; }
|
||||||
|
|
||||||
#endregion Public Properties
|
#endregion Public Properties
|
||||||
|
|
||||||
@@ -503,6 +503,8 @@ namespace MP.AppAuth
|
|||||||
.HasMaxLength(500);
|
.HasMaxLength(500);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
OnModelCreatingPartial(modelBuilder);
|
OnModelCreatingPartial(modelBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MP.Data.Conf
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Struttura conf del file conf TAG x IOB
|
||||||
|
/// </summary>
|
||||||
|
public class IobTags
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Oggetto dizionario di configurazione x IOB
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<string, List<TagData>> IobSetup = new Dictionary<string, List<TagData>>();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MP.Data.Conf
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Item da mostrare nei blocchi MON degli impianti come override ai dati MSE
|
||||||
|
/// </summary>
|
||||||
|
public class TagData
|
||||||
|
{
|
||||||
|
/// <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>
|
||||||
|
/// Clone dell'oggetto
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public TagData Clone()
|
||||||
|
{
|
||||||
|
return (TagData)this.MemberwiseClone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace MP.Data
|
||||||
|
{
|
||||||
|
public class Constants
|
||||||
|
{
|
||||||
|
|
||||||
|
// 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_FLUX_DATA_KEY = $"{BASE_HASH}:Current:FluxData";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">
|
||||||
|
Gruppi
|
||||||
|
</div>
|
||||||
|
<div class="col-6 text-right">
|
||||||
|
<select @bind="@groupName" class="form-control form-control-sm">
|
||||||
|
<option value="">--- Tutti ---</option>
|
||||||
|
@if (ListGroups != null)
|
||||||
|
{
|
||||||
|
@foreach (var item in ListGroups)
|
||||||
|
{
|
||||||
|
<option value="@item.CodGruppo">@item.DescrGruppo</option>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using System.Net.Http;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Components.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Components.Forms;
|
||||||
|
using Microsoft.AspNetCore.Components.Routing;
|
||||||
|
using Microsoft.AspNetCore.Components.Web;
|
||||||
|
using Microsoft.AspNetCore.Components.Web.Virtualization;
|
||||||
|
using Microsoft.JSInterop;
|
||||||
|
using MP.Land;
|
||||||
|
using MP.Land.Shared;
|
||||||
|
using MP.AppAuth.Models;
|
||||||
|
using MP.Land.Data;
|
||||||
|
|
||||||
|
namespace MP.Land.Components
|
||||||
|
{
|
||||||
|
public partial class CmpGroupFilt
|
||||||
|
{
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
protected MessageService AppMService { get; set; }
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
protected AppAuthService DataService { get; set; }
|
||||||
|
|
||||||
|
private List<AnagraficaGruppi> ListGroups;
|
||||||
|
private string groupName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return AppMService.CodGruppo;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
AppMService.CodGruppo = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
await ReloadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ReloadData()
|
||||||
|
{
|
||||||
|
// carico i gruppi
|
||||||
|
ListGroups = await DataService.AnagGruppiFilt("REPARTO");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -42,9 +42,9 @@
|
|||||||
{
|
{
|
||||||
<div class="input-group input-group-sm">
|
<div class="input-group input-group-sm">
|
||||||
<select @bind="@PageSize" class="form-control form-control-sm">
|
<select @bind="@PageSize" class="form-control form-control-sm">
|
||||||
<option value="2">2</option>
|
<option value="3">3</option>
|
||||||
<option value="4">4</option>
|
<option value="6">6</option>
|
||||||
<option value="10">10</option>
|
<option value="9">9</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ namespace MP.Land.Components
|
|||||||
|
|
||||||
protected int _numPage { get; set; } = 1;
|
protected int _numPage { get; set; } = 1;
|
||||||
|
|
||||||
protected int _numRecord { get; set; } = 4;
|
protected int _numRecord { get; set; } = 6;
|
||||||
|
|
||||||
protected int percLoading { get; set; } = 0;
|
protected int percLoading { get; set; } = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
{
|
{
|
||||||
if (!firstRender)
|
if (firstRender)
|
||||||
{
|
{
|
||||||
await JSRuntime.InvokeVoidAsync("clearContent", $"qrCodeImg_{CurrItem.MatrOpr}");
|
await JSRuntime.InvokeVoidAsync("clearContent", $"qrCodeImg_{CurrItem.MatrOpr}");
|
||||||
await JSRuntime.InvokeVoidAsync("displayQr", $"qrCodeImg_{CurrItem.MatrOpr}", rawCode);
|
await JSRuntime.InvokeVoidAsync("displayQr", $"qrCodeImg_{CurrItem.MatrOpr}", rawCode);
|
||||||
|
|||||||
@@ -129,6 +129,46 @@ namespace MP.Land.Data
|
|||||||
|
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
|
|
||||||
|
public async Task<List<AppAuth.Models.AnagraficaGruppi>> AnagGruppiAll()
|
||||||
|
{
|
||||||
|
List<AppAuth.Models.AnagraficaGruppi> dbResult = new List<AppAuth.Models.AnagraficaGruppi>();
|
||||||
|
Stopwatch stopWatch = new Stopwatch();
|
||||||
|
stopWatch.Start();
|
||||||
|
dbResult = dbController.AnagGruppiGetAll();
|
||||||
|
stopWatch.Stop();
|
||||||
|
TimeSpan ts = stopWatch.Elapsed;
|
||||||
|
Log.Trace($"Effettuata lettura da DB per AnagGruppiAll: {ts.TotalMilliseconds} ms");
|
||||||
|
return await Task.FromResult(dbResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<AppAuth.Models.AnagraficaGruppi>> AnagGruppiFilt(string codTipo)
|
||||||
|
{
|
||||||
|
List<AppAuth.Models.AnagraficaGruppi> dbResult = new List<AppAuth.Models.AnagraficaGruppi>();
|
||||||
|
Stopwatch stopWatch = new Stopwatch();
|
||||||
|
stopWatch.Start();
|
||||||
|
dbResult = dbController.AnagGruppiFilt(codTipo);
|
||||||
|
stopWatch.Stop();
|
||||||
|
TimeSpan ts = stopWatch.Elapsed;
|
||||||
|
Log.Trace($"Effettuata lettura da DB per AnagGruppiFilt: {ts.TotalMilliseconds} ms");
|
||||||
|
return await Task.FromResult(dbResult);
|
||||||
|
}
|
||||||
|
public async Task<List<AppAuth.Models.AnagraficaOperatori>> AnagOperByGroupList(string codGruppo, string searchVal)
|
||||||
|
{
|
||||||
|
List<AppAuth.Models.AnagraficaOperatori> dbResult = new List<AppAuth.Models.AnagraficaOperatori>();
|
||||||
|
Stopwatch stopWatch = new Stopwatch();
|
||||||
|
stopWatch.Start();
|
||||||
|
var rawData = dbController
|
||||||
|
.AnagOpByGruppoGetFilt(codGruppo, searchVal);
|
||||||
|
dbResult = rawData
|
||||||
|
.GroupBy(user => user.MatrOpr)
|
||||||
|
.Select(grp => grp.First())
|
||||||
|
.ToList();
|
||||||
|
stopWatch.Stop();
|
||||||
|
TimeSpan ts = stopWatch.Elapsed;
|
||||||
|
Log.Trace($"Effettuata lettura da DB per AnagOperByGroupList: {ts.TotalMilliseconds} ms");
|
||||||
|
return await Task.FromResult(dbResult);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<List<AppAuth.Models.AnagraficaOperatori>> AnagOperList(string searchVal)
|
public async Task<List<AppAuth.Models.AnagraficaOperatori>> AnagOperList(string searchVal)
|
||||||
{
|
{
|
||||||
List<AppAuth.Models.AnagraficaOperatori> dbResult = new List<AppAuth.Models.AnagraficaOperatori>();
|
List<AppAuth.Models.AnagraficaOperatori> dbResult = new List<AppAuth.Models.AnagraficaOperatori>();
|
||||||
|
|||||||
+180
-50
@@ -28,6 +28,12 @@ namespace MP.Land.Data
|
|||||||
/// URL dell'API x chiamate gestione licenze
|
/// URL dell'API x chiamate gestione licenze
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static string apiUrl = "https://liman.egalware.com/ELM.API/";
|
private static string apiUrl = "https://liman.egalware.com/ELM.API/";
|
||||||
|
//private static string apiUrl = "https://localhost:44351/";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Chiave redis x info della licenza
|
||||||
|
/// </summary>
|
||||||
|
private static string rkeyAppInfo = "LongCache:AppInfo";
|
||||||
|
|
||||||
private readonly IDistributedCache distributedCache;
|
private readonly IDistributedCache distributedCache;
|
||||||
|
|
||||||
@@ -120,10 +126,26 @@ namespace MP.Land.Data
|
|||||||
|
|
||||||
public DateTime infoExpiry { get; set; } = DateTime.Today.AddDays(1);
|
public DateTime infoExpiry { get; set; } = DateTime.Today.AddDays(1);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Codice cliente/installazione
|
||||||
|
/// </summary>
|
||||||
public string Installazione { get; set; } = "";
|
public string Installazione { get; set; } = "";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Master key licenza principale
|
||||||
|
/// </summary>
|
||||||
public string MasterKey { get; set; } = "";
|
public string MasterKey { get; set; } = "";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Numero licenze da DB
|
||||||
|
/// </summary>
|
||||||
|
public int NumLicDb { get; set; } = -1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Numero licenze da auth remota
|
||||||
|
/// </summary>
|
||||||
|
public int NumLicRemote { get; set; } = -1;
|
||||||
|
|
||||||
public bool ValidData
|
public bool ValidData
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -160,7 +182,7 @@ namespace MP.Land.Data
|
|||||||
RestClient client = new RestClient(apiUrl);
|
RestClient client = new RestClient(apiUrl);
|
||||||
//client.Authenticator = new HttpBasicAuthenticator("username", "password");
|
//client.Authenticator = new HttpBasicAuthenticator("username", "password");
|
||||||
string MKeyEnc = HttpUtility.UrlEncode(MasterKey);
|
string MKeyEnc = HttpUtility.UrlEncode(MasterKey);
|
||||||
var request = new RestRequest($"/api/attivazioni/?chiave={MKeyEnc}", Method.Get);
|
var request = new RestRequest($"api/attivazioni/?chiave={MKeyEnc}", Method.Get);
|
||||||
var response = await client.GetAsync(request);
|
var response = await client.GetAsync(request);
|
||||||
// controllo risposta
|
// controllo risposta
|
||||||
if (response.StatusCode == System.Net.HttpStatusCode.OK)
|
if (response.StatusCode == System.Net.HttpStatusCode.OK)
|
||||||
@@ -172,6 +194,29 @@ namespace MP.Land.Data
|
|||||||
return await Task.FromResult(answ);
|
return await Task.FromResult(answ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recupera info licenza da remoto
|
||||||
|
/// </summary>
|
||||||
|
private async Task<List<LiManObj.ApplicativoDTO>> OnlineAppInfo()
|
||||||
|
{
|
||||||
|
List<LiManObj.ApplicativoDTO> answ = new List<LiManObj.ApplicativoDTO>();
|
||||||
|
// cerco online
|
||||||
|
RestClient client = new RestClient(apiUrl);
|
||||||
|
string MKeyEnc = HttpUtility.UrlEncode(MasterKey);
|
||||||
|
//string mKey = System.Net.WebUtility.UrlEncode(MasterKey);
|
||||||
|
string reqUrl = $"api/licenza/{Installazione}?CodApp={Applicazione}&Chiave={MKeyEnc}";
|
||||||
|
var request = new RestRequest(reqUrl, Method.Get);
|
||||||
|
var response = await client.GetAsync(request);
|
||||||
|
// controllo risposta
|
||||||
|
if (response.StatusCode == System.Net.HttpStatusCode.OK)
|
||||||
|
{
|
||||||
|
// verifico risposta
|
||||||
|
string rawData = $"{response.Content}";
|
||||||
|
answ = JsonConvert.DeserializeObject<List<LiManObj.ApplicativoDTO>?>(rawData);
|
||||||
|
}
|
||||||
|
return await Task.FromResult(answ);
|
||||||
|
}
|
||||||
|
|
||||||
private void ReportUpdated()
|
private void ReportUpdated()
|
||||||
{
|
{
|
||||||
if (EA_InfoUpdated != null)
|
if (EA_InfoUpdated != null)
|
||||||
@@ -184,6 +229,25 @@ namespace MP.Land.Data
|
|||||||
|
|
||||||
#region Protected Methods
|
#region Protected Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cerca di recuperare valore INT da elenco AKV
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="varReq">Chiave AKV richiesta</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected int getAVKInt(string varReq)
|
||||||
|
{
|
||||||
|
int answ = -9999;
|
||||||
|
if (AKVList != null && AKVList.Count > 0)
|
||||||
|
{
|
||||||
|
var currRec = AKVList.Where(x => x.NomeVar == varReq).FirstOrDefault();
|
||||||
|
if (currRec != null)
|
||||||
|
{
|
||||||
|
answ = currRec.ValInt ?? 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return answ;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Cerca di recuperare valore string da elenco AKV
|
/// Cerca di recuperare valore string da elenco AKV
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -285,55 +349,6 @@ namespace MP.Land.Data
|
|||||||
return await Task.FromResult(dbResult);
|
return await Task.FromResult(dbResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Init della classe con variabili di base da Redis/DB
|
|
||||||
/// </summary>
|
|
||||||
public bool InitAkv()
|
|
||||||
{
|
|
||||||
bool fatto = false;
|
|
||||||
Applicazione = "MAPO";
|
|
||||||
Installazione = getAVKStr("Installazione");
|
|
||||||
MasterKey = getAVKStr(Applicazione);
|
|
||||||
fatto = !string.IsNullOrEmpty($"{Installazione}{MasterKey}");
|
|
||||||
return fatto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Init della classe con variabili di base da Redis/DB
|
|
||||||
/// </summary>
|
|
||||||
public async Task<bool> RefreshLicense()
|
|
||||||
{
|
|
||||||
bool fatto = false;
|
|
||||||
var onlineAct = await OnlineActivationList();
|
|
||||||
if (onlineAct != null)
|
|
||||||
{
|
|
||||||
if (onlineAct.Count > 0)
|
|
||||||
{
|
|
||||||
// scadenza info a 15 gg...
|
|
||||||
int numDays = 15;
|
|
||||||
infoExpiry = DateTime.Now.AddDays(numDays);
|
|
||||||
ActivList = onlineAct;
|
|
||||||
fatto = await setActivList(onlineAct, numDays);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await Task.Delay(1);
|
|
||||||
return fatto;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> setActivList(List<LiManObj.AttivazioneDTO> newActList, int numDays)
|
|
||||||
{
|
|
||||||
bool fatto = false;
|
|
||||||
string cacheKey = $"{rKeyAttByLic}:{MasterKey}";
|
|
||||||
var rawData = JsonConvert.SerializeObject(newActList);
|
|
||||||
await setRSV(cacheKey, rawData, numDays * cacheFact * 24);
|
|
||||||
fatto = true;
|
|
||||||
if (EA_InfoUpdated != null)
|
|
||||||
{
|
|
||||||
EA_InfoUpdated?.Invoke();
|
|
||||||
}
|
|
||||||
return fatto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Verifica attivazione licenza
|
/// Verifica attivazione licenza
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -363,6 +378,121 @@ namespace MP.Land.Data
|
|||||||
return answ;
|
return answ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stato server gestione licenze
|
||||||
|
/// </summary>
|
||||||
|
public async Task<string> checkLimanServer()
|
||||||
|
{
|
||||||
|
string answ = "ND";
|
||||||
|
// cerco online
|
||||||
|
RestClient client = new RestClient(apiUrl);
|
||||||
|
var request = new RestRequest($"api/health", Method.Get);
|
||||||
|
var response = await client.GetAsync(request);
|
||||||
|
// controllo risposta
|
||||||
|
if (response.StatusCode == System.Net.HttpStatusCode.OK)
|
||||||
|
{
|
||||||
|
// verifico risposta
|
||||||
|
answ = response.Content.Replace("\"", "");
|
||||||
|
}
|
||||||
|
return await Task.FromResult(answ);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Init della classe con variabili di base da Redis/DB
|
||||||
|
/// </summary>
|
||||||
|
public bool InitAkv()
|
||||||
|
{
|
||||||
|
bool fatto = false;
|
||||||
|
Applicazione = "MAPO";
|
||||||
|
Installazione = getAVKStr("Installazione");
|
||||||
|
MasterKey = getAVKStr(Applicazione);
|
||||||
|
NumLicDb = getAVKInt(Applicazione);
|
||||||
|
fatto = !string.IsNullOrEmpty($"{Installazione}{MasterKey}");
|
||||||
|
return fatto;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<LiManObj.ApplicativoDTO>> LicAppCache()
|
||||||
|
{
|
||||||
|
List<LiManObj.ApplicativoDTO> dbResult = new List<LiManObj.ApplicativoDTO>();
|
||||||
|
string cacheKey = $"{rkeyAppInfo}:{MasterKey}";
|
||||||
|
trackCache(cacheKey);
|
||||||
|
string rawData = await getRSV(cacheKey);
|
||||||
|
if (!string.IsNullOrEmpty(rawData))
|
||||||
|
{
|
||||||
|
var cacheRes = JsonConvert.DeserializeObject<List<LiManObj.ApplicativoDTO>?>(rawData);
|
||||||
|
if (cacheRes != null)
|
||||||
|
{
|
||||||
|
dbResult = cacheRes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return await Task.FromResult(dbResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Init della classe con variabili di base da Redis/DB
|
||||||
|
/// </summary>
|
||||||
|
public async Task<bool> RefreshLicense()
|
||||||
|
{
|
||||||
|
bool fatto = false;
|
||||||
|
// scadenza info a 15 gg...
|
||||||
|
int numDays = 15;
|
||||||
|
|
||||||
|
// dati applicativo
|
||||||
|
var appData = await OnlineAppInfo();
|
||||||
|
if (appData != null)
|
||||||
|
{
|
||||||
|
if (appData.Count > 0)
|
||||||
|
{
|
||||||
|
fatto = await setAppInfo(appData, numDays);
|
||||||
|
// salvo info licenza...
|
||||||
|
NumLicRemote = appData[0].NumLicenze;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// dati attivazioni
|
||||||
|
var onlineAct = await OnlineActivationList();
|
||||||
|
if (onlineAct != null)
|
||||||
|
{
|
||||||
|
if (onlineAct.Count > 0)
|
||||||
|
{
|
||||||
|
infoExpiry = DateTime.Now.AddDays(numDays);
|
||||||
|
ActivList = onlineAct;
|
||||||
|
fatto = await setActivList(onlineAct, numDays);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await Task.Delay(1);
|
||||||
|
return fatto;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> setActivList(List<LiManObj.AttivazioneDTO> newActList, int numDays)
|
||||||
|
{
|
||||||
|
bool fatto = false;
|
||||||
|
string cacheKey = $"{rKeyAttByLic}:{MasterKey}";
|
||||||
|
var rawData = JsonConvert.SerializeObject(newActList);
|
||||||
|
await setRSV(cacheKey, rawData, numDays * cacheFact * 24);
|
||||||
|
fatto = true;
|
||||||
|
if (EA_InfoUpdated != null)
|
||||||
|
{
|
||||||
|
EA_InfoUpdated?.Invoke();
|
||||||
|
}
|
||||||
|
return fatto;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> setAppInfo(List<LiManObj.ApplicativoDTO> newAppInfo, int numDays)
|
||||||
|
{
|
||||||
|
bool fatto = false;
|
||||||
|
string cacheKey = $"{rkeyAppInfo}:{MasterKey}";
|
||||||
|
var rawData = JsonConvert.SerializeObject(newAppInfo);
|
||||||
|
await setRSV(cacheKey, rawData, numDays * cacheFact * 24);
|
||||||
|
fatto = true;
|
||||||
|
if (EA_InfoUpdated != null)
|
||||||
|
{
|
||||||
|
EA_InfoUpdated?.Invoke();
|
||||||
|
}
|
||||||
|
return fatto;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion Public Methods
|
#endregion Public Methods
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,6 +106,21 @@ namespace MP.Land.Data
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected string _groupName { get; set; } = "";
|
||||||
|
public string CodGruppo
|
||||||
|
{
|
||||||
|
get => _groupName;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_groupName != value)
|
||||||
|
{
|
||||||
|
_groupName = value;
|
||||||
|
ReportFilter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endregion Public Properties
|
#endregion Public Properties
|
||||||
|
|
||||||
#region Private Methods
|
#region Private Methods
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ namespace MP.Land.Data
|
|||||||
public bool OnlyMod { get; set; } = false;
|
public bool OnlyMod { get; set; } = false;
|
||||||
public bool OnlyNoTag { get; set; } = false;
|
public bool OnlyNoTag { get; set; } = false;
|
||||||
public int PageNum { get; set; } = 1;
|
public int PageNum { get; set; } = 1;
|
||||||
public int PageSize { get; set; } = 4;
|
public int PageSize { get; set; } = 6;
|
||||||
public string SearchVal { get; set; } = "";
|
public string SearchVal { get; set; } = "";
|
||||||
public string Tag { get; set; } = "";
|
public string Tag { get; set; } = "";
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<RootNamespace>MP.Land</RootNamespace>
|
<RootNamespace>MP.Land</RootNamespace>
|
||||||
<Version>6.15.2204.1216</Version>
|
<Version>6.15.2207.0419</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
+59
-15
@@ -2,9 +2,10 @@
|
|||||||
@using MP.Land.Data
|
@using MP.Land.Data
|
||||||
|
|
||||||
@inject MessageService AppMService
|
@inject MessageService AppMService
|
||||||
|
@inject LicenseService LicServ
|
||||||
|
|
||||||
<div class="row mx-2">
|
<div class="row mx-2">
|
||||||
<div class="col-12 col-lg-8 offset-lg-2">
|
<div class="col-12 col-lg-10 offset-lg-1">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-center">
|
<div class="card-header text-center">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -28,28 +29,71 @@
|
|||||||
<img src="img/LogoMapoFull.png" class="img-fluid" />
|
<img src="img/LogoMapoFull.png" class="img-fluid" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-3"></div>
|
<div class="col-lg-3"></div>
|
||||||
<div class="col-12">
|
<div class="col-6">
|
||||||
<h4 class="card-title">@Messaggio</h4>
|
<h4 class="card-title">@Messaggio</h4>
|
||||||
|
<br />
|
||||||
<p>MoonPro / MAPO sono una suite di applicazioni e dispositivi hw dedicati per l'IOT,l'industry 4.0 e la gestione automatizzata dei processi produttivi.</p>
|
<p>MoonPro / MAPO sono una suite di applicazioni e dispositivi hw dedicati per l'IOT,l'industry 4.0 e la gestione automatizzata dei processi produttivi.</p>
|
||||||
|
<hr />
|
||||||
<p>Per maggiori informazioni <a href="http://www.steamware.net/iot" target="_blank">visita il link</a> sul nostro sito.</p>
|
<p>Per maggiori informazioni <a href="http://www.steamware.net/iot" target="_blank">visita il link</a> sul nostro sito.</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-6 text-right">
|
||||||
|
<div runat="server" id="divCheck" class="@mainCss">
|
||||||
|
<h4>Info installazione</h4>
|
||||||
|
<hr />
|
||||||
|
<div class="d-flex justify-content-between @remSrvCss">
|
||||||
|
<div class="px-2">
|
||||||
|
<i class="fa fa-server" aria-hidden="true"></i> Remote Server:
|
||||||
|
</div>
|
||||||
|
<div class="px-2">
|
||||||
|
<b>@ServerStatus</b>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<div class="px-2">
|
||||||
|
<i class="fa fa-certificate" aria-hidden="true"></i> Cliente:
|
||||||
|
</div>
|
||||||
|
<div class="px-2">
|
||||||
|
<b>@Installazione</b>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<div class="px-2">
|
||||||
|
<i class="fa fa-desktop" aria-hidden="true"></i> App:
|
||||||
|
</div>
|
||||||
|
<div class="px-2">
|
||||||
|
<b>@Applicazione</b>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<div class="px-2">
|
||||||
|
<i class="fa fa-users" aria-hidden="true"></i> Licenze:
|
||||||
|
</div>
|
||||||
|
<div class="px-2">
|
||||||
|
<b title="# Licenze locali / # Licenze Remote">@Licenze</b>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-between @expDateCss">
|
||||||
|
<div class="px-2">
|
||||||
|
<i class="far fa-calendar-check" aria-hidden="true"></i> Scadenza:
|
||||||
|
</div>
|
||||||
|
<div class="px-2">
|
||||||
|
<b>@($"{Scadenza:yyyy/MM/dd}")</b>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<div class="px-2">
|
||||||
|
<i class="fa fa-key" aria-hidden="true"></i> Key
|
||||||
|
</div>
|
||||||
|
<div class="px-2">
|
||||||
|
<span Font-Size="0.6em" class="small">@MastKey</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
protected string Titolo = "";
|
|
||||||
protected string Messaggio = "";
|
|
||||||
|
|
||||||
protected override void OnInitialized()
|
|
||||||
{
|
|
||||||
Titolo = "MES | SCADA | IOT";
|
|
||||||
Messaggio = "Soluzione integrata per la gestione della produzione";
|
|
||||||
AppMService.ShowSearch = false;
|
|
||||||
AppMService.PageName = "About";
|
|
||||||
AppMService.PageIcon = "fas fa-info-circle pr-2";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using System.Net.Http;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Components.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Components.Forms;
|
||||||
|
using Microsoft.AspNetCore.Components.Routing;
|
||||||
|
using Microsoft.AspNetCore.Components.Web;
|
||||||
|
using Microsoft.AspNetCore.Components.Web.Virtualization;
|
||||||
|
using Microsoft.JSInterop;
|
||||||
|
using MP.Land;
|
||||||
|
using MP.Land.Shared;
|
||||||
|
using MP.Land.Data;
|
||||||
|
|
||||||
|
namespace MP.Land.Pages
|
||||||
|
{
|
||||||
|
public partial class About
|
||||||
|
{
|
||||||
|
protected string Titolo = "";
|
||||||
|
protected string Messaggio = "";
|
||||||
|
|
||||||
|
protected string ServerStatus = "SrvState";
|
||||||
|
protected string Installazione = "Inst";
|
||||||
|
protected string Applicazione = "App";
|
||||||
|
protected string Licenze = "#";
|
||||||
|
protected DateTime Scadenza = DateTime.Today;
|
||||||
|
protected string MastKey = "########################";
|
||||||
|
|
||||||
|
protected string mainCss = "alert alert-info";
|
||||||
|
protected string remSrvCss = "bg-danger text-warning";
|
||||||
|
protected string expDateCss = "bg-danger text-warning";
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
updatePageHead();
|
||||||
|
|
||||||
|
await reloadLicenseData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task reloadLicenseData()
|
||||||
|
{
|
||||||
|
int cDelay = 5;
|
||||||
|
// recupero dati
|
||||||
|
await Task.Delay(cDelay);
|
||||||
|
LicServ.InitAkv();
|
||||||
|
Installazione = LicServ.Installazione;
|
||||||
|
Applicazione = LicServ.Applicazione;
|
||||||
|
MastKey = LicServ.MasterKey;
|
||||||
|
await Task.Delay(cDelay);
|
||||||
|
var fatto = await LicServ.RefreshLicense();
|
||||||
|
await Task.Delay(cDelay);
|
||||||
|
Licenze = $"{LicServ.NumLicDb}/{LicServ.NumLicRemote}";
|
||||||
|
// verifico stati
|
||||||
|
ServerStatus = await LicServ.checkLimanServer();
|
||||||
|
bool okRemoteSrv = ServerStatus == "OK";
|
||||||
|
bool okScadenza = LicServ.checkLicenseActive(LicServ.MasterKey);
|
||||||
|
bool okNumLic = (LicServ.NumLicDb <= LicServ.NumLicRemote);
|
||||||
|
|
||||||
|
// aggiornamento css secondo status colore da check
|
||||||
|
mainCss = okNumLic ? "alert alert-success shadowBox" : "alert alert-warning shadowBox";
|
||||||
|
expDateCss = okScadenza ? "d-flex justify-content-between" : "d-flex justify-content-between bg-danger text-warning";
|
||||||
|
remSrvCss = okRemoteSrv ? "d-flex justify-content-between" : "d-flex justify-content-between bg-danger text-warning";
|
||||||
|
await Task.Delay(cDelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePageHead()
|
||||||
|
{
|
||||||
|
Titolo = "MES | SCADA | IOT";
|
||||||
|
Messaggio = "Soluzione integrata per la gestione della produzione";
|
||||||
|
AppMService.ShowSearch = false;
|
||||||
|
AppMService.PageName = "About";
|
||||||
|
AppMService.PageIcon = "fas fa-info-circle pr-2";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
<CmpGroupFilt></CmpGroupFilt>
|
||||||
@if (ListRecords == null)
|
@if (ListRecords == null)
|
||||||
{
|
{
|
||||||
<LoadingData></LoadingData>
|
<LoadingData></LoadingData>
|
||||||
@@ -15,6 +16,7 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@foreach (var item in ListRecords)
|
@foreach (var item in ListRecords)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,12 +11,14 @@ namespace MP.Land.Pages
|
|||||||
{
|
{
|
||||||
public partial class UserQr : IDisposable
|
public partial class UserQr : IDisposable
|
||||||
{
|
{
|
||||||
#region Private Fields
|
#region Public Methods
|
||||||
|
|
||||||
private List<AnagraficaOperatori> ListRecords;
|
public void Dispose()
|
||||||
private List<AnagraficaOperatori> SearchRecords;
|
{
|
||||||
|
AppMService.EA_SearchUpdated -= OnSeachUpdated;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion Private Fields
|
#endregion Public Methods
|
||||||
|
|
||||||
#region Protected Fields
|
#region Protected Fields
|
||||||
|
|
||||||
@@ -25,39 +27,6 @@ namespace MP.Land.Pages
|
|||||||
|
|
||||||
#endregion Protected Fields
|
#endregion Protected Fields
|
||||||
|
|
||||||
#region Private Properties
|
|
||||||
|
|
||||||
[Inject]
|
|
||||||
private IConfiguration Configuration { get; set; }
|
|
||||||
|
|
||||||
private int currPage
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return AppMService.SelFilter.PageNum;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
AppMService.SelFilter.PageNum = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool isLoading { get; set; } = false;
|
|
||||||
|
|
||||||
private int numRecord
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return AppMService.SelFilter.PageSize;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
AppMService.SelFilter.PageSize = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Private Properties
|
|
||||||
|
|
||||||
#region Protected Properties
|
#region Protected Properties
|
||||||
|
|
||||||
[Inject]
|
[Inject]
|
||||||
@@ -78,18 +47,6 @@ namespace MP.Land.Pages
|
|||||||
|
|
||||||
#endregion Protected Properties
|
#endregion Protected Properties
|
||||||
|
|
||||||
#region Private Methods
|
|
||||||
|
|
||||||
private async void OnSeachUpdated()
|
|
||||||
{
|
|
||||||
ListRecords = null;
|
|
||||||
currPage = 1;
|
|
||||||
await Task.Delay(1);
|
|
||||||
await ReloadData();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Private Methods
|
|
||||||
|
|
||||||
#region Protected Methods
|
#region Protected Methods
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
@@ -99,6 +56,7 @@ namespace MP.Land.Pages
|
|||||||
AppMService.PageIcon = "fas fa-qrcode pr-2";
|
AppMService.PageIcon = "fas fa-qrcode pr-2";
|
||||||
await ReloadData();
|
await ReloadData();
|
||||||
AppMService.EA_SearchUpdated += OnSeachUpdated;
|
AppMService.EA_SearchUpdated += OnSeachUpdated;
|
||||||
|
AppMService.EA_FilterUpdated += OnFilterUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task PagerReloadNum(int newNum)
|
protected async Task PagerReloadNum(int newNum)
|
||||||
@@ -117,19 +75,6 @@ namespace MP.Land.Pages
|
|||||||
isLoading = false;
|
isLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task ReloadData()
|
|
||||||
{
|
|
||||||
isLoading = true;
|
|
||||||
// importante altrimenti NON mostra update UI
|
|
||||||
await Task.Delay(1);
|
|
||||||
SearchRecords = await DataService.AnagOperList(AppMService.SearchVal);
|
|
||||||
ListRecords = SearchRecords.Skip((currPage - 1) * numRecord).Take(numRecord).ToList();
|
|
||||||
totalCount = SearchRecords.Count();
|
|
||||||
await Task.Delay(1);
|
|
||||||
isLoading = false;
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected MarkupString traduci(string lemma)
|
protected MarkupString traduci(string lemma)
|
||||||
{
|
{
|
||||||
MarkupString answ;
|
MarkupString answ;
|
||||||
@@ -142,13 +87,95 @@ namespace MP.Land.Pages
|
|||||||
|
|
||||||
#endregion Protected Methods
|
#endregion Protected Methods
|
||||||
|
|
||||||
#region Public Methods
|
#region Private Fields
|
||||||
|
|
||||||
public void Dispose()
|
private List<AnagraficaOperatori> ListRecords;
|
||||||
|
|
||||||
|
private List<AnagraficaOperatori> SearchRecords;
|
||||||
|
|
||||||
|
#endregion Private Fields
|
||||||
|
|
||||||
|
#region Private Properties
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
private IConfiguration Configuration { get; set; }
|
||||||
|
|
||||||
|
private int currPage
|
||||||
{
|
{
|
||||||
AppMService.EA_SearchUpdated -= OnSeachUpdated;
|
get
|
||||||
|
{
|
||||||
|
return AppMService.SelFilter.PageNum;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
AppMService.SelFilter.PageNum = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion Public Methods
|
private string groupName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return AppMService.CodGruppo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool isLoading { get; set; } = false;
|
||||||
|
|
||||||
|
private int numRecord
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return AppMService.SelFilter.PageSize;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
AppMService.SelFilter.PageSize = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Private Properties
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
|
private async void OnFilterUpdated()
|
||||||
|
{
|
||||||
|
ListRecords = null;
|
||||||
|
currPage = 1;
|
||||||
|
await Task.Delay(1);
|
||||||
|
await ReloadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void OnSeachUpdated()
|
||||||
|
{
|
||||||
|
ListRecords = null;
|
||||||
|
currPage = 1;
|
||||||
|
await Task.Delay(1);
|
||||||
|
await ReloadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ReloadData()
|
||||||
|
{
|
||||||
|
isLoading = true;
|
||||||
|
// importante altrimenti NON mostra update UI
|
||||||
|
await Task.Delay(1);
|
||||||
|
// se ho selezionato qualcosa cerco x gruppo
|
||||||
|
//if (groupName != "")
|
||||||
|
//{
|
||||||
|
SearchRecords = await DataService.AnagOperByGroupList(groupName, AppMService.SearchVal);
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// //altrimenti TUTTI
|
||||||
|
// SearchRecords = await DataService.AnagOperList(AppMService.SearchVal);
|
||||||
|
//}
|
||||||
|
ListRecords = SearchRecords.Skip((currPage - 1) * numRecord).Take(numRecord).ToList();
|
||||||
|
totalCount = SearchRecords.Count();
|
||||||
|
await Task.Delay(1);
|
||||||
|
isLoading = false;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Private Methods
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,31 +52,6 @@
|
|||||||
<script src="_framework/blazor.server.js"></script>
|
<script src="_framework/blazor.server.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="~/lib/qrcode.js"></script>
|
<script type="text/javascript" src="~/lib/qrcode.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript" src="~/lib/qrHelper.js"></script>
|
||||||
function clearContent(elementID) {
|
|
||||||
console.log(elementID);
|
|
||||||
document.getElementById(elementID).innerHTML = "";
|
|
||||||
}
|
|
||||||
// gestione qrcode... da https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity-enable-qrcodes?view=aspnetcore-5.0
|
|
||||||
//var qrcode = new QRCode("qrCodeImg");
|
|
||||||
function displayQr(elementName, rawData) {
|
|
||||||
console.log(elementName);
|
|
||||||
try {
|
|
||||||
if (elementName != "" && rawData != "") {
|
|
||||||
qrcode = new QRCode(document.getElementById(elementName),
|
|
||||||
{
|
|
||||||
text: rawData,
|
|
||||||
width: 200,
|
|
||||||
height: 200
|
|
||||||
});
|
|
||||||
//qrcode = new QRCode(document.getElementById(elementName));
|
|
||||||
//qrcode.clear();
|
|
||||||
//qrcode.makeCode(rawData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{ }
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<body>
|
<body>
|
||||||
<i>Modulo gestione Programmi MAPO</i>
|
<i>Modulo gestione Programmi MAPO</i>
|
||||||
<h4>Versione: 6.15.2204.1216</h4>
|
<h4>Versione: 6.15.2207.0419</h4>
|
||||||
<br />
|
<br />
|
||||||
Note di rilascio:
|
Note di rilascio:
|
||||||
<ul>
|
<ul>
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
6.15.2204.1216
|
6.15.2207.0419
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<item>
|
<item>
|
||||||
<version>6.15.2204.1216</version>
|
<version>6.15.2207.0419</version>
|
||||||
<url>https://nexus.steamware.net/repository/SWS/MP-LAND/stable/LAST/MP.Land.zip</url>
|
<url>https://nexus.steamware.net/repository/SWS/MP-LAND/stable/LAST/MP.Land.zip</url>
|
||||||
<changelog>https://nexus.steamware.net/repository/SWS/MP-LAND/stable/LAST/ChangeLog.html</changelog>
|
<changelog>https://nexus.steamware.net/repository/SWS/MP-LAND/stable/LAST/ChangeLog.html</changelog>
|
||||||
<mandatory>false</mandatory>
|
<mandatory>false</mandatory>
|
||||||
|
|||||||
@@ -63,6 +63,52 @@ a,
|
|||||||
.footer {
|
.footer {
|
||||||
line-height: 1.8em;
|
line-height: 1.8em;
|
||||||
}
|
}
|
||||||
|
.textTrim {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.maxChar {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.max5Char {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 5rem;
|
||||||
|
}
|
||||||
|
.max10Char {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 10rem;
|
||||||
|
}
|
||||||
|
.max20Char {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 20rem;
|
||||||
|
}
|
||||||
|
.max30Char {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 30rem;
|
||||||
|
}
|
||||||
|
.max40Char {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 40rem;
|
||||||
|
}
|
||||||
|
.max50Char {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 50rem;
|
||||||
|
}
|
||||||
/*------------------------------------------------------------------
|
/*------------------------------------------------------------------
|
||||||
[ Shortcuts / .shortcuts ]
|
[ Shortcuts / .shortcuts ]
|
||||||
*/
|
*/
|
||||||
@@ -76,7 +122,7 @@ a,
|
|||||||
min-width: 9rem;
|
min-width: 9rem;
|
||||||
min-height: 5rem;
|
min-height: 5rem;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 0.66666667rem 0;
|
padding: 2rem/3 0;
|
||||||
margin: 0 2px 1em;
|
margin: 0 2px 1em;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
@@ -89,13 +135,13 @@ a,
|
|||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffeeeeee', GradientType=0);
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffeeeeee', GradientType=0);
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border-radius: 0.5rem;
|
border-radius: 1rem/2;
|
||||||
}
|
}
|
||||||
.shortcuts .shortcut-sm {
|
.shortcuts .shortcut-sm {
|
||||||
min-width: 4.5rem;
|
min-width: 4.5rem;
|
||||||
min-height: 3rem;
|
min-height: 3rem;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 0.25rem 0;
|
padding: 1rem/4 0;
|
||||||
margin: 0 2px 1em;
|
margin: 0 2px 1em;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
@@ -108,7 +154,7 @@ a,
|
|||||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffeeeeee', GradientType=0);
|
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffeeeeee', GradientType=0);
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border-radius: 0.5rem;
|
border-radius: 1rem/2;
|
||||||
}
|
}
|
||||||
.shortcuts .shortcut .shortcut-icon {
|
.shortcuts .shortcut .shortcut-icon {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -63,6 +63,50 @@ a, .btn-link {
|
|||||||
line-height: 1.8em;
|
line-height: 1.8em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.textTrim {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.maxChar {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.max5Char {
|
||||||
|
.maxChar;
|
||||||
|
width: 5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.max10Char {
|
||||||
|
.maxChar;
|
||||||
|
width: 10rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.max20Char {
|
||||||
|
.maxChar;
|
||||||
|
width: 20rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.max30Char {
|
||||||
|
.maxChar;
|
||||||
|
width: 30rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.max40Char {
|
||||||
|
.maxChar;
|
||||||
|
width: 40rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.max50Char {
|
||||||
|
.maxChar;
|
||||||
|
width: 50rem;
|
||||||
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------
|
/*------------------------------------------------------------------
|
||||||
[ Shortcuts / .shortcuts ]
|
[ Shortcuts / .shortcuts ]
|
||||||
*/
|
*/
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
@import url('open-iconic/font/css/open-iconic-bootstrap.min.css');@import url('fonts.min.css');h1,h2,h3,h4,h5,h6,b,display-1,display-2,display-3,display-4{font-family:'Lato',sans-serif}html,body,.textCondensed{font-family:'Roboto Condensed',sans-serif}a,.btn-link{color:#0366d6}.btn-primary{color:#fff;background-color:#1b6ec2;border-color:#1861ac}.content{padding-top:1.1rem}.valid.modified:not([type=checkbox]){outline:1px solid #26b050}.invalid{outline:1px solid #f00}.validation-message{color:#f00}.textStriked{text-decoration:line-through}#blazor-error-ui{background:#ffffe0;bottom:0;box-shadow:0 -1px 2px rgba(0,0,0,.2);display:none;left:0;padding:.6rem 1.25rem .7rem 1.25rem;position:fixed;width:100%;z-index:1000}#blazor-error-ui .dismiss{cursor:pointer;position:absolute;right:.75rem;top:.5rem}.footer{line-height:1.8em}.shortcuts{text-align:center}.shortcuts .shortcut-icon{font-size:2rem}.shortcuts .shortcut{min-width:9rem;min-height:5rem;display:inline-block;padding:.66666667rem 0;margin:0 2px 1em;vertical-align:top;text-decoration:none;background:#f3f3f3;background-image:-webkit-gradient(linear,left 0%,left 100%,from(#fff),to(#eee));background-image:-webkit-linear-gradient(top,#fff,0%,#eee,100%);background-image:-moz-linear-gradient(top,#fff 0%,#eee 100%);background-image:linear-gradient(to bottom,#fff 0%,#eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffeeeeee',GradientType=0);border:1px solid #ddd;box-sizing:border-box;border-radius:.5rem}.shortcuts .shortcut-sm{min-width:4.5rem;min-height:3rem;display:inline-block;padding:.25rem 0;margin:0 2px 1em;vertical-align:top;text-decoration:none;background:#f3f3f3;background-image:-webkit-gradient(linear,left 0%,left 100%,from(#fff),to(#eee));background-image:-webkit-linear-gradient(top,#fff,0%,#eee,100%);background-image:-moz-linear-gradient(top,#fff 0%,#eee 100%);background-image:linear-gradient(to bottom,#fff 0%,#eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffeeeeee',GradientType=0);border:1px solid #ddd;box-sizing:border-box;border-radius:.5rem}.shortcuts .shortcut .shortcut-icon{width:100%;margin-top:0;margin-bottom:0;font-size:2rem;color:#333}.shortcuts .shortcut-sm .shortcut-icon{width:100%;margin-top:0;margin-bottom:0;font-size:2rem;color:#333}.shortcuts .shortcut:hover{background:#e8e8e8;background-image:-webkit-gradient(linear,left 0%,left 100%,from(#fafafa),to(#e1e1e1));background-image:-webkit-linear-gradient(top,#fafafa,0%,#e1e1e1,100%);background-image:-moz-linear-gradient(top,#fafafa 0%,#e1e1e1 100%);background-image:linear-gradient(to bottom,#fafafa 0%,#e1e1e1 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa',endColorstr='#ffe1e1e1',GradientType=0)}.shortcuts .shortcut-sm:hover{background:#e8e8e8;background-image:-webkit-gradient(linear,left 0%,left 100%,from(#fafafa),to(#e1e1e1));background-image:-webkit-linear-gradient(top,#fafafa,0%,#e1e1e1,100%);background-image:-moz-linear-gradient(top,#fafafa 0%,#e1e1e1 100%);background-image:linear-gradient(to bottom,#fafafa 0%,#e1e1e1 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa',endColorstr='#ffe1e1e1',GradientType=0)}.shortcuts .shortcut:active{box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.shortcuts .shortcut-sm:active{box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.shortcuts .shortcut:hover .shortcut-icon{color:#c93}.shortcuts .shortcut-sm:hover .shortcut-icon{color:#666}.shortcuts .shortcut-label{display:block;margin-top:.75em;font-weight:400;color:#666}@media(max-width:640px){.shortcuts .shortcut{min-width:8rem;min-height:4rem}body{font-size:.8em}}
|
@import url('open-iconic/font/css/open-iconic-bootstrap.min.css');@import url('fonts.min.css');h1,h2,h3,h4,h5,h6,b,display-1,display-2,display-3,display-4{font-family:'Lato',sans-serif}html,body,.textCondensed{font-family:'Roboto Condensed',sans-serif}a,.btn-link{color:#0366d6}.btn-primary{color:#fff;background-color:#1b6ec2;border-color:#1861ac}.content{padding-top:1.1rem}.valid.modified:not([type=checkbox]){outline:1px solid #26b050}.invalid{outline:1px solid #f00}.validation-message{color:#f00}.textStriked{text-decoration:line-through}#blazor-error-ui{background:#ffffe0;bottom:0;box-shadow:0 -1px 2px rgba(0,0,0,.2);display:none;left:0;padding:.6rem 1.25rem .7rem 1.25rem;position:fixed;width:100%;z-index:1000}#blazor-error-ui .dismiss{cursor:pointer;position:absolute;right:.75rem;top:.5rem}.footer{line-height:1.8em}.textTrim{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.maxChar{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.max5Char{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:5rem}.max10Char{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:10rem}.max20Char{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:20rem}.max30Char{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:30rem}.max40Char{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:40rem}.max50Char{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:50rem}.shortcuts{text-align:center}.shortcuts .shortcut-icon{font-size:2rem}.shortcuts .shortcut{min-width:9rem;min-height:5rem;display:inline-block;padding:2rem/3 0;margin:0 2px 1em;vertical-align:top;text-decoration:none;background:#f3f3f3;background-image:-webkit-gradient(linear,left 0%,left 100%,from(#fff),to(#eee));background-image:-webkit-linear-gradient(top,#fff,0%,#eee,100%);background-image:-moz-linear-gradient(top,#fff 0%,#eee 100%);background-image:linear-gradient(to bottom,#fff 0%,#eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffeeeeee',GradientType=0);border:1px solid #ddd;box-sizing:border-box;border-radius:1rem/2}.shortcuts .shortcut-sm{min-width:4.5rem;min-height:3rem;display:inline-block;padding:1rem/4 0;margin:0 2px 1em;vertical-align:top;text-decoration:none;background:#f3f3f3;background-image:-webkit-gradient(linear,left 0%,left 100%,from(#fff),to(#eee));background-image:-webkit-linear-gradient(top,#fff,0%,#eee,100%);background-image:-moz-linear-gradient(top,#fff 0%,#eee 100%);background-image:linear-gradient(to bottom,#fff 0%,#eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffeeeeee',GradientType=0);border:1px solid #ddd;box-sizing:border-box;border-radius:1rem/2}.shortcuts .shortcut .shortcut-icon{width:100%;margin-top:0;margin-bottom:0;font-size:2rem;color:#333}.shortcuts .shortcut-sm .shortcut-icon{width:100%;margin-top:0;margin-bottom:0;font-size:2rem;color:#333}.shortcuts .shortcut:hover{background:#e8e8e8;background-image:-webkit-gradient(linear,left 0%,left 100%,from(#fafafa),to(#e1e1e1));background-image:-webkit-linear-gradient(top,#fafafa,0%,#e1e1e1,100%);background-image:-moz-linear-gradient(top,#fafafa 0%,#e1e1e1 100%);background-image:linear-gradient(to bottom,#fafafa 0%,#e1e1e1 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa',endColorstr='#ffe1e1e1',GradientType=0)}.shortcuts .shortcut-sm:hover{background:#e8e8e8;background-image:-webkit-gradient(linear,left 0%,left 100%,from(#fafafa),to(#e1e1e1));background-image:-webkit-linear-gradient(top,#fafafa,0%,#e1e1e1,100%);background-image:-moz-linear-gradient(top,#fafafa 0%,#e1e1e1 100%);background-image:linear-gradient(to bottom,#fafafa 0%,#e1e1e1 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa',endColorstr='#ffe1e1e1',GradientType=0)}.shortcuts .shortcut:active{box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.shortcuts .shortcut-sm:active{box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.shortcuts .shortcut:hover .shortcut-icon{color:#c93}.shortcuts .shortcut-sm:hover .shortcut-icon{color:#666}.shortcuts .shortcut-label{display:block;margin-top:.75em;font-weight:400;color:#666}@media(max-width:640px){.shortcuts .shortcut{min-width:8rem;min-height:4rem}body{font-size:.8em}}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
function clearContent(elementID) {
|
||||||
|
//console.log("Remove " + elementID);
|
||||||
|
document.getElementById(elementID).innerHTML = "";
|
||||||
|
}
|
||||||
|
// gestione qrcode... da https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity-enable-qrcodes?view=aspnetcore-5.0
|
||||||
|
//var qrcode = new QRCode("qrCodeImg");
|
||||||
|
function displayQr(elementName, rawData) {
|
||||||
|
//console.log("Add " + elementName);
|
||||||
|
try {
|
||||||
|
if (elementName != "" && rawData != "") {
|
||||||
|
qrcode = new QRCode(document.getElementById(elementName),
|
||||||
|
{
|
||||||
|
text: rawData,
|
||||||
|
width: 200,
|
||||||
|
height: 200
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{ }
|
||||||
|
}
|
||||||
@@ -9,6 +9,17 @@
|
|||||||
<div class="d-flex mb-1 ui-title justify-content-center align-items-center text-uppercase">
|
<div class="d-flex mb-1 ui-title justify-content-center align-items-center text-uppercase">
|
||||||
@CurrRecord.Nome
|
@CurrRecord.Nome
|
||||||
</div>
|
</div>
|
||||||
|
@if (hasRow(1))
|
||||||
|
{
|
||||||
|
<div class="d-flex justify-content-between pt-0 pb-0 px-1">
|
||||||
|
@foreach (var item in rowValues(1))
|
||||||
|
{
|
||||||
|
<div class="px-1 @item.TagCss">@item.TagName: <b>@currVal(item.TagLocation)</b></div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
<div class="d-flex justify-content-between pt-0 pb-2 px-1 fontSmall text-uppercase">
|
<div class="d-flex justify-content-between pt-0 pb-2 px-1 fontSmall text-uppercase">
|
||||||
<div class="px-1 pe-0">Art</div>
|
<div class="px-1 pe-0">Art</div>
|
||||||
<div class="px-1 ps-0 ui-art">
|
<div class="px-1 ps-0 ui-art">
|
||||||
@@ -29,10 +40,34 @@
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
@if (hasRow(2))
|
||||||
|
{
|
||||||
|
<div class="d-flex justify-content-between pt-0 pb-0 px-1">
|
||||||
|
@foreach (var item in rowValues(2))
|
||||||
|
{
|
||||||
|
<div class="px-1 @item.TagCss">@item.TagName: <b>@currVal(item.TagLocation)</b></div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
<div class="d-flex justify-content-between pt-0 pb-2 px-1 fontSmall">
|
<div class="d-flex justify-content-between pt-0 pb-2 px-1 fontSmall">
|
||||||
<div class="px-1 text-uppercase"><b>@CurrRecord.DescrizioneStato</b></div>
|
<div class="px-1 text-uppercase"><b>@CurrRecord.DescrizioneStato</b></div>
|
||||||
<div class="px-1 ps-0">@getMinSec((decimal)CurrRecord.Durata)</div>
|
<div class="px-1 ps-0">@getMinSec((decimal)CurrRecord.Durata)</div>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
@if (hasRow(3))
|
||||||
|
{
|
||||||
|
<div class="d-flex justify-content-between pt-0 pb-0 px-1">
|
||||||
|
@foreach (var item in rowValues(3))
|
||||||
|
{
|
||||||
|
<div class="px-1 @item.TagCss">@item.TagName: <b>@currVal(item.TagLocation)</b></div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
<div class="d-flex justify-content-between pt-0 pb-2 px-1 fontSmall text-uppercase">
|
<div class="d-flex justify-content-between pt-0 pb-2 px-1 fontSmall text-uppercase">
|
||||||
@*<div class="col-6 pe-0">OEE</div>
|
@*<div class="col-6 pe-0">OEE</div>
|
||||||
<div class="col-6 ps-0">xx%</div>*@
|
<div class="col-6 ps-0">xx%</div>*@
|
||||||
@@ -40,13 +75,41 @@
|
|||||||
<div class="px-1 ps-0">std: @getMinSec(@CurrRecord.TCAssegnato)</div>
|
<div class="px-1 ps-0">std: @getMinSec(@CurrRecord.TCAssegnato)</div>
|
||||||
<div class="px-1 ps-0">act: @getMinSec(@CurrRecord.TCLavRT)</div>
|
<div class="px-1 ps-0">act: @getMinSec(@CurrRecord.TCLavRT)</div>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
@if (hasRow(4))
|
||||||
|
{
|
||||||
|
<div class="d-flex justify-content-between pt-0 pb-0 px-1">
|
||||||
|
@foreach (var item in rowValues(4))
|
||||||
|
{
|
||||||
|
<div class="px-1 @item.TagCss">@item.TagName: <b>@currVal(item.TagLocation)</b></div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
<div class="d-flex justify-content-between pt-0 pb-0 px-1 fontSmall1 text-uppercase">
|
<div class="d-flex justify-content-between pt-0 pb-0 px-1 fontSmall1 text-uppercase">
|
||||||
@*<div class="px-1 pe-0">Pezzi</div>
|
|
||||||
<div class="px-1 ps-0">prod: @CurrRecord.PezziProd</div>
|
|
||||||
<div class="px-1 ps-0">ord: @CurrRecord.NumPezzi</div>*@
|
|
||||||
<div class="px-1 pe-0">Pezzi<sub>(prod/ord)</sub></div>
|
<div class="px-1 pe-0">Pezzi<sub>(prod/ord)</sub></div>
|
||||||
<div class="px-1 ps-0">@CurrRecord.PezziProd / @CurrRecord.NumPezzi</div>
|
<div class="px-1 ps-0">@CurrRecord.PezziProd / @CurrRecord.NumPezzi</div>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
@if (hasRow(5))
|
||||||
|
{
|
||||||
|
<div class="d-flex justify-content-between pt-0 pb-0 px-1">
|
||||||
|
@foreach (var item in rowValues(5))
|
||||||
|
{
|
||||||
|
<div class="px-1 @item.TagCss">@item.TagName: <b>@currVal(item.TagLocation)</b></div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@if (hasRow(6))
|
||||||
|
{
|
||||||
|
<div class="d-flex justify-content-between pt-0 pb-0 px-1">
|
||||||
|
@foreach (var item in rowValues(6))
|
||||||
|
{
|
||||||
|
<div class="px-1 @item.TagCss">@item.TagName: <b>@currVal(item.TagLocation)</b></div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="@cssComStatus(CurrRecord.Semaforo, CurrRecord.LastUpdate) p-1">
|
<div class="@cssComStatus(CurrRecord.Semaforo, CurrRecord.LastUpdate) p-1">
|
||||||
<div class="row fontSmaller mt-1">
|
<div class="row fontSmaller mt-1">
|
||||||
|
|||||||
@@ -15,45 +15,168 @@ using MP.Mon;
|
|||||||
using MP.Mon.Shared;
|
using MP.Mon.Shared;
|
||||||
using MP.Mon.Components;
|
using MP.Mon.Components;
|
||||||
using MP.Data.DatabaseModels;
|
using MP.Data.DatabaseModels;
|
||||||
|
using MP.Data.Conf;
|
||||||
|
|
||||||
namespace MP.Mon.Components
|
namespace MP.Mon.Components
|
||||||
{
|
{
|
||||||
public partial class DetailMSE
|
public partial class DetailMSE
|
||||||
{
|
{
|
||||||
|
#region Protected Fields
|
||||||
|
|
||||||
protected string baseCss = "sem";
|
protected string baseCss = "sem";
|
||||||
protected bool dataLoaded { get; set; } = false;
|
|
||||||
protected int kaFactor = 60 / 2;
|
protected int kaFactor = 60 / 2;
|
||||||
|
|
||||||
|
#endregion Protected Fields
|
||||||
|
|
||||||
|
#region Private Fields
|
||||||
|
|
||||||
|
private static System.Timers.Timer aTimer = new System.Timers.Timer(60 * 1000);
|
||||||
|
|
||||||
|
#endregion Private Fields
|
||||||
|
|
||||||
|
#region Public Properties
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public MappaStatoExpl? CurrRecord { get; set; } = null;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public List<TagData>? currTagConf { get; set; } = null;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public Dictionary<string, string> currTagVal { get; set; } = new Dictionary<string, string>();
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public bool doAnimate { get; set; } = true;
|
public bool doAnimate { get; set; } = true;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public int keepAliveMin { get; set; } = 5;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string showArt { get; set; } = "";
|
public string showArt { get; set; } = "";
|
||||||
|
|
||||||
[Parameter]
|
#endregion Public Properties
|
||||||
public int keepAliveMin { get; set; } = 5;
|
|
||||||
[Parameter]
|
|
||||||
public MappaStatoExpl? CurrRecord { get; set; } = null;
|
|
||||||
|
|
||||||
private string cssStatus(string codSemaforo)
|
/// <summary>
|
||||||
|
/// Verifica se ci sia un override per la riga indicata
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="numRow"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected bool hasRow(int numRow)
|
||||||
{
|
{
|
||||||
string codColore = codSemaforo.Substring(1, 2);
|
bool answ = false;
|
||||||
string answ = $"{baseCss}{codColore}";
|
if (currTagConf != null)
|
||||||
if (doAnimate && codColore != "Ve")
|
|
||||||
{
|
{
|
||||||
// blink se secondo pari...
|
if (currTagConf.Count > 0)
|
||||||
DateTime adesso = DateTime.Now;
|
|
||||||
int resto = 0;
|
|
||||||
Math.DivRem(adesso.Second, 2, out resto);
|
|
||||||
if (resto == 0)
|
|
||||||
{
|
{
|
||||||
answ += "_b";
|
var currVals = rowValues(numRow);
|
||||||
|
answ = currVals.Count > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return answ;
|
return answ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Restituisce (se presenti) valori di override per la riga indicata
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="numRow"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected List<TagData> rowValues(int numRow)
|
||||||
|
{
|
||||||
|
List<TagData>? rowVals = null;
|
||||||
|
if (currTagConf != null)
|
||||||
|
{
|
||||||
|
if (currTagConf.Count > 0)
|
||||||
|
{
|
||||||
|
//cerco solo la riga corrente...
|
||||||
|
rowVals = currTagConf.Where(x => x.RowNum == numRow).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rowVals == null)
|
||||||
|
{
|
||||||
|
rowVals = new List<TagData>();
|
||||||
|
}
|
||||||
|
return rowVals;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// restituisce il valore data la tagLocation
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tagLocation"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected string currVal(string tagLocation)
|
||||||
|
{
|
||||||
|
string answ = "";
|
||||||
|
if (currTagVal.ContainsKey(tagLocation))
|
||||||
|
{
|
||||||
|
answ = currTagVal[tagLocation];
|
||||||
|
}
|
||||||
|
return answ;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Protected Properties
|
||||||
|
|
||||||
|
protected string codIOB
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string answ = "";
|
||||||
|
if (CurrRecord != null)
|
||||||
|
{
|
||||||
|
answ = CurrRecord.IdxMacchina;
|
||||||
|
}
|
||||||
|
return answ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool dataLoaded { get; set; } = false;
|
||||||
|
|
||||||
|
#endregion Protected Properties
|
||||||
|
|
||||||
|
#region Public Methods
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
aTimer.Stop();
|
||||||
|
aTimer.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ElapsedTimer(Object source, System.Timers.ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
var pUpd = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await Task.Delay(1);
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
});
|
||||||
|
pUpd.Wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StartTimer()
|
||||||
|
{
|
||||||
|
int tOutPeriod = 1000;
|
||||||
|
//int.TryParse(Configuration["ReloadStatusTimer"], out tOutPeriod);
|
||||||
|
aTimer = new System.Timers.Timer(tOutPeriod);
|
||||||
|
aTimer.Elapsed += ElapsedTimer;
|
||||||
|
aTimer.Enabled = true;
|
||||||
|
aTimer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Public Methods
|
||||||
|
|
||||||
|
#region Protected Methods
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
StartTimer();
|
||||||
|
Random rnd = new Random();
|
||||||
|
//await Task.Delay(rnd.Next(500));
|
||||||
|
dataLoaded = true;
|
||||||
|
setupConf();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Protected Methods
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
private string cssComStatus(string semaforo, DateTime? lastUpdateN)
|
private string cssComStatus(string semaforo, DateTime? lastUpdateN)
|
||||||
{
|
{
|
||||||
DateTime lastUpdate = lastUpdateN.HasValue ? (DateTime)lastUpdateN : DateTime.Now.AddHours(-1);
|
DateTime lastUpdate = lastUpdateN.HasValue ? (DateTime)lastUpdateN : DateTime.Now.AddHours(-1);
|
||||||
@@ -72,25 +195,26 @@ namespace MP.Mon.Components
|
|||||||
}
|
}
|
||||||
return answ;
|
return answ;
|
||||||
}
|
}
|
||||||
protected override async Task OnInitializedAsync()
|
|
||||||
|
private string cssStatus(string codSemaforo)
|
||||||
{
|
{
|
||||||
StartTimer();
|
// se vuoto --> mostra nero!
|
||||||
Random rnd = new Random();
|
if (string.IsNullOrEmpty(codSemaforo))
|
||||||
//await Task.Delay(rnd.Next(500));
|
{
|
||||||
dataLoaded = true;
|
codSemaforo = "sNe";
|
||||||
setupConf();
|
|
||||||
}
|
}
|
||||||
private void setupConf()
|
string codColore = codSemaforo.Substring(1, 2);
|
||||||
|
string answ = $"{baseCss}{codColore}";
|
||||||
|
if (doAnimate && codColore != "Ve")
|
||||||
{
|
{
|
||||||
//baseCss = doAnimate ? "semBlink" : "sem";
|
// blink se secondo pari...
|
||||||
|
DateTime adesso = DateTime.Now;
|
||||||
|
int resto = 0;
|
||||||
|
Math.DivRem(adesso.Second, 2, out resto);
|
||||||
|
if (resto == 0)
|
||||||
|
{
|
||||||
|
answ += "_b";
|
||||||
}
|
}
|
||||||
private bool showComErr(DateTime? lastUpdateN)
|
|
||||||
{
|
|
||||||
DateTime lastUpdate = lastUpdateN.HasValue ? (DateTime)lastUpdateN : DateTime.Now.AddHours(-1);
|
|
||||||
bool answ = false;
|
|
||||||
if (DateTime.Now.Subtract(lastUpdate).TotalSeconds > (keepAliveMin * kaFactor))
|
|
||||||
{
|
|
||||||
answ = true;
|
|
||||||
}
|
}
|
||||||
return answ;
|
return answ;
|
||||||
}
|
}
|
||||||
@@ -108,32 +232,23 @@ namespace MP.Mon.Components
|
|||||||
{ }
|
{ }
|
||||||
return answ;
|
return answ;
|
||||||
}
|
}
|
||||||
public void Dispose()
|
|
||||||
|
private void setupConf()
|
||||||
{
|
{
|
||||||
aTimer.Stop();
|
//baseCss = doAnimate ? "semBlink" : "sem";
|
||||||
aTimer.Dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static System.Timers.Timer aTimer = new System.Timers.Timer(60 * 1000);
|
private bool showComErr(DateTime? lastUpdateN)
|
||||||
|
|
||||||
public void StartTimer()
|
|
||||||
{
|
{
|
||||||
int tOutPeriod = 1000;
|
DateTime lastUpdate = lastUpdateN.HasValue ? (DateTime)lastUpdateN : DateTime.Now.AddHours(-1);
|
||||||
//int.TryParse(Configuration["ReloadStatusTimer"], out tOutPeriod);
|
bool answ = false;
|
||||||
aTimer = new System.Timers.Timer(tOutPeriod);
|
if (DateTime.Now.Subtract(lastUpdate).TotalSeconds > (keepAliveMin * kaFactor))
|
||||||
aTimer.Elapsed += ElapsedTimer;
|
{
|
||||||
aTimer.Enabled = true;
|
answ = true;
|
||||||
aTimer.Start();
|
}
|
||||||
|
return answ;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ElapsedTimer(Object source, System.Timers.ElapsedEventArgs e)
|
#endregion Private Methods
|
||||||
{
|
|
||||||
var pUpd = Task.Run(async () =>
|
|
||||||
{
|
|
||||||
await Task.Delay(1);
|
|
||||||
await InvokeAsync(StateHasChanged);
|
|
||||||
});
|
|
||||||
pUpd.Wait();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
{
|
||||||
|
"IobSetup": {
|
||||||
|
"***": [
|
||||||
|
{
|
||||||
|
"ColNum": 1,
|
||||||
|
"RowNum": 5,
|
||||||
|
"TagCss": "fontSmall",
|
||||||
|
"TagName": "Feed Over",
|
||||||
|
"TagLocation": "MoonPro:SQL2016DEV:MoonPro:FLOG:***:FEED_OVER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ColNum": 2,
|
||||||
|
"RowNum": 5,
|
||||||
|
"TagCss": "fontSmall",
|
||||||
|
"TagName": "Rapid Over",
|
||||||
|
"TagLocation": "MoonPro:SQL2016DEV:MoonPro:FLOG:***:RAPID_OVER"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"SIMUL_01": [
|
||||||
|
{
|
||||||
|
"ColNum": 1,
|
||||||
|
"RowNum": 6,
|
||||||
|
"TagCss": "fontSmall",
|
||||||
|
"TagName": "Power",
|
||||||
|
"TagLocation": "MoonPro:SQL2016DEV:MoonPro:FLOG:SIMUL_01:POWER_01"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"SIMUL_02": [
|
||||||
|
{
|
||||||
|
"ColNum": 1,
|
||||||
|
"RowNum": 6,
|
||||||
|
"TagCss": "fontSmall",
|
||||||
|
"TagName": "Power",
|
||||||
|
"TagLocation": "MoonPro:SQL2016DEV:MoonPro:FLOG:SIMUL_02:POWER_01"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"GIACO_ICOEL_001": [
|
||||||
|
{
|
||||||
|
"ColNum": 1,
|
||||||
|
"RowNum": 1,
|
||||||
|
"TagName": "Vel",
|
||||||
|
"TagLocation": "FluxData:TonnOra"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ColNum": 2,
|
||||||
|
"RowNum": 1,
|
||||||
|
"TagName": "Vel",
|
||||||
|
"TagLocation": "FluxData:PezziMin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ColNum": 1,
|
||||||
|
"RowNum": 2,
|
||||||
|
"TagName": "Batch SX",
|
||||||
|
"TagLocation": "FluxData:BatchL1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ColNum": 2,
|
||||||
|
"RowNum": 2,
|
||||||
|
"TagName": "Batch DX",
|
||||||
|
"TagLocation": "FluxData:BatchL2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"GIACO_ICOEL_002": [
|
||||||
|
{
|
||||||
|
"ColNum": 1,
|
||||||
|
"RowNum": 1,
|
||||||
|
"TagName": "Vel",
|
||||||
|
"TagLocation": "FluxData:TonnOra"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ColNum": 2,
|
||||||
|
"RowNum": 1,
|
||||||
|
"TagName": "Vel",
|
||||||
|
"TagLocation": "FluxData:PezziMin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ColNum": 1,
|
||||||
|
"RowNum": 2,
|
||||||
|
"TagName": "Batch SX",
|
||||||
|
"TagLocation": "FluxData:BatchL1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ColNum": 2,
|
||||||
|
"RowNum": 2,
|
||||||
|
"TagName": "Batch DX",
|
||||||
|
"TagLocation": "FluxData:BatchL2"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,29 +1,53 @@
|
|||||||
using MP.Data.DatabaseModels;
|
using MP.Data.Conf;
|
||||||
|
using MP.Data.DatabaseModels;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using NLog;
|
||||||
|
using StackExchange.Redis;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace MP.Mon.Data
|
namespace MP.Mon.Data
|
||||||
{
|
{
|
||||||
public class MpDataService : IDisposable
|
public class MpDataService : IDisposable
|
||||||
{
|
{
|
||||||
#region Private Fields
|
|
||||||
|
|
||||||
private static IConfiguration _configuration;
|
|
||||||
private static ILogger<MpDataService> _logger;
|
|
||||||
|
|
||||||
#endregion Private Fields
|
|
||||||
|
|
||||||
#region Public Fields
|
#region Public Fields
|
||||||
|
|
||||||
public static MP.Data.Controllers.MpMonController dbController;
|
public static MP.Data.Controllers.MpMonController dbController;
|
||||||
|
|
||||||
#endregion Public Fields
|
#endregion Public Fields
|
||||||
|
|
||||||
|
#region Private Fields
|
||||||
|
|
||||||
|
private static IConfiguration _configuration;
|
||||||
|
private static ILogger<MpDataService> _logger;
|
||||||
|
|
||||||
|
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Oggetto per connessione a REDIS
|
||||||
|
/// </summary>
|
||||||
|
private ConnectionMultiplexer redisConn = null!;
|
||||||
|
|
||||||
|
//ISubscriber sub = redis.GetSubscriber();
|
||||||
|
/// <summary>
|
||||||
|
/// Oggetto DB redis da impiegare x chiamate R/W
|
||||||
|
/// </summary>
|
||||||
|
private IDatabase redisDb = null!;
|
||||||
|
|
||||||
|
#endregion Private Fields
|
||||||
|
|
||||||
#region Public Constructors
|
#region Public Constructors
|
||||||
|
|
||||||
public MpDataService(IConfiguration configuration, ILogger<MpDataService> logger)
|
public MpDataService(IConfiguration configuration, ILogger<MpDataService> logger)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_configuration = configuration;
|
_configuration = configuration;
|
||||||
|
|
||||||
|
// setup compoenti REDIS
|
||||||
|
this.redisConn = ConnectionMultiplexer.Connect(_configuration.GetConnectionString("Redis"));
|
||||||
|
this.redisDb = this.redisConn.GetDatabase();
|
||||||
|
//// setup canali pub/sub
|
||||||
|
//actLogPipe = new MessagePipe(redisConn, Constants.ACT_LOG_M_QUEUE);
|
||||||
|
|
||||||
// conf DB
|
// conf DB
|
||||||
string connStr = _configuration.GetConnectionString("Mp.Mon");
|
string connStr = _configuration.GetConnectionString("Mp.Mon");
|
||||||
if (string.IsNullOrEmpty(connStr))
|
if (string.IsNullOrEmpty(connStr))
|
||||||
@@ -38,10 +62,22 @@ namespace MP.Mon.Data
|
|||||||
//sb.AppendLine($"CST: {dbController.CustomersCount()} | CNT: {dbController.CountersCount()} | BSK: {dbController.BasketsCount()} | NGT: {dbController.NegotiationsCount()} | DOC: {dbController.DocsCount()} | ITM: {dbController.ItemsCount()} | RES: {dbController.ResourcesCount()}");
|
//sb.AppendLine($"CST: {dbController.CustomersCount()} | CNT: {dbController.CountersCount()} | BSK: {dbController.BasketsCount()} | NGT: {dbController.NegotiationsCount()} | DOC: {dbController.DocsCount()} | ITM: {dbController.ItemsCount()} | RES: {dbController.ResourcesCount()}");
|
||||||
_logger.LogInformation(sb.ToString());
|
_logger.LogInformation(sb.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setup conf IOB da dizionario
|
||||||
|
tryLoadIobTags();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion Public Constructors
|
#endregion Public Constructors
|
||||||
|
|
||||||
|
#region Public Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dizionario dei tag configurati per IOB
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<string, List<TagData>> currTagConf { get; set; } = new Dictionary<string, List<TagData>>();
|
||||||
|
|
||||||
|
#endregion Public Properties
|
||||||
|
|
||||||
#region Public Methods
|
#region Public Methods
|
||||||
|
|
||||||
public Task<List<ConfigModel>> ConfigGetAll()
|
public Task<List<ConfigModel>> ConfigGetAll()
|
||||||
@@ -55,6 +91,23 @@ namespace MP.Mon.Data
|
|||||||
dbController.Dispose();
|
dbController.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// restituisce il valore da REDIS associato al tag richeisto
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="redKey">Chiave in cui cercare il valore</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string getTagConf(string redKey)
|
||||||
|
{
|
||||||
|
string outVal = "";
|
||||||
|
// cerco in REDIS la conf x l'IOB
|
||||||
|
string rawData = redisDb.StringGet(redKey);
|
||||||
|
if (!string.IsNullOrEmpty(rawData))
|
||||||
|
{
|
||||||
|
outVal = rawData;
|
||||||
|
}
|
||||||
|
return outVal;
|
||||||
|
}
|
||||||
|
|
||||||
public Task<List<Macchine>> MacchineGetAll()
|
public Task<List<Macchine>> MacchineGetAll()
|
||||||
{
|
{
|
||||||
return Task.FromResult(dbController.MacchineGetAll().ToList());
|
return Task.FromResult(dbController.MacchineGetAll().ToList());
|
||||||
@@ -71,5 +124,92 @@ namespace MP.Mon.Data
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion Public Methods
|
#endregion Public Methods
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Prova a caricare da file la conf degli IOB se presente
|
||||||
|
/// </summary>
|
||||||
|
private void tryLoadIobTags()
|
||||||
|
{
|
||||||
|
Dictionary<string, List<TagData>> currConf = new Dictionary<string, List<TagData>>();
|
||||||
|
string strExeFilePath = System.Reflection.Assembly.GetExecutingAssembly().Location;
|
||||||
|
if (!string.IsNullOrEmpty(strExeFilePath))
|
||||||
|
{
|
||||||
|
string? strWorkPath = Path.GetDirectoryName(strExeFilePath);
|
||||||
|
if (!string.IsNullOrEmpty(strWorkPath))
|
||||||
|
{
|
||||||
|
string filePath = $"{strWorkPath}/Conf/iobTagsConf.json";
|
||||||
|
if (File.Exists(filePath))
|
||||||
|
{
|
||||||
|
string rawData = File.ReadAllText(filePath);
|
||||||
|
if (!string.IsNullOrEmpty(rawData))
|
||||||
|
{
|
||||||
|
var fileConfData = JsonConvert.DeserializeObject<IobTags>(rawData);
|
||||||
|
if (fileConfData != null)
|
||||||
|
{
|
||||||
|
// effettuo esplosione conf SE contenesse il valore "***" = tutti gli IOB
|
||||||
|
if (fileConfData.IobSetup.ContainsKey("***"))
|
||||||
|
{
|
||||||
|
// recupero elenco macchine...
|
||||||
|
var elencoMacc = dbController.MacchineGetAll();
|
||||||
|
// x ogni macchina creo le righe standard da conf...
|
||||||
|
var baseConf = fileConfData.IobSetup.Where(x => x.Key == "***").FirstOrDefault();
|
||||||
|
foreach (var item in elencoMacc)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(item.IdxMacchina))
|
||||||
|
{
|
||||||
|
// converto i valori x la macchina corrente...
|
||||||
|
// clono in nuovo oggetto
|
||||||
|
var specVal = baseConf.Value.Select(i => i.Clone()).ToList();
|
||||||
|
// sostituisco segnaposto
|
||||||
|
foreach (var singleVal in specVal)
|
||||||
|
{
|
||||||
|
singleVal.TagLocation = singleVal.TagLocation.Replace("***", item.IdxMacchina);
|
||||||
|
}
|
||||||
|
// ora aggiungo eventuali valori in override...
|
||||||
|
if (fileConfData.IobSetup.ContainsKey(item.IdxMacchina))
|
||||||
|
{
|
||||||
|
var otConf = fileConfData.IobSetup.Where(x => x.Key == item.IdxMacchina).FirstOrDefault();
|
||||||
|
//verifico x ogni valore other...
|
||||||
|
foreach (var otTag in otConf.Value)
|
||||||
|
{
|
||||||
|
var ovrTag = specVal.Where(x => x.ColNum == otTag.ColNum && x.RowNum == otTag.RowNum).FirstOrDefault();
|
||||||
|
// se contiene --> sovrascrivo
|
||||||
|
if (ovrTag != null)
|
||||||
|
{
|
||||||
|
//ovrTag = otTag.Clone();
|
||||||
|
specVal.Remove(ovrTag);
|
||||||
|
specVal.Add(otTag.Clone());
|
||||||
|
}
|
||||||
|
// se non contiene --> aggiungo
|
||||||
|
else
|
||||||
|
{
|
||||||
|
specVal.Add(otTag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currConf.Add(item.IdxMacchina, specVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// altrimenti copio ed ho finito
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currConf = fileConfData.IobSetup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currConf != null)
|
||||||
|
{
|
||||||
|
currTagConf = currConf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Private Methods
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Version>6.15.2206.616</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -37,4 +38,12 @@
|
|||||||
<ProjectReference Include="..\MP.Data\MP.Data.csproj" />
|
<ProjectReference Include="..\MP.Data\MP.Data.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="logs\.placeholder">
|
||||||
|
<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>
|
</Project>
|
||||||
|
|||||||
@@ -24,15 +24,14 @@
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
int currIdx = 0;
|
int currIdx = 0;
|
||||||
foreach (var macchina in ListMSE)
|
foreach (var recordIob in ListMSE)
|
||||||
{
|
{
|
||||||
<DetailMSE CurrRecord="@macchina" doAnimate="@doAnimate" keepAliveMin="@keepAliveMin" showArt="@showArt"></DetailMSE>
|
<DetailMSE CurrRecord="@recordIob" currTagConf="@getIobTag(recordIob.IdxMacchina)" currTagVal="@getTagVal(recordIob.IdxMacchina)" doAnimate="@doAnimate" keepAliveMin="@keepAliveMin" showArt="@showArt"></DetailMSE>
|
||||||
currIdx++;
|
currIdx++;
|
||||||
if (currIdx >= maxCol)
|
if (currIdx >= maxCol)
|
||||||
{
|
{
|
||||||
currIdx = 0;
|
currIdx = 0;
|
||||||
@((MarkupString)"</div><div class=\"row statusMap mx-1 my-1\">")
|
@((MarkupString)"</div><div class=\"row statusMap mx-1 my-1\">");
|
||||||
;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// controllo se devo "chiudere riga...
|
// controllo se devo "chiudere riga...
|
||||||
|
|||||||
+141
-103
@@ -1,21 +1,6 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using System.Net.Http;
|
using MP.Data.Conf;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Components.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Components.Forms;
|
|
||||||
using Microsoft.AspNetCore.Components.Routing;
|
|
||||||
using Microsoft.AspNetCore.Components.Web;
|
|
||||||
using Microsoft.AspNetCore.Components.Web.Virtualization;
|
|
||||||
using Microsoft.JSInterop;
|
|
||||||
using MP.Mon;
|
|
||||||
using MP.Mon.Shared;
|
|
||||||
using MP.Mon.Components;
|
|
||||||
using MP.Data.DatabaseModels;
|
using MP.Data.DatabaseModels;
|
||||||
using MP.Mon.Components;
|
|
||||||
using MP.Mon.Data;
|
using MP.Mon.Data;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
|
||||||
@@ -23,66 +8,113 @@ namespace MP.Mon.Pages
|
|||||||
{
|
{
|
||||||
public partial class Index : IDisposable
|
public partial class Index : IDisposable
|
||||||
{
|
{
|
||||||
protected List<MappaStatoExpl>? ListMSE = null;
|
#region Protected Fields
|
||||||
List<ConfigModel>? CurrConfig = null;
|
|
||||||
|
|
||||||
|
|
||||||
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
|
|
||||||
|
|
||||||
protected int keepAliveMin = 1;
|
|
||||||
|
|
||||||
protected int maxCol = 4;
|
|
||||||
|
|
||||||
protected bool doAnimate = true;
|
protected bool doAnimate = true;
|
||||||
|
|
||||||
protected string showArt = "";
|
|
||||||
|
|
||||||
protected int slowRefreshSec = 300;
|
|
||||||
protected int fastRefreshSec = 10;
|
protected int fastRefreshSec = 10;
|
||||||
|
protected int keepAliveMin = 1;
|
||||||
|
protected List<MappaStatoExpl>? ListMSE = null;
|
||||||
|
protected int maxCol = 4;
|
||||||
|
protected string showArt = "";
|
||||||
|
protected int slowRefreshSec = 300;
|
||||||
|
|
||||||
|
#endregion Protected Fields
|
||||||
|
|
||||||
|
#region Private Fields
|
||||||
|
|
||||||
|
private static System.Timers.Timer fastTimer = new System.Timers.Timer(4000);
|
||||||
|
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
|
||||||
|
private static System.Timers.Timer slowTimer = new System.Timers.Timer(300000);
|
||||||
|
private List<ConfigModel>? CurrConfig = null;
|
||||||
|
|
||||||
|
#endregion Private Fields
|
||||||
|
|
||||||
|
#region Protected Properties
|
||||||
|
|
||||||
protected int slowRefreshMs
|
|
||||||
{
|
|
||||||
get => 1000 * slowRefreshSec;
|
|
||||||
}
|
|
||||||
protected int fastRefreshMs
|
protected int fastRefreshMs
|
||||||
{
|
{
|
||||||
get => 1000 * fastRefreshSec;
|
get => 1000 * fastRefreshSec;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
|
||||||
{
|
|
||||||
await setupConf();
|
|
||||||
await ReloadData();
|
|
||||||
StartTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Inject]
|
[Inject]
|
||||||
protected MpDataService MMDataService { get; set; } = null!;
|
protected MpDataService MMDataService { get; set; } = null!;
|
||||||
|
|
||||||
[Inject]
|
[Inject]
|
||||||
protected NavigationManager NavManager { get; set; } = null!;
|
protected NavigationManager NavManager { get; set; } = null!;
|
||||||
|
|
||||||
private async Task setupConf()
|
protected int slowRefreshMs
|
||||||
{
|
{
|
||||||
CurrConfig = await MMDataService.ConfigGetAll();
|
get => 1000 * slowRefreshSec;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Protected Properties
|
||||||
|
|
||||||
|
#region Public Methods
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
fastTimer.Stop();
|
||||||
|
fastTimer.Dispose();
|
||||||
|
slowTimer.Stop();
|
||||||
|
slowTimer.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ElapsedFastTimer(Object source, System.Timers.ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
var pUpd = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await ReloadData();
|
||||||
|
//await Task.Delay(1);
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
});
|
||||||
|
pUpd.Wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void ElapsedSlowTimer(Object source, System.Timers.ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
ListMSE = null;
|
||||||
|
NavManager.NavigateTo(NavManager.Uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StartTimer()
|
||||||
|
{
|
||||||
|
// timer veloce
|
||||||
|
fastTimer = new System.Timers.Timer(fastRefreshMs);
|
||||||
|
fastTimer.Elapsed += ElapsedFastTimer;
|
||||||
|
fastTimer.Enabled = true;
|
||||||
|
fastTimer.Start();
|
||||||
|
// timer lento
|
||||||
|
slowTimer = new System.Timers.Timer(slowRefreshMs);
|
||||||
|
slowTimer.Elapsed += ElapsedSlowTimer;
|
||||||
|
slowTimer.Enabled = true;
|
||||||
|
slowTimer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Public Methods
|
||||||
|
|
||||||
|
#region Protected Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recupera il valore e se trovato aggiorna
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chiave">Valore da cercare</param>
|
||||||
|
/// <param name="varObj">String in cui salvare il valore se trovato</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected bool getConfVal(string chiave, ref string varObj)
|
||||||
|
{
|
||||||
|
bool answ = false;
|
||||||
if (CurrConfig != null && CurrConfig.Count > 0)
|
if (CurrConfig != null && CurrConfig.Count > 0)
|
||||||
{
|
{
|
||||||
// sistemo i parametri opzionali...
|
// sistemo i parametri opzionali...
|
||||||
|
ConfigModel? risultato = CurrConfig.FirstOrDefault(x => x.Chiave == chiave);
|
||||||
getConfValInt("keepAliveMin", ref keepAliveMin);
|
if (risultato != null)
|
||||||
getConfValInt("MON_maxCol", ref maxCol);
|
{
|
||||||
int intDoAnim = 0;
|
varObj = risultato.Valore;
|
||||||
getConfValInt("doAnimate", ref intDoAnim);
|
answ = !string.IsNullOrEmpty(risultato.Valore);
|
||||||
doAnimate = intDoAnim == 1;
|
|
||||||
getConfValInt("pageRefreshSec", ref slowRefreshSec);
|
|
||||||
getConfValInt("MSE_cacheDuration", ref fastRefreshSec);
|
|
||||||
getConfVal("sART", ref showArt);
|
|
||||||
|
|
||||||
Log.Info($"Effettuato setup parametri | keepAlive: {keepAliveMin} | MaxCol: {maxCol} | doAnimate: {doAnimate} | slowRefreshSec: {slowRefreshSec} | fastRefreshSec: {fastRefreshSec}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return answ;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Recupera il valore e se trovato aggiorna
|
/// Recupera il valore e se trovato aggiorna
|
||||||
@@ -106,72 +138,78 @@ namespace MP.Mon.Pages
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Recupera il valore e se trovato aggiorna
|
/// Recupera da conf eventuale setup tag dell'IOB indicato
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="chiave">Valore da cercare</param>
|
/// <param name="codIob"></param>
|
||||||
/// <param name="varObj">String in cui salvare il valore se trovato</param>
|
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected bool getConfVal(string chiave, ref string varObj)
|
protected List<TagData>? getIobTag(string codIob)
|
||||||
{
|
{
|
||||||
bool answ = false;
|
List<TagData>? answ = null;
|
||||||
if (CurrConfig != null && CurrConfig.Count > 0)
|
if (MMDataService.currTagConf != null)
|
||||||
{
|
{
|
||||||
// sistemo i parametri opzionali...
|
// cerco x chiave IOB...
|
||||||
ConfigModel? risultato = CurrConfig.FirstOrDefault(x => x.Chiave == chiave);
|
if (MMDataService.currTagConf.ContainsKey(codIob))
|
||||||
if (risultato != null)
|
|
||||||
{
|
{
|
||||||
varObj = risultato.Valore;
|
answ = MMDataService.currTagConf[codIob];
|
||||||
answ = !string.IsNullOrEmpty(risultato.Valore);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return answ;
|
return answ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recupera da redis (in una chiamata soltanto) tutti i valori richiesti e compone un dizionario x ottimizzare visualizzazione
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="codIob"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected Dictionary<string, string> getTagVal(string codIob)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> answ = new Dictionary<string, string>();
|
||||||
|
// recupero conf tags...
|
||||||
|
var currTags = getIobTag(codIob);
|
||||||
|
if (currTags != null && currTags.Count > 0)
|
||||||
|
{
|
||||||
|
// FIXME TODO !!!! FARE !!!! - da verificare
|
||||||
|
answ = currTags.ToDictionary(x => x.TagLocation, x => MMDataService.getTagConf(x.TagLocation));
|
||||||
|
}
|
||||||
|
return answ;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
await setupConf();
|
||||||
|
await ReloadData();
|
||||||
|
StartTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Protected Methods
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
private async Task ReloadData()
|
private async Task ReloadData()
|
||||||
{
|
{
|
||||||
ListMSE = await MMDataService.MseGetAll();
|
ListMSE = await MMDataService.MseGetAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
private async Task setupConf()
|
||||||
{
|
{
|
||||||
fastTimer.Stop();
|
CurrConfig = await MMDataService.ConfigGetAll();
|
||||||
fastTimer.Dispose();
|
if (CurrConfig != null && CurrConfig.Count > 0)
|
||||||
slowTimer.Stop();
|
{
|
||||||
slowTimer.Dispose();
|
// sistemo i parametri opzionali...
|
||||||
|
|
||||||
|
getConfValInt("keepAliveMin", ref keepAliveMin);
|
||||||
|
getConfValInt("MON_maxCol", ref maxCol);
|
||||||
|
int intDoAnim = 0;
|
||||||
|
getConfValInt("doAnimate", ref intDoAnim);
|
||||||
|
doAnimate = intDoAnim == 1;
|
||||||
|
getConfValInt("pageRefreshSec", ref slowRefreshSec);
|
||||||
|
getConfValInt("MSE_cacheDuration", ref fastRefreshSec);
|
||||||
|
getConfVal("sART", ref showArt);
|
||||||
|
|
||||||
|
Log.Info($"Effettuato setup parametri | keepAlive: {keepAliveMin} | MaxCol: {maxCol} | doAnimate: {doAnimate} | slowRefreshSec: {slowRefreshSec} | fastRefreshSec: {fastRefreshSec}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static System.Timers.Timer fastTimer = new System.Timers.Timer(4000);
|
#endregion Private Methods
|
||||||
private static System.Timers.Timer slowTimer = new System.Timers.Timer(300000);
|
|
||||||
|
|
||||||
public void StartTimer()
|
|
||||||
{
|
|
||||||
// timer veloce
|
|
||||||
fastTimer = new System.Timers.Timer(fastRefreshMs);
|
|
||||||
fastTimer.Elapsed += ElapsedFastTimer;
|
|
||||||
fastTimer.Enabled = true;
|
|
||||||
fastTimer.Start();
|
|
||||||
// timer lento
|
|
||||||
slowTimer = new System.Timers.Timer(slowRefreshMs);
|
|
||||||
slowTimer.Elapsed += ElapsedSlowTimer;
|
|
||||||
slowTimer.Enabled = true;
|
|
||||||
slowTimer.Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ElapsedFastTimer(Object source, System.Timers.ElapsedEventArgs e)
|
|
||||||
{
|
|
||||||
var pUpd = Task.Run(async () =>
|
|
||||||
{
|
|
||||||
await ReloadData();
|
|
||||||
//await Task.Delay(1);
|
|
||||||
await InvokeAsync(StateHasChanged);
|
|
||||||
});
|
|
||||||
pUpd.Wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void ElapsedSlowTimer(Object source, System.Timers.ElapsedEventArgs e)
|
|
||||||
{
|
|
||||||
ListMSE = null;
|
|
||||||
NavManager.NavigateTo(NavManager.Uri);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -28,6 +28,13 @@
|
|||||||
<a class="dismiss">🗙</a>
|
<a class="dismiss">🗙</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@* Riconnessione server app: https://www.syncfusion.com/faq/how-do-i-reconnect-blazor-server-side-automatically *@
|
||||||
|
<script>
|
||||||
|
Blazor.defaultReconnectionHandler._reconnectCallback = function (d) {
|
||||||
|
document.location.reload();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<script src="_framework/blazor.server.js"></script>
|
<script src="_framework/blazor.server.js"></script>
|
||||||
<script src="lib/Chart.js/chart.js"></script>
|
<script src="lib/Chart.js/chart.js"></script>
|
||||||
<script src="lib/luxon/luxon.js"></script>
|
<script src="lib/luxon/luxon.js"></script>
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ string redisSrvAddr = connStringRedis.Substring(0, connStringRedis.IndexOf(":"))
|
|||||||
// avvio oggetto shared x redis...
|
// avvio oggetto shared x redis...
|
||||||
var redisMultiplexer = ConnectionMultiplexer.Connect(connStringRedis);
|
var redisMultiplexer = ConnectionMultiplexer.Connect(connStringRedis);
|
||||||
|
|
||||||
|
|
||||||
// Add services to the container.
|
// Add services to the container.
|
||||||
builder.Services.AddRazorPages();
|
builder.Services.AddRazorPages();
|
||||||
builder.Services.AddServerSideBlazor();
|
builder.Services.AddServerSideBlazor();
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
<body>
|
<body>
|
||||||
<i>Modulo statistiche MAPO</i>
|
<i>Modulo MON MAPO</i>
|
||||||
<h4>Versione: 6.15.2204.1414</h4>
|
<h4>Versione: 6.15.2206.616</h4>
|
||||||
<br />
|
<br /> Note di rilascio:
|
||||||
Note di rilascio:
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<b>Ultime modifiche:</b>
|
<b>Ultime modifiche:</b>
|
||||||
<ul>{{LAST-CHANGES}}</ul>
|
<ul>{{LAST-CHANGES}}</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<b>v.1.* →</b>
|
<b>v.6.15.* →</b>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Prima release dotnet5</li>
|
<li>Prima release dotnet6</li>
|
||||||
<li>Integrazione EFCore</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
6.15.2204.1414
|
6.15.2206.616
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<item>
|
<item>
|
||||||
<version>6.15.2204.1414</version>
|
<version>6.15.2206.616</version>
|
||||||
<url>https://nexus.steamware.net/repository/SWS/MP-STATS/stable/LAST/MP.Stats.zip</url>
|
<url>https://nexus.steamware.net/repository/SWS/MP-MON/stable/LAST/MP.Mon.zip</url>
|
||||||
<changelog>https://nexus.steamware.net/repository/SWS/MP-STATS/stable/LAST/ChangeLog.html</changelog>
|
<changelog>https://nexus.steamware.net/repository/SWS/MP-MON/stable/LAST/ChangeLog.html</changelog>
|
||||||
<mandatory>false</mandatory>
|
<mandatory>false</mandatory>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"DetailedErrors": true,
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*",
|
||||||
|
"CodApp": "MP.MON",
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"MP.Mon": "Server=localhost\\SQLEXPRESS;Database=MoonPro; User ID=steamware;Password=viadante16; integrated security=False; MultipleActiveResultSets=True; App=Blazor.ServerApp;",
|
||||||
|
"MP.Stats": "Server=localhost\\SQLEXPRESS;Database=MoonPro_STATS; User ID=steamware;Password=viadante16; integrated security=False; MultipleActiveResultSets=True; App=Blazor.ServerApp;",
|
||||||
|
"Redis": "localhost:6379,DefaultDatabase=13,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,6 @@
|
|||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"MP.Mon": "Server=SQL2016DEV;Database=MoonPro; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=Blazor.ServerApp;",
|
"MP.Mon": "Server=SQL2016DEV;Database=MoonPro; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=Blazor.ServerApp;",
|
||||||
"MP.Stats": "Server=SQL2016DEV;Database=MoonPro_STATS; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=Blazor.ServerApp;",
|
"MP.Stats": "Server=SQL2016DEV;Database=MoonPro_STATS; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=Blazor.ServerApp;",
|
||||||
"Redis": "localhost:6379,DefaultDatabase=13,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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
param([string]$ProjectDir, [string]$ProjectPath);
|
||||||
|
|
||||||
|
$FileMajMin = "..\MajMin.vers"
|
||||||
|
$FileVers = "Resources\VersNum.txt"
|
||||||
|
$FileManIn = "Resources\manifest-original.xml"
|
||||||
|
$FileManOut = "Resources\manifest.xml"
|
||||||
|
$FileCLogIn = "Resources\ChangeLog-original.html"
|
||||||
|
$FileCLogOut = "Resources\ChangeLog.html"
|
||||||
|
$MajMin = Get-Content $FileMajMin
|
||||||
|
$currentDate = get-date -format yyMM;
|
||||||
|
$currentTime = get-date -format dHH;
|
||||||
|
$find = "<Version>(.|\n)*?</Version>";
|
||||||
|
$currRelNum = $MajMin + $currentDate +"." + $currentTime
|
||||||
|
$replace = "<Version>" + $MajMin + $currentDate +"." + $currentTime + "</Version>";
|
||||||
|
$csproj = Get-Content $ProjectPath
|
||||||
|
$csprojUpdated = $csproj -replace $find, $replace
|
||||||
|
|
||||||
|
Set-Content -Path $ProjectPath -Value $csprojUpdated
|
||||||
|
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 "{{BRANCHNAME}}", "stable/LAST"
|
||||||
|
$manData = $manData -replace "{{PACKNAME}}", "MP.Mon"
|
||||||
|
Set-Content -Path $FileManOut -Value $manData
|
||||||
|
|
||||||
|
# replace x ChangeLog
|
||||||
|
$clogData = Get-Content $FileCLogIn
|
||||||
|
$clogData = $clogData -replace "{{CURRENT-REL}}", $currRelNum
|
||||||
|
Set-Content -Path $FileCLogOut -Value $clogData
|
||||||
@@ -36,6 +36,17 @@
|
|||||||
{
|
{
|
||||||
<span>@totalCount records</span>
|
<span>@totalCount records</span>
|
||||||
}
|
}
|
||||||
|
@if (totalCount > 0)
|
||||||
|
{
|
||||||
|
if (!fileExist)
|
||||||
|
{
|
||||||
|
<button class="btn btn-block btn-sm btn-primary" @onclick="() => requestSave()"><span class="oi oi-wrench"></span> Prepare Data</button>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<a target="_blank" href="Download?fileName=@fileName" class="btn btn-block btn-sm btn-success"><span class="oi oi-cloud-download"></span> Download Data</a>
|
||||||
|
}
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="p-1 flex-fill text-right small">
|
<div class="p-1 flex-fill text-right small">
|
||||||
@if (totalCount > 0)
|
@if (totalCount > 0)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<RootNamespace>MP.Stats</RootNamespace>
|
<RootNamespace>MP.Stats</RootNamespace>
|
||||||
<UserSecretsId>826e877c-ba70-4253-84cb-d0b1cafd4440</UserSecretsId>
|
<UserSecretsId>826e877c-ba70-4253-84cb-d0b1cafd4440</UserSecretsId>
|
||||||
<Version>6.15.2204.1414</Version>
|
<Version>6.15.2205.2311</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<body>
|
<body>
|
||||||
<i>Modulo statistiche MAPO</i>
|
<i>Modulo statistiche MAPO</i>
|
||||||
<h4>Versione: 6.15.2204.1414</h4>
|
<h4>Versione: 6.15.2205.2311</h4>
|
||||||
<br />
|
<br />
|
||||||
Note di rilascio:
|
Note di rilascio:
|
||||||
<ul>
|
<ul>
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
6.15.2204.1414
|
6.15.2205.2311
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<item>
|
<item>
|
||||||
<version>6.15.2204.1414</version>
|
<version>6.15.2205.2311</version>
|
||||||
<url>https://nexus.steamware.net/repository/SWS/MP-STATS/stable/LAST/MP.Stats.zip</url>
|
<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>
|
<changelog>https://nexus.steamware.net/repository/SWS/MP-STATS/stable/LAST/ChangeLog.html</changelog>
|
||||||
<mandatory>false</mandatory>
|
<mandatory>false</mandatory>
|
||||||
|
|||||||
Reference in New Issue
Block a user