Merge branch 'release/UpdateMain221010'

This commit is contained in:
Samuele E. Locatelli
2022-10-11 08:01:04 +02:00
66 changed files with 25682 additions and 298 deletions
+53 -9
View File
@@ -6,6 +6,7 @@ using NLog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
namespace MP.Data.Controllers
@@ -183,7 +184,7 @@ namespace MP.Data.Controllers
using (var dbCtx = new MoonProContext(_configuration))
{
dbResult = dbCtx
.DbSetArticoli
.DbSetArticoli
.FromSqlRaw("EXEC stp_ART_getUsed")
.AsNoTracking()
.ToList();
@@ -191,6 +192,26 @@ namespace MP.Data.Controllers
return dbResult;
}
/// <summary>
/// Statistiche ODL calcolate (da stored stp_STAT_ODL)
/// </summary>
/// <returns></returns>
public async Task<List<StatODLModel>> StatOdl(int IdxOdl)
{
List<StatODLModel> dbResult = new List<StatODLModel>();
using (var dbCtx = new MoonProContext(_configuration))
{
var IdxODL = new SqlParameter("@IdxODL", IdxOdl);
dbResult = await dbCtx
.DbSetStatOdl
.FromSqlRaw("EXEC stp_STAT_ODL @IdxODL", IdxODL)
.AsNoTracking()
.ToListAsync();
}
return dbResult;
}
/// <summary>
/// Update Record
/// </summary>
@@ -313,10 +334,11 @@ namespace MP.Data.Controllers
/// macchina (ordinato x data registrazione)
/// </summary>
/// <param name="IdxMacchina">* = tutte, altrimenti solo x una data macchina</param>
/// <param name="CodArticolo">* = tutti, altrimenti solo x un dato articolo</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<Dossiers> DossiersGetLastFilt(string IdxMacchina, DateTime DtRef, int MaxRec)
public List<Dossiers> DossiersGetLastFilt(string IdxMacchina, string CodArticolo, DateTime DtRef, int MaxRec)
{
List<Dossiers> dbResult = new List<Dossiers>();
using (var dbCtx = new MoonProContext(_configuration))
@@ -324,9 +346,10 @@ namespace MP.Data.Controllers
dbResult = dbCtx
.DbSetDossiers
.AsNoTracking()
.Where(x => (IdxMacchina == "*" || x.IdxMacchina == IdxMacchina) && x.DtRif <= DtRef)
.Where(x => (IdxMacchina == "*" || x.IdxMacchina == IdxMacchina) && (CodArticolo == "*" || x.OdlNav.CodArticolo == CodArticolo) && x.DtRif <= DtRef)
.Include(m => m.MachineNav)
.Include(o => o.OdlNav)
.Include(a => a.OdlNav.ArticoloNav)
.OrderByDescending(x => x.DtRif)
.Take(MaxRec)
.ToList();
@@ -434,19 +457,21 @@ namespace MP.Data.Controllers
/// <param name="inCorso">Stato ODL: true=in corso/completato</param>
/// <param name="codArt">Cod articolo</param>
/// <param name="keyRichPart">KeyRich (parziale) da cercare (es cod stato x yacht)</param>
/// <param name="startDate">Data inizio</param>
/// <param name="endDate">Data fine</param>
/// <returns></returns>
public List<ODLModel> ListODLFilt(bool inCorso, string codArt, string keyRichPart)
public List<ODLModel> ListODLFilt(bool inCorso, string codArt, string keyRichPart, DateTime startDate, DateTime endDate)
{
List<ODLModel> dbResult = new List<ODLModel>();
using (var dbCtx = new MoonProContext(_configuration))
{
dbResult = dbCtx
.DbSetODL
.Where(x => ((inCorso && x.DataFine == null) || (!inCorso && x.DataFine != null)) && (x.KeyRichiesta.Contains(keyRichPart) || keyRichPart == "*") && (codArt == "*" || x.CodArticolo.Contains(codArt)))
.Where(x => ((inCorso && x.DataFine == null) || ((!inCorso && x.DataFine != null) && x.DataInizio >= startDate && x.DataInizio <= endDate)) && (x.KeyRichiesta.Contains(keyRichPart) || keyRichPart == "*") && (codArt == "*" || x.CodArticolo.Contains(codArt)))
.AsNoTracking()
.Include(m => m.MachineNav)
.Include(a => a.ArticoloNav)
.OrderBy(x => x.IdxOdl)
.OrderByDescending(x => x.IdxOdl)
.ToList();
}
return dbResult;
@@ -518,15 +543,34 @@ namespace MP.Data.Controllers
/// Elenco id Macchine che abbiano dati FLuxLog
/// </summary>
/// <returns></returns>
public List<string> MacchineWithFlux()
public async Task<List<string>> MacchineWithFlux()
{
List<string> dbResult = new List<string>();
using (var dbCtx = new MoonProContext(_configuration))
{
dbResult = await dbCtx
.DbSetFluxLog
.AsNoTracking()
.Select(i => i.IdxMacchina)
.Distinct()
.ToListAsync();
}
return dbResult;
}
/// <summary>
/// Elenco codice articoli che abbiano dati Dossier
/// </summary>
/// <returns></returns>
public List<string> ArticleWithDossier()
{
List<string> dbResult = new List<string>();
using (var dbCtx = new MoonProContext(_configuration))
{
dbResult = dbCtx
.DbSetFluxLog
.DbSetDossiers
.AsNoTracking()
.Select(i => i.IdxMacchina)
.Select(i => i.OdlNav.CodArticolo)
.Distinct()
.ToList();
}
+5 -3
View File
@@ -23,11 +23,13 @@ namespace MP.Data.DatabaseModels
public DateTime DtRif { get; set; }
[MaxLength(50)]
public string IdxMacchina { get; set; }
public string IdxMacchina { get; set; } = "";
[MaxLength(50)]
public string CodArticolo { get; set; } = "";
public int IdxODL { get; set; }
public int IdxODL { get; set; } = 0;
public string Valore { get; set; }
public string Valore { get; set; } = "";
+20
View File
@@ -33,6 +33,26 @@ namespace MP.Data.DatabaseModels
[MaxLength(50)]
public string CodCli { get; set; } = "";
[NotMapped]
public string DurataMinuti
{
get
{
string answ = "";
DateTime end = DataFine != null ? (DateTime)DataFine : DateTime.Now;
var tsDurata = (end).Subtract((DateTime)DataInizio);
if (tsDurata.TotalDays < 1)
{
answ = $"{tsDurata.Hours:00}h {tsDurata.Minutes:00}'";
}
else
{
answ = $"{tsDurata.Days}gg {tsDurata.Hours:00}h";
}
return answ;
}
}
/// <summary>
/// Navigazione oggetto Machine
/// </summary>
+26
View File
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
#nullable disable
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
namespace MP.Data.DatabaseModels
{
public partial class StatODLModel
{
#region Public Properties
[Key]
public int IdxStato { get; set; }
public string Descrizione { get; set; } = "";
public string Semaforo { get; set; }
public string Css { get; set; }
public double TotDurata { get; set; }
#endregion Public Properties
}
}
+1
View File
@@ -48,6 +48,7 @@ namespace MP.Data
public virtual DbSet<PODLModel> DbSetPODL { get; set; }
public virtual DbSet<FluxLog> DbSetFluxLog { get; set; }
public virtual DbSet<Dossiers> DbSetDossiers { get; set; }
public virtual DbSet<StatODLModel> DbSetStatOdl { get; set; }
#endregion Public Properties
+24 -2
View File
@@ -57,17 +57,39 @@ namespace MP.Data
return answ;
}
public static async Task SaveToCsv<T>(List<T> reportData, string path)
/// <summary>
/// Effettua salvataggio in file di un generico oggetto in formato CSV
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="reportData"></param>
/// <param name="path"></param>
/// <param name="separator">Separatore da impiegare</param>
/// <returns></returns>
public static async Task SaveToCsv<T>(List<T> reportData, string path, char separator)
{
var lines = new List<string>();
IEnumerable<PropertyDescriptor> props = TypeDescriptor.GetProperties(typeof(T)).OfType<PropertyDescriptor>();
var header = string.Join(";", props.ToList().Select(x => x.Name));
lines.Add(header);
var valueLines = reportData.Select(row => string.Join(";", header.Split(';').Select(a => row.GetType().GetProperty(a).GetValue(row, null))));
var valueLines = reportData.Select(row => string.Join(separator, header.Split(separator).Select(a => row.GetType().GetProperty(a).GetValue(row, null))));
//var valueLines = reportData.Select(row => string.Join(";", header.Split(';').Select(a => row.GetType().GetProperty(a).GetValue(row, null))));
lines.AddRange(valueLines);
await Task.Run(() => File.WriteAllLines(path, lines.ToArray()));
}
/// <summary>
/// Inizializzazione con periodo e arrotondamento
/// </summary>
/// <param name="minRound"></param>
/// <returns></returns>
public static DateTime InitDatetime(DateTime dtRif, int minRound)
{
TimeSpan DayElapsed = dtRif.Subtract(dtRif.Date);
int minDay = (int)Math.Ceiling((double)(DayElapsed.TotalMinutes / minRound)) * minRound;
DateTime endRounded = DateTime.Today.AddMinutes(minDay);
return endRounded;
}
#endregion Public Methods
}
}
+1
View File
@@ -0,0 +1 @@
<canvas id="@Id"></canvas>
@@ -0,0 +1,66 @@
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using MP.Data;
namespace MP.SPEC.Components.Chart
{
public partial class Doughnut
{
[Inject]
private IJSRuntime JSRuntime { get; set; } = null!;
public enum ChartType
{
Pie,
Bar,
Doughnut
}
[Parameter]
public string Id { get; set; }
[Parameter]
public ChartType Type { get; set; }
[Parameter]
public double[] Data { get; set; }
[Parameter]
public string[] BackgroundColor { get; set; }
[Parameter]
public string[] Labels { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
var config = new
{
Type = Type.ToString().ToLower(),
Options = new
{
Responsive = true,
Scales = new
{
YAxes = new[]
{
new { Ticks = new {
BeginAtZero=true
} }
}
}
},
Data = new
{
Datasets = new[]
{
new { Data = Data, BackgroundColor = BackgroundColor}
},
Labels = Labels
}
};
await JSRuntime.InvokeVoidAsync("setup", Id, config);
}
}
}
+1
View File
@@ -0,0 +1 @@
<canvas id="@Id"></canvas>
+162
View File
@@ -0,0 +1,162 @@
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using MP.Data;
namespace MP.SPEC.Components.Chart
{
public partial class Line
{
#region Public Properties
[Parameter]
public double AspRatio { get; set; } = 0;
[Parameter]
public List<string> backColor { get; set; } = new List<string>();
[Parameter]
public string ChartId
{
get
{
return Id;
}
set
{
Id = value;
}
}
[Parameter]
public List<chartJsData.chartJsTSerie> DataTS
{
get
{
return _DataTS;
}
set
{
_DataTS = value;
//var pUpd = Task.Run(async () => await renderChart());
//pUpd.Wait();
}
}
[Parameter]
public List<string> Labels { get; set; } = new List<string>();
[Parameter]
public List<string> lineColor { get; set; } = new List<string>();
[Parameter]
public int lTens { get; set; } = 0;
[Parameter]
public string MaxValue { get; set; } = "0";
[Parameter]
public string MinValue { get; set; } = "0";
[Parameter]
public List<string> pointColor { get; set; } = new List<string>();
[Parameter]
public string Title { get; set; } = "Demo Line";
#endregion Public Properties
#region Protected Properties
protected string Id { get; set; } = "CurrId";
#endregion Protected Properties
#region Protected Methods
/// <summary>
/// Inizializzazione rendering componente
///
/// partendo da qui: https://www.williamleme.com/posts/2020/003-chartjs-blazor/
/// https://www.puresourcecode.com/dotnet/blazor/using-chart-js-with-blazor/ https://www.tutorialsteacher.com/csharp/csharp-anonymous-type
/// </summary>
/// <param name="firstRender"></param>
/// <returns></returns>
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await renderChart();
}
/// <summary>
/// Inizializzazione rendering componente
///
/// partendo da qui: https://www.williamleme.com/posts/2020/003-chartjs-blazor/
/// https://www.puresourcecode.com/dotnet/blazor/using-chart-js-with-blazor/ https://www.tutorialsteacher.com/csharp/csharp-anonymous-type
/// </summary>
/// <param name="firstRender"></param>
/// <returns></returns>
protected async Task renderChart()
{
// creazione di un oggetto anonymous type con tutte le opzioni da passare a chart.js
var config = new
{
type = "line",
options = new
{
responsive = true,
scales = new
{
yAxes = new
{
display = true,
position = "right",
ticks = new
{
maxTicksLimit = 10
},
suggestedMin = MinValue != MaxValue ? MinValue : "auto",
suggestedMax = MinValue != MaxValue ? MaxValue : "auto"
},
xAxes = new
{
type = "time",
distribution = "linear",
}
},
plugins = new
{
legend = new
{
display = false
},
},
Animation = false,
AspectRatio = AspRatio == 0 ? "auto" : $"{AspRatio}"
},
data = new
{
labels = Labels,
datasets = new[]{new
{
data = DataTS, pointBorderColor = backColor, borderColor = lineColor, backgroundColor = backColor, fill = true, PointRadius = 2, BorderWidth = 1, lineTension = lTens, stepped = false, label = Title
}
}
}
}
;
await JSRuntime.InvokeVoidAsync("setup", Id, config);
}
#endregion Protected Methods
#region Private Properties
private List<chartJsData.chartJsTSerie> _DataTS { get; set; } = null!;
[Inject]
private IJSRuntime JSRuntime { get; set; } = null!;
#endregion Private Properties
}
}
+49 -31
View File
@@ -1,36 +1,54 @@
<div class="d-flex justify-content-between">
<div class="px-0 py-1">
</div>
<div class="px-0 col-8">
<div class="">
<div class="px-0 py-1">
<div class="px-2 input-group">
<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="10">10</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
<option value="250">250</option>
<option value="500">500</option>
</select>
<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)
<div class="d-flex justify-content-end">
<a class="pt-2 text-dark" data-bs-toggle="offcanvas" data-bs-target="#paramsFilterExample" aria-controls="paramsFilterExample">
<i class="fa-solid fa-bars"></i>
</a>
<div class="offcanvas offcanvas-end" tabindex="-1" id="paramsFilterExample" aria-labelledby="paramsFilterExampleLabel">
<div class="offcanvas-header">
<h3 class="offcanvas-title" id="paramsFilterExampleLabel"><b>FILTRI</b></h3>
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<div>
Seleziona i filtri per:
</div>
<div class="input-group p-2">
<label class="input-group-text" for="macchina" title="Selezionare l'articolo"><i class="fa-solid fa-file"></i></label>
<select @bind="@selArticolo" class="form-select" id="macchina" title="Selezionare la macchina">
<option value="*">--- Tutti ---</option>
@if (ListArticoli != null)
{
foreach (var item in ListArticoli)
{
foreach (var item in ListMacchine)
{
<option value="@item">@item</option>
}
<option value="@item">@item</option>
}
</select>
<label class="input-group-text" for="DtMin" title="Selezionare la data da visualizzare"><i class="fa-solid fa-calendar-check"></i></label>
<input @bind="@selDtRef" id="DtMin" class="form-control" type="datetime-local" title="Selezionare la data minima da visualizzare" />
</div>
}
</select>
</div>
<div class="input-group p-2">
<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>
</div>
<div class="input-group p-2">
<label class="input-group-text" for="DtMin" title="Selezionare la data da visualizzare"><i class="fa-solid fa-calendar-check"></i></label>
<input @bind="@selDtRef" id="DtMin" class="form-control" type="datetime-local" title="Selezionare la data minima da visualizzare" />
</div>
<div class="input-group p-2">
<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="250">250</option>
<option value="500">500</option>
</select>
</div>
</div>
</div>
+35 -2
View File
@@ -14,6 +14,8 @@ namespace MP.SPEC.Components
[Parameter]
public SelectDossierParams SelFilterDossier { get; set; } = null!;
protected bool showParam { get; set; } = false;
#endregion Public Properties
#region Protected Properties
@@ -58,6 +60,25 @@ namespace MP.SPEC.Components
}
}
protected string selArticolo
{
get
{
return SelFilterDossier.CodArticolo;
}
set
{
if (!SelFilterDossier.CodArticolo.Equals(value))
{
SelFilterDossier.CurrPage = 1;
SelFilterDossier.CodArticolo = value;
StateHasChanged();
Task.Delay(1);
reportChange();
}
}
}
protected int selMaxRecord
{
get
@@ -83,7 +104,10 @@ namespace MP.SPEC.Components
{
SelFilterDossier = new SelectDossierParams();
ListMacchine = await MDService.MacchineWithFlux();
ListDossier = await MDService.DossiersGetLastFilt(selMacchina, selDtRef, selMaxRecord);
ListArticoli = await MDService.ArticleWithDossier();
#if false
ListDossier = await MDService.DossiersGetLastFilt(selMacchina, selArticolo, selDtRef, selMaxRecord);
#endif
await FilterChanged.InvokeAsync(SelFilterDossier);
}
@@ -96,9 +120,13 @@ namespace MP.SPEC.Components
#region Private Fields
private List<Dossiers>? ListDossier = null;
#if false
private List<Dossiers>? ListDossier = null;
#endif
private List<string>? ListMacchine = null;
private List<string>? ListArticoli = null;
#endregion Private Fields
#region Private Properties
@@ -114,6 +142,11 @@ namespace MP.SPEC.Components
FilterChanged.InvokeAsync(SelFilterDossier);
}
private void toggleShowParams()
{
showParam = !showParam;
}
#endregion Private Methods
}
}
+2
View File
@@ -37,12 +37,14 @@ else
</td>
<td>
@record.OdlNav.CodArticolo
<div class="small textConsensed text-secondary">@record.OdlNav.ArticoloNav.DescArticolo</div>
</td>
<td>
@tradFase(record.OdlNav.KeyRichiesta)
</td>
<td>
@record.IdxMacchina
<div class="small textConsensed text-secondary">@record.MachineNav.Descrizione</div>
</td>
<td>
@record.DtRif
+32 -19
View File
@@ -37,20 +37,6 @@ namespace MP.SPEC.Components
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
@@ -80,7 +66,7 @@ namespace MP.SPEC.Components
await Task.Delay(1);
var done = await MDService.DossiersDeleteRecord(selRec);
currRecord = null;
await reloadData();
await reloadData(true);
await Task.Delay(1);
}
@@ -91,9 +77,11 @@ namespace MP.SPEC.Components
ListStati = await MDService.AnagStatiComm();
ListRecords = await MDService.DossiersGetLastFilt(SelMacchina, SelDtRef, MaxRecord);
#if false
ListRecords = await MDService.DossiersGetLastFilt(SelMacchina, SelArticolo, SelDtRef, MaxRecord);
#endif
await reloadData();
await reloadData(true);
}
protected async void OnSeachUpdated()
@@ -124,9 +112,13 @@ namespace MP.SPEC.Components
#region Private Fields
private int _totalCount = 0;
private Dossiers? currRecord = null;
private List<Dossiers>? ListRecords;
private List<ListValues>? ListStati;
private List<Dossiers>? SearchRecords;
#endregion Private Fields
@@ -154,6 +146,11 @@ namespace MP.SPEC.Components
set => MessageService.numRecord = value;
}
private string SelArticolo
{
get => SelFilter.CodArticolo;
}
private DateTime SelDtRef
{
get => SelFilter.DtRef;
@@ -185,19 +182,35 @@ namespace MP.SPEC.Components
private async void MessageService_EA_PageUpdated()
{
await reloadData();
await reloadData(true);
}
private async Task reloadData(bool setChanged)
{
isLoading = true;
SearchRecords = await MDService.DossiersGetLastFilt(SelMacchina, SelArticolo, 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;
}
#if false
private async Task reloadData()
{
isLoading = true;
SearchRecords = await MDService.DossiersGetLastFilt(SelMacchina, SelDtRef, MaxRecord);
SearchRecords = await MDService.DossiersGetLastFilt(SelMacchina, SelArticolo, SelDtRef, MaxRecord);
totalCount = SearchRecords.Count;
ListRecords = SearchRecords.Skip(numRecord * (currPage - 1)).Take(numRecord).ToList();
await Task.Delay(1);
await InvokeAsync(() => StateHasChanged());
isLoading = false;
}
#endif
private async Task toggleTableFlux()
{
+139 -25
View File
@@ -16,52 +16,166 @@ else
<table class="table table-sm table-striped">
<thead>
<tr>
<th>
@*<button @onclick="() => resetSel()" class="btn btn-primary btn-sm"><i class="bi bi-arrow-counterclockwise"></i></button>*@
</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><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>
<th><i class="fa-solid fa-circle-info"></i> Info ciclo</th>
<th><i class="fa-solid fa-calendar-day"></i> Periodo</th>
<th title="Durata in ore:min"><i class="fa-solid fa-clock"></i> Durata</th>
</tr>
</thead>
<tbody>
@foreach (var record in ListRecords)
{
<tr class="@checkSelect(@record.CodArticolo)">
<td>
@*<button @onclick="() => selRecord(record)" class="btn btn-primary btn-sm"><i class="bi bi-pencil-square"></i></button>*@
</td>
<tr class="@checkSelect(@record.IdxOdl)">
<td>
@record.CodArticolo
<div class="small textConsensed text-secondary">@record.ArticoloNav.DescArticolo</div>
</td>
<td>@tradFase(record.KeyRichiesta)</td>
<td>
<div>
@tradFase(record.KeyRichiesta)
</div>
@if (record.Note != "")
{
<div class="small textConsensed text-secondary badge text-bg-light border border-secondary rounded">
<b class="text-dark"></b> <span class="text-wrap text-start"> @record.Note </span>
</div>
}
</td>
<td>
@record.IdxMacchina
<div class="small textConsensed text-secondary">@record.MachineNav.Descrizione</div>
</td>
<td>
@record.NumPezzi
<div class="small textConsensed"><b>N° pezzi:</b> @record.NumPezzi</div>
<div class="small textConsensed"><b>T. Ciclo:</b> @record.Tcassegnato.ToString("N3")</div>
</td>
<td>
@record.Tcassegnato.ToString("N3")
<div class="small d-flex justify-content-between">
<div>
<div><b>@($"{@record.DataInizio:yyyy/MM/dd}")</b></div>
<div>@($"{@record.DataInizio:ddd HH:mm:ss}")</div>
</div>
<div class="p-0">
<i class="fa-solid fa-angles-right"></i>
</div>
<div>
@if (@record.DataFine != null)
{
<div><b>@($"{@record.DataFine:yyyy/MM/dd}")</b></div>
<div>@($"{@record.DataFine:ddd HH:mm:ss}")</div>
}
else
{
<div class="text-secondary">
<div><b>@($"{DateTime.Now:yyyy/MM/dd}")</b></div>
<div>@($"{DateTime.Now:ddd HH:mm:ss}")</div>
</div>
}
</div>
</div>
</td>
<td>
<div>@record.DataInizio</div>
</td>
<td>@record.Note</td>
@*<td>@record.KeyRichiesta</td>*@
<td>
@*@if (ArticoloDelEnabled(record.CodArticolo))
{
<button @onclick="() => deleteRecord(record)" class="btn btn-danger btn-sm"><i class="bi bi-trash-fill"></i></button>
}*@
<div>
<b>@record.DurataMinuti</b>
</div>
<div>
<button class="btn btn-sm btn-primary py-0" type="button" @onclick="() => selectRecord(record)" data-bs-toggle="modal" data-bs-target="#staticBackdrop" title="Mostra statistiche"><i class="fa-solid fa-chart-pie"></i></button>
</div>
<!-- Modal -->
<div class="modal fade" id="staticBackdrop" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="staticBackdropLabel">Modal title</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body col-12">
@if (currRecord != null)
{
<h3>ODL @currRecord.IdxOdl</h3>
<div class="d-flex justify-content-between">
<div class="col-6">
<div>
<table class="table table-sm" style="max-width:500px;">
<thead>
<tr>
<th><i class="fa-solid fa-file"></i> Articolo</th>
<th><i class="fa-solid fa-file"></i> Descrizione Art.</th>
<th><i class="fa-solid fa-screwdriver-wrench"></i> Fase</th>
<th><i class="fa-solid fa-screwdriver-wrench"></i> Note</th>
</tr>
</thead>
<tbody>
<tr>
<th>@currRecord.CodArticolo</th>
<td>@currRecord.ArticoloNav.DescArticolo</td>
<td>@currRecord.KeyRichiesta</td>
<td>@currRecord.Note</td>
</tr>
</tbody>
</table>
</div>
<div>
<table class="table table-sm" style="max-width:500px;">
<thead>
<tr>
<th><i class="fa-solid fa-hard-drive"></i> Macchina</th>
<th><i class="fa-solid fa-hard-drive"></i> Info macchina</th>
<th><i class="fa-solid fa-calendar-day"></i> Periodo</th>
</tr>
</thead>
<tbody>
<tr>
<td>@currRecord.IdxMacchina</td>
<td>@currRecord.MachineNav.CodMacchina</td>
<td>
<div class="small d-flex justify-content-between">
<div>
<div><b>@($"{@record.DataInizio:yyyy/MM/dd}")</b></div>
<div>@($"{@record.DataInizio:ddd HH:mm:ss}")</div>
</div>
<div class="p-0">
<i class="fa-solid fa-angles-right"></i>
</div>
<div>
@if (@record.DataFine != null)
{
<div><b>@($"{@record.DataFine:yyyy/MM/dd}")</b></div>
<div>@($"{@record.DataFine:ddd HH:mm:ss}")</div>
}
else
{
<div class="text-secondary">
<div><b>@($"{DateTime.Now:yyyy/MM/dd}")</b></div>
<div>@($"{DateTime.Now:ddd HH:mm:ss}")</div>
</div>
}
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div>
<ODLPlot SelectedOdl="@currRecord.IdxOdl"></ODLPlot>
</div>
</div>
}
</div>
</div>
</div>
</div>
</td>
</tr>
}
+56 -24
View File
@@ -1,7 +1,10 @@
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using MP.Data;
using MP.Data.DatabaseModels;
using MP.SPEC.Data;
using Newtonsoft.Json.Linq;
using System.Text;
namespace MP.SPEC.Components
{
@@ -10,20 +13,10 @@ namespace MP.SPEC.Components
#region Public Properties
[Parameter]
public EventCallback<bool> PagerResetReq { get; set; }
public SelectOdlParams currFilter { get; set; } = null!;
[Parameter]
public string StatoSel
{
get => _statoSel;
set
{
if (_statoSel != value)
{
_statoSel = value;
}
}
}
public EventCallback<bool> PagerResetReq { get; set; }
[Parameter]
public EventCallback<int> updateRecordCount { get; set; }
@@ -32,14 +25,14 @@ namespace MP.SPEC.Components
#region Public Methods
public string checkSelect(string CodArticolo)
public string checkSelect(int IdxOdl)
{
string answ = "";
if (currRecord != null)
{
try
{
answ = (currRecord.CodArticolo == CodArticolo) ? "table-info" : "";
answ = (currRecord.IdxOdl == IdxOdl) ? "table-info" : "";
}
catch
{ }
@@ -49,12 +42,15 @@ namespace MP.SPEC.Components
public void Dispose()
{
#if false
MessageService.EA_PageUpdated -= MessageService_EA_PageUpdated;
MessageService.EA_SearchUpdated -= OnSeachUpdated;
MessageService.EA_SearchUpdated -= OnSeachUpdated;
#endif
}
#endregion Public Methods
#region Protected Properties
[Inject]
@@ -73,8 +69,10 @@ namespace MP.SPEC.Components
protected override async Task OnInitializedAsync()
{
ListStati = await MDService.AnagStatiComm();
#if false
MessageService.EA_PageUpdated += MessageService_EA_PageUpdated;
MessageService.EA_SearchUpdated += OnSeachUpdated;
MessageService.EA_SearchUpdated += OnSeachUpdated;
#endif
}
protected override async Task OnParametersSetAsync()
@@ -95,7 +93,10 @@ namespace MP.SPEC.Components
protected async Task UpdateData()
{
currRecord = null;
#if false
currRecord = null;
#endif
await selectRecord(null);
await reloadData();
}
@@ -103,11 +104,28 @@ namespace MP.SPEC.Components
#region Private Fields
private string _statoSel = "*";
private ODLModel? currRecord = null;
protected async Task selectRecord(ODLModel? currRec)
{
await Task.Delay(1);
currRecord = currRec;
if (currRec != null)
{
ListOdlStats = await MDService.StatOdl(currRec.IdxOdl);
}
else
{
ListOdlStats = null;
}
}
private List<ODLModel>? ListRecords;
private List<ListValues>? ListStati;
private List<ODLModel>? SearchRecords;
private List<StatODLModel>? ListOdlStats;
private List<double>? ListOdlStatsData = new List<double>();
private List<string>? ListOdlStatsLabels = new List<string>();
#endregion Private Fields
@@ -127,11 +145,6 @@ namespace MP.SPEC.Components
set => MessageService.numRecord = value;
}
private string SearchVal
{
get => string.IsNullOrEmpty(MessageService.SearchVal) ? "*" : MessageService.SearchVal;
}
private int totalCount { get; set; } = 0;
#endregion Private Properties
@@ -146,7 +159,7 @@ namespace MP.SPEC.Components
private async Task reloadData()
{
isLoading = true;
SearchRecords = await MDService.ListODLFilt(true, SearchVal, StatoSel);
SearchRecords = await MDService.ListODLFilt(currFilter.IsActive, currFilter.SearchVal, currFilter.CodStato, currFilter.DtStart, currFilter.DtEnd);
totalCount = SearchRecords.Count;
ListRecords = SearchRecords.Skip(numRecord * (currPage - 1)).Take(numRecord).ToList();
await Task.Delay(1);
@@ -168,7 +181,26 @@ namespace MP.SPEC.Components
}
return answ;
}
private double[] addODLData()
{
var eleStats = ListOdlStats.Where(x => x.IdxStato == currRecord.IdxOdl).ToList();
foreach (var item in eleStats)
{
ListOdlStatsData.Add(item.TotDurata);
}
return ListOdlStatsData.ToArray();
}
private string[] addODLLabels()
{
var eleStats = ListOdlStats.Where(x => x.IdxStato == currRecord.IdxOdl).ToList();
foreach (var item in eleStats)
{
ListOdlStatsLabels.Add(item.Descrizione);
}
return ListOdlStatsLabels.ToArray();
}
#endregion Private Methods
}
}
+17 -10
View File
@@ -22,9 +22,8 @@ else
<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><i class="fa-solid fa-clock"></i> T.Ciclo</th>
<th><i class="fa-solid fa-pen-to-square"></i> Note</th>
<th><i class="fa-solid fa-circle-info"></i> Info ciclo</th>
@*<th><i class="fa-solid fa-pen-to-square"></i> Note</th>*@
<th title="Attivabile"><i class="fa-regular fa-square-check"></i> Att</th>
<th></th>
</tr>
@@ -33,7 +32,7 @@ else
@foreach (var record in ListRecords)
{
<tr class="@checkSelect(@record)">
<td>
<td class="text-nowrap">
<button @onclick="() => selRecord(record)" class="btn btn-primary btn-sm" title="Modifica Record"><i class="bi bi-pencil-square"></i></button>
<button @onclick="() => cloneRecord(record)" class="btn btn-info btn-sm" title="Duplica Record"><i class="bi bi-clipboard-check"></i></button>
</td>
@@ -41,18 +40,26 @@ else
@record.CodArticolo
<div class="small textConsensed text-secondary">@record.ArticoloNav.DescArticolo</div>
</td>
<td>@tradFase(record.KeyRichiesta)</td>
<td>
<div>
@tradFase(record.KeyRichiesta)
</div>
@if (record.Note != "")
{
<div class="small textConsensed text-secondary badge text-bg-light border border-primary rounded">
<b class="text-dark">Note:</b> @record.Note
</div>
}
</td>
<td>
@record.IdxMacchina
<div class="small textConsensed text-secondary">@record.MachineNav.Descrizione</div>
</td>
<td>
@record.NumPezzi
<div class="small textConsensed"><b>N° pezzi:</b> @record.NumPezzi</div>
<div class="small textConsensed"><b>T. Ciclo:</b> @record.Tcassegnato.ToString("N3")</div>
</td>
<td>
@record.Tcassegnato.ToString("N3")
</td>
<td>@record.Note</td>
@*<td>@record.Note</td>*@
<td>
@if (@record.Attivabile)
{
+19
View File
@@ -2,6 +2,7 @@
using Microsoft.JSInterop;
using MP.Data.DatabaseModels;
using MP.SPEC.Data;
using MP.SPEC.Services;
namespace MP.SPEC.Components
{
@@ -47,6 +48,9 @@ namespace MP.SPEC.Components
[Inject]
protected MpDataService MDService { get; set; } = null!;
[Inject]
protected IOApiService MpIoApiCall { get; set; }
[Inject]
protected MessageService MsgService { get; set; } = null!;
@@ -91,6 +95,7 @@ namespace MP.SPEC.Components
return;
await Task.Delay(1);
var done = await MDService.PODLDeleteRecord(selRec);
await callSyncDb(selRec);
currRecord = null;
await reloadData();
await Task.Delay(1);
@@ -152,6 +157,7 @@ namespace MP.SPEC.Components
private List<PODLModel>? ListRecords;
private List<ListValues>? ListStati;
private List<PODLModel>? SearchRecords;
#endregion Private Fields
@@ -189,6 +195,19 @@ namespace MP.SPEC.Components
#region Private Methods
/// <summary>
/// Chiama metodo x chiedere sync DB
/// </summary>
/// <param name="selRec"></param>
/// <returns></returns>
private async Task callSyncDb(PODLModel selRec)
{
// chiamo aggiunta task SyncDb...
string idxMacc = selRec.IdxMacchina;
string restUrl = $"IOB/addTask2Exe/{idxMacc}?taskName=syncDbData&taskVal=";
var response = await MpIoApiCall.callMpIoUrlGet(restUrl);
}
private async void MessageService_EA_PageUpdated()
{
await reloadData();
+20
View File
@@ -0,0 +1,20 @@
@if (@SelectedOdl != -1)
{
<div class="d-flex justify-content-between mb-2">
<div class="px-1 border border-success rounded">
<i class="fa-solid fa-calendar-days"></i> <b>@SelectedOdl</b>
</div>
</div>
<div class="d-flex">
<div class="px-1 flex-fill">
@if (isLoading)
{
<LoadingDataSmall></LoadingDataSmall>
}
else
{
<MP.SPEC.Components.Chart.Doughnut Id="@OdlId.ToString()" Type="@Chart.Doughnut.ChartType.Doughnut" Data="@Data.ToArray()" BackgroundColor="@(new[] { "yellow","red", "green"})" Labels="@Labels.ToArray()"></MP.SPEC.Components.Chart.Doughnut>
}
</div>
</div>
}
+72
View File
@@ -0,0 +1,72 @@
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using MP.Data.DatabaseModels;
using MP.SPEC.Components;
using MP.SPEC.Data;
namespace MP.SPEC.Components
{
public partial class ODLPlot
{
#region Public Properties
public int OdlId
{
get => _selParam;
}
[Parameter]
public int SelectedOdl
{
get => _selParam;
set => _selParam = value;
}
#endregion Public Properties
#region Protected Properties
//protected DataLogFilter _SelFilter { get; set; } = new DataLogFilter();
protected int _selParam { get; set; } = -1;
#endregion Protected Properties
#region Protected Methods
private bool isLoading { get; set; } = false;
protected override async Task OnInitializedAsync()
{
isLoading = true;
await Task.Delay(1);
}
private List<StatODLModel>? ListRecords = null;
protected override async Task OnParametersSetAsync()
{
await ReloadData();
await Task.Delay(1);
}
public List<double> Data = new List<double>();
public List<string> Labels = new List<string>();
protected async Task ReloadData()
{
ListRecords = await MDService.StatOdl(SelectedOdl);
foreach (var record in ListRecords)
{
Data.Add(record.TotDurata);
Labels.Add($"{record.Descrizione} - {record.TotDurata:N1}min");
}
await Task.Delay(1);
isLoading = false;
}
[Inject]
protected MpDataService MDService { get; set; } = null!;
#endregion Protected Methods
}
}
+112 -101
View File
@@ -1,115 +1,126 @@
<div class="d-flex justify-content-between">
<div class="px-0 py-1">
<div class="d-flex justify-content-between">
<div class="px-2">
<div class="d-flex justify-content-between pt-1 mb-1">
<div class="px-2">
@if (!liveUpdate)
{
<button class="btn btn-secondary" type="button" @onclick="() => toggleUpdate()" title="Click per tornare a Valori Live">
<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>
@snapMode
</button>
}
</div>
<div class="px-2">
@if (snapshotDone)
{
<button class="btn btn-success" type="button" @onclick="() => navDossier()">
<div class="spinner-border spinner-border-sm" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<i class="fa-solid fa-camera"></i>
Fatto! Mostra Dossier
</button>
}
</div>
</div>
</div>
<div class="px-0">
<div class="d-flex justify-content-end">
@if (showEditPar)
@if (!liveUpdate)
{
<div class="px-0 input-group py-1">
<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" style="width: 3em;">
<option value="2">2</option>
<option value="5">5</option>
<option value="10">10</option>
<option value="30">30</option>
<option value="60">60</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="250">250</option>
<option value="500">500</option>
<option value="1000">1000</option>
<option value="2500">2500</option>
<option value="5000">5000</option>
</select>
</div>
<button class="btn btn-secondary" type="button" @onclick="() => toggleUpdate()" title="Click per tornare a Valori Live">
<small>@lastUpdate</small>
</button>
}
else
{
<div class="px-2 py-1">
<button class="btn btn-primary" @onclick="() => toggleParams()"><i class="fa-solid fa-arrow-left"></i></button>
</div>
<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="px-2 input-group">
<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="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)
{
foreach (var item in ListFlux)
{
<option value="@item">@item</option>
}
}
</select>
@if (selDtMax == null)
</div>
<div class="px-2">
@if (selMacchina != "*")
{
<button class="btn btn-warning" type="button" @onclick="() => takeSnapshot()">
<i class="fa-solid fa-camera"></i>
@snapMode
</button>
}
</div>
<div class="px-2">
@if (snapshotDone)
{
<button class="btn btn-success" type="button" @onclick="() => navDossier()">
<div class="spinner-border spinner-border-sm" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<i class="fa-solid fa-camera"></i>
Fatto! Mostra Dossier
</button>
}
</div>
</div>
<a class="pt-2" data-bs-toggle="offcanvas" data-bs-target="#paramsFilterExample" aria-controls="paramsFilterExample" @onclick="setDtMax">
<i class="fa-solid fa-bars text-dark"></i>
</a>
<div class="offcanvas offcanvas-end" tabindex="-1" id="paramsFilterExample" aria-labelledby="paramsFilterExampleLabel">
<div class="offcanvas-header">
<h3 class="offcanvas-title" id="paramsFilterExampleLabel"><b>FILTRI</b></h3>
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<div class="small">
<label class="px-2" for="macchina" title="Selezionare impianto">Impianto</label>
</div>
<div class="px-2 input-group">
<label class="input-group-text" for="macchina" title="Selezionare impianto"><i class="fa-solid fa-hard-drive"></i></label>
<select @bind="@selMacchina" class="form-select" id="macchina" title="Selezionare impianto">
<option value="*">--- Tutti ---</option>
@if (ListMacchine != null)
{
<button class="btn btn-primary" @onclick="() => setDtMax()"><i class="fa-regular fa-calendar-check"></i></button>
foreach (var item in ListMacchine)
{
<option value="@item">@item</option>
}
}
else
</select>
</div>
<div class="small mt-2">
<label class="px-2" for="flusso" title="Selezionare il parametro">Parametro</label>
</div>
<div class="px-2 input-group">
<label class="input-group-text" for="flusso" title="Selezionare il parametro"><i class="fa-solid fa-sliders"></i></label>
<select @bind="@selFlux" class="form-select" id="flusso" title="Selezionare il parametro">
<option value="*">--- Tutti ---</option>
@if (ListFlux != null)
{
<label class="input-group-text" for="flusso" title="Selezionare la data minima eventi da visualizzare"><i class="fa-regular fa-calendar-minus"></i></label>
<input class="form-control" @bind="@selDtMin" type="datetime-local" title="Data minima eventi da visualizzare">
<label class="input-group-text" for="flusso" title="Selezionare la data massima eventi da visualizzare"><i class="fa-regular fa-calendar-plus"></i></label>
<input class="form-control" @bind="@selDtMax" type="datetime-local" title="Selezionare la data massima eventi da visualizzare">
foreach (var item in ListFlux)
{
<option value="@item">@item</option>
}
}
</div>
</select>
</div>
<div class="small mt-2">
<label class="px-2" for="dtMin" title="Selezionare inizio periodo">Inizio Periodo</label>
</div>
<div class="px-2 input-group">
<label class="input-group-text" for="dtMin" title="Selezionare inizio periodo"><i class="fa-regular fa-calendar-minus"></i></label>
<input class="form-control" @bind="@selDtMin" id="dtMin" type="datetime-local" title="Data minima eventi da visualizzare">
</div>
<div class="small mt-2">
<label class="px-2" for="dtMax" title="Selezionare fine periodo">Fine Periodo</label>
</div>
<div class="px-2 input-group">
<label class="input-group-text" for="dtMax" title="Selezionare fine periodo"><i class="fa-regular fa-calendar-plus"></i></label>
<input class="form-control" @bind="@selDtMax" id="dtMax" type="datetime-local" title="Selezionare fine periodo">
</div>
<div class="small mt-2">
<label class="px-2" for="tempoAgg" title="Selezionare refresh rate (sec) periodo">Refresh rate (sec)</label>
</div>
<div class="px-2 input-group">
<label class="input-group-text" for="tempoAgg" title="Selezionare refresh rate (sec)"><i class="fa-solid fa-clock"></i></label>
<select @bind="@selTempoAgg" class="form-select" id="tempoAgg" title="Selezionare refresh rate (sec)" style="width: 3em;">
<option value="2">2</option>
<option value="5">5</option>
<option value="10">10</option>
<option value="30">30</option>
<option value="60">60</option>
</select>
</div>
<div class="small mt-2">
<label class="px-2" for="maxRecord" title="Numero massimo record da mostrare">Max Record</label>
</div>
<div class="px-2 input-group">
<label class="input-group-text" for="maxRecord" title="Numero massimo record da mostrare"><i class="fa-solid fa-list-ol"></i></label>
<select @bind="@selMaxRecord" class="form-select" id="maxRecord" title="Numero massimo record da mostrare">
<option value="50">50</option>
<option value="100">100</option>
<option value="250">250</option>
<option value="500">500</option>
<option value="1000">1000</option>
<option value="2500">2500</option>
<option value="5000">5000</option>
</select>
</div>
</div>
</div>
+4 -2
View File
@@ -99,7 +99,8 @@ namespace MP.SPEC.Components
}
}
}
protected bool showParam { get; set; } = false;
protected bool selDt { get; set; } = false;
protected string selMacchina
{
get => SelFilter.IdxMacchina;
@@ -185,7 +186,7 @@ namespace MP.SPEC.Components
// copio il filtro
var currFilt = SelFilter;
// fermo update
currFilt.LiveUpdate = false;
//currFilt.LiveUpdate = false;
currFilt.CurrPage = 0;
currFilt.lastUpdate = $"{DateTime.Now:yyyy/MM/dd HH:mm:ss}";
currFilt.dtMax = RoundDatetime(5);
@@ -193,6 +194,7 @@ namespace MP.SPEC.Components
SelFilter = currFilt;
}
protected void startTimer()
{
aTimer = new System.Timers.Timer(5000);
+12
View File
@@ -0,0 +1,12 @@
<div class="input-group input-group-sm">
<div class="input-group-text">
<span class="me-1 @leftStringCSS">@leftString</span>
<div class="form-check form-check-sm form-switch py-1" title="Parameter View Mode (RealTime / LogData)">
<input class="form-check-input" type="checkbox" id="mySwitch" name="setupAlarms" checked @onclick="() => toggle()">
</div>
<span class="@rightStringCSS">@rightString</span>
</div>
</div>
+127
View File
@@ -0,0 +1,127 @@
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;
namespace MP.SPEC.Components
{
public partial class ToggleMode
{
[Parameter]
public EventCallback<SelectGlobalToggle> FilterChanged { get; set; }
[Parameter]
public SelectGlobalToggle SelFilter { get; set; } = new SelectGlobalToggle();
protected bool isActive
{
get => SelFilter.isActive;
set
{
if (SelFilter.isActive != value)
{
SelFilter.isActive = value;
reportChange();
}
}
}
protected string leftString
{
get => SelFilter.leftString;
set
{
if (SelFilter.leftString != value)
{
SelFilter.leftString = value;
reportChange();
}
}
}
protected string leftStringCSS
{
get => SelFilter.leftStringCSS;
set
{
if (SelFilter.leftStringCSS != value)
{
SelFilter.leftStringCSS = value;
reportChange();
}
}
}
protected string rightString
{
get => SelFilter.rightString;
set
{
if (SelFilter.rightString != value)
{
SelFilter.rightString = value;
reportChange();
}
}
}
protected string rightStringCSS
{
get => SelFilter.rightStringCSS;
set
{
if (SelFilter.rightStringCSS != value)
{
SelFilter.rightStringCSS = value;
reportChange();
}
}
}
protected void toggle()
{
var currFilt = SelFilter;
currFilt.isActive = !currFilt.isActive;
SelFilter = currFilt;
if (isActive)
{
rightStringCSS = "fw-bold";
leftStringCSS = "text-secondary";
}
else
{
leftStringCSS = "fw-bold";
rightStringCSS = "text-secondary";
}
}
protected override async Task OnInitializedAsync()
{
if (isActive)
{
rightStringCSS = "fw-bold";
leftStringCSS = "text-secondary";
}
else
{
leftStringCSS = "fw-bold";
rightStringCSS = "text-secondary";
}
await FilterChanged.InvokeAsync(SelFilter);
}
private void reportChange()
{
FilterChanged.InvokeAsync(SelFilter);
}
}
}
+67 -10
View File
@@ -276,10 +276,19 @@ namespace MP.SPEC.Data
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;
List<FluxLog> answ = new List<FluxLog>();
DossierFluxLogDTO? result = JsonConvert.DeserializeObject<DossierFluxLogDTO>(Valore);
if (result != null)
{
if (result.ODL != null)
{
answ = result
.ODL
.OrderBy(x => x.CodFlux)
.ToList();
}
}
return answ;
}
public void Dispose()
@@ -317,13 +326,13 @@ namespace MP.SPEC.Data
/// <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)
public async Task<List<Dossiers>> DossiersGetLastFilt(string IdxMacchina, string CodArticolo, DateTime DtRef, int MaxRec)
{
List<Dossiers>? result = new List<Dossiers>();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string readType = "DB";
string currKey = $"{redisDossByMac}:{IdxMacchina}:{DtRef:yyyy/MM/dd HH:mm:ss}:{MaxRec}";
string currKey = $"{redisDossByMac}:{IdxMacchina}:{CodArticolo}:{DtRef}:{MaxRec}";
// cerco in redis dato valore sel macchina...
RedisValue rawData = redisDb.StringGet(currKey);
if (rawData.HasValue)
@@ -333,7 +342,7 @@ namespace MP.SPEC.Data
}
else
{
result = await Task.FromResult(dbController.DossiersGetLastFilt(IdxMacchina, DtRef, MaxRec));
result = await Task.FromResult(dbController.DossiersGetLastFilt(IdxMacchina, CodArticolo, DtRef, MaxRec));
// serializzp e salvo...
rawData = JsonConvert.SerializeObject(result);
redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache / 5));
@@ -399,6 +408,16 @@ namespace MP.SPEC.Data
return Task.FromResult(dbController.AnagGruppiAziende());
}
/// <summary>
/// Statistiche ODL calcolate (da stored stp_STAT_ODL)
/// </summary>
/// <returns></returns>
public Task<List<StatODLModel>> StatOdl(int IdxOdl)
{
return dbController.StatOdl(IdxOdl);
}
/// <summary>
/// Restitusice elenco fasi
/// </summary>
@@ -473,9 +492,9 @@ namespace MP.SPEC.Data
/// <param name="codArt">Cod articolo</param>
/// <param name="keyRichPart">KeyRich (parziale) da cercare (es cod stato x yacht)</param>
/// <returns></returns>
public async Task<List<ODLModel>> ListODLFilt(bool inCorso, string codArt, string keyRichPart)
public async Task<List<ODLModel>> ListODLFilt(bool inCorso, string codArt, string keyRichPart, DateTime startDate, DateTime endDate)
{
return await Task.FromResult(dbController.ListODLFilt(inCorso, codArt, keyRichPart));
return await Task.FromResult(dbController.ListODLFilt(inCorso, codArt, keyRichPart, startDate, endDate));
}
/// <summary>
@@ -544,7 +563,7 @@ namespace MP.SPEC.Data
}
else
{
result = await Task.FromResult(dbController.MacchineWithFlux());
result = await dbController.MacchineWithFlux();
// serializzp e salvo...
rawData = JsonConvert.SerializeObject(result);
redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache));
@@ -559,6 +578,42 @@ namespace MP.SPEC.Data
return result;
}
/// <summary>
/// Elenco Codice articolo con dati dossier gestiti
/// </summary>
/// <returns></returns>
public async Task<List<string>> ArticleWithDossier()
{
List<string>? result = new List<string>();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string readType = "DB";
string currKey = redisArtByDossier;
// cerco in redis dato valore sel macchina...
RedisValue rawData = redisDb.StringGet(currKey);
if (rawData.HasValue)
{
result = JsonConvert.DeserializeObject<List<string>>($"{rawData}");
readType = "REDIS";
}
else
{
result = await Task.FromResult(dbController.ArticleWithDossier());
// serializzp e salvo...
rawData = JsonConvert.SerializeObject(result);
redisDb.StringSet(currKey, rawData, getRandTOut(redisLongTimeCache));
}
if (result == null)
{
result = new List<string>();
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"ArticleWithDossier | Read from {readType}: {ts.TotalMilliseconds}ms");
return result;
}
/// <summary>
/// Elenco di tutti i parametri filtrati x macchina
/// </summary>
@@ -650,6 +705,8 @@ namespace MP.SPEC.Data
private const string redisMacByFlux = redisBaseAddr + "SPEC:Cache:MacByFlux";
private const string redisArtByDossier = redisBaseAddr + "SPEC:Cache:ArtByDossier";
private const string redisMacList = redisBaseAddr + "SPEC:Cache:MacList";
private const string redisStatoCom = redisBaseAddr + "SPEC:Cache:StatoCom";
+6 -1
View File
@@ -17,7 +17,9 @@
public string IdxMacchina { get; set; } = "*";
public int MaxRecord { get; set; } = 10;
public string CodArticolo { get; set; } = "*";
public int MaxRecord { get; set; } = 100;
#endregion Public Properties
@@ -44,6 +46,9 @@
if (IdxMacchina != item.IdxMacchina)
return false;
if (CodArticolo != item.CodArticolo)
return false;
if (MaxRecord != item.MaxRecord)
return false;
+74
View File
@@ -0,0 +1,74 @@
namespace MP.SPEC.Data
{
public class SelectGlobalToggle
{
#region Public Constructors
public SelectGlobalToggle()
{ }
#endregion Public Constructors
#region Public Properties
/// <summary>
/// Bool: indica se il toggle è attivo
/// </summary>
public bool isActive { get; set; } = true;
/// <summary>
/// string: stringa da mostrare a sinistra (disattivo onInitialize)
/// </summary>
public string leftString { get; set; } = "";
/// <summary>
/// string: stringa da mostrare a destra (attivo onInitialize)
/// </summary>
public string rightString { get; set; } = "";
/// <summary>
/// string: stile stringa da mostrare a sinistra (disattivo onInitialize)
/// </summary>
public string leftStringCSS { get; set; } = "";
/// <summary>
/// string: stile stringa da mostrare a destra (attivo onInitialize)
/// </summary>
public string rightStringCSS { get; set; } = "";
#endregion Public Properties
#region Public Methods
public override bool Equals(object obj)
{
if (!(obj is SelectGlobalToggle item))
return false;
if (isActive != item.isActive)
return false;
if (leftString != item.leftString)
return false;
if (rightString != item.rightString)
return false;
if (leftStringCSS != item.leftStringCSS)
return false;
if (rightStringCSS != item.rightStringCSS)
return false;
return true;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
#endregion Public Methods
}
}
+68
View File
@@ -0,0 +1,68 @@
using MP.Data;
namespace MP.SPEC.Data
{
public class SelectOdlParams
{
#region Public Constructors
public SelectOdlParams()
{ }
#endregion Public Constructors
#region Public Properties
public string CodStato { get; set; } = "*";
public int CurrPage { get; set; } = 1;
public int NumRec { get; set; } = 10;
public DateTime DtEnd { get; set; } = Utils.InitDatetime(DateTime.Now, 5);
public DateTime DtStart { get; set; } = Utils.InitDatetime(DateTime.Now, 5).AddDays(-7);
public int MaxRecord { get; set; } = 100;
public bool IsActive { get; set; } = true;
public string SearchVal { get; set; } = "*";
#endregion Public Properties
#region Public Methods
public override bool Equals(object obj)
{
if (!(obj is SelectOdlParams item))
return false;
if (IsActive != item.IsActive)
return false;
if (CodStato != item.CodStato)
return false;
if (MaxRecord != item.MaxRecord)
return false;
if (NumRec != item.NumRec)
return false;
if (DtStart != item.DtStart)
return false;
if (DtEnd != item.DtEnd)
return false;
if (CurrPage != item.CurrPage)
return false;
if (SearchVal != item.SearchVal)
return false;
return true;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
#endregion Public Methods
}
}
+11 -5
View File
@@ -5,7 +5,7 @@
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>MP.SPEC</RootNamespace>
<Version>6.16.2210.511</Version>
<Version>6.16.2210.1016</Version>
</PropertyGroup>
<ItemGroup>
@@ -14,6 +14,16 @@
<ItemGroup>
<None Include="compilerconfig.json" />
<None Include="wwwroot\lib\Chart.js\chart.esm.js" />
<None Include="wwwroot\lib\Chart.js\chart.esm.min.js" />
<None Include="wwwroot\lib\Chart.js\chart.js" />
<None Include="wwwroot\lib\Chart.js\chart.min.js" />
<None Include="wwwroot\lib\Chart.js\helpers.esm.js" />
<None Include="wwwroot\lib\Chart.js\helpers.esm.min.js" />
<None Include="wwwroot\lib\chartjs-adapter-luxon\chartjs-adapter-luxon.esm.js" />
<None Include="wwwroot\lib\chartjs-adapter-luxon\chartjs-adapter-luxon.esm.min.js" />
<None Include="wwwroot\lib\chartjs-adapter-luxon\chartjs-adapter-luxon.js" />
<None Include="wwwroot\lib\chartjs-adapter-luxon\chartjs-adapter-luxon.min.js" />
</ItemGroup>
<ItemGroup>
@@ -21,10 +31,6 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
<ItemGroup>
<Folder Include="wwwroot\lib\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MP.Data\MP.Data.csproj" />
</ItemGroup>
+1
View File
@@ -14,6 +14,7 @@
}
else
{
<DossiersFilter FilterChanged="updateFilter"></DossiersFilter>
}
</div>
+2 -1
View File
@@ -18,7 +18,7 @@
</div>
<div class="card-body text-center">
<div class="shortcuts my-5 py-5">
<div class="shortcuts my-3 py-3">
<div class="row">
<div class="col-12">
@if (ElencoLink == null)
@@ -33,6 +33,7 @@
}
else
{
foreach (var item in ElencoLink)
{
<a href="@item.NavigateUrl" class="shortcut">
+68 -16
View File
@@ -1,30 +1,82 @@
@page "/ODL"
<div class="card mb-5">
<div class="card-header table-primary">
<div class="d-flex justify-content-between">
<div class="px-1">
<h3><b>ODL</b></h3>
<div class="card-header table-primary ">
<div class="d-flex justify-content-between col-12">
<div class="px-1 col-4">
<div>
<h3><b>ODL</b></h3>
</div>
</div>
<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)
<div class="col-4">
<div class="input-group input-group-sm">
<div class="input-group-text">
<span class="me-1 @leftStringCSS">Completati</span>
<span class="form-check form-check-sm form-switch py-1" title="ODL Chiusi / Correnti">
<input class="form-check-input" type="checkbox" id="switchActive" @bind="@isActive">
</span>
<span class="@rightStringCSS">In Corso</span>
</div>
</div>
</div>
<div class="d-flex justify-content-end">
<a class="pt-2 text-dark" data-bs-toggle="offcanvas" data-bs-target="#paramsFilterExample" aria-controls="paramsFilterExample" @onclick="setDtMax">
<i class="fa-solid fa-bars"></i>
</a>
<div class="offcanvas offcanvas-end" tabindex="-1" id="paramsFilterExample" aria-labelledby="paramsFilterExampleLabel">
<div class="offcanvas-header">
<h3 class="offcanvas-title" id="paramsFilterExampleLabel"><b>FILTRI</b></h3>
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<div>
<div>
Seleziona i filtri per:
</div>
</div>
<div>
<div class="small mt-2">
<label class="px-2" for="macchina" title="Selezionare inizio periodo">Macchina</label>
</div>
<div class="input-group px-2">
<label class="input-group-text" for="macchina" title="Selezionare la fase da visualizzare"><i class="fa-solid fa-screwdriver-wrench"></i></label>
<select @bind="@selStato" id="macchina" class="form-select" title="Selezionare la fase da visualizzare">
<option value="*">--- Tutti ---</option>
@if (ListStati != null)
{
foreach (var item in ListStati)
{
<option value="@item.value">@item.label</option>
}
}
</select>
</div>
</div>
@if (!isActive)
{
foreach (var item in ListStati)
{
<option value="@item.value">@item.label</option>
}
<div class="small mt-2">
<label class="px-2" for="dtMin" title="Selezionare inizio periodo">Inizio Periodo</label>
</div>
<div class="px-2 input-group">
<label class="input-group-text" for="dtMin" title="Selezionare inizio periodo"><i class="fa-regular fa-calendar-minus"></i></label>
<input class="form-control" @bind="@selDtStart" id="dtMin" type="datetime-local" title="Data minima eventi da visualizzare">
</div>
<div class="small mt-2">
<label class="px-2" for="dtMax" title="Selezionare fine periodo">Fine Periodo</label>
</div>
<div class="px-2 input-group">
<label class="input-group-text" for="dtMax" title="Selezionare fine periodo"><i class="fa-regular fa-calendar-plus"></i></label>
<input class="form-control" @bind="@selDtEnd" id="dtMax" type="datetime-local" title="Selezionare fine periodo">
</div>
}
</select>
</div>
</div>
</div>
</div>
</div>
<div class="card-body">
<ListODL StatoSel="@selStato" PagerResetReq="pgResetReq" updateRecordCount="UpdateTotCount"></ListODL>
<ListODL PagerResetReq="pgResetReq" updateRecordCount="UpdateTotCount" currFilter="@currFilter"></ListODL>
</div>
<div class="card-footer py-1">
<DataPager @ref="pagerODL" PageSize="numRecord" currPage="currPage" numRecordChanged="ForceReload" numPageChanged="ForceReloadPage" totalCount="totalCount" showLoading="isLoading" />
+77 -18
View File
@@ -7,6 +7,23 @@ namespace MP.SPEC.Pages
{
public partial class ODL
{
#region Public Methods
/// <summary>
/// Inizializzazione con periodo e arrotondamento
/// </summary>
/// <param name="minRound"></param>
/// <returns></returns>
public static DateTime RoundDatetime(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;
}
#endregion Public Methods
#region Protected Fields
protected DataPager pagerODL;
@@ -15,6 +32,12 @@ namespace MP.SPEC.Pages
#region Protected Properties
protected bool isActive
{
get => currFilter.IsActive;
set => currFilter.IsActive = value;
}
[Inject]
protected IJSRuntime JSRuntime { get; set; } = null!;
@@ -24,15 +47,34 @@ namespace MP.SPEC.Pages
[Inject]
protected MessageService MsgService { get; set; } = null!;
protected DateTime selDtEnd
{
get => currFilter.DtEnd;
set
{
if (currFilter.DtEnd != value)
{
currFilter.DtEnd = value;
}
}
}
protected DateTime selDtStart
{
get => currFilter.DtStart;
set
{
if (currFilter.DtStart != value)
{
currFilter.DtStart = value;
}
}
}
#endregion Protected Properties
#region Protected Methods
protected void UpdateTotCount(int newTotCount)
{
totalCount = newTotCount;
}
protected void ForceReload(int newNum)
{
numRecord = newNum;
@@ -50,8 +92,10 @@ namespace MP.SPEC.Pages
// resetto search
MsgService.SearchVal = "";
ListStati = await MDService.AnagStatiComm();
#if false
// carico dati
await reloadData();
#endif
}
protected async Task pgResetReq(bool doReset)
@@ -62,6 +106,18 @@ namespace MP.SPEC.Pages
}
}
protected void setDtMax()
{
// copio il filtro
currFilter.DtEnd = RoundDatetime(5);
currFilter.DtStart = RoundDatetime(5).AddDays(-1);
}
protected void UpdateTotCount(int newTotCount)
{
totalCount = newTotCount;
}
#endregion Protected Methods
#region Private Fields
@@ -72,7 +128,7 @@ namespace MP.SPEC.Pages
#region Private Properties
private string currAzienda { get; set; } = "*";
private SelectOdlParams currFilter { get; set; } = new SelectOdlParams();
private int currPage
{
@@ -82,13 +138,27 @@ namespace MP.SPEC.Pages
private bool isLoading { get; set; } = false;
private string leftStringCSS
{
get => isActive ? "text-secondary" : "text-dark fw-bold";
}
private int numRecord
{
get => MsgService.numRecord;
set => MsgService.numRecord = value;
}
private string selStato { get; set; } = "*";
private string rightStringCSS
{
get => isActive ? "text-dark fw-bold" : "text-secondary";
}
private string selStato
{
get => currFilter.CodStato;
set => currFilter.CodStato = value;
}
private int totalCount
{
@@ -97,16 +167,5 @@ namespace MP.SPEC.Pages
}
#endregion Private Properties
#region Private Methods
private async Task reloadData()
{
isLoading = true;
await Task.Delay(1);
isLoading = false;
}
#endregion Private Methods
}
}
+25
View File
@@ -3,6 +3,7 @@ using Microsoft.JSInterop;
using MP.Data.DatabaseModels;
using MP.SPEC.Components;
using MP.SPEC.Data;
using MP.SPEC.Services;
namespace MP.SPEC.Pages
{
@@ -24,6 +25,9 @@ namespace MP.SPEC.Pages
[Inject]
protected MpDataService MDService { get; set; }
[Inject]
protected IOApiService MpIoApiCall { get; set; }
[Inject]
protected MessageService MsgService { get; set; }
@@ -150,6 +154,7 @@ namespace MP.SPEC.Pages
return;
await Task.Delay(1);
var done = await MDService.POdlUpdateRecord(selRec);
await callSyncDb(selRec);
currRecord = null;
await reloadData();
await Task.Delay(1);
@@ -165,10 +170,15 @@ namespace MP.SPEC.Pages
#region Private Fields
private PODLModel? _currRecord = null;
private List<AnagArticoli>? ListArticoli;
private List<AnagGruppi>? ListAziende;
private List<AnagGruppi>? ListGruppiFase;
private List<Macchine>? ListMacchine;
private List<ListValues>? ListStati;
#endregion Private Fields
@@ -176,6 +186,7 @@ namespace MP.SPEC.Pages
#region Private Properties
private string _artSearch { get; set; } = "";
private string _currAzienda { get; set; } = "*";
private bool addEnabled
@@ -206,6 +217,7 @@ namespace MP.SPEC.Pages
}
private List<ConfigModel>? configData { get; set; } = null;
private string currArticolo { get; set; } = "";
private string currAzienda
@@ -265,6 +277,19 @@ namespace MP.SPEC.Pages
#region Private Methods
/// <summary>
/// Chiama metodo x chiedere sync DB
/// </summary>
/// <param name="selRec"></param>
/// <returns></returns>
private async Task callSyncDb(PODLModel selRec)
{
// chiamo aggiunta task SyncDb...
string idxMacc = selRec.IdxMacchina;
string restUrl = $"IOB/addTask2Exe/{idxMacc}?taskName=syncDbData&taskVal=";
var response = await MpIoApiCall.callMpIoUrlGet(restUrl);
}
private async Task reloadData()
{
isLoading = true;
+32
View File
@@ -0,0 +1,32 @@
@page "/Test"
<h3>Test</h3>
<button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasExample" aria-controls="offcanvasExample">
Button with data-bs-target
</button>
<div class="offcanvas offcanvas-start" tabindex="-1" id="offcanvasExample" aria-labelledby="offcanvasExampleLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="offcanvasExampleLabel">Offcanvas</h5>
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<div>
Some text as placeholder. In real life you can have the elements you have chosen. Like, text, images, lists, etc.
</div>
<div class="dropdown mt-3">
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-bs-toggle="dropdown">
Dropdown button
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
</ul>
</div>
</div>
</div>
@code {
}
+1 -1
View File
@@ -5,6 +5,6 @@
<h3>Utils</h3>
<div class="px-2">
<div class="">
<button class="btn btn-primary" @onclick="() => flushCache()"> Flush Cache </button>
</div>
+5
View File
@@ -30,7 +30,12 @@
<a class="dismiss">🗙</a>
</div>
<script src="lib/bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="_framework/blazor.server.js" autostart="false"></script>
<script src="lib/chartjs-adapter-luxon/chartjs-adapter-luxon.js"></script>
<script src="lib/chartBoot.js"></script>
<script src="lib/Chart.js/chart.js"></script>
@*Gestione autoriconnessione: https://github.com/dotnet/aspnetcore/issues/38305 (vedere anche https://docs.microsoft.com/it-it/aspnet/core/blazor/fundamentals/signalr?view=aspnetcore-6.0#modify-the-reconnection-handler-blazor-server)*@
<script>
Blazor.start({
+4
View File
@@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using MP.SPEC.Components;
using MP.SPEC.Data;
using MP.SPEC.Services;
using StackExchange.Redis;
var builder = WebApplication.CreateBuilder(args);
@@ -38,6 +39,9 @@ builder.Services.AddSingleton<IConnectionMultiplexer>(redisMultiplexer);
builder.Services.AddSingleton<MpDataService>();
builder.Services.AddScoped<MessageService>();
builder.Services.AddHttpClient();
builder.Services.AddSingleton<IOApiService>();
var app = builder.Build();
// Configure the HTTP request pipeline.
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>Modulo MAPOSPEC </i>
<h4>Versione: 6.16.2210.511</h4>
<h4>Versione: 6.16.2210.1016</h4>
<br /> Note di rilascio:
<ul>
<li>
+5 -1
View File
@@ -1 +1,5 @@
6.16.2210.511
<<<<<<< HEAD
6.16.2210.1016
=======
6.16.2210.1011
>>>>>>> 91174a2f6752f9d3cf06484367ebf4b92a2b8d69
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>6.16.2210.511</version>
<version>6.16.2210.1016</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>
+56
View File
@@ -0,0 +1,56 @@
using Microsoft.Extensions.Configuration;
using MP.SPEC.Data;
using System.Text.Json;
namespace MP.SPEC.Services
{
/// <summary>
/// Classe per chiamare metodi da MP-IO
///
/// rif:
/// https://www.ezzylearning.net/tutorial/making-http-requests-in-blazor-server-apps
/// https://wellsb.com/csharp/aspnet/blazor-httpclientfactory-and-web-api/
/// </summary>
public class IOApiService
{
private readonly IHttpClientFactory _clientFactory;
private static ILogger<MpDataService> _logger = null!;
private static IConfiguration _configuration = null!;
private static string MpIoBaseUrl = "";
public IOApiService(IHttpClientFactory clientFactory, IConfiguration configuration, ILogger<MpDataService> logger)
{
_logger = logger;
_logger.LogInformation("Starting IOApiService INIT");
_configuration = configuration;
_clientFactory = clientFactory;
// conf url x chiamate REST
MpIoBaseUrl = _configuration.GetValue<string>("ServerConf:MpIoBaseUrl");
}
/// <summary>
/// Effettua chiamata ad MP-IO
/// </summary>
/// <param name="relUrl">URL metodo relativo alla base path di MP-IO</param>
/// <returns></returns>
public async Task<string> callMpIoUrlGet(string relUrl)
{
string result = "";
var request = new HttpRequestMessage(HttpMethod.Get, $"{MpIoBaseUrl}{relUrl}");
request.Headers.Add("Accept", "application/vnd.github.v3+json");
var client = _clientFactory.CreateClient();
var response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
var stringResponse = await response.Content.ReadAsStringAsync();
result = stringResponse;
}
else
{
result = "NO";
}
return result;
}
}
}
+14 -4
View File
@@ -20,9 +20,14 @@
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
<nav class="flex-column">
<div class="nav-item px-2">
<div class="nav-item px-2 col-12">
<NavLink class="nav-link px-2" href="" Match="NavLinkMatch.All">
<span class="fa-solid fa-house px-2" aria-hidden="true"></span> <span class="@hideText">Home</span>
<div class ="col-2">
<span class="fa-solid fa-house px-2" aria-hidden="true"></span>
</div>
<div>
<span class="@hideText">Home</span>
</div>
</NavLink>
</div>
@if (ElencoLink == null)
@@ -33,9 +38,14 @@
{
foreach (var item in ElencoLink)
{
<div class="nav-item px-2">
<div class="nav-item px-2 col-12">
<NavLink class="nav-link px-2" href="@item.NavigateUrl">
<span class="@item.icona px-2" aria-hidden="true"></span> <span class="@hideText">@item.Testo</span>
<div class="col-2">
<span class="@item.icona px-2" aria-hidden="true"></span>
</div>
<div>
<span class="@hideText">@item.Testo</span>
</div>
</NavLink>
</div>
}
+6
View File
@@ -12,5 +12,11 @@
"ConnectionStrings": {
"Mp.Data": "Server=localhost\\SQLEXPRESS;Database=MoonPro; 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"
},
"ServerConf": {
"maxAge": "2000",
"cacheCheckArtUsato": 2,
"redisLongTimeCache": 15,
"MpIoBaseUrl": "http://localhost/MP/IO/"
}
}
+2 -1
View File
@@ -15,6 +15,7 @@
"ServerConf": {
"maxAge": "2000",
"cacheCheckArtUsato": 2,
"redisLongTimeCache": 15
"redisLongTimeCache": 15,
"MpIoBaseUrl": "http://localhost:20967/"
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,7 @@
/*!
* Chart.js v3.7.0
* https://www.chartjs.org
* (c) 2021 Chart.js Contributors
* Released under the MIT License
*/
export { H as HALF_PI, aX as INFINITY, P as PI, aW as PITAU, aZ as QUARTER_PI, aY as RAD_PER_DEG, T as TAU, a_ as TWO_THIRDS_PI, Q as _addGrace, V as _alignPixel, a0 as _alignStartEnd, p as _angleBetween, a$ as _angleDiff, _ as _arrayUnique, a6 as _attachContext, aq as _bezierCurveTo, an as _bezierInterpolation, av as _boundSegment, al as _boundSegments, a3 as _capitalize, ak as _computeSegments, a7 as _createResolver, aH as _decimalPlaces, aP as _deprecated, a8 as _descriptors, af as _elementsEqual, M as _factorize, aJ as _filterBetween, F as _getParentNode, U as _int16Range, ah as _isBetween, ag as _isClickEvent, K as _isDomSupported, z as _isPointInArea, w as _limitValue, aI as _longestText, aK as _lookup, x as _lookupByKey, S as _measureText, aN as _merger, aO as _mergerIf, aw as _normalizeAngle, ao as _pointInLine, ai as _readValueToProps, A as _rlookupByKey, aD as _setMinAndMaxByKey, am as _steppedInterpolation, ap as _steppedLineTo, az as _textX, $ as _toLeftRightCenter, aj as _updateBezierControlPoints, as as addRoundedRectPath, aG as almostEquals, aF as almostWhole, O as callback, ad as clearCanvas, W as clipArea, aM as clone, c as color, h as createContext, ab as debounce, j as defined, aC as distanceBetweenPoints, ar as drawPoint, D as each, e as easingEffects, N as finiteOrDefault, aU as fontString, o as formatNumber, B as getAngleFromPoint, aL as getHoverColor, E as getMaximumSize, y as getRelativePosition, ax as getRtlAdapter, aT as getStyle, b as isArray, g as isFinite, a5 as isFunction, k as isNullOrUndef, q as isNumber, i as isObject, l as listenArrayEvents, L as log10, a2 as merge, a9 as mergeIf, aE as niceNum, aB as noop, ay as overrideTextDirection, G as readUsedSize, X as renderText, r as requestAnimFrame, a as resolve, f as resolveObjectKey, aA as restoreTextDirection, ac as retinaScale, ae as setsEqual, s as sign, aR as splineCurve, aS as splineCurveMonotone, J as supportsEventListenerOptions, I as throttled, R as toDegrees, n as toDimension, Z as toFont, aQ as toFontString, aV as toLineHeight, C as toPadding, m as toPercentage, t as toRadians, at as toTRBL, au as toTRBLCorners, aa as uid, Y as unclipArea, u as unlistenArrayEvents, v as valueOrDefault } from './chunks/helpers.segment.js';
+1
View File
@@ -0,0 +1 @@
export{H as HALF_PI,aX as INFINITY,P as PI,aW as PITAU,aZ as QUARTER_PI,aY as RAD_PER_DEG,T as TAU,a_ as TWO_THIRDS_PI,Q as _addGrace,V as _alignPixel,a0 as _alignStartEnd,p as _angleBetween,a$ as _angleDiff,_ as _arrayUnique,a6 as _attachContext,aq as _bezierCurveTo,an as _bezierInterpolation,av as _boundSegment,al as _boundSegments,a3 as _capitalize,ak as _computeSegments,a7 as _createResolver,aH as _decimalPlaces,aP as _deprecated,a8 as _descriptors,af as _elementsEqual,M as _factorize,aJ as _filterBetween,F as _getParentNode,U as _int16Range,ah as _isBetween,ag as _isClickEvent,K as _isDomSupported,z as _isPointInArea,w as _limitValue,aI as _longestText,aK as _lookup,x as _lookupByKey,S as _measureText,aN as _merger,aO as _mergerIf,aw as _normalizeAngle,ao as _pointInLine,ai as _readValueToProps,A as _rlookupByKey,aD as _setMinAndMaxByKey,am as _steppedInterpolation,ap as _steppedLineTo,az as _textX,$ as _toLeftRightCenter,aj as _updateBezierControlPoints,as as addRoundedRectPath,aG as almostEquals,aF as almostWhole,O as callback,ad as clearCanvas,W as clipArea,aM as clone,c as color,h as createContext,ab as debounce,j as defined,aC as distanceBetweenPoints,ar as drawPoint,D as each,e as easingEffects,N as finiteOrDefault,aU as fontString,o as formatNumber,B as getAngleFromPoint,aL as getHoverColor,E as getMaximumSize,y as getRelativePosition,ax as getRtlAdapter,aT as getStyle,b as isArray,g as isFinite,a5 as isFunction,k as isNullOrUndef,q as isNumber,i as isObject,l as listenArrayEvents,L as log10,a2 as merge,a9 as mergeIf,aE as niceNum,aB as noop,ay as overrideTextDirection,G as readUsedSize,X as renderText,r as requestAnimFrame,a as resolve,f as resolveObjectKey,aA as restoreTextDirection,ac as retinaScale,ae as setsEqual,s as sign,aR as splineCurve,aS as splineCurveMonotone,J as supportsEventListenerOptions,I as throttled,R as toDegrees,n as toDimension,Z as toFont,aQ as toFontString,aV as toLineHeight,C as toPadding,m as toPercentage,t as toRadians,at as toTRBL,au as toTRBLCorners,aa as uid,Y as unclipArea,u as unlistenArrayEvents,v as valueOrDefault}from"./chunks/helpers.segment.js";
+16
View File
@@ -0,0 +1,16 @@
///Setup del chart desiderato con id univoco
window.setup = (id, config) => {
var ctx = document.getElementById(id).getContext('2d');
//let currentDate = new Date();
//console.log(currentDate + " - Calling setup...");
console.log(id);
if (window['chart-' + id] instanceof Chart) {
//window.myChart.destroy();
window['chart-' + id].destroy();
//console.log("Chart " + id + " destroyed!");
}
window['chart-' + id] = new Chart(ctx, config);
//console.log("Chart " + id + " created!");
console.log(window['chart-' + id]);
}
@@ -0,0 +1,91 @@
/*!
* chartjs-adapter-luxon v1.1.0
* https://www.chartjs.org
* (c) 2021 chartjs-adapter-luxon Contributors
* Released under the MIT license
*/
import { _adapters } from 'chart.js';
import { DateTime } from 'luxon';
const FORMATS = {
datetime: DateTime.DATETIME_MED_WITH_SECONDS,
millisecond: 'h:mm:ss.SSS a',
second: DateTime.TIME_WITH_SECONDS,
minute: DateTime.TIME_SIMPLE,
hour: {hour: 'numeric'},
day: {day: 'numeric', month: 'short'},
week: 'DD',
month: {month: 'short', year: 'numeric'},
quarter: "'Q'q - yyyy",
year: {year: 'numeric'}
};
_adapters._date.override({
_id: 'luxon', // DEBUG
/**
* @private
*/
_create: function(time) {
return DateTime.fromMillis(time, this.options);
},
formats: function() {
return FORMATS;
},
parse: function(value, format) {
const options = this.options;
if (value === null || typeof value === 'undefined') {
return null;
}
const type = typeof value;
if (type === 'number') {
value = this._create(value);
} else if (type === 'string') {
if (typeof format === 'string') {
value = DateTime.fromFormat(value, format, options);
} else {
value = DateTime.fromISO(value, options);
}
} else if (value instanceof Date) {
value = DateTime.fromJSDate(value, options);
} else if (type === 'object' && !(value instanceof DateTime)) {
value = DateTime.fromObject(value);
}
return value.isValid ? value.valueOf() : null;
},
format: function(time, format) {
const datetime = this._create(time);
return typeof format === 'string'
? datetime.toFormat(format, this.options)
: datetime.toLocaleString(format);
},
add: function(time, amount, unit) {
const args = {};
args[unit] = amount;
return this._create(time).plus(args).valueOf();
},
diff: function(max, min, unit) {
return this._create(max).diff(this._create(min)).as(unit).valueOf();
},
startOf: function(time, unit, weekday) {
if (unit === 'isoWeek') {
weekday = Math.trunc(Math.min(Math.max(0, weekday), 6));
const dateTime = this._create(time);
return dateTime.minus({days: (dateTime.weekday - weekday + 7) % 7}).startOf('day').valueOf();
}
return unit ? this._create(time).startOf(unit).valueOf() : time;
},
endOf: function(time, unit) {
return this._create(time).endOf(unit).valueOf();
}
});
@@ -0,0 +1 @@
import{_adapters}from"chart.js";import{DateTime}from"luxon";const FORMATS={datetime:DateTime.DATETIME_MED_WITH_SECONDS,millisecond:"h:mm:ss.SSS a",second:DateTime.TIME_WITH_SECONDS,minute:DateTime.TIME_SIMPLE,hour:{hour:"numeric"},day:{day:"numeric",month:"short"},week:"DD",month:{month:"short",year:"numeric"},quarter:"'Q'q - yyyy",year:{year:"numeric"}};_adapters._date.override({_id:"luxon",_create:function(t){return DateTime.fromMillis(t,this.options)},formats:function(){return FORMATS},parse:function(t,e){var r=this.options;if(null==t)return null;var a=typeof t;return"number"==a?t=this._create(t):"string"==a?t="string"==typeof e?DateTime.fromFormat(t,e,r):DateTime.fromISO(t,r):t instanceof Date?t=DateTime.fromJSDate(t,r):"object"!=a||t instanceof DateTime||(t=DateTime.fromObject(t)),t.isValid?t.valueOf():null},format:function(t,e){const r=this._create(t);return"string"==typeof e?r.toFormat(e,this.options):r.toLocaleString(e)},add:function(t,e,r){const a={};return a[r]=e,this._create(t).plus(a).valueOf()},diff:function(t,e,r){return this._create(t).diff(this._create(e)).as(r).valueOf()},startOf:function(t,e,r){if("isoWeek"!==e)return e?this._create(t).startOf(e).valueOf():t;{r=Math.trunc(Math.min(Math.max(0,r),6));const a=this._create(t);return a.minus({days:(a.weekday-r+7)%7}).startOf("day").valueOf()}},endOf:function(t,e){return this._create(t).endOf(e).valueOf()}});
@@ -0,0 +1,96 @@
/*!
* chartjs-adapter-luxon v1.1.0
* https://www.chartjs.org
* (c) 2021 chartjs-adapter-luxon Contributors
* Released under the MIT license
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('chart.js'), require('luxon')) :
typeof define === 'function' && define.amd ? define(['chart.js', 'luxon'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Chart, global.luxon));
}(this, (function (chart_js, luxon) { 'use strict';
const FORMATS = {
datetime: luxon.DateTime.DATETIME_MED_WITH_SECONDS,
millisecond: 'h:mm:ss.SSS a',
second: luxon.DateTime.TIME_WITH_SECONDS,
minute: luxon.DateTime.TIME_SIMPLE,
hour: {hour: 'numeric'},
day: {day: 'numeric', month: 'short'},
week: 'DD',
month: {month: 'short', year: 'numeric'},
quarter: "'Q'q - yyyy",
year: {year: 'numeric'}
};
chart_js._adapters._date.override({
_id: 'luxon', // DEBUG
/**
* @private
*/
_create: function(time) {
return luxon.DateTime.fromMillis(time, this.options);
},
formats: function() {
return FORMATS;
},
parse: function(value, format) {
const options = this.options;
if (value === null || typeof value === 'undefined') {
return null;
}
const type = typeof value;
if (type === 'number') {
value = this._create(value);
} else if (type === 'string') {
if (typeof format === 'string') {
value = luxon.DateTime.fromFormat(value, format, options);
} else {
value = luxon.DateTime.fromISO(value, options);
}
} else if (value instanceof Date) {
value = luxon.DateTime.fromJSDate(value, options);
} else if (type === 'object' && !(value instanceof luxon.DateTime)) {
value = luxon.DateTime.fromObject(value);
}
return value.isValid ? value.valueOf() : null;
},
format: function(time, format) {
const datetime = this._create(time);
return typeof format === 'string'
? datetime.toFormat(format, this.options)
: datetime.toLocaleString(format);
},
add: function(time, amount, unit) {
const args = {};
args[unit] = amount;
return this._create(time).plus(args).valueOf();
},
diff: function(max, min, unit) {
return this._create(max).diff(this._create(min)).as(unit).valueOf();
},
startOf: function(time, unit, weekday) {
if (unit === 'isoWeek') {
weekday = Math.trunc(Math.min(Math.max(0, weekday), 6));
const dateTime = this._create(time);
return dateTime.minus({days: (dateTime.weekday - weekday + 7) % 7}).startOf('day').valueOf();
}
return unit ? this._create(time).startOf(unit).valueOf() : time;
},
endOf: function(time, unit) {
return this._create(time).endOf(unit).valueOf();
}
});
})));
@@ -0,0 +1,7 @@
/*!
* chartjs-adapter-luxon v1.1.0
* https://www.chartjs.org
* (c) 2021 chartjs-adapter-luxon Contributors
* Released under the MIT license
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(require("chart.js"),require("luxon")):"function"==typeof define&&define.amd?define(["chart.js","luxon"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Chart,e.luxon)}(this,(function(e,t){"use strict";const n={datetime:t.DateTime.DATETIME_MED_WITH_SECONDS,millisecond:"h:mm:ss.SSS a",second:t.DateTime.TIME_WITH_SECONDS,minute:t.DateTime.TIME_SIMPLE,hour:{hour:"numeric"},day:{day:"numeric",month:"short"},week:"DD",month:{month:"short",year:"numeric"},quarter:"'Q'q - yyyy",year:{year:"numeric"}};e._adapters._date.override({_id:"luxon",_create:function(e){return t.DateTime.fromMillis(e,this.options)},formats:function(){return n},parse:function(e,n){const r=this.options;if(null==e)return null;const i=typeof e;return"number"===i?e=this._create(e):"string"===i?e="string"==typeof n?t.DateTime.fromFormat(e,n,r):t.DateTime.fromISO(e,r):e instanceof Date?e=t.DateTime.fromJSDate(e,r):"object"!==i||e instanceof t.DateTime||(e=t.DateTime.fromObject(e)),e.isValid?e.valueOf():null},format:function(e,t){const n=this._create(e);return"string"==typeof t?n.toFormat(t,this.options):n.toLocaleString(t)},add:function(e,t,n){const r={};return r[n]=t,this._create(e).plus(r).valueOf()},diff:function(e,t,n){return this._create(e).diff(this._create(t)).as(n).valueOf()},startOf:function(e,t,n){if("isoWeek"===t){n=Math.trunc(Math.min(Math.max(0,n),6));const t=this._create(e);return t.minus({days:(t.weekday-n+7)%7}).startOf("day").valueOf()}return t?this._create(e).startOf(t).valueOf():e},endOf:function(e,t){return this._create(e).endOf(t).valueOf()}})}));
+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.16.2209.2211</Version>
<Version>6.16.2210.0716</Version>
</PropertyGroup>
<ItemGroup>
+1 -1
View File
@@ -123,7 +123,7 @@ namespace MP.Stats.Pages
{
isLoading = true;
// salvo davvero!
await MP.Data.Utils.SaveToCsv(SearchRecords, fullPath);
await MP.Data.Utils.SaveToCsv(SearchRecords, fullPath, ';');
isLoading = false;
}
+1 -1
View File
@@ -100,7 +100,7 @@ namespace MP.Stats.Pages
// recupero TUTTI i dati
var allRecords = await StatService.StatDdbGetAllExport(currFilter, MessageService.SearchVal);
// salvo davvero!
await MP.Data.Utils.SaveToCsv(allRecords, fullPath);
await MP.Data.Utils.SaveToCsv(allRecords, fullPath, ';');
isLoading = false;
}
+1 -1
View File
@@ -124,7 +124,7 @@ namespace MP.Stats.Pages
isLoading = true;
// calcolo nome file
// salvo davvero!
await MP.Data.Utils.SaveToCsv(SearchRecords, fullPath);
await MP.Data.Utils.SaveToCsv(SearchRecords, fullPath, ';');
isLoading = false;
}
+1 -1
View File
@@ -92,7 +92,7 @@ namespace MP.Stats.Pages
{
isLoading = true;
// salvo davvero!
await MP.Data.Utils.SaveToCsv(SearchRecords, fullPath);
await MP.Data.Utils.SaveToCsv(SearchRecords, fullPath, ';');
isLoading = false;
}
+1 -1
View File
@@ -123,7 +123,7 @@ namespace MP.Stats.Pages
{
isLoading = true;
// salvo davvero!
await MP.Data.Utils.SaveToCsv(SearchRecords, fullPath);
await MP.Data.Utils.SaveToCsv(SearchRecords, fullPath, ';');
isLoading = false;
}
+1 -1
View File
@@ -118,7 +118,7 @@ namespace MP.Stats.Pages
{
isLoading = true;
// salvo davvero!
await MP.Data.Utils.SaveToCsv(SearchRecords, fullPath);
await MP.Data.Utils.SaveToCsv(SearchRecords, fullPath, ';');
isLoading = false;
}
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>Modulo statistiche MAPO</i>
<h4>Versione: 6.16.2209.2211</h4>
<h4>Versione: 6.16.2210.0716</h4>
<br />
Note di rilascio:
<ul>
+1 -1
View File
@@ -1 +1 @@
6.16.2209.2211
6.16.2210.0716
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>6.16.2209.2211</version>
<version>6.16.2210.0716</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>