Compare commits

..

44 Commits

Author SHA1 Message Date
Samuele Locatelli e945aad224 Merge branch 'Release/FirstSpecStableRelease' 2022-09-21 10:36:40 +02:00
Samuele Locatelli 8510731366 Update home page 2022-09-21 10:36:29 +02:00
Samuele Locatelli 5df4195e6c Completato salvataggio snapshot + refresh 2022-09-21 10:26:09 +02:00
Samuele Locatelli a3dc1e1657 Start ver 6.16 2022-09-21 09:52:54 +02:00
Samuele Locatelli 27149e2131 Fix grafici minori 2022-09-21 09:46:44 +02:00
Samuele Locatelli 91be755781 Fix conf key redis cache:
- era overlapping parametri/dossiers
2022-09-21 09:27:00 +02:00
Samuele Locatelli 84f6730023 Merge remote-tracking branch 'origin/develop' into develop 2022-09-21 09:22:12 +02:00
zaccaria.majid b51c2679e4 aggiunta cache redis 2022-09-21 09:17:28 +02:00
zaccaria.majid 9d7502d1a4 modifiche grafiche e round orario datetime 2022-09-21 09:13:39 +02:00
zaccaria.majid d3b8160634 fix deserializzazione oggetto fluxlog 2022-09-20 17:35:45 +02:00
zaccaria.majid 601c817aa2 Modifiche grafiche 2022-09-20 17:16:42 +02:00
zaccaria.majid d0d30bd1c3 Modifiche per permettere la deserializzazione dei
valori in dossier
2022-09-20 17:16:21 +02:00
zaccaria.majid 0e9e7f3dda Creazione pagina per la visualizzazione Dossier
con relativi filtri
2022-09-20 12:54:46 +02:00
Samuele Locatelli e518c17db2 Aggiunta traccia x pagina dossiers 2022-09-20 09:03:22 +02:00
Samuele Locatelli 0a281827f9 Refresh 2022-09-19 20:01:24 +02:00
Samuele Locatelli 141473ce28 Aggiunta metodi gestione lettura dossiers da DB + refresh 2022-09-19 20:01:13 +02:00
Samuele Locatelli 45af089e3f Aggiunta preliminare modello Dossiers 2022-09-19 20:00:56 +02:00
Samuele Locatelli 4e4387620b Merge branch 'develop' of https://gitlab.steamware.net/steamware/mapo-core into develop 2022-09-19 09:58:28 +02:00
Samuele Locatelli 8c2c48a63f Fix procedura di flux dati:
- aggiunta conn tipo admin
- tolta cancellazione intero DB
- ricerca x pattern delle sole chaivi interessate
2022-09-19 09:54:30 +02:00
zaccaria.majid 534a668496 tentativo fix redis Flush 2022-09-19 09:22:29 +02:00
zaccaria.majid eed45695e8 continuo flushCache 2022-09-19 08:43:48 +02:00
zaccaria.majid ff2fbe0c34 modifiche grafiche
inizio pagina utils
2022-09-16 17:37:39 +02:00
Samuele Locatelli 3324c736c6 Minor fix 2022-09-16 16:49:19 +02:00
zaccaria.majid 0a6a0bc5cb modifiche grafiche varie 2022-09-16 16:00:13 +02:00
Samuele Locatelli e18e0ddff3 Fix last update da pagina main 2022-09-16 15:18:56 +02:00
zaccaria.majid 580a498238 tentativo fix lastUpdate 2022-09-16 14:47:31 +02:00
zaccaria.majid c97557722e Modifiche grafiche 2022-09-16 14:22:23 +02:00
zaccaria.majid c17fa17d76 fix filtri aggiunta titles 2022-09-16 12:40:18 +02:00
zaccaria.majid 5b054ee2ec fix last snapshot che non veniva
scritto al primo giro
2022-09-16 11:55:23 +02:00
zaccaria.majid 2771d9957d Merge branch 'develop' of https://gitlab.steamware.net/steamware/mapo-core into develop 2022-09-16 11:47:43 +02:00
zaccaria.majid 5893152761 aggiornamento grafico filtri 2022-09-16 11:47:35 +02:00
Samuele Locatelli b7d57e935a COmpletato fix version number 2022-09-16 11:21:03 +02:00
Samuele Locatelli 61b613a8fb Fix proj config x calcolo versione 2022-09-16 11:19:26 +02:00
Samuele Locatelli d2fef81f55 Merge remote-tracking branch 'origin/develop' into develop 2022-09-16 11:17:33 +02:00
Samuele Locatelli cd7a8ccad8 Fix x display numero versione 2022-09-16 11:17:28 +02:00
zaccaria.majid 08079d3e0e Merge branch 'develop' of https://gitlab.steamware.net/steamware/mapo-core into develop 2022-09-16 10:51:19 +02:00
zaccaria.majid 8156828ec3 fix bottone filtri avanzati 2022-09-16 10:44:45 +02:00
Samuele Locatelli 9bb95c5a49 Merge tag 'FixMasterDeploy' into develop
Fix deploy IIS x icone, errore cancellazione, log
2022-09-16 10:37:26 +02:00
Samuele Locatelli 7ba3aeb65d Merge branch 'Release/FixMasterDeploy' 2022-09-16 10:37:10 +02:00
Samuele Locatelli 6ea938a91a Aggiunta web.config x windows auth 2022-09-16 10:36:25 +02:00
Samuele Locatelli 92c196023d fix posizione img home page 2022-09-16 10:33:13 +02:00
Samuele Locatelli 10d9625b6d fix articoli:
- tolto refuso cancellazione csv temp appoggio
2022-09-16 10:33:03 +02:00
Samuele Locatelli 5f955499e2 Fix file favicon e logfolder 2022-09-16 10:32:47 +02:00
Samuele Locatelli 716813abe1 Merge tag 'AddSpecInstaller' into develop
Aggiornamento x generazione installer SPEC su nexus
2022-09-16 09:13:19 +02:00
51 changed files with 1197 additions and 490 deletions
+40
View File
@@ -277,6 +277,46 @@ namespace MP.Data.Controllers
{
}
/// <summary>
/// Elenco ultimi n record DOssiers (che contengono ad esempio "salvataggi" di FLuxLog) dato
/// macchina (ordinato x data registrazione)
/// </summary>
/// <param name="IdxMacchina">* = tutte, altrimenti solo x una data macchina</param>
/// <param name="DtRef">Data di riferimento (Massima) per estrazioen records</param>
/// <param name="MaxRec">numero massimo record da restituire</param>
/// <returns></returns>
public List<DatabaseModels.Dossiers> DossiersGetLastFilt(string IdxMacchina, DateTime DtRef, int MaxRec)
{
List<DatabaseModels.Dossiers> dbResult = new List<DatabaseModels.Dossiers>();
using (var dbCtx = new MoonProContext(_configuration))
{
dbResult = dbCtx
.DbSetDossiers
.AsNoTracking()
.Where(x => (IdxMacchina == "*" || x.IdxMacchina == IdxMacchina) && x.DtRif <= DtRef)
.OrderByDescending(x => x.DtRif)
.Take(MaxRec)
.ToList();
}
return dbResult;
}
public bool DossiersTakeParamsSnapshot(string idxMacchina, int maxSec)
{
bool answ = false;
using (var dbCtx = new MoonProContext(_configuration))
{
var pIdxMacchina = new SqlParameter("@IdxMacchina", idxMacchina);
var pMaxSec = new SqlParameter("@MaxSec", maxSec);
var dbResult = dbCtx
.Database
.ExecuteSqlRaw("EXEC stp_FL_TakeSnapshot @IdxMacchina,@MaxSec", pIdxMacchina, pMaxSec);
answ = true;
}
return answ;
}
/// <summary>
/// Elenco valori link (x home e navMenu laterale)
/// </summary>
+14
View File
@@ -0,0 +1,14 @@
using MP.Data.DatabaseModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MP.Data.DTO
{
public class DossierFluxLogDTO
{
public List<FluxLog> ODL { get; set; } = new List<FluxLog>();
}
}
+28
View File
@@ -0,0 +1,28 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
#nullable disable
namespace MP.Data.DatabaseModels
{
[Table("Dossiers")]
public partial class Dossiers
{
#region Public Properties
[MaxLength(50)]
public string IdxMacchina { get; set; }
public DateTime DtRif { get; set; }
public int IdxODL { get; set; }
[MaxLength(50)]
public string DataType { get; set; }
public string Valore { get; set; }
#endregion Public Properties
}
}
+7 -1
View File
@@ -45,6 +45,7 @@ namespace MP.Data
public virtual DbSet<ODLModel> DbSetODL { get; set; }
public virtual DbSet<PODLModel> DbSetPODL { get; set; }
public virtual DbSet<FluxLog> DbSetFluxLog { get; set; }
public virtual DbSet<Dossiers> DbSetDossiers { get; set; }
#endregion Public Properties
@@ -291,7 +292,12 @@ namespace MP.Data
});
modelBuilder.Entity<FluxLog>(entity =>
{
entity.HasKey(e => new { e.IdxMacchina, e.dtEvento, e.CodFlux});
entity.HasKey(e => new { e.IdxMacchina, e.dtEvento, e.CodFlux });
});
modelBuilder.Entity<Dossiers>(entity =>
{
entity.HasKey(e => new { e.IdxMacchina, e.DtRif });
});
+1 -1
View File
@@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>MP.Prog</RootNamespace>
<Version>6.15.2202.2715</Version>
<Version>6.15.2209.1609</Version>
</PropertyGroup>
<ItemGroup>
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>Modulo gestione Programmi MAPO</i>
<h4>Versione: 6.15.2202.2715</h4>
<h4>Versione: 6.15.2209.1609</h4>
<br />
Note di rilascio:
<ul>
+1 -1
View File
@@ -1 +1 @@
6.15.2202.2715
6.15.2209.1609
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>6.15.2202.2715</version>
<version>6.15.2209.1609</version>
<url>https://nexus.steamware.net/repository/SWS/MP-PROG/stable/LAST/MP.Prog.zip</url>
<changelog>https://nexus.steamware.net/repository/SWS/MP-PROG/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>
+6 -2
View File
@@ -8,7 +8,7 @@ namespace MP.SPEC.Components
public void Dispose()
{
//aTimer.Elapsed -= ElapsedTimer;
aTimer.Elapsed -= ElapsedTimer;
aTimer.Stop();
aTimer.Dispose();
}
@@ -21,7 +21,6 @@ namespace MP.SPEC.Components
await InvokeAsync(() => StateHasChanged());
});
pUpd.Wait();
//Log.Trace($"Elapsed Timer Footer");
}
public void StartTimer()
@@ -34,6 +33,11 @@ namespace MP.SPEC.Components
aTimer.Start();
}
protected override void OnInitialized()
{
version = typeof(Program).Assembly.GetName().Version;
}
#endregion Public Methods
#region Protected Methods
+1 -2
View File
@@ -43,7 +43,6 @@
}
private async void MService_EA_ShowSearch()
{
//await forceReload();
await Task.Delay(1);
await InvokeAsync(() => StateHasChanged());
}
@@ -54,7 +53,7 @@
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
var user = authState.User;
if (user.Identity.IsAuthenticated)
if (user.Identity != null&& user.Identity.IsAuthenticated)
{
userName = $"{user.Identity.Name}";
}
+77
View File
@@ -0,0 +1,77 @@
<div class="d-flex justify-content-between">
<div class="px-0 py-1">
</div>
<div class="px-0 col-6">
<div class="">
@*@if (showEditPar)
{
<div class="px-0 input-group py-1" id="basic-addon1">
<button class="btn btn-primary" @onclick="() => toggleParams()"> <i class="fa-solid fa-arrow-right"></i></button>
<label class="input-group-text" for="tempoAgg" title="Selezionare il tempo di aggiornamento dei dati"><i class="fa-solid fa-clock"></i></label>
<select @bind="@selTempoAgg" class="form-select" id="tempoAgg" title="Selezionare il tempo di aggiornamento dei dati">
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="18">18</option>
<option value="19">19</option>
<option value="20">20</option>
</select>
<label class="input-group-text" for="maxRecord" title="Selezionare il numero massimo di record da visualizzare"><i class="fa-solid fa-list-ol"></i></label>
<select @bind="@selMaxRecord" class="form-select" id="maxRecord" title="Selezionare il numero massimo di record da visualizzare">
<option value="50">50</option>
<option value="100">100</option>
<option value="150">150</option>
<option value="200">200</option>
<option value="250">250</option>
<option value="300">300</option>
<option value="350">350</option>
<option value="400">400</option>
<option value="450">450</option>
<option value="500">500</option>
</select>
</div>
}
else
{
<div class="px-2 py-1">
<button class="btn btn-primary" @onclick="() => toggleParams()"><i class="fa-solid fa-arrow-left"></i></button>
</div>
}*@
<div class="px-0 py-1">
<div class="px-2 input-group" id="basic-addon1">
<label class="input-group-text" for="macchina" title="Selezionare la macchina"><i class="fa-solid fa-hard-drive"></i></label>
<select @bind="@selMacchina" class="form-select" id="macchina" title="Selezionare la macchina">
<option value="*">--- Tutti ---</option>
@if (ListMacchine != null)
{
foreach (var item in ListMacchine)
{
<option value="@item">@item</option>
}
}
</select>
<label class="input-group-text" for="DtRef" title="Selezionare il tipo di flusso"><i class="fa-solid fa-calendar-check"></i></label>
<input @bind="@selDtRef" id="DtRef" class="form-control" type="datetime-local" />
</div>
</div>
</div>
</div>
</div>
+139
View File
@@ -0,0 +1,139 @@
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.SPEC;
using MP.SPEC.Shared;
using MP.SPEC.Components;
using MP.SPEC.Data;
using MP.Data.DatabaseModels;
namespace MP.SPEC.Components
{
public partial class DossiersFilter
{
#region Public Properties
[Parameter]
public EventCallback<SelectDossierParams> FilterChanged { get; set; }
[Parameter]
public SelectDossierParams SelFilterDossier { get; set; } = null!;
#endregion Public Properties
#region Protected Fields
#endregion Protected Fields
#region Protected Properties
[Inject]
protected MpDataService MDService { get; set; } = null!;
protected string selMacchina
{
get
{
return SelFilterDossier.IdxMacchina;
}
set
{
if (!SelFilterDossier.IdxMacchina.Equals(value))
{
SelFilterDossier.CurrPage = 1;
SelFilterDossier.IdxMacchina = value;
StateHasChanged();
Task.Delay(1);
reportChange();
}
}
}
protected int selMaxRecord
{
get
{
return SelFilterDossier.MaxRecord;
}
set
{
if (!SelFilterDossier.MaxRecord.Equals(value))
{
SelFilterDossier.MaxRecord = value;
reportChange();
}
}
}
protected DateTime selDtRef
{
get
{
return SelFilterDossier.DtRef;
}
set
{
if (!SelFilterDossier.DtRef.Equals(value))
{
SelFilterDossier.DtRef = value;
reportChange();
}
}
}
#endregion Protected Properties
#region Protected Methods
protected override async Task OnInitializedAsync()
{
SelFilterDossier = new SelectDossierParams();
ListMacchine = await MDService.MacchineWithFlux();
ListDossier = await MDService.DossiersGetLastFilt(selMacchina, selDtRef, selMaxRecord);
await FilterChanged.InvokeAsync(SelFilterDossier);
}
protected void toggleParams()
{
showEditPar = !showEditPar;
}
#endregion Protected Methods
#region Private Fields
private List<Dossiers>? ListDossier = null;
private List<string>? ListMacchine = null;
#endregion Private Fields
#region Private Properties
private bool showEditPar { get; set; } = false;
#endregion Private Properties
#region Private Methods
private void reportChange()
{
FilterChanged.InvokeAsync(SelFilterDossier);
}
#endregion Private Methods
}
}
+103
View File
@@ -0,0 +1,103 @@
@using MP.SPEC.Components
@using MP.SPEC.Data
@if (ListRecords == null)
{
<LoadingData></LoadingData>
}
else if (totalCount == 0)
{
<div class="alert alert-warning text-center display-4">Nessun record trovato</div>
}
else
{
<div class="row">
<div class="d-flex justify justify-content-between">
<table class="table table-sm table-striped small">
<thead>
<tr>
<th>
<button @onclick="() => unToggleTableFlux()" class="btn btn-primary btn-sm"><i class="bi bi-arrow-counterclockwise"></i></button>
</th>
<th><i class="fa-solid fa-hard-drive"></i> Macchina</th>
<th><i class="fa-regular fa-calendar-days"></i> Data</th>
<th><i class="fa-solid fa-sliders"></i> ODL</th>
<th><i class="fa-solid fa-sliders"></i> DATA TYPE</th>
</tr>
</thead>
<tbody>
@foreach (var record in ListRecords)
{
<tr class="@checkSelect(@record)">
<td>
<button class="btn btn-primary btn-sm" @onclick="() => selRecord(record)"><i class="fa-solid fa-magnifying-glass"></i></button>
</td>
<td>
@record.IdxMacchina
</td>
<td>
@record.DtRif
</td>
<td>
@record.IdxODL
</td>
<td>
@record.DataType
</td>
</tr>
}
</tbody>
</table>
@if (!visualizzaFlux)
{
if (listaFlux == null)
{
<div class="alert alert-warning text-center display-4">Nessun record trovato</div>
}
else
{
<div class="table selBlock p-2">
<table class="table table-light table-sm table-striped small mb-0">
<thead>
<tr>
<th><i class="fa-solid fa-hard-drive"></i> Macchina</th>
<th><i class="fa-regular fa-calendar-days"></i> Data</th>
<th><i class="fa-solid fa-sliders"></i> ODL</th>
<th class="d-flex justify-content-between"><i class="fa-solid fa-sliders"></i> Valore <button class="btn btn-primary btn-sm py-0" @onclick="() => unToggleTableFlux()"><i class="fa-solid fa-xmark"></i></button></th>
@*<th class="d-flex justify-content-end"><button class="btn btn-primary btn-sm py-0" @onclick="() => unToggleTableFlux()"><i class="fa-solid fa-xmark"></i></button></th>*@
</tr>
</thead>
<tbody>
@foreach (var record in listaFlux)
{
<tr>
<td>
@record.IdxMacchina
</td>
<td>
@record.dtEvento
</td>
<td>
@record.CodFlux
</td>
<td style="text-align: right;">
<b>@record.Valore</b>
</td>
@* <td>
</td>*@
</tr>
}
</tbody>
</table>
</div>
}
}
</div>
</div>
}
+197
View File
@@ -0,0 +1,197 @@
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using MP.Data.DatabaseModels;
using MP.SPEC.Data;
namespace MP.SPEC.Components
{
public partial class ListDossiers
{
#region Public Properties
[Parameter]
public EventCallback<Dossiers> RecordSel { get; set; }
[Parameter]
public SelectDossierParams SelFilter { get; set; } = null!;
[Parameter]
public EventCallback<int> TotRecordChanged { get; set; }
#endregion Public Properties
#region Public Methods
public string checkSelect(Dossiers recordSel)
{
string answ = "";
if (currRecord != null)
{
try
{
answ = (currRecord.IdxMacchina == recordSel.IdxMacchina && currRecord.DtRif == recordSel.DtRif) ? "table-info" : "";
}
catch
{ }
}
return answ;
}
public async Task reloadData(bool setChanged)
{
isLoading = true;
SearchRecords = await MDService.DossiersGetLastFilt(SelMacchina, SelDtRef, MaxRecord);
totalCount = SearchRecords.Count;
ListRecords = SearchRecords.Skip(numRecord * (currPage - 1)).Take(numRecord).ToList();
await Task.Delay(1);
if (setChanged)
{
await InvokeAsync(() => StateHasChanged());
}
isLoading = false;
}
#endregion Public Methods
#region Protected Properties
[Inject]
protected IJSRuntime JSRuntime { get; set; } = null!;
[Inject]
protected MpDataService MDService { get; set; } = null!;
[Inject]
protected MessageService MessageService { get; set; } = null!;
#endregion Protected Properties
#region Protected Methods
protected override async Task OnInitializedAsync()
{
MessageService.EA_PageUpdated += MessageService_EA_PageUpdated;
MessageService.EA_SearchUpdated += OnSeachUpdated;
ListRecords = await MDService.DossiersGetLastFilt(SelMacchina, SelDtRef, MaxRecord);
await reloadData();
}
protected async void OnSeachUpdated()
{
await InvokeAsync(() =>
{
currPage = 1;
StateHasChanged();
});
}
protected async Task selRecord(Dossiers selRec)
{
currRecord = selRec;
await RecordSel.InvokeAsync(selRec);
listaFlux = MDService.convertToFluxLog(selRec.Valore);
await toggleTableFlux();
}
protected async Task UpdateData()
{
currRecord = null;
await reloadData(true);
}
#endregion Protected Methods
#region Private Fields
private int _totalCount = 0;
private Dossiers? currRecord = null;
private List<Dossiers>? ListRecords;
private List<Dossiers>? SearchRecords;
#endregion Private Fields
#region Private Properties
private int currPage
{
get => MessageService.currPage;
set => MessageService.currPage = value;
}
private bool isLoading { get; set; } = false;
private List<FluxLog>? listaFlux { get; set; } = null;
private int MaxRecord
{
get => SelFilter.MaxRecord;
}
private int numRecord
{
get => MessageService.numRecord;
set => MessageService.numRecord = value;
}
private DateTime SelDtRef
{
get => SelFilter.DtRef;
}
private string SelMacchina
{
get => SelFilter.IdxMacchina;
}
private int totalCount
{
get => _totalCount;
set
{
if (_totalCount != value)
{
_totalCount = value;
TotRecordChanged.InvokeAsync(value);
}
}
}
private bool visualizzaFlux { get; set; } = true;
#endregion Private Properties
#region Private Methods
private async void MessageService_EA_PageUpdated()
{
await reloadData();
}
private async Task reloadData()
{
isLoading = true;
SearchRecords = await MDService.DossiersGetLastFilt(SelMacchina, SelDtRef, MaxRecord);
totalCount = SearchRecords.Count;
ListRecords = SearchRecords.Skip(numRecord * (currPage - 1)).Take(numRecord).ToList();
await Task.Delay(1);
await InvokeAsync(() => StateHasChanged());
isLoading = false;
}
private async Task toggleTableFlux()
{
visualizzaFlux = false;
await Task.Delay(1);
}
private async Task unToggleTableFlux()
{
currRecord = null;
visualizzaFlux = true;
await Task.Delay(1);
}
#endregion Private Methods
}
}
+6 -6
View File
@@ -19,13 +19,13 @@ else
<th>
@*<button @onclick="() => resetSel()" class="btn btn-primary btn-sm"><i class="bi bi-arrow-counterclockwise"></i></button>*@
</th>
<th>Articolo</th>
<th>Macchina</th>
<th><i class="fa-solid fa-file"></i> Articolo</th>
<th><i class="fa-solid fa-hard-drive"></i> Macchina</th>
<th># pz</th>
<th>T.Ciclo</th>
<th>Inizio</th>
<th>Note</th>
<th>Richiesta</th>
<th><i class="fa-solid fa-clock"></i> T.Ciclo</th>
<th><i class="fa-solid fa-play"></i> Inizio</th>
<th><i class="fa-solid fa-pen-to-square"></i> Note</th>
<th><i class="fa-solid fa-code-pull-request"></i> Richiesta</th>
<th></th>
</tr>
</thead>
+3 -3
View File
@@ -19,9 +19,9 @@ else
<th>
@*<button @onclick="() => resetSel()" class="btn btn-primary btn-sm"><i class="bi bi-arrow-counterclockwise"></i></button>*@
</th>
<th>Data</th>
<th>Macchina</th>
<th>Parametro</th>
<th><i class="fa-regular fa-calendar-days"></i> Data</th>
<th><i class="fa-solid fa-hard-drive"></i> Macchina</th>
<th><i class="fa-solid fa-sliders"></i> Parametro</th>
<th style="text-align: right">Valore</th>
<th></th>
</tr>
+5 -5
View File
@@ -19,12 +19,12 @@ else
<th>
<button @onclick="() => resetSel()" class="btn btn-primary btn-sm"><i class="bi bi-arrow-counterclockwise"></i></button>
</th>
<th>Articolo</th>
<th>Fase</th>
<th>Macchina</th>
<th><i class="fa-solid fa-file"></i> Articolo</th>
<th><i class="fa-solid fa-screwdriver-wrench"></i> Fase</th>
<th><i class="fa-solid fa-hard-drive"></i> Macchina</th>
<th># pz</th>
<th>T.Ciclo</th>
<th>Note</th>
<th><i class="fa-solid fa-clock"></i> T.Ciclo</th>
<th><i class="fa-solid fa-pen-to-square"></i> Note</th>
<th></th>
</tr>
</thead>
+59 -42
View File
@@ -1,29 +1,44 @@
<div class="d-flex justify-content-between">
<div class="px-0">
@if (!liveUpdate)
{
<button class="btn btn-secondary" type="button" @onclick="() => toggleUpdate()">
<small>@lastUpdate</small>
</button>
}
else
{
<button class="btn btn-primary" type="button" @onclick="() => toggleUpdate()">
<span class="spinner-grow spinner-grow-sm" role="status" aria-hidden="true"></span>
Valori live
</button>
}
<div class="px-0 py-1">
<div class="d-flex justify-content-between">
<div class="px-2">
@if (!liveUpdate)
{
<button class="btn btn-secondary" type="button" @onclick="() => toggleUpdate()">
<small>@lastUpdate</small>
</button>
}
else
{
<button class="btn btn-primary" type="button" @onclick="() => toggleUpdate()">
<span class="spinner-grow spinner-grow-sm" role="status" aria-hidden="true"></span>
Valori live
</button>
}
</div>
<div class="px-2">
@if (selMacchina != "*")
{
<button class="btn btn-warning" type="button" @onclick="() => takeSnapshot()">
<i class="fa-solid fa-camera"></i>
Registra
</button>
}
</div>
</div>
</div>
<div class="px-0">
<div class="d-flex justify-content-end">
@if (showEditPar)
{
<div class="px-2">
<div class="px-0 input-group py-1" id="basic-addon1">
<button class="btn btn-primary" @onclick="() => toggleParams()"> <i class="fa-solid fa-arrow-right"></i></button>
</div>
<div class="px-2">
<select @bind="@selTempoAgg" class="form-select">
<label class="input-group-text" for="tempoAgg" title="Selezionare il tempo di aggiornamento dei dati"><i class="fa-solid fa-clock"></i></label>
<select @bind="@selTempoAgg" class="form-select" id="tempoAgg" title="Selezionare il tempo di aggiornamento dei dati" style="width: 3em;">
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
@@ -44,9 +59,8 @@
<option value="19">19</option>
<option value="20">20</option>
</select>
</div>
<div class="px-2">
<select @bind="@selMaxRecord" class="form-select">
<label class="input-group-text" for="maxRecord" title="Selezionare il numero massimo di record da visualizzare"><i class="fa-solid fa-list-ol"></i></label>
<select @bind="@selMaxRecord" class="form-select" id="maxRecord" title="Selezionare il numero massimo di record da visualizzare">
<option value="50">50</option>
<option value="100">100</option>
<option value="150">150</option>
@@ -62,34 +76,37 @@
}
else
{
<div class="px-2">
<div class="px-2 py-1">
<button class="btn btn-primary" @onclick="() => toggleParams()"><i class="fa-solid fa-arrow-left"></i></button>
</div>
}
<div class="px-2">
<select @bind="@selMacchina" class="form-select">
<option value="*">--- Tutti ---</option>
@if (ListMacchine != null)
{
foreach (var item in ListMacchine)
<div class="px-0 py-1">
<div class="px-2 input-group" id="basic-addon1">
<label class="input-group-text" for="macchina" title="Selezionare la macchina"><i class="fa-solid fa-hard-drive"></i></label>
<select @bind="@selMacchina" class="form-select" id="macchina" title="Selezionare la macchina">
<option value="*">--- Tutti ---</option>
@if (ListMacchine != null)
{
<option value="@item">@item</option>
foreach (var item in ListMacchine)
{
<option value="@item">@item</option>
}
}
}
</select>
</div>
<div class="px-2">
<select @bind="@selFlux" class="form-select">
<option value="*">--- Tutti ---</option>
@if (ListFlux != null)
{
foreach (var item in ListFlux)
</select>
<label class="input-group-text" for="flusso" title="Selezionare il tipo di flusso"><i class="fa-solid fa-sliders"></i></label>
<select @bind="@selFlux" class="form-select" id="flusso" title="Selezionare il tipo di flusso">
<option value="*">--- Tutti ---</option>
@if (ListFlux != null)
{
<option value="@item">@item</option>
foreach (var item in ListFlux)
{
<option value="@item">@item</option>
}
}
}
</select>
</select>
</div>
</div>
</div>
</div>
</div>
+13 -1
View File
@@ -17,7 +17,11 @@ namespace MP.SPEC.Components
#region Protected Fields
protected string lastUpdate = "-";
protected string lastUpdate
{
get => SelFilter.lastUpdate;
set => SelFilter.lastUpdate = value;
}
#endregion Protected Fields
@@ -145,6 +149,14 @@ namespace MP.SPEC.Components
}
}
protected async Task takeSnapshot()
{
// fermo udpate
liveUpdate = false;
await MDService.DossiersTakeParamsSnapshot(selMacchina, 10);
lastUpdate = $"Last Snapshot: {DateTime.Now:yyyy/MM/dd HH:mm:ss}";
}
#endregion Protected Methods
#region Private Fields
+1 -1
View File
@@ -150,7 +150,7 @@
private string searchVal = "";
private bool showSearch;
private string stateSel = "*";
private string tipoSearch = "*";
private string tipoSearch = "";
#endregion Private Fields
+114 -23
View File
@@ -1,6 +1,7 @@
using MP.Data;
using MP.Data.Conf;
using MP.Data.DatabaseModels;
using MP.Data.DTO;
using Newtonsoft.Json;
using NLog;
using StackExchange.Redis;
@@ -20,8 +21,12 @@ namespace MP.SPEC.Data
// setup compoenti REDIS
redisConn = ConnectionMultiplexer.Connect(_configuration.GetConnectionString("Redis"));
redisConnAdmin = ConnectionMultiplexer.Connect(_configuration.GetConnectionString("RedisAdmin"));
redisDb = redisConn.GetDatabase();
// leggo cache lungo periodo
int.TryParse(_configuration.GetValue<string>("ServerConf:redisLongTimeCache"), out redisLongTimeCache);
_logger.LogInformation("Redis INIT");
// setup canali pub/sub
@@ -62,7 +67,6 @@ namespace MP.SPEC.Data
public async Task<List<ListValues>> AnagStatiComm()
{
int maxAgeConfig = 5;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
List<ListValues>? result = new List<ListValues>();
@@ -80,7 +84,7 @@ namespace MP.SPEC.Data
result = await Task.FromResult(dbController.AnagStatiComm());
// serializzp e salvo...
rawData = JsonConvert.SerializeObject(result);
await redisDb.StringSetAsync(redisStatoCom, rawData, getRandTOut(maxAgeConfig));
await redisDb.StringSetAsync(redisStatoCom, rawData, getRandTOut(redisLongTimeCache));
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"AnagStatiComm Read from DB: {ts.TotalMilliseconds}ms");
@@ -94,7 +98,6 @@ namespace MP.SPEC.Data
public async Task<List<ListValues>> AnagTipoArtLV()
{
int maxAgeConfig = 5;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
List<ListValues>? result = new List<ListValues>();
@@ -112,7 +115,7 @@ namespace MP.SPEC.Data
result = await Task.FromResult(dbController.AnagTipoArtLV());
// serializzp e salvo...
rawData = JsonConvert.SerializeObject(result);
await redisDb.StringSetAsync(redisTipoArt, rawData, getRandTOut(maxAgeConfig));
await redisDb.StringSetAsync(redisTipoArt, rawData, getRandTOut(redisLongTimeCache));
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"AnagTipoArtLV Read from DB: {ts.TotalMilliseconds}ms");
@@ -224,7 +227,6 @@ namespace MP.SPEC.Data
public async Task<List<ConfigModel>> ConfigGetAll()
{
int maxAgeConfig = 5;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
List<ConfigModel>? result = new List<ConfigModel>();
@@ -242,7 +244,7 @@ namespace MP.SPEC.Data
result = await Task.FromResult(dbController.ConfigGetAll());
// serializzp e salvo...
rawData = JsonConvert.SerializeObject(result);
await redisDb.StringSetAsync(redisConfKey, rawData, getRandTOut(maxAgeConfig));
await redisDb.StringSetAsync(redisConfKey, rawData, getRandTOut(redisLongTimeCache));
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"ConfigGetAll Read from DB: {ts.TotalMilliseconds}ms");
@@ -272,6 +274,14 @@ namespace MP.SPEC.Data
return await Task.FromResult(dbController.ConfigUpdate(updRec));
}
public List<FluxLog> convertToFluxLog(string Valore)
{
//string valStriped = Valore.Substring(7, Valore.Length - 8);
//var result = JsonConvert.DeserializeObject<List<FluxLog>>(valStriped);
var result = JsonConvert.DeserializeObject<DossierFluxLogDTO>(Valore);
return result.ODL;
}
public void Dispose()
{
// Clear database controller
@@ -279,6 +289,65 @@ namespace MP.SPEC.Data
redisConn.Dispose();
}
/// <summary>
/// Elenco ultimi n record DOssiers (che contengono ad esempio "salvataggi" di FLuxLog) dato
/// macchina (ordinato x data registrazione)
/// </summary>
/// <param name="IdxMacchina">* = tutte, altrimenti solo x una data macchina</param>
/// <param name="DtRef">Data di riferimento (Massima) per estrazione records</param>
/// <param name="MaxRec">numero massimo record da restituire</param>
/// <returns></returns>
public async Task<List<Dossiers>> DossiersGetLastFilt(string IdxMacchina, DateTime DtRef, int MaxRec)
{
List<Dossiers>? result = new List<Dossiers>();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string readType = "DB";
string currKey = $"{redisDossByMac}:{IdxMacchina}";
// cerco in redis dato valore sel macchina...
RedisValue rawData = redisDb.StringGet(currKey);
if (rawData.HasValue)
{
result = JsonConvert.DeserializeObject<List<Dossiers>>($"{rawData}");
readType = "REDIS";
}
else
{
result = await Task.FromResult(dbController.DossiersGetLastFilt(IdxMacchina, DtRef, MaxRec));
// serializzp e salvo...
rawData = JsonConvert.SerializeObject(result);
redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache / 5));
}
if (result == null)
{
result = new List<Dossiers>();
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"DossiersGetLastFilt | Read from {readType}: {ts.TotalMilliseconds}ms");
return result;
}
/// <summary>
/// Effettua salvataggio snapshot parametri (con stored) + svuota eventuale cache redis
/// </summary>
/// <param name="IdxMacchina">macchina</param>
/// <param name="maxSec">NUm massimo secondi per recuperare dati correnti</param>
/// <returns></returns>
public async Task<bool> DossiersTakeParamsSnapshot(string IdxMacchina, int MaxSec)
{
bool answ = false;
await Task.Delay(1);
// chiamo stored x salvare parametri
dbController.DossiersTakeParamsSnapshot(IdxMacchina, MaxSec);
// svuoto cache redis x macchina
string currKey = $"{redisDossByMac}:{IdxMacchina}";
redisDb.StringSet(currKey, "", TimeSpan.FromSeconds(1));
currKey = $"{redisDossByMac}:*";
redisDb.StringSet(currKey, "", TimeSpan.FromSeconds(1));
return answ;
}
/// <summary>
/// Restitusice elenco aziende
/// </summary>
@@ -302,6 +371,27 @@ namespace MP.SPEC.Data
return Task.FromResult(dbController.ElencoLink());
}
public async Task<bool> FlushRedisCache()
{
await Task.Delay(1);
bool answ = false;
var listEndpoints = redisConnAdmin.GetEndPoints();
var server = redisConnAdmin.GetServer(listEndpoints[0]);
RedisValue pattern = new RedisValue($"{redisBaseAddr}*");
if (server != null)
{
var keyList = server.Keys(redisDb.Database, pattern);
foreach (var item in keyList)
{
await redisDb.KeyDeleteAsync(item);
}
// brutalmente rimuovo intero contenuto DB... DANGER
//await server.FlushDatabaseAsync();
answ = true;
}
return answ;
}
/// <summary>
/// Elenco ultimi n record flux log dato macchina e flusso (ordinato x data registrazione)
/// </summary>
@@ -379,8 +469,6 @@ namespace MP.SPEC.Data
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string readType = "DB";
// 5 minuti valore cache
int maxAgeMin = 5;
string currKey = redisMacList;
// cerco in redis dato valore sel macchina...
RedisValue rawData = redisDb.StringGet(currKey);
@@ -394,7 +482,7 @@ namespace MP.SPEC.Data
result = await Task.FromResult(dbController.MacchineGetAll());
// serializzp e salvo...
rawData = JsonConvert.SerializeObject(result);
redisDb.StringSet(currKey, rawData, getRandTOut(maxAgeMin));
redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache));
}
if (result == null)
{
@@ -416,8 +504,6 @@ namespace MP.SPEC.Data
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string readType = "DB";
// 5 minuti valore cache
int maxAgeMin = 5;
string currKey = redisMacByFlux;
// cerco in redis dato valore sel macchina...
RedisValue rawData = redisDb.StringGet(currKey);
@@ -431,7 +517,7 @@ namespace MP.SPEC.Data
result = await Task.FromResult(dbController.MacchineWithFlux());
// serializzp e salvo...
rawData = JsonConvert.SerializeObject(result);
redisDb.StringSet(currKey, rawData, getRandTOut(maxAgeMin));
redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache));
}
if (result == null)
{
@@ -454,8 +540,6 @@ namespace MP.SPEC.Data
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string readType = "DB";
// 5 minuti valore cache
int maxAgeMin = 5;
string currKey = $"{redisFluxByMac}:{IdxMacchina}";
// cerco in redis dato valore sel macchina...
RedisValue rawData = redisDb.StringGet(currKey);
@@ -469,7 +553,7 @@ namespace MP.SPEC.Data
result = await Task.FromResult(dbController.ParametriGetFilt(IdxMacchina));
// serializzp e salvo...
rawData = JsonConvert.SerializeObject(result);
redisDb.StringSet(currKey, rawData, getRandTOut(maxAgeMin));
redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache));
}
if (result == null)
{
@@ -526,16 +610,16 @@ namespace MP.SPEC.Data
#region Private Fields
private const string redisConfKey = "MP:SPEC:Cache:Config";
private const string redisFluxByMac = "MP:SPEC:Cache:FluxByMac";
private const string redisMacByFlux = "MP:SPEC:Cache:MacByFlux";
private const string redisMacList = "MP:SPEC:Cache:MacList";
private const string redisStatoCom = "MP:SPEC:Cache:StatoCom";
private const string redisTipoArt = "MP:SPEC:Cache:TipoArt";
private const string redisBaseAddr = "MP:";
private const string redisConfKey = redisBaseAddr + "SPEC:Cache:Config";
private const string redisDossByMac = redisBaseAddr + "SPEC:Cache:DossByMac";
private const string redisFluxByMac = redisBaseAddr + "SPEC:Cache:FluxByMac";
private const string redisMacByFlux = redisBaseAddr + "SPEC:Cache:MacByFlux";
private const string redisMacList = redisBaseAddr + "SPEC:Cache:MacList";
private const string redisStatoCom = redisBaseAddr + "SPEC:Cache:StatoCom";
private const string redisTipoArt = redisBaseAddr + "SPEC:Cache:TipoArt";
private static IConfiguration _configuration = null!;
private static ILogger<MpDataService> _logger = null!;
private static Logger Log = LogManager.GetCurrentClassLogger();
/// <summary>
@@ -543,11 +627,18 @@ namespace MP.SPEC.Data
/// </summary>
private ConnectionMultiplexer redisConn = null!;
/// <summary>
/// Oggetto per connessione a REDIS modalità admin (ex flux dati)
/// </summary>
private ConnectionMultiplexer redisConnAdmin = null!;
/// <summary>
/// Oggetto DB redis da impiegare x chiamate R/W
/// </summary>
private IDatabase redisDb = null!;
private int redisLongTimeCache = 5;
#endregion Private Fields
}
}
+68
View File
@@ -0,0 +1,68 @@
namespace MP.SPEC.Data
{
public class SelectDossierParams
{
#region Public Constructors
public SelectDossierParams()
{ }
#endregion Public Constructors
#region Public Properties
/// <summary>
        /// Inizializzazione con periodo e arrotondamento
        /// </summary>
        /// <param name="minRound"></param>
        /// <param name="numDayPrev"></param>
        /// <returns></returns>
        public static DateTime Init(int minRound)
{
TimeSpan DayElapsed = DateTime.Now.Subtract(DateTime.Today);
int minDay = (int)Math.Ceiling((double)(DayElapsed.TotalMinutes / minRound)) * minRound;
DateTime endRounded = DateTime.Today.AddMinutes(minDay);
return endRounded;
}
public string IdxMacchina { get; set; } = "*";
public int MaxRecord { get; set; } = 100;
public DateTime DtRef { get; set; } = Init(5);
public int CurrPage { get; set; } = 1;
#endregion Public Properties
#region Public Methods
public override bool Equals(object obj)
{
if (!(obj is SelectDossierParams item))
return false;
if (IdxMacchina != item.IdxMacchina)
return false;
if (MaxRecord != item.MaxRecord)
return false;
if (DtRef != item.DtRef)
return false;
if (CurrPage != item.CurrPage)
return false;
//if (lastUpdate != item.lastUpdate)
// return false;
return true;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
#endregion Public Methods
}
}
+4
View File
@@ -18,6 +18,7 @@
public int MaxRecord { get; set; } = 100;
public int TempoAgg { get; set; } = 2000;
public int CurrPage { get; set; } = 1;
public string lastUpdate { get; set; } = "-";
#endregion Public Properties
@@ -46,6 +47,9 @@
if (CurrPage != item.CurrPage)
return false;
if (lastUpdate != item.lastUpdate)
return false;
return true;
}
+19
View File
@@ -5,6 +5,7 @@
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>MP.SPEC</RootNamespace>
<Version>6.16.2209.2110</Version>
</PropertyGroup>
<ItemGroup>
@@ -28,4 +29,22 @@
<ProjectReference Include="..\MP.Data\MP.Data.csproj" />
</ItemGroup>
<ItemGroup>
<Content Update="wwwroot\favicon.ico">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<None Update="logs\.placeholder">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="post-build.ps1">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="powershell.exe -ExecutionPolicy Unrestricted -NoProfile -NonInteractive -File $(ProjectDir)\post-build.ps1 -ProjectDir $(ProjectDir) -ProjectPath $(ProjectPath)" />
</Target>
</Project>
+15 -12
View File
@@ -17,15 +17,18 @@
</div>
</div>
<div class="px-0 align-content-center">
<select @bind="@selAzienda" class="form-select">
@if (ListAziende != null)
{
foreach (var item in ListAziende)
<div class="input-group input-group">
<label class="input-group-text" for="maxRecord" title="Selezionare l'azienda da visualizzare"><i class="fa-solid fa-industry"></i></label>
<select @bind="@selAzienda" class="form-select" title="Selezionare l'azienda da visualizzare">
@if (ListAziende != null)
{
<option value="@item.CodGruppo">@item.DescrGruppo</option>
foreach (var item in ListAziende)
{
<option value="@item.CodGruppo">@item.DescrGruppo</option>
}
}
}
</select>
</select>
</div>
</div>
</div>
@if (currRecord != null)
@@ -119,11 +122,11 @@
<th>
<button @onclick="() => resetSel()" class="btn btn-primary btn-sm"><i class="bi bi-arrow-counterclockwise"></i></button>
</th>
<th>Articolo</th>
<th>Disegno</th>
<th>Descrizione</th>
<th>Tipo</th>
<th>Azienda</th>
<th><i class="fa-solid fa-file"></i> Articolo</th>
<th><i class="fa-solid fa-compass-drafting"></i> Disegno</th>
<th><i class="fa-solid fa-file-word"></i> Descrizione</th>
<th><i class="fa-solid fa-rectangle-list"></i> Tipo</th>
<th><i class="fa-solid fa-industry"></i> Azienda</th>
<th></th>
</tr>
</thead>
+12 -33
View File
@@ -44,13 +44,13 @@ namespace MP.SPEC.Pages
#region Protected Properties
[Inject]
protected IJSRuntime JSRuntime { get; set; }
protected IJSRuntime JSRuntime { get; set; } = null!;
[Inject]
protected MpDataService MDService { get; set; }
protected MpDataService MDService { get; set; } = null!;
[Inject]
protected MessageService MessageService { get; set; }
protected MessageService MessageService { get; set; } = null!;
[Inject]
protected NavigationManager NavManager { get; set; }
@@ -78,7 +78,7 @@ namespace MP.SPEC.Pages
/// <returns></returns>
protected async Task addNew()
{
currRecord = new MP.Data.DatabaseModels.AnagArticoli()
currRecord = new AnagArticoli()
{
CodArticolo = $"_NEW_{DateTime.Now:yyyyMMdd.HHmmss}",
DescArticolo = "Nuovo articolo",
@@ -101,7 +101,7 @@ namespace MP.SPEC.Pages
/// </summary>
/// <param name="selRec"></param>
/// <returns></returns>
protected async Task deleteRecord(MP.Data.DatabaseModels.AnagArticoli selRec)
protected async Task deleteRecord(AnagArticoli selRec)
{
if (!await JSRuntime.InvokeAsync<bool>("confirm", "Eliminazione Articolo: sei sicuro di voler procedere?"))
return;
@@ -124,7 +124,6 @@ namespace MP.SPEC.Pages
protected override async Task OnInitializedAsync()
{
clearFile();
numRecord = 10;
// mostro ricerca
MessageService.ShowSearch = true;
@@ -142,7 +141,6 @@ namespace MP.SPEC.Pages
protected void ResetData()
{
clearFile();
currRecord = null;
}
@@ -152,13 +150,13 @@ namespace MP.SPEC.Pages
await Task.Delay(1);
}
protected async Task selRecord(MP.Data.DatabaseModels.AnagArticoli selRec)
protected async Task selRecord(AnagArticoli selRec)
{
currRecord = selRec;
await Task.Delay(1);
}
protected async Task update(MP.Data.DatabaseModels.AnagArticoli selRec)
protected async Task update(AnagArticoli selRec)
{
if (!await JSRuntime.InvokeAsync<bool>("confirm", "Confermi di voler salvare le modifiche?"))
return;
@@ -180,12 +178,11 @@ namespace MP.SPEC.Pages
#region Private Fields
private string _selAzienda = "*";
private MP.Data.DatabaseModels.AnagArticoli? currRecord = null;
private string fileName = "Controlli.csv";
private List<MP.Data.DatabaseModels.AnagGruppi>? ListAziende;
private List<MP.Data.DatabaseModels.AnagArticoli>? ListRecords;
private List<MP.Data.DatabaseModels.ListValues>? ListTipoArt;
private List<MP.Data.DatabaseModels.AnagArticoli>? SearchRecords;
private AnagArticoli? currRecord = null;
private List<AnagGruppi>? ListAziende;
private List<AnagArticoli>? ListRecords;
private List<ListValues>? ListTipoArt;
private List<AnagArticoli>? SearchRecords;
#endregion Private Fields
@@ -209,11 +206,6 @@ namespace MP.SPEC.Pages
}
}
private string fullPath
{
get => $"{Directory.GetCurrentDirectory()}\\temp\\{fileName}";
}
private bool isLoading { get; set; } = false;
private int numRecord
@@ -274,19 +266,6 @@ namespace MP.SPEC.Pages
return answ;
}
private async void clearFile()
{
await Task.Run(() => File.Delete(fullPath));
}
private async Task ExportCsv()
{
isLoading = true;
// salvo davvero!
await MP.Data.Utils.SaveToCsv(SearchRecords, fullPath);
isLoading = false;
}
private async Task reloadData()
{
isLoading = true;
+37
View File
@@ -0,0 +1,37 @@
@page "/DOSS"
<div class="card">
<div class="card-header table-primary">
<div class="d-flex">
<div class="px-0 py-1">
<h3><b>DOSSIERS</b></h3>
</div>
<div class="px-2 flex-fill">
@if (isFiltering)
{
<LoadingDataSmall></LoadingDataSmall>
<i>filtro x macchina / periodo</i>
}
else
{
<DossiersFilter FilterChanged="updateFilter"></DossiersFilter>
}
</div>
</div>
</div>
<div class="card-body">
@if (isLoading)
{
<LoadingData></LoadingData>
}
else
{
<ListDossiers SelFilter="@currFilter" TotRecordChanged="updateTotal"></ListDossiers>
}
</div>
<div class="card-footer py-1">
<DataPager @ref="pagerODL" PageSize="numRecord" currPage="currPage" numRecordChanged="ForceReload" totalCount="totalCount" showLoading="isLoading" />
</div>
</div>
+91
View File
@@ -0,0 +1,91 @@
using Microsoft.AspNetCore.Components;
using MP.SPEC.Components;
using MP.SPEC.Data;
namespace MP.SPEC.Pages
{
public partial class DOSS
{
#region Protected Fields
protected DataPager pagerODL = null!;
#endregion Protected Fields
#region Protected Properties
[Inject]
protected MessageService MsgService { get; set; } = null!;
#endregion Protected Properties
#region Protected Methods
protected void ForceReload(int newNum)
{
numRecord = newNum;
}
protected override async Task OnInitializedAsync()
{
isLoading = true;
isFiltering = true;
// disabilito ricerca...
MsgService.SearchVal = "";
MsgService.ShowSearch = false;
// fix pagina
await Task.Delay(1);
var modFilter = currFilter;
modFilter.CurrPage = 1;
currFilter = modFilter;
await Task.Delay(1);
isFiltering = false;
}
protected void updateTotal(int newTotCount)
{
totalCount = newTotCount;
}
#endregion Protected Methods
#region Private Properties
private SelectDossierParams currFilter { get; set; } = new SelectDossierParams();
private int currPage
{
get => MsgService.currPage;
set => MsgService.currPage = value;
}
private bool isFiltering { get; set; } = false;
private bool isLoading { get; set; } = true;
private int numRecord
{
get => MsgService.numRecord;
set => MsgService.numRecord = value;
}
private int totalCount { get; set; } = 0;
#endregion Private Properties
#region Private Methods
private async Task updateFilter(SelectDossierParams newParams)
{
isFiltering = false;
isLoading = true;
await Task.Delay(1);
currPage = 1;
await Task.Delay(1);
await InvokeAsync(() => StateHasChanged());
currFilter = newParams;
isLoading = false;
}
#endregion Private Methods
}
}
+13 -6
View File
@@ -6,21 +6,19 @@
<div class="card-header bg-dark text-light">
<div class="d-flex justify-content-between">
<div class="p-2">
<img src="/images/LogoMapo.png" class="image-fluid" height="64" />
<img src="images/LogoMapo.png" class="image-fluid" height="64" />
</div>
<div class="p-2 align-content-center fs-1">
<b>MAPO SPEC</b>
</div>
<div class="p-2 bg-light">
<img src="/images/LogoEgw.png" class="image-fluid" height="64" />
<img src="images/LogoEgw.png" class="image-fluid" height="64" />
</div>
</div>
</div>
<div class="card-body text-center">
<h5 class="card-title">MAPO MES Custom Pages</h5>
<div class="shortcuts">
<div class="shortcuts my-5 py-5">
<div class="row">
<div class="col-12">
@if (ElencoLink == null)
@@ -46,7 +44,16 @@
</div>
</div>
</div>
<p class="card-text">Custom pages azienda <b>@currAzienda</b></p>
</div>
<dic class="card-footer bg-primary">
<div class="d-flex text-white justify-content-between">
<div class="px-2">
<h1>@currAzienda</h1>
</div>
<div class="px-2">
<h3 class="my-2">MAPO MES Custom Pages</h3>
</div>
</div>
</dic>
</div>
+15 -209
View File
@@ -2,223 +2,29 @@
<div class="card">
<div class="card-header table-primary">
<div class="row">
<div class="col-5">
<div class="d-flex justify-content-between">
<div class="px-2">
<h3><b>ODL</b></h3>
</div>
<div class="px-2">
<button class="btn btn-success" disabled="!@addEnabled" @onclick="() => reqNewPODL()">Nuovo ODL <i class="bi bi-plus-square"></i></button>
</div><div class="px-2">
</div>
</div>
<div class="d-flex justify-content-between">
<div class="px-1">
<h3><b>ODL</b></h3>
</div>
<div class="col-2">
</div>
<div class="col-5">
<div class="d-flex justify-content-between">
<div class="px-2">
<div class="form-check form-switch" title="Visualizzazione ODL Programmati / In Corso" style="padding-top: 3px">
@*<input class="form-check-input" type="checkbox" id="flexSwitchCheckDefault" @onclick="() => toggleCurrent()">*@
<button type="button" class="btn btn-primary btn-sm" @onclick="() => navToPODL()">PODL</button>
<label class="form-check-label" for="flexSwitchCheckDefault">Visualizza programmati</label>
</div>
</div>
<div class="px-2">
<select @bind="@selStato" class="form-select">
<option value="*">--- Tutti ---</option>
@if (ListStati != null)
<div class="px-2">
<div class="input-group input-group">
<label class="input-group-text" for="maxRecord" title="Selezionare la fase da visualizzare"><i class="fa-solid fa-screwdriver-wrench"></i></label>
<select @bind="@selStato" class="form-select"title="Selezionare la fase da visualizzare">
<option value="*">--- Tutti ---</option>
@if (ListStati != null)
{
foreach (var item in ListStati)
{
foreach (var item in ListStati)
{
<option value="@item.value">@item.label</option>
}
<option value="@item.value">@item.label</option>
}
</select>
</div>
}
</select>
</div>
</div>
</div>
@if (reqNew)
{
<div class="d-flex justify-content-around">
<div class="px-2">
<div class="input-group input-group-sm">
<span class="input-group-text" id="inputGroup-sizing-sm">Azienda</span>
<select @bind="@currAzienda" class="form-select">
@if (ListAziende != null)
{
foreach (var item in ListAziende.Where(x => x.CodGruppo != "*").ToList())
{
<option value="@item.CodGruppo">@item.DescrGruppo</option>
}
}
</select>
<span class="input-group-text" id="inputGroup-sizing-sm">Art Search</span>
<input type="text" class="form-control" aria-label="Art search" aria-describedby="inputGroup-sizing-sm">
</div>
</div>
</div>
<div class="d-flex justify-content-around">
<div class="px-2">
<div class="input-group input-group-sm">
<span class="input-group-text" id="inputGroup-sizing-sm">Articolo</span>
<select @bind="@currAzienda" class="form-select">
@if (ListAziende != null)
{
foreach (var item in ListAziende.Where(x => x.CodGruppo != "*").ToList())
{
<option value="@item.CodGruppo">@item.DescrGruppo</option>
}
}
</select>
</div>
</div>
</div>
}
else if (currRecordOdl != null)
{
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header bg-primary text-light">Modifica ODL</div>
<div class="card-body">
@*<div class="row">
<div class="col-4">
<div class="input-group">
<span class="input-group-text">Codice</span>
<input type="text" class="form-control" placeholder="Articolo" @bind-value="@currRecord.CodArticolo">
</div>
</div>
<div class="col-4">
<div class="input-group">
<span class="input-group-text">Disegno</span>
<input type="text" class="form-control" placeholder="Disegno" @bind-value="@currRecord.Disegno">
</div>
</div>
<div class="col-1">
<div class="input-group" title="Tipo">
<select @bind="@currRecord.Tipo" class="form-select text-end">
@if (ListTipoArt != null)
{
foreach (var item in ListTipoArt)
{
<option value="@item.value">@item.label</option>
}
}
</select>
</div>
</div>
<div class="col-3">
<div class="input-group" title="Azienda">
<select @bind="@currRecord.Azienda" class="form-select text-end">
@if (ListAziende != null)
{
foreach (var item in ListAziende.Where(x => x.CodGruppo != "*").ToList())
{
<option value="@item.CodGruppo">@item.DescrGruppo</option>
}
}
</select>
</div>
</div>
</div>
<div class="row mt-2">
<div class="col-8">
<input type="text" class="form-control" placeholder="Descrizione Articolo" @bind-value="@currRecord.DescArticolo">
</div>
<div class="col-2">
<div class="d-grid gap-2">
<button class="btn btn-warning" @onclick="() => cancel()">Annulla <i class="bi bi-x-circle"></i></button>
</div>
</div>
<div class="col-2">
<div class="d-grid gap-2">
<button class="btn btn-success" @onclick="() => update(currRecord)">Salva <i class="bi bi-save"></i></button>
</div>
</div>
</div>*@
</div>
</div>
</div>
</div>
}
else if (currRecordPOdl != null)
{
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header bg-primary text-light">Modifica PODL</div>
<div class="card-body">
@*<div class="row">
<div class="col-4">
<div class="input-group">
<span class="input-group-text">Codice</span>
<input type="text" class="form-control" placeholder="Articolo" @bind-value="@currRecord.CodArticolo">
</div>
</div>
<div class="col-4">
<div class="input-group">
<span class="input-group-text">Disegno</span>
<input type="text" class="form-control" placeholder="Disegno" @bind-value="@currRecord.Disegno">
</div>
</div>
<div class="col-1">
<div class="input-group" title="Tipo">
<select @bind="@currRecord.Tipo" class="form-select text-end">
@if (ListTipoArt != null)
{
foreach (var item in ListTipoArt)
{
<option value="@item.value">@item.label</option>
}
}
</select>
</div>
</div>
<div class="col-3">
<div class="input-group" title="Azienda">
<select @bind="@currRecord.Azienda" class="form-select text-end">
@if (ListAziende != null)
{
foreach (var item in ListAziende.Where(x => x.CodGruppo != "*").ToList())
{
<option value="@item.CodGruppo">@item.DescrGruppo</option>
}
}
</select>
</div>
</div>
</div>
<div class="row mt-2">
<div class="col-8">
<input type="text" class="form-control" placeholder="Descrizione Articolo" @bind-value="@currRecord.DescArticolo">
</div>
<div class="col-2">
<div class="d-grid gap-2">
<button class="btn btn-warning" @onclick="() => cancel()">Annulla <i class="bi bi-x-circle"></i></button>
</div>
</div>
<div class="col-2">
<div class="d-grid gap-2">
<button class="btn btn-success" @onclick="() => update(currRecord)">Salva <i class="bi bi-save"></i></button>
</div>
</div>
</div>*@
</div>
</div>
</div>
</div>
}
</div>
<div class="card-body">
<ListODL StatoSel="@selStato" PagerResetReq="pgResetReq"></ListODL>
<ListODL StatoSel="@selStato" PagerResetReq="pgResetReq"></ListODL>
</div>
<div class="card-footer py-1">
<DataPager @ref="pagerODL" PageSize="numRecord" currPage="currPage" numRecordChanged="ForceReload" numPageChanged="ForceReloadPage" totalCount="totalCount" showLoading="isLoading" />
+21 -101
View File
@@ -7,19 +7,22 @@ namespace MP.SPEC.Pages
{
public partial class ODL
{
#region Protected Fields
protected DataPager pagerODL;
#endregion Protected Fields
#region Protected Properties
[Inject]
protected IJSRuntime JSRuntime { get; set; }
protected IJSRuntime JSRuntime { get; set; } = null!;
[Inject]
protected MpDataService MDService { get; set; }
protected MpDataService MDService { get; set; } = null!;
[Inject]
protected MessageService MsgService { get; set; }
[Inject]
protected NavigationManager NavManager { get; set; }
protected MessageService MsgService { get; set; } = null!;
#endregion Protected Properties
@@ -35,54 +38,6 @@ namespace MP.SPEC.Pages
currPage = newNum;
}
protected async Task pgResetReq(bool doReset)
{
if (doReset)
{
await pagerODL.resetCurrPage();
}
}
private MP.Data.DatabaseModels.ODLModel? currRecordOdl = null;
private MP.Data.DatabaseModels.PODLModel? currRecordPOdl = null;
/// <summary>
/// Crea nuovo record e va in editing...
/// </summary>
/// <returns></returns>
protected async Task addNew()
{
currRecordPOdl = new MP.Data.DatabaseModels.PODLModel()
{
CodArticolo = $"_NEW_{DateTime.Now:yyyyMMdd.HHmmss}"
};
await Task.Delay(1);
}
protected async Task cancel()
{
currRecordOdl = null;
currRecordPOdl = null;
await reloadData();
await Task.Delay(1);
}
protected DataPager pagerODL;
protected bool reqNew = false;
/// <summary>
/// Crea nuovo record e va in editing...
/// </summary>
/// <returns></returns>
protected async Task reqNewPODL()
{
reqNew = !reqNew;
await Task.Delay(1);
}
protected override async Task OnInitializedAsync()
{
// abilito ricerca...
@@ -95,20 +50,29 @@ namespace MP.SPEC.Pages
await reloadData();
}
private string currAzienda { get; set; } = "*";
private List<MP.Data.DatabaseModels.AnagGruppi>? ListAziende;
protected async Task pgResetReq(bool doReset)
{
if (doReset)
{
await pagerODL.resetCurrPage();
}
}
#endregion Protected Methods
#region Private Fields
private MP.Data.DatabaseModels.ODLModel? currRecordOdl = null;
private MP.Data.DatabaseModels.PODLModel? currRecordPOdl = null;
private List<MP.Data.DatabaseModels.AnagGruppi>? ListAziende;
private List<MP.Data.DatabaseModels.ListValues>? ListStati;
#endregion Private Fields
#region Private Properties
private string currAzienda { get; set; } = "*";
private int currPage
{
get => MsgService.currPage;
@@ -124,37 +88,6 @@ namespace MP.SPEC.Pages
}
private string selStato { get; set; } = "*";
#if false
private string selStato
{
get => _selStato;
set
{
if (!_selStato.Equals(value))
{
_selStato = value;
addEnabled = selStato != "*";
////StateHasChanged();
//var pUpd = Task.Run(async () =>
//{
// //await reloadData();
// await Task.Delay(1);
// await InvokeAsync(() => StateHasChanged());
//});
//pUpd.Wait();
}
}
}
#endif
//private bool showODL { get; set; } = false;
private bool addEnabled = false;
//private string textToggle
//{
// get => showODL ? "In Corso" : "Programmati";
//}
private int totalCount
{
@@ -173,19 +106,6 @@ namespace MP.SPEC.Pages
isLoading = false;
}
//private async Task toggleCurrent()
//{
// //NavManager.NavigateTo("/PODL");
// showODL = !showODL;
// await Task.Delay(1);
//}
private async Task navToPODL()
{
NavManager.NavigateTo("/PODL");
//showODL = !showODL;
await Task.Delay(1);
}
#endregion Private Methods
}
}
+1 -1
View File
@@ -3,7 +3,7 @@
<div class="card">
<div class="card-header table-primary">
<div class="d-flex">
<div class="px-0">
<div class="px-0 py-1">
<h3><b>PARAMETERS</b></h3>
</div>
<div class="px-2 flex-fill">
+1
View File
@@ -29,6 +29,7 @@ namespace MP.SPEC.Pages
protected void ForceReloadPage(int newNum)
{
currPage = newNum;
currFilter.lastUpdate= $"Last Snapshot: {DateTime.Now:yyyy/MM/dd HH:mm:ss}";
currFilter.LiveUpdate = (currPage == 1);
StateHasChanged();
}
+14 -19
View File
@@ -3,7 +3,7 @@
<div class="card">
<div class="card-header table-primary">
<div class="row">
<div class="d-flex justify-content-between">
<div class="col-6">
<div class="d-flex">
<div class="px-2">
@@ -17,10 +17,10 @@
</div>
</div>
</div>
<div class="col-3">
<div class="col-6">
<div class="input-group input-group-sm">
<span class="input-group-text" id="inputGroup-sizing-sm">Azienda</span>
<select @bind="@currAzienda" class="form-select">
<label class="input-group-text" for="maxRecord" title="Selezionare l'azienda da visualizzare"><i class="fa-solid fa-industry"></i></label>
<select @bind="@currAzienda" class="form-select" title="Selezionare l'azienda da visualizzare">
@if (ListAziende != null)
{
foreach (var item in ListAziende)
@@ -29,25 +29,20 @@
}
}
</select>
</div>
</div>
<div class="col-3">
<div class="d-flex text-end">
<div class="input-group input-group-sm">
<span class="input-group-text" id="inputGroup-sizing-sm">Fase</span>
<select @bind="@selStato" class="form-select">
<option value="*">--- Tutti ---</option>
@if (ListStati != null)
<label class="input-group-text" for="maxRecord" title="Selezionare la fase da visualizzare"><i class="fa-solid fa-screwdriver-wrench"></i></label>
<select @bind="@selStato" class="form-select" title="Selezionare la fase da visualizzare">
<option value="*">--- Tutti ---</option>
@if (ListStati != null)
{
foreach (var item in ListStati)
{
foreach (var item in ListStati)
{
<option value="@item.value">@item.label</option>
}
<option value="@item.value">@item.label</option>
}
</select>
</div>
}
</select>
</div>
</div>
</div>
@if (currRecord != null)
{
+10
View File
@@ -0,0 +1,10 @@
@page "/Utils"
@using MP.SPEC.Components
@using MP.SPEC.Data
<h3>Utils</h3>
<div class="px-2">
<button class="btn btn-primary" @onclick="() => flushCache()"> Flush Cache </button>
</div>
+18
View File
@@ -0,0 +1,18 @@
using Microsoft.AspNetCore.Components;
using MP.SPEC.Data;
using System.Reflection;
namespace MP.SPEC.Pages
{
public partial class Utils
{
[Inject]
protected MpDataService MDService { get; set; }
public async Task flushCache()
{
await Task.Delay(1);
await MDService.FlushRedisCache();
}
}
}
+2 -2
View File
@@ -1,5 +1,5 @@
<body>
<i>Modulo MON MAPO</i>
<i>Modulo MAPOSPEC </i>
<h4>Versione: {{CURRENT-REL}}</h4>
<br /> Note di rilascio:
<ul>
@@ -19,7 +19,7 @@
<img src="logoSteamware.png" />
</div>
<div style="float: right;">
<a href="https://www.steamware.net/IOT" target="_blank">&copy; Steamware 2006-2021</a>
<a href="https://www.steamware.net/IOT" target="_blank">&copy; Steamware 2006-2022</a>
</div>
</div>
</body>
+3 -3
View File
@@ -1,6 +1,6 @@
<body>
<i>Modulo MON MAPO</i>
<h4>Versione: 6.15.2207.2109</h4>
<i>Modulo MAPOSPEC </i>
<h4>Versione: 6.16.2209.2110</h4>
<br /> Note di rilascio:
<ul>
<li>
@@ -19,7 +19,7 @@
<img src="logoSteamware.png" />
</div>
<div style="float: right;">
<a href="https://www.steamware.net/IOT" target="_blank">&copy; Steamware 2006-2021</a>
<a href="https://www.steamware.net/IOT" target="_blank">&copy; Steamware 2006-2022</a>
</div>
</div>
</body>
+1 -1
View File
@@ -1 +1 @@
6.15.2207.2109
6.16.2209.2110
+3 -3
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>6.15.2207.2109</version>
<url>https://nexus.steamware.net/repository/SWS/MP-MON/stable/LAST/MP.Mon.zip</url>
<changelog>https://nexus.steamware.net/repository/SWS/MP-MON/stable/LAST/ChangeLog.html</changelog>
<version>6.16.2209.2110</version>
<url>https://nexus.steamware.net/repository/SWS/MP-SPEC/stable/LAST/MP.SPEC.zip</url>
<changelog>https://nexus.steamware.net/repository/SWS/MP-SPEC/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>
</item>
+4 -2
View File
@@ -9,10 +9,12 @@
"CodApp": "MP.SPEC",
"ConnectionStrings": {
"Mp.Data": "Server=SQL2016DEV;Database=MoonPro; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=MP.SPEC;",
"Redis": "localhost:6379,DefaultDatabase=1,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false"
"Redis": "localhost:6379,DefaultDatabase=1,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false",
"RedisAdmin": "localhost:6379,DefaultDatabase=1,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false,allowAdmin=true"
},
"ServerConf": {
"maxAge": "2000",
"cacheCheckArtUsato": 2
"cacheCheckArtUsato": 2,
"redisLongTimeCache": 15
}
}
+2 -2
View File
@@ -21,9 +21,9 @@ Set-Content -Path $FileVers -Value $currRelNum
# replace x manifest
$manData = Get-Content $FileManIn
$manData = $manData -replace "1.0.0.0", $currRelNum
$manData = $manData -replace "{{DIRNAME}}", "MP-MON"
$manData = $manData -replace "{{DIRNAME}}", "MP-SPEC"
$manData = $manData -replace "{{BRANCHNAME}}", "stable/LAST"
$manData = $manData -replace "{{PACKNAME}}", "MP.Mon"
$manData = $manData -replace "{{PACKNAME}}", "MP.SPEC"
Set-Content -Path $FileManOut -Value $manData
# replace x ChangeLog
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<security>
<authentication>
<!--<anonymousAuthentication enabled="false" />
<windowsAuthentication enabled="true" />-->
</authentication>
</security>
</system.webServer>
</location>
</configuration>
+3
View File
@@ -46,6 +46,9 @@ a,
.validation-message {
color: red;
}
.selBlock {
background-color: #CFF4FC;
}
.watermark {
position: absolute;
top: 250px;
+4
View File
@@ -45,6 +45,10 @@ a, .btn-link {
color: red;
}
.selBlock {
background-color: #CFF4FC;
}
.watermark {
position: absolute;
top: 250px;
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -4,7 +4,7 @@
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>MP.Stats</RootNamespace>
<UserSecretsId>826e877c-ba70-4253-84cb-d0b1cafd4440</UserSecretsId>
<Version>6.15.2209.0917</Version>
<Version>6.15.2209.1609</Version>
</PropertyGroup>
<ItemGroup>
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>Modulo statistiche MAPO</i>
<h4>Versione: 6.15.2209.0917</h4>
<h4>Versione: 6.15.2209.1609</h4>
<br />
Note di rilascio:
<ul>
+1 -1
View File
@@ -1 +1 @@
6.15.2209.0917
6.15.2209.1609
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>6.15.2209.0917</version>
<version>6.15.2209.1609</version>
<url>https://nexus.steamware.net/repository/SWS/MP-STATS/stable/LAST/MP.Stats.zip</url>
<changelog>https://nexus.steamware.net/repository/SWS/MP-STATS/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>
+1 -1
View File
@@ -1 +1 @@
6.15.
6.16.