Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2f7337348e | |||
| 7f88624935 | |||
| dacd3b9bcd | |||
| 596449f259 | |||
| e149445529 | |||
| 178d7a3ef0 | |||
| 53d505006a | |||
| 53e1abd2c0 | |||
| 321b7a3a6f | |||
| 2e54c8b164 | |||
| 8c978f68c2 | |||
| 781c570a3d | |||
| de2a8cb6a5 | |||
| 63e92f0c83 | |||
| 73a28e33b4 | |||
| f4d2265de2 | |||
| b40764c2bc | |||
| 0333154935 | |||
| fc19fb563e | |||
| fd6a0512ba | |||
| 7c4ae1f7dc | |||
| b9c2418532 | |||
| 50a6848f25 | |||
| 6e1b60cc71 | |||
| 23a3985251 | |||
| 274d58ab68 | |||
| 14637860e0 | |||
| fe0545084a | |||
| e37b5050e2 | |||
| fc3a6a70da | |||
| 9837f276d7 | |||
| 865aa0afab | |||
| ef2bd7c5d5 | |||
| 3c92333f0e | |||
| 190b7a10b7 | |||
| 7a89709a29 | |||
| 3777090416 | |||
| 16d13748c9 | |||
| 5a46df0f19 | |||
| d3ff540382 | |||
| 15fcbd57b9 | |||
| 07ac5aa9a5 | |||
| 488ca47e50 |
@@ -21,7 +21,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="6.0.14" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="StackExchange.Redis" Version="2.6.122" />
|
||||
<PackageReference Include="StackExchange.Redis" Version="2.7.27" />
|
||||
<PackageReference Include="StackExchange.Redis.Extensions.AspNetCore" Version="9.1.0" />
|
||||
<PackageReference Include="StackExchange.Redis.Extensions.Core" Version="9.1.0" />
|
||||
<PackageReference Include="StackExchange.Redis.Extensions.Newtonsoft" Version="9.1.0" />
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GPW.CORE.Data
|
||||
{
|
||||
public class Const
|
||||
{
|
||||
#region Public Fields
|
||||
|
||||
public const string rPipeChRich = $"Channel_Rich";
|
||||
public const string rPipeChTimb = $"Channel_Timb";
|
||||
|
||||
#endregion Public Fields
|
||||
}
|
||||
}
|
||||
@@ -615,6 +615,117 @@ namespace GPW.CORE.Data.Controllers
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recupera l'elenco dei dettaglio giornaliero attività di tutti i dipendenti, dato giorno riferimento
|
||||
/// </summary>
|
||||
/// <param name="dtRif">Data di riferimento</param>
|
||||
/// <returns></returns>
|
||||
public List<DailyDataDTO> DailyDetailAllDip(DateTime dtRif)
|
||||
{
|
||||
//resetto valoredtRif a giornata (mezzanotte)
|
||||
dtRif = dtRif.Date;
|
||||
// init dati necessari
|
||||
List<DailyDataDTO> dbResult = new List<DailyDataDTO>();
|
||||
List<TimbratureExplModel> rawTimbExp = new List<TimbratureExplModel>();
|
||||
List<TimbratureModel> rawTimbr = new List<TimbratureModel>();
|
||||
List<RegAttivitaModel> rawRegAtt = new List<RegAttivitaModel>();
|
||||
List<RilievoTempModel> rawRilTemp = new List<RilievoTempModel>();
|
||||
List<CheckVc19Model> rawCheckC19 = new List<CheckVc19Model>();
|
||||
|
||||
// fermate/festività/ferie
|
||||
List<CalFesteFerieModel> rawFermateAz = new List<CalFesteFerieModel>();
|
||||
List<RegMalattieModel> rawMalattie = new List<RegMalattieModel>();
|
||||
List<RegRichiesteModel> rawRichDip = new List<RegRichiesteModel>();
|
||||
|
||||
// cerco su DB recuperando set di dati....
|
||||
using (GPWContext localDbCtx = new GPWContext(_configuration))
|
||||
{
|
||||
// recupero intero set dati timbrature e attività....
|
||||
rawTimbExp = localDbCtx
|
||||
.DbSetTimbratureExpl
|
||||
.Where(x => dtRif == x.DataLav)
|
||||
.ToList();
|
||||
|
||||
rawTimbr = localDbCtx
|
||||
.DbSetTimbrature
|
||||
.Where(x => dtRif == x.DataOra.Date)
|
||||
.ToList();
|
||||
|
||||
rawRegAtt = localDbCtx
|
||||
.DbSetRegAttivita
|
||||
.Where(x => dtRif == x.Inizio.Date)
|
||||
.Include(a => a.FasiNav).ThenInclude(p => p.ProgettoNav).ThenInclude(c => c.ClienteNav)
|
||||
.ToList();
|
||||
|
||||
rawRilTemp = localDbCtx
|
||||
.DbSetRilievoTemp
|
||||
.Where(x => dtRif <= x.DtRilievo.Date)
|
||||
.ToList();
|
||||
|
||||
rawCheckC19 = localDbCtx
|
||||
.DbSetCheckVc19
|
||||
.Where(x => dtRif <= x.DtCheck.Date)
|
||||
.ToList();
|
||||
|
||||
// recupero fermate e malattie/permessi del dipendente...
|
||||
rawFermateAz = localDbCtx
|
||||
.DbSetCalFesteFerie
|
||||
.Where(x => x.data == dtRif)
|
||||
.ToList();
|
||||
rawMalattie = localDbCtx
|
||||
.DbSetRegMalattie
|
||||
.Where(x => x.DtInizio.Date <= dtRif && x.DtInizio.AddDays(x.NumGG) >= dtRif)
|
||||
.ToList();
|
||||
rawRichDip = localDbCtx
|
||||
.DbSetRegRichieste
|
||||
.Where(x => x.DtStart.Date <= dtRif && x.DtEnd >= dtRif)
|
||||
.ToList();
|
||||
|
||||
// calcolo elenco DIP
|
||||
List<int> listDip = rawTimbExp.Select(x => x.IdxDipendente).Distinct().ToList();
|
||||
|
||||
// x ogni giorno scompongo il set di info...
|
||||
foreach (var idxDip in listDip)
|
||||
{
|
||||
DailyDataDTO currDayDto = new DailyDataDTO()
|
||||
{
|
||||
IdxDipendente = idxDip,
|
||||
DtRif = dtRif,
|
||||
ListRA = rawRegAtt
|
||||
.Where(x => x.IdxDipendente == idxDip)
|
||||
.OrderBy(x => x.Inizio)
|
||||
.ToList(),
|
||||
ListTimbr = rawTimbr
|
||||
.Where(x => x.IdxDipendente == idxDip)
|
||||
.OrderBy(x => x.DataOra)
|
||||
.ToList(),
|
||||
TimbrExpl = rawTimbExp
|
||||
.Where(x => x.IdxDipendente == idxDip)
|
||||
.FirstOrDefault(),
|
||||
ListRilTemp = rawRilTemp
|
||||
.Where(x => x.IdxDipendente == idxDip)
|
||||
.ToList(),
|
||||
ListCheckC19 = rawCheckC19
|
||||
.Where(x => x.IdxDipendente == idxDip)
|
||||
.ToList(),
|
||||
ListFermateAzienda = rawFermateAz,
|
||||
ListMalattie = rawMalattie
|
||||
.Where(x => x.IdxDipendente == idxDip)
|
||||
.ToList(),
|
||||
ListFerieDip = rawRichDip
|
||||
.Where(x => x.IdxDipendente == idxDip)
|
||||
.ToList(),
|
||||
ListRichiesteDip = rawRichDip
|
||||
.Where(x => x.IdxDipendente == idxDip)
|
||||
.ToList()
|
||||
};
|
||||
|
||||
dbResult.Add(currDayDto);
|
||||
}
|
||||
}
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
public bool DbForceMigrate()
|
||||
{
|
||||
bool answ = false;
|
||||
@@ -984,6 +1095,26 @@ namespace GPW.CORE.Data.Controllers
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Righe presenze giornaliere
|
||||
/// </summary>
|
||||
/// <param name="dtRif">DataOra riferimento per richiesta presenze</param>
|
||||
/// <returns></returns>
|
||||
public List<StatsDayPresModel> PresenzeDay(DateTime dtRif)
|
||||
{
|
||||
List<StatsDayPresModel> dbResult = new List<StatsDayPresModel>();
|
||||
using (GPWContext localDbCtx = new GPWContext(_configuration))
|
||||
{
|
||||
var idxProgetto = new SqlParameter("@dataRif", dtRif);
|
||||
|
||||
dbResult = localDbCtx
|
||||
.DbSetStatsDayPres
|
||||
.FromSqlRaw("EXEC stp_statsDayPres @dataRif", idxProgetto)
|
||||
.ToList();
|
||||
}
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
public bool RegAttDelete(RegAttivitaModel currItem)
|
||||
{
|
||||
bool answ = false;
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace GPW.CORE.Data.DbModels
|
||||
{
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
public partial class StatsDayPresModel
|
||||
{
|
||||
[Key]
|
||||
public int IdxDipendente { get; set; }
|
||||
public DateTime LastOp { get; set; }
|
||||
public int NEnt { get; set; } = 0;
|
||||
public int NUsc { get; set; } = 0;
|
||||
public int IsPresent { get; set; } = 0;
|
||||
|
||||
#if false
|
||||
/// <summary>
|
||||
/// Navigation property to Dipendente
|
||||
/// </summary>
|
||||
[ForeignKey("IdxDipendente")]
|
||||
public virtual DipendentiModel DipNav { get; set; } = null!;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="EgwCoreLib.Utils" Version="1.5.2402.2411" />
|
||||
<PackageReference Include="MailKit" Version="3.5.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="6.0.14" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.14" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.14" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.14" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.14">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NLog" Version="5.2.2" />
|
||||
<PackageReference Include="StackExchange.Redis" Version="2.7.27" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -7,7 +7,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="EgwCoreLib.Utils" Version="1.4.2307.3111" />
|
||||
<PackageReference Include="EgwCoreLib.Utils" Version="1.5.2402.2411" />
|
||||
<PackageReference Include="MailKit" Version="3.5.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="6.0.14" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.14" />
|
||||
@@ -19,6 +19,7 @@
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NLog" Version="5.2.2" />
|
||||
<PackageReference Include="StackExchange.Redis" Version="2.7.27" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -65,6 +65,7 @@ namespace GPW.CORE.Data
|
||||
public virtual DbSet<RegistroEventiModel> DbSetRegEventi { get; set; } = null!;
|
||||
public virtual DbSet<DipendendiAndAnomalie> DbSetDipAndAnom { get; set; } = null!;
|
||||
public virtual DbSet<TeRaExplModel> DbSetTeRaExpl { get; set; } = null!;
|
||||
public virtual DbSet<StatsDayPresModel> DbSetStatsDayPres { get; set; } = null!;
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
using NLog;
|
||||
using StackExchange.Redis;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GPW.CORE.Data
|
||||
{
|
||||
public class MessagePipe
|
||||
{
|
||||
#region Public Constructors
|
||||
|
||||
public MessagePipe(IConnectionMultiplexer redisConn, string channelName, bool enableLog = false)
|
||||
{
|
||||
_channel = channelName;
|
||||
redis = redisConn;
|
||||
redisDb = redis.GetDatabase();
|
||||
this.enableLog = enableLog;
|
||||
// aggiungo sottoscrittore
|
||||
setupSubscriber();
|
||||
}
|
||||
|
||||
#endregion Public Constructors
|
||||
|
||||
#region Public Events
|
||||
|
||||
public event EventHandler EA_NewMessage = delegate { };
|
||||
|
||||
#endregion Public Events
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Invio messaggio sul canale + salvataggio in cache REDIS
|
||||
/// </summary>
|
||||
/// <param name="memKey">Chiave REDIS x salvare valore</param>
|
||||
/// <param name="message">Messaggio serializzato da inviare</param>
|
||||
public bool saveAndSendMessage(string memKey, string message)
|
||||
{
|
||||
bool answ = false;
|
||||
Stopwatch stopWatch = new Stopwatch();
|
||||
stopWatch.Start();
|
||||
|
||||
// invio notifica tramite il canale richiesto
|
||||
answ = sendMessage(message);
|
||||
if (redisDb != null)
|
||||
{
|
||||
redisDb.StringSetAsync(memKey, message);
|
||||
}
|
||||
stopWatch.Stop();
|
||||
TimeSpan ts = stopWatch.Elapsed;
|
||||
if (numSent.ContainsKey(memKey))
|
||||
{
|
||||
numSent[memKey]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
numSent.Add(memKey, 1);
|
||||
}
|
||||
if (enableLog || numSent[memKey] > 30)
|
||||
{
|
||||
Log.Info($"saveAndSendMessage| mKey {memKey} x {numSent[memKey]} | {message.Length} size | {ts.TotalMilliseconds} ms");
|
||||
|
||||
numSent[memKey] = 0;
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invio messaggio sul canale
|
||||
/// </summary>
|
||||
/// <param name="newMess"></param>
|
||||
/// <returns></returns>
|
||||
public bool sendMessage(string newMess)
|
||||
{
|
||||
bool answ = false;
|
||||
ISubscriber sub = redis.GetSubscriber();
|
||||
sub.Publish(_channel, newMess);
|
||||
return answ;
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#region Protected Fields
|
||||
|
||||
protected static Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
#endregion Protected Fields
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private bool enableLog = false;
|
||||
private Dictionary<string, int> numSent = new Dictionary<string, int>();
|
||||
private IConnectionMultiplexer redis;
|
||||
private StackExchange.Redis.IDatabase redisDb;
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Private Properties
|
||||
|
||||
/// <summary>
|
||||
/// Canale associato al gestore pipeline messaggi
|
||||
/// </summary>
|
||||
private string _channel { get; set; } = "";
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private void setupSubscriber()
|
||||
{
|
||||
ISubscriber sub = redis.GetSubscriber();
|
||||
//Subscribe to the channel named messages
|
||||
sub.Subscribe(_channel, (channel, message) =>
|
||||
{
|
||||
if (enableLog)
|
||||
{
|
||||
Log.Trace($"req setup ch {channel} | {message}");
|
||||
}
|
||||
// messaggio
|
||||
PubSubEventArgs mea = new PubSubEventArgs(message);
|
||||
// se qualcuno ascolta sollevo evento nuovo valore...
|
||||
if (EA_NewMessage != null)
|
||||
{
|
||||
EA_NewMessage(this, mea);
|
||||
}
|
||||
});
|
||||
if (enableLog)
|
||||
{
|
||||
Log.Info($"Subscribed {_channel}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
|
||||
public class PubSubEventArgs : EventArgs
|
||||
{
|
||||
#region Public Constructors
|
||||
|
||||
public PubSubEventArgs(string messaggio)
|
||||
{
|
||||
this.newMessage = messaggio;
|
||||
}
|
||||
|
||||
#endregion Public Constructors
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public string newMessage { get; set; } = "";
|
||||
|
||||
#endregion Public Properties
|
||||
}
|
||||
}
|
||||
@@ -98,7 +98,7 @@ namespace GPW.CORE.Smart.Components
|
||||
IdxDipendente = idxDip,
|
||||
Ipv4 = $"{ipv4}"
|
||||
};
|
||||
done= await CDService.TimbratureUpdate(currRecord);
|
||||
done = await CDService.TimbratureUpdate(currRecord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,22 @@
|
||||
|
||||
@if (ListRecords == null)
|
||||
{
|
||||
<LoadingData DisplaySize="LoadingData.CtrlSize.Large"></LoadingData>
|
||||
<div class="row m-2 placeholder-glow">
|
||||
<span class="placeholder col-4 my-1"></span>
|
||||
<span class="placeholder col-7 my-1"></span>
|
||||
<span class="placeholder col-8 my-1"></span>
|
||||
<span class="placeholder col-3 my-1"></span>
|
||||
</div>
|
||||
<LoadingData DisplaySize="LoadingData.CtrlSize.Large" DisplayMode="LoadingData.SpinMode.Growl"></LoadingData>
|
||||
<div class="row m-2 placeholder-glow">
|
||||
<span class="placeholder col-4 my-1"></span>
|
||||
<span class="placeholder col-7 my-1"></span>
|
||||
<span class="placeholder col-8 my-1"></span>
|
||||
<span class="placeholder col-3 my-1"></span>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
<div style="background-color: #34495E; border-radius: 12px; width:100%" class="pb-1 mb-5">
|
||||
<CalendarMonth DtRif="@dtCurr" MainCss="table table-dark table-borderless" DateSelected="DisplayDate" MonthChanged="ReloadMonth" DateCheck="@DateCheck" DateCheckBlock="@DateCFF" SingleWeek="@showDetail" SelDayCss="selDate rounded-top p-2" HeadStyle="color: #E67E22"></CalendarMonth>
|
||||
@if (showDetail)
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace GPW.CORE.Smart.Components
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
MService.EA_DipUpdated -= MService_EA_DipUpdated;
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
@@ -149,6 +150,14 @@ namespace GPW.CORE.Smart.Components
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
MService.EA_DipUpdated += MService_EA_DipUpdated;
|
||||
// lettura dati base
|
||||
await ReloadData();
|
||||
// verifica attivazione
|
||||
await VerifyActiv();
|
||||
}
|
||||
private async void MService_EA_DipUpdated()
|
||||
{
|
||||
// lettura dati base
|
||||
await ReloadData();
|
||||
|
||||
@@ -51,7 +51,10 @@ namespace GPW.CORE.Smart.Components
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
await Task.Delay(1);
|
||||
await reloadData();
|
||||
if (IdxDipCurr > 0)
|
||||
{
|
||||
await reloadData();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
@if (IsRicTimb)
|
||||
{
|
||||
<div class="cardContainerMancTimb">
|
||||
<div class="data">
|
||||
<span>@($"{oraRichiesta:dddd dd MMMM}")</span>
|
||||
<div class="cardContainerMancTimb py-2 px-3">
|
||||
<div class="data d-flex justify-content-between">
|
||||
<div class="px-0">
|
||||
<span>@($"{oraRichiesta:dddd}")</span>
|
||||
</div>
|
||||
<div class="px-0">
|
||||
<span>@($"{oraRichiesta:dd MMMM}")</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oraRichiesta">
|
||||
<input @bind="oraRichiesta" type="time" step="300" />
|
||||
@@ -13,10 +18,14 @@ else
|
||||
{
|
||||
@if (!isCompactMode)
|
||||
{
|
||||
|
||||
<div class="cardContainer @cardCss">
|
||||
<div class="data">
|
||||
<span>@($"{dtCurr:dddd dd MMMM}")</span>
|
||||
<div class="cardContainer @cardCss py-2 px-3">
|
||||
<div class="data d-flex justify-content-between">
|
||||
<div class="px-0">
|
||||
<span>@($"{dtCurr:dddd}")</span>
|
||||
</div>
|
||||
<div class="px-0">
|
||||
<span>@($"{dtCurr:dd MMMM}")</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ora">
|
||||
<div class="d-flex justify-content-center">
|
||||
@@ -33,11 +42,16 @@ else
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="cardContainerCompact @cardCss">
|
||||
<div class="cardContainerCompact @cardCss py-1 px-3">
|
||||
<div class="dataComp">
|
||||
<span>@($"{dtCurr:dddd}")</span>
|
||||
<span>@($"{dtCurr:dd MMMM}")</span>
|
||||
|
||||
<div class="data d-flex justify-content-between">
|
||||
<div class="px-0">
|
||||
<span>@($"{dtCurr:dddd}")</span>
|
||||
</div>
|
||||
<div class="px-0">
|
||||
<span>@($"{dtCurr:dd MMMM}")</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ora">
|
||||
<div class="d-flex justify-content-center">
|
||||
<div>
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
}
|
||||
.cardContainerCompact .dataComp {
|
||||
font-weight: bold;
|
||||
padding-top: 1.5rem;
|
||||
padding-left: 1.5rem;
|
||||
/*padding-top: 1.5rem;*/
|
||||
/*padding-left: 1.5rem;*/
|
||||
position: relative;
|
||||
text-transform: uppercase;
|
||||
font-size: 1rem;
|
||||
@@ -49,8 +49,8 @@
|
||||
}
|
||||
.data {
|
||||
font-weight: bold;
|
||||
padding-top: 1.5rem;
|
||||
padding-left: 1.5rem;
|
||||
/*padding-top: 1.5rem;*/
|
||||
/*padding-left: 1.5rem;*/
|
||||
position: relative;
|
||||
font-size: 1.25rem;
|
||||
text-transform: uppercase;
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
.cardContainerCompact .dataComp {
|
||||
font-weight: bold;
|
||||
padding-top: 1.5rem;
|
||||
padding-left: 1.5rem;
|
||||
/*padding-top: 1.5rem;*/
|
||||
/*padding-left: 1.5rem;*/
|
||||
position: relative;
|
||||
text-transform: uppercase;
|
||||
font-size: 1rem;
|
||||
@@ -47,8 +47,8 @@
|
||||
|
||||
.data {
|
||||
font-weight: bold;
|
||||
padding-top: 1.5rem;
|
||||
padding-left: 1.5rem;
|
||||
/*padding-top: 1.5rem;*/
|
||||
/*padding-left: 1.5rem;*/
|
||||
position: relative;
|
||||
font-size: 1.25rem;
|
||||
text-transform: uppercase;
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
.cardContainerAll{border-radius:12px;width:100%;box-shadow:0 3px 4px rgba(0,0,0,.7);color:#fff;}.cardContainer{border-radius:12px;width:100%;box-shadow:0 3px 4px rgba(0,0,0,.7);color:#fff;min-height:8.5rem;padding-bottom:1rem;}.cardContainerCompact{border-radius:12px;width:100%;box-shadow:0 3px 4px rgba(0,0,0,.7);color:#fff;min-height:4rem;}.cardContainerCompact .dataComp{font-weight:bold;padding-top:1.5rem;padding-left:1.5rem;position:relative;text-transform:uppercase;font-size:1rem;}.cardContainerCompact .ora{width:100%;font-weight:bold;position:relative;font-size:3.5rem;text-align:center;font-size:2.8rem;}.cardContainerMancTimb{padding-bottom:1rem;min-height:8.5rem;border-radius:12px;width:100%;box-shadow:0 3px 4px rgba(0,0,0,.7);color:#fff;background-color:#2980b9;}.titolo{font-size:1rem;}.data{font-weight:bold;padding-top:1.5rem;padding-left:1.5rem;position:relative;font-size:1.25rem;text-transform:uppercase;display:flex;justify-content:space-between;}.ora{width:100%;font-weight:bold;position:relative;font-size:3.5rem;text-align:center;}.oraRichiesta{width:100%;font-weight:bold;position:relative;font-size:2rem;text-align:center;padding-top:1.5rem;}.oraRichiesta input{border-radius:.5rem;border:0;padding:.25rem;}.defaultCard{background-color:rgba(0,128,255,.8);}.cardEntrata{background-color:#9b59b6;}.cardUscita{background-color:#4caf50;}.txtSec{font-weight:normal;font-size:2rem;}.pulse-warning{box-shadow:0 0 20px 5px rgba(0,128,255,.8);animation:pulse-warning 2.5s infinite;}@-webkit-keyframes pulse-warning{0%{-webkit-box-shadow:0 0 20px 5px rgba(0,128,255,.8);color:#fff;}70%{-webkit-box-shadow:0 0 20px 5px rgba(0,128,255,0);}100%{-webkit-box-shadow:0 0 20px 5px rgba(0,128,255,.8);color:#fff;}}@keyframes pulse-warning{0%{-moz-box-shadow:0 0 20px 5px rgba(0,128,255,.8);box-shadow:0 0 20px 5px rgba(0,128,255,.8);color:#fff;}70%{-moz-box-shadow:0 0 20px 5px rgba(0,128,255,0);box-shadow:0 0 20px 5px rgba(0,128,255,0);}100%{-moz-box-shadow:0 0 20px 5px rgba(255,170,0,.8);box-shadow:0 0 20px 5px rgba(0,128,255,.8);color:#fff;}}
|
||||
.cardContainerAll{border-radius:12px;width:100%;box-shadow:0 3px 4px rgba(0,0,0,.7);color:#fff;}.cardContainer{border-radius:12px;width:100%;box-shadow:0 3px 4px rgba(0,0,0,.7);color:#fff;min-height:8.5rem;padding-bottom:1rem;}.cardContainerCompact{border-radius:12px;width:100%;box-shadow:0 3px 4px rgba(0,0,0,.7);color:#fff;min-height:4rem;}.cardContainerCompact .dataComp{font-weight:bold;position:relative;text-transform:uppercase;font-size:1rem;}.cardContainerCompact .ora{width:100%;font-weight:bold;position:relative;font-size:3.5rem;text-align:center;font-size:2.8rem;}.cardContainerMancTimb{padding-bottom:1rem;min-height:8.5rem;border-radius:12px;width:100%;box-shadow:0 3px 4px rgba(0,0,0,.7);color:#fff;background-color:#2980b9;}.titolo{font-size:1rem;}.data{font-weight:bold;position:relative;font-size:1.25rem;text-transform:uppercase;display:flex;justify-content:space-between;}.ora{width:100%;font-weight:bold;position:relative;font-size:3.5rem;text-align:center;}.oraRichiesta{width:100%;font-weight:bold;position:relative;font-size:2rem;text-align:center;padding-top:1.5rem;}.oraRichiesta input{border-radius:.5rem;border:0;padding:.25rem;}.defaultCard{background-color:rgba(0,128,255,.8);}.cardEntrata{background-color:#9b59b6;}.cardUscita{background-color:#4caf50;}.txtSec{font-weight:normal;font-size:2rem;}.pulse-warning{box-shadow:0 0 20px 5px rgba(0,128,255,.8);animation:pulse-warning 2.5s infinite;}@-webkit-keyframes pulse-warning{0%{-webkit-box-shadow:0 0 20px 5px rgba(0,128,255,.8);color:#fff;}70%{-webkit-box-shadow:0 0 20px 5px rgba(0,128,255,0);}100%{-webkit-box-shadow:0 0 20px 5px rgba(0,128,255,.8);color:#fff;}}@keyframes pulse-warning{0%{-moz-box-shadow:0 0 20px 5px rgba(0,128,255,.8);box-shadow:0 0 20px 5px rgba(0,128,255,.8);color:#fff;}70%{-moz-box-shadow:0 0 20px 5px rgba(0,128,255,0);box-shadow:0 0 20px 5px rgba(0,128,255,0);}100%{-moz-box-shadow:0 0 20px 5px rgba(255,170,0,.8);box-shadow:0 0 20px 5px rgba(0,128,255,.8);color:#fff;}}
|
||||
@@ -1,8 +1,10 @@
|
||||
using EgwCoreLib.Razor.Data;
|
||||
using EgwCoreLib.Utils;
|
||||
using GPW.CORE.Data;
|
||||
using GPW.CORE.Data.DbModels;
|
||||
using GPW.CORE.Data.DTO;
|
||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||
using Microsoft.VisualBasic;
|
||||
using Newtonsoft.Json;
|
||||
using NLog;
|
||||
using StackExchange.Redis;
|
||||
@@ -51,6 +53,11 @@ namespace GPW.CORE.Smart.Data
|
||||
{
|
||||
dbController = new CORE.Data.Controllers.GPWController(configuration);
|
||||
}
|
||||
|
||||
// init datapipe...
|
||||
mPipeTimb = new MessagePipe(redisConn, Const.rPipeChTimb);
|
||||
mPipeRich = new MessagePipe(redisConn, Const.rPipeChRich);
|
||||
|
||||
_logger.LogInformation("Avviata classe CoreSmartDataService");
|
||||
}
|
||||
|
||||
@@ -60,6 +67,16 @@ namespace GPW.CORE.Smart.Data
|
||||
|
||||
public string CodApp { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Pipe messaggi richieste
|
||||
/// </summary>
|
||||
public MessagePipe mPipeRich { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Pipe messaggi timbrature
|
||||
/// </summary>
|
||||
public MessagePipe mPipeTimb { get; set; } = null!;
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Public Methods
|
||||
@@ -1301,7 +1318,7 @@ namespace GPW.CORE.Smart.Data
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserimento richeista mancata timbratura
|
||||
/// Inserimento richiesta mancata timbratura
|
||||
/// </summary>
|
||||
/// <param name="currItem"></param>
|
||||
/// <returns></returns>
|
||||
@@ -1315,6 +1332,8 @@ namespace GPW.CORE.Smart.Data
|
||||
currItem.Approv = false;
|
||||
// upsert!
|
||||
answ = dbController.TimbratureUpdate(currItem);
|
||||
// invio in pipe timbratura
|
||||
mPipeRich.sendMessage(JsonConvert.SerializeObject(currItem));
|
||||
Log.Info($"Registrata richiesta Mancata Timbratura | idxDip {currItem.IdxDipendente} | data-ora: {currItem.DataOra} | isEntrata: {currItem.Entrata}");
|
||||
// invalido la cache...
|
||||
await FlushRedisCache();
|
||||
@@ -1347,6 +1366,8 @@ namespace GPW.CORE.Smart.Data
|
||||
try
|
||||
{
|
||||
answ = dbController.TimbratureUpdate(currItem);
|
||||
// invio in pipe timbratura
|
||||
mPipeTimb.sendMessage(JsonConvert.SerializeObject(currItem));
|
||||
// invalido la cache...
|
||||
await ExecFlushRedisPattern($"{rKeyDailyData}:*");
|
||||
}
|
||||
|
||||
@@ -162,23 +162,6 @@ namespace GPW.CORE.Smart.Data
|
||||
}
|
||||
}
|
||||
|
||||
public string SearchVal
|
||||
{
|
||||
get => _searchVal;
|
||||
set
|
||||
{
|
||||
if (_searchVal != value)
|
||||
{
|
||||
_searchVal = value;
|
||||
|
||||
if (EA_DipUpdated != null)
|
||||
{
|
||||
EA_DipUpdated?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int selWeekNum { get; set; } = 0;
|
||||
public int selYear { get; set; } = DateTime.Today.Year;
|
||||
|
||||
@@ -356,8 +339,6 @@ namespace GPW.CORE.Smart.Data
|
||||
|
||||
private DipendentiModel? _rigaDip;
|
||||
|
||||
private string _searchVal = "";
|
||||
|
||||
private Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private bool showSearch;
|
||||
@@ -382,13 +363,6 @@ namespace GPW.CORE.Smart.Data
|
||||
}
|
||||
}
|
||||
|
||||
private void ReportSearch()
|
||||
{
|
||||
if (EA_DipUpdated != null)
|
||||
{
|
||||
EA_DipUpdated?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<Version>3.0.2312.0708</Version>
|
||||
<Version>3.0.2403.0510</Version>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<PackageProjectUrl>www.egalware.com</PackageProjectUrl>
|
||||
<Description>GPW Smart UI</Description>
|
||||
@@ -28,10 +28,10 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Blazored.LocalStorage" Version="4.3.0" />
|
||||
<PackageReference Include="Blazored.SessionStorage" Version="2.3.0" />
|
||||
<PackageReference Include="EgwCoreLib.Razor" Version="1.4.2307.3111" />
|
||||
<PackageReference Include="EgwCoreLib.Utils" Version="1.4.2307.3111" />
|
||||
<PackageReference Include="EgwCoreLib.Razor" Version="1.5.2402.2411" />
|
||||
<PackageReference Include="EgwCoreLib.Utils" Version="1.5.2402.2411" />
|
||||
<PackageReference Include="RestSharp" Version="108.0.3" />
|
||||
<PackageReference Include="StackExchange.Redis" Version="2.6.122" />
|
||||
<PackageReference Include="StackExchange.Redis" Version="2.7.27" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -48,7 +48,10 @@ namespace GPW.CORE.Smart.Pages
|
||||
{
|
||||
idxDipendente = MService.IdxDipendente;
|
||||
await Task.Delay(1);
|
||||
await InvokeAsync(StateHasChanged);
|
||||
if (idxDipendente > 0)
|
||||
{
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
|
||||
@@ -37,12 +37,34 @@
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="lib/css/bootstrap/js/bootstrap.min.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 src="_framework/blazor.server.js" autostart="false"></script>
|
||||
<script>
|
||||
Blazor.start({
|
||||
reconnectionOptions: {
|
||||
maxRetries: 300,
|
||||
retryIntervalMilliseconds: 2000
|
||||
maxRetries: 3600,
|
||||
retryIntervalMilliseconds: 1000
|
||||
},
|
||||
}).then(() => {
|
||||
Blazor.defaultReconnectionHandler._reconnectCallback = function (d) {
|
||||
console.log("Client reconnected, waiting 5 sec and reload!");
|
||||
setTimeout(function () {
|
||||
document.location.reload();
|
||||
}, 2000);
|
||||
}
|
||||
});
|
||||
</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({
|
||||
reconnectionOptions: {
|
||||
maxRetries: 1500,
|
||||
retryIntervalMilliseconds: 4000
|
||||
},
|
||||
reconnectionHandler: {
|
||||
onConnectionDown: (options, error) => console.error(error),
|
||||
onConnectionUp: () => console.log("Connection up!,restarting!")
|
||||
}
|
||||
}).then(() => {
|
||||
Object.defineProperty(Blazor.defaultReconnectionHandler, '_reconnectionDisplay', {
|
||||
@@ -58,7 +80,27 @@
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</script> *@
|
||||
@* <script>
|
||||
Blazor.start({
|
||||
reconnectionOptions: {
|
||||
maxRetries: 3000,
|
||||
retryIntervalMilliseconds: 2000
|
||||
},
|
||||
reconnectionHandler: {
|
||||
onConnectionDown: (options, error) => console.error(error),
|
||||
onConnectionUp: () => console.log("Client reconnected!")
|
||||
}
|
||||
}).then(() => {
|
||||
Blazor.defaultReconnectionHandler._reconnectCallback = function (d) {
|
||||
document.location.reload();
|
||||
}
|
||||
});
|
||||
</script> *@
|
||||
|
||||
|
||||
@* Versione alternativa da testare... https://github.com/dotnet/aspnetcore/issues/10325 *@
|
||||
|
||||
<script type="text/javascript" src="lib/font-awesome/js/all.min.js"></script>
|
||||
<script type="text/javascript" src="lib/Chart.js/chart.js"></script>
|
||||
<script type="text/javascript" src="lib/luxon/luxon.js"></script>
|
||||
@@ -70,7 +112,5 @@
|
||||
@*<script type="text/javascript" src="lib/ToastTrigger.js"></script>*@
|
||||
<script type="text/javascript" src="lib/qrcode.js"></script>
|
||||
<script type="text/javascript" src="lib/qrHelper.js"></script>
|
||||
<script type="text/javascript" src="lib/MenuHandler.js"></script>
|
||||
<script src="_framework/blazor.server.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
<div class="alert alert-secondary mt-4">
|
||||
<span class="oi oi-pencil me-2" aria-hidden="true"></span>
|
||||
<strong>@Title</strong>
|
||||
|
||||
<span class="text-nowrap">
|
||||
Please take our
|
||||
<a target="_blank" class="font-weight-bold link-dark" href="https://go.microsoft.com/fwlink/?linkid=2149017">brief survey</a>
|
||||
</span>
|
||||
and tell us what you think.
|
||||
</div>
|
||||
|
||||
@code {
|
||||
// Demonstrates how a parent component can supply parameters
|
||||
[Parameter]
|
||||
public string? Title { get; set; }
|
||||
}
|
||||
@@ -1,16 +1,66 @@
|
||||
namespace GPW.CORE.WRKLOG.Components
|
||||
{
|
||||
public partial class CmpFooter
|
||||
public partial class CmpFooter : IDisposable
|
||||
{
|
||||
#region Public Methods
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (aTimer != null)
|
||||
{
|
||||
aTimer.Elapsed -= ElapsedTimer;
|
||||
aTimer.Stop();
|
||||
aTimer.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#region Protected Fields
|
||||
|
||||
protected DateTime adesso = DateTime.Now;
|
||||
|
||||
#endregion Protected Fields
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected void ElapsedTimer(object? source, System.Timers.ElapsedEventArgs e)
|
||||
{
|
||||
var pUpd = Task.Run(async () =>
|
||||
{
|
||||
adesso = DateTime.Now;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
});
|
||||
pUpd.Wait();
|
||||
}
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
var rawVers = typeof(Program).Assembly.GetName().Version;
|
||||
version = rawVers != null ? rawVers : new Version("0.0.0.0");
|
||||
StartTimer();
|
||||
}
|
||||
|
||||
protected void StartTimer()
|
||||
{
|
||||
if (aTimer != null)
|
||||
{
|
||||
aTimer.Stop();
|
||||
aTimer.Dispose();
|
||||
}
|
||||
int tOutPeriod = 1000;
|
||||
aTimer = new System.Timers.Timer(tOutPeriod);
|
||||
aTimer.Elapsed += ElapsedTimer;
|
||||
aTimer.Enabled = true;
|
||||
aTimer.Start();
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private Version? version = typeof(Program).Assembly.GetName().Version;
|
||||
private System.Timers.Timer aTimer = null!;
|
||||
private Version? version = null!;
|
||||
|
||||
#endregion Private Fields
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<LoadingDataSmall></LoadingDataSmall>
|
||||
<LoadingData DisplaySize="LoadingData.CtrlSize.Small"></LoadingData>
|
||||
}
|
||||
</div>
|
||||
<div class="@cssTemp px-0">
|
||||
@@ -43,7 +43,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<LoadingDataSmall></LoadingDataSmall>
|
||||
<LoadingData DisplaySize="LoadingData.CtrlSize.Small"></LoadingData>
|
||||
}
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
@@ -101,7 +101,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<LoadingDataSmall></LoadingDataSmall>
|
||||
<LoadingData DisplaySize="LoadingData.CtrlSize.Small"></LoadingData>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,15 +4,31 @@
|
||||
<div class="p-1" style="width: 3.4rem;">
|
||||
@if (IsTitle)
|
||||
{
|
||||
<b>DAY</b>
|
||||
@if (MultiUser)
|
||||
{
|
||||
<div class="text-uppercase"><b>@DtRif.ToString("ddd")</b></div>
|
||||
<div class="small">@DtRif.ToString("dd.MM")</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<b>DAY</b>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DayDTO != null)
|
||||
{
|
||||
<div class="@dayCardCss text-center text-uppercase">
|
||||
<div class="text-uppercase"><b>@DayDTO.DtRif.ToString("ddd")</b></div>
|
||||
<div class="small">@DayDTO.DtRif.ToString("dd.MM")</div>
|
||||
@if (MultiUser)
|
||||
{
|
||||
<div class="small text-truncate" title="@Cognome"><b>@Cognome</b></div>
|
||||
<div class="small text-truncate" title="@Nome">@Nome</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="text-uppercase"><b>@DayDTO.DtRif.ToString("ddd")</b></div>
|
||||
<div class="small">@DayDTO.DtRif.ToString("dd.MM")</div>
|
||||
}
|
||||
@if (hasFest && DayDTO.ListFermateAzienda != null && DayDTO.ListFermateAzienda.Count > 0)
|
||||
{
|
||||
@foreach (var fermata in DayDTO.ListFermateAzienda)
|
||||
@@ -33,7 +49,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="small mt-2">
|
||||
<div class="my-2">
|
||||
|
||||
</div>
|
||||
}
|
||||
@@ -57,7 +73,7 @@
|
||||
{
|
||||
@*<!-- MPF -->*@
|
||||
<div class="d-flex justify-content-between text-center small">
|
||||
@if (hasFest && DayDTO.ListFermateAzienda != null)
|
||||
@if (hasFest && DayDTO != null && DayDTO.ListFermateAzienda != null)
|
||||
{
|
||||
@foreach (var fermata in DayDTO.ListFermateAzienda)
|
||||
{
|
||||
@@ -75,7 +91,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
@if (hasFerie && DayDTO.ListFerieDip != null)
|
||||
@if (hasFerie && DayDTO != null && DayDTO.ListFerieDip != null)
|
||||
{
|
||||
@foreach (var richiesta in DayDTO.ListFerieDip)
|
||||
{
|
||||
@@ -86,7 +102,7 @@
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@if (hasPerm && DayDTO.ListRichiesteDip != null)
|
||||
@if (hasPerm && DayDTO != null && DayDTO.ListRichiesteDip != null)
|
||||
{
|
||||
@foreach (var richiesta in DayDTO.ListRichiesteDip)
|
||||
{
|
||||
@@ -125,10 +141,18 @@
|
||||
}
|
||||
if (doShow)
|
||||
{
|
||||
<PeriodoLav Periodo="periodo" CurrPeriodo="item" ItemSelected="PeriodoSelected"></PeriodoLav>
|
||||
string fSize = MultiUser ? "0.6rem" : "0.7em";
|
||||
<PeriodoLav Periodo="periodo" CurrPeriodo="item" ItemSelected="PeriodoSelected" FontSize="@fSize"></PeriodoLav>
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
<div class="py-0 mb-1 flex-fill" style="font-size: 1em;">
|
||||
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@*<!-- RegAtt -->*@
|
||||
<div class="d-flex justify-content-between text-center">
|
||||
@@ -162,7 +186,8 @@
|
||||
}
|
||||
if (doShow)
|
||||
{
|
||||
<RegAtt CurrData="item" Periodo="periodo" MidHour="midHour" ListFasi="@ListFasi" IdxDipSel="@IdxDipSel" ItemCloned="ReportCloned" ItemSelected="ReportSelected" ItemUpdated="ReportUpdated" EnableActionMenu="@EnableActionMenu"></RegAtt>
|
||||
string fSize = MultiUser ? "0.6rem" : "0.75em";
|
||||
<RegAtt CurrData="item" Periodo="periodo" MidHour="midHour" ListFasi="@ListFasi" IdxDipSel="@IdxDipSel" ItemCloned="ReportCloned" ItemSelected="ReportSelected" ItemUpdated="ReportUpdated" EnableActionMenu="@EnableActionMenu" FontSize="@fSize"></RegAtt>
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -179,7 +204,10 @@
|
||||
{
|
||||
<div class="btn btn-sm w-100 btn-dark px-1 py-0" @onclick="SelTimbrature"><b>@TotLav</b> <i class="far fa-calendar-alt"></i></div>
|
||||
<div class="btn btn-sm w-100 @cssBadgeLav px-1 py-0 mt-1" @onclick="SelDayAgenda"><b>@TotComm</b> <i class="far fa-hourglass"></i></div>
|
||||
<div class="btn btn-sm w-100 btn-light border border-dark px-1 py-0 mt-1" @onclick="SelTemperature"><i class="fas fa-thermometer-half @cssThermo"></i> <i class="fas fa-certificate @cssCheck"></i></div>
|
||||
@if (!MultiUser)
|
||||
{
|
||||
<div class="btn btn-sm w-100 btn-light border border-dark px-1 py-0 mt-1" @onclick="SelTemperature"><i class="fas fa-thermometer-half @cssThermo"></i> <i class="fas fa-certificate @cssCheck"></i></div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -8,68 +8,12 @@ namespace GPW.CORE.WRKLOG.Components
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
public string cssBadgeLav
|
||||
{
|
||||
get
|
||||
{
|
||||
string bCtr = "btn";
|
||||
string answ = $"{bCtr}-light";
|
||||
var deltaComm = oreComm - oreLav;
|
||||
if (Math.Abs(deltaComm) < 0.5)
|
||||
{
|
||||
answ = $"{bCtr}-primary bg-opacity-75";
|
||||
}
|
||||
else if (Math.Abs(deltaComm) < 1)
|
||||
{
|
||||
answ = $"{bCtr}-warning";
|
||||
}
|
||||
else
|
||||
{
|
||||
answ = $"{bCtr}-danger";
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
|
||||
public string cssCheck
|
||||
{
|
||||
get => OkVC19 ? "text-success" : "text-secondary";
|
||||
}
|
||||
|
||||
public string cssThermo
|
||||
{
|
||||
get
|
||||
{
|
||||
string answ = "";
|
||||
// verifico in base a ok temp o meno...
|
||||
if (OkTemp)
|
||||
{
|
||||
// colore in base al valore...
|
||||
var currTemp = tempRil;
|
||||
if (currTemp >= (decimal)37.5)
|
||||
{
|
||||
answ = "text-danger";
|
||||
}
|
||||
else if (currTemp >= 37)
|
||||
{
|
||||
answ = "text-warning";
|
||||
}
|
||||
else
|
||||
{
|
||||
answ = "text-success";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
answ = "text-secondary";
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
public DailyDataDTO? DayDTO { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public DateTime DtRif { get; set; } = DateTime.MinValue.Date;
|
||||
|
||||
[Parameter]
|
||||
public bool EnableActionMenu { get; set; } = true;
|
||||
|
||||
@@ -91,11 +35,11 @@ namespace GPW.CORE.WRKLOG.Components
|
||||
[Parameter]
|
||||
public List<AnagFasiModel> ListFasi { get; set; } = null!;
|
||||
|
||||
[Parameter]
|
||||
public bool MultiUser { get; set; } = false;
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<DailyDataDTO> PeriodSelected { get; set; }
|
||||
#if false
|
||||
//public EventCallback<List<TimbratureModel>?> PeriodSelected { get; set; }
|
||||
#endif
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<DailyDataDTO> ReqDayAgenda { get; set; }
|
||||
@@ -128,7 +72,7 @@ namespace GPW.CORE.WRKLOG.Components
|
||||
{
|
||||
await PeriodSelected.InvokeAsync(DayDTO);
|
||||
#if false
|
||||
//await PeriodSelected.InvokeAsync(DayDTO.ListTimbr);
|
||||
//await PeriodSelected.InvokeAsync(DayDTO.ListTimbr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -179,7 +123,7 @@ namespace GPW.CORE.WRKLOG.Components
|
||||
{
|
||||
await PeriodSelected.InvokeAsync(DayDTO);
|
||||
#if false
|
||||
//await PeriodSelected.InvokeAsync(DayDTO.ListTimbr);
|
||||
//await PeriodSelected.InvokeAsync(DayDTO.ListTimbr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -188,6 +132,78 @@ namespace GPW.CORE.WRKLOG.Components
|
||||
|
||||
#region Private Properties
|
||||
|
||||
private string Cognome
|
||||
{
|
||||
get
|
||||
{
|
||||
string answ = "NA";
|
||||
if (DayDTO != null)
|
||||
{
|
||||
answ = DayDTO.TimbrExpl.CognomeNome.Split(" ")[0] ?? " NA";
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
|
||||
private string cssBadgeLav
|
||||
{
|
||||
get
|
||||
{
|
||||
string bCtr = "btn";
|
||||
string answ = $"{bCtr}-light";
|
||||
var deltaComm = oreComm - oreLav;
|
||||
if (Math.Abs(deltaComm) < 0.5)
|
||||
{
|
||||
answ = $"{bCtr}-primary bg-opacity-75";
|
||||
}
|
||||
else if (Math.Abs(deltaComm) < 1)
|
||||
{
|
||||
answ = $"{bCtr}-warning";
|
||||
}
|
||||
else
|
||||
{
|
||||
answ = $"{bCtr}-danger";
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
|
||||
private string cssCheck
|
||||
{
|
||||
get => OkVC19 ? "text-success" : "text-secondary";
|
||||
}
|
||||
|
||||
private string cssThermo
|
||||
{
|
||||
get
|
||||
{
|
||||
string answ = "";
|
||||
// verifico in base a ok temp o meno...
|
||||
if (OkTemp)
|
||||
{
|
||||
// colore in base al valore...
|
||||
var currTemp = tempRil;
|
||||
if (currTemp >= (decimal)37.5)
|
||||
{
|
||||
answ = "text-danger";
|
||||
}
|
||||
else if (currTemp >= 37)
|
||||
{
|
||||
answ = "text-warning";
|
||||
}
|
||||
else
|
||||
{
|
||||
answ = "text-success";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
answ = "text-secondary";
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
|
||||
private string dayCardCss
|
||||
{
|
||||
get => hasTimb ? "border border-dark text-dark rounded shadow" : "text-secondary rounded";
|
||||
@@ -223,6 +239,23 @@ namespace GPW.CORE.WRKLOG.Components
|
||||
get => DayDTO == null || DayDTO.ListRA == null || DayDTO.ListRA.Count == 0;
|
||||
}
|
||||
|
||||
private string Nome
|
||||
{
|
||||
get
|
||||
{
|
||||
string answ = "NA";
|
||||
if (DayDTO != null)
|
||||
{
|
||||
answ = DayDTO.TimbrExpl.CognomeNome.Replace($"{Cognome} ", "");
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
|
||||
#if false
|
||||
//public EventCallback<List<TimbratureModel>?> PeriodSelected { get; set; }
|
||||
#endif
|
||||
|
||||
private bool OkTemp
|
||||
{
|
||||
get
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
@inject MessageService AppMServ
|
||||
@inject IJSRuntime JSRuntime
|
||||
|
||||
<div class="py-0 mb-1 flex-fill @blockCss" style="width: @widthPerc; font-size: 0.7em;">
|
||||
<div class="py-0 mb-1 flex-fill @blockCss" style="width: @widthPerc; font-size: @FontSize;">
|
||||
@if (CurrPeriodo.Tipo != CORE.Data.TipoPeriodo.ND)
|
||||
{
|
||||
|
||||
@@ -48,6 +48,9 @@
|
||||
[Parameter]
|
||||
public EventCallback<PeriodoDTO> ItemSelected { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string FontSize { get; set; } = "0.7em";
|
||||
|
||||
private string widthPerc
|
||||
{
|
||||
get
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
@if (CalcOreFasi == null)
|
||||
{
|
||||
<LoadingDataSmall></LoadingDataSmall>
|
||||
<LoadingData DisplaySize="LoadingData.CtrlSize.Small"></LoadingData>
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
@if (@CurrData.IdxFase > 0)
|
||||
{
|
||||
<div class="dropdown shadow-lg">
|
||||
<button @onclick="() => Edit()" class="@buttonCss px-1 text-center border border-0 rounded-0 rounded-start btn btn-primary bg-opacity-75 btn-sm py-1 font-monospace2" style="font-size: 0.75rem;" disabled="@(IsClipboard)">
|
||||
<button @onclick="() => Edit()" class="@buttonCss px-1 text-center border border-0 rounded-0 rounded-start btn btn-primary bg-opacity-75 btn-sm py-1 font-monospace2" style="font-size: @FontSize;" disabled="@(IsClipboard)">
|
||||
@if (@CurrData.OreTot > 1)
|
||||
{
|
||||
<div>@CurrData.Inizio.ToString("HH:mm")</div>
|
||||
@@ -72,7 +72,7 @@
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="px-1 py-0 text-start textTrim flex-fill shadow-lg">
|
||||
<div class="px-1 py-0 text-start textTrim flex-fill shadow">
|
||||
<div class="text-dark" title="@CurrData.FasiNav?.ProgettoNav?.ClienteNav?.RagSociale - @CurrData.FasiNav?.ProgettoNav?.NomeProj"><b>@(trimLine($"{CurrData.FasiNav?.ProgettoNav?.ClienteNav?.RagSociale}", 60))</b> @(trimLine($"{CurrData.FasiNav?.ProgettoNav?.NomeProj}", 60))</div>
|
||||
<div class="text-secondary" title="@CurrData.FasiNav?.DescrizioneFase">@(trimLine($"{CurrData.FasiNav?.DescrizioneFase}", 150))</div>
|
||||
<div class="small" title="@CurrData.Descrizione">@(trimLine($"{CurrData.Descrizione}", 200))</div>
|
||||
@@ -80,7 +80,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="px-1 small textTrim py-2">
|
||||
<div class="px-1 small textTrim py-0">
|
||||
<AddRA IdxDip="@IdxDipSel" NewItemCreated="ReportSelect" InizioPer="@CurrData.Inizio" EnableAction="@EnableActionMenu"></AddRA>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -6,75 +6,49 @@ namespace GPW.CORE.WRKLOG.Components
|
||||
{
|
||||
public partial class RegAtt
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
[Parameter]
|
||||
public RegAttivitaModel CurrData { get; set; } = null!;
|
||||
|
||||
[Parameter]
|
||||
public bool EnableActionMenu { get; set; } = true;
|
||||
|
||||
[Parameter]
|
||||
public string FontSize { get; set; } = "0.75em";
|
||||
|
||||
[Parameter]
|
||||
public int IdxDipSel { get; set; } = 0;
|
||||
|
||||
[Parameter]
|
||||
public bool IsClipboard { get; set; } = false;
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<RegAttivitaModel> ItemCloned { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<RegAttivitaModel> ItemSelected { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<RegAttivitaModel> ItemUpdated { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public List<AnagFasiModel> ListFasi { get; set; } = null!;
|
||||
|
||||
[Parameter]
|
||||
public int MidHour { get; set; } = 12;
|
||||
|
||||
[Parameter]
|
||||
public double Periodo { get; set; } = 1;
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Protected Fields
|
||||
|
||||
protected bool isSelected = false;
|
||||
|
||||
#endregion Protected Fields
|
||||
|
||||
#region Private Properties
|
||||
|
||||
private string blockCss
|
||||
{
|
||||
get
|
||||
{
|
||||
string answ = CurrData.IdxFase == 0 ? "" : " bg-body rounded shadow";
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
|
||||
private bool dropActionTop
|
||||
|
||||
{
|
||||
get
|
||||
{
|
||||
bool answ = false;
|
||||
switch (CurrData.Inizio.DayOfWeek)
|
||||
{
|
||||
case DayOfWeek.Sunday:
|
||||
case DayOfWeek.Saturday:
|
||||
case DayOfWeek.Friday:
|
||||
answ = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
private bool dropActionLeft
|
||||
|
||||
{
|
||||
get
|
||||
{
|
||||
bool answ = CurrData.Inizio.Hour >= MidHour ? true : false;
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
|
||||
private string widthPerc
|
||||
{
|
||||
get
|
||||
{
|
||||
string answ = "1%";
|
||||
if (CurrData != null)
|
||||
{
|
||||
double num = CurrData.OreTot != null ? (double)CurrData.OreTot : 0;
|
||||
answ = $"{num / Periodo:P2}".Replace(",", ".");
|
||||
}
|
||||
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
|
||||
private bool VetoInsert
|
||||
{
|
||||
get => GDataServ.VetoInsert;
|
||||
}
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#region Protected Properties
|
||||
|
||||
protected string buttonCss
|
||||
@@ -82,11 +56,6 @@ namespace GPW.CORE.WRKLOG.Components
|
||||
get => !IsClipboard ? "dropbtn" : "";
|
||||
}
|
||||
|
||||
protected string cssSelected
|
||||
{
|
||||
get => isSelected ? "table-info" : "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// definizione CSS posizionale secondo condizioni top/left
|
||||
/// </summary>
|
||||
@@ -107,67 +76,12 @@ namespace GPW.CORE.WRKLOG.Components
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Public Properties
|
||||
|
||||
[Parameter]
|
||||
public RegAttivitaModel CurrData { get; set; } = null!;
|
||||
|
||||
[Parameter]
|
||||
public bool EnableActionMenu { get; set; } = true;
|
||||
|
||||
[Parameter]
|
||||
public int IdxDipSel { get; set; } = 0;
|
||||
|
||||
[Parameter]
|
||||
public bool IsClipboard { get; set; } = false;
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<RegAttivitaModel> ItemCloned { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<RegAttivitaModel> ItemSelected { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<RegAttivitaModel> ItemUpdated { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public List<AnagFasiModel> ListFasi { get; set; } = null!;
|
||||
|
||||
[Parameter]
|
||||
public double Periodo { get; set; } = 1;
|
||||
|
||||
[Parameter]
|
||||
public int MidHour { get; set; } = 12;
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary>
|
||||
/// Verifico coerenza date (inizio < fine)
|
||||
/// </summary>
|
||||
/// <param name="modInizio">indica se la data modificata sia l'inizio</param>
|
||||
private void checkCoerenzaDate(bool modInizio)
|
||||
protected string cssSelected
|
||||
{
|
||||
// verifica presenza errori
|
||||
bool inError = CurrData.Inizio >= CurrData.Fine;
|
||||
if (inError)
|
||||
{
|
||||
// se ho mod inizio --> tengo ferma fine, inizio 1/2 h prima
|
||||
if (modInizio)
|
||||
{
|
||||
CurrData.Inizio = CurrData.Fine.AddMinutes(-30);
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrData.Fine = CurrData.Inizio.AddMinutes(30);
|
||||
}
|
||||
}
|
||||
get => isSelected ? "table-info" : "";
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
@@ -246,8 +160,8 @@ namespace GPW.CORE.WRKLOG.Components
|
||||
/// <summary>
|
||||
/// Trim linea di testo secondo regole
|
||||
/// </summary>
|
||||
/// <param name = "stringOrig">Stringa origiale</param>
|
||||
/// <param name = "multFact">Fattore di moltiplicazione (std: 130)</param>
|
||||
/// <param name="stringOrig">Stringa origiale</param>
|
||||
/// <param name="multFact">Fattore di moltiplicazione (std: 130)</param>
|
||||
/// <returns></returns>
|
||||
protected string trimLine(object stringOrig, int multFact = 130)
|
||||
{
|
||||
@@ -269,5 +183,93 @@ namespace GPW.CORE.WRKLOG.Components
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Properties
|
||||
|
||||
private string blockCss
|
||||
{
|
||||
get
|
||||
{
|
||||
string answ = CurrData.IdxFase == 0 ? "" : " bg-body rounded shadow";
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
|
||||
private bool dropActionLeft
|
||||
|
||||
{
|
||||
get
|
||||
{
|
||||
bool answ = CurrData.Inizio.Hour >= MidHour ? true : false;
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
|
||||
private bool dropActionTop
|
||||
|
||||
{
|
||||
get
|
||||
{
|
||||
bool answ = false;
|
||||
switch (CurrData.Inizio.DayOfWeek)
|
||||
{
|
||||
case DayOfWeek.Sunday:
|
||||
case DayOfWeek.Saturday:
|
||||
case DayOfWeek.Friday:
|
||||
answ = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
|
||||
private bool VetoInsert
|
||||
{
|
||||
get => GDataServ.VetoInsert;
|
||||
}
|
||||
|
||||
private string widthPerc
|
||||
{
|
||||
get
|
||||
{
|
||||
string answ = "1%";
|
||||
if (CurrData != null)
|
||||
{
|
||||
double num = CurrData.OreTot != null ? (double)CurrData.OreTot : 0;
|
||||
answ = $"{num / Periodo:P2}".Replace(",", ".");
|
||||
}
|
||||
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#region Private Methods
|
||||
|
||||
/// <summary> Verifico coerenza date (inizio < fine) </summary> <param
|
||||
/// name="modInizio">indica se la data modificata sia l'inizio</param>
|
||||
private void checkCoerenzaDate(bool modInizio)
|
||||
{
|
||||
// verifica presenza errori
|
||||
bool inError = CurrData.Inizio >= CurrData.Fine;
|
||||
if (inError)
|
||||
{
|
||||
// se ho mod inizio --> tengo ferma fine, inizio 1/2 h prima
|
||||
if (modInizio)
|
||||
{
|
||||
CurrData.Inizio = CurrData.Fine.AddMinutes(-30);
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrData.Fine = CurrData.Inizio.AddMinutes(30);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,11 @@
|
||||
else
|
||||
{ @if (isSendingData)
|
||||
{
|
||||
<ProgressDisplay Title="Salvataggio ed invio richiesta" CurrVal="@sendDataVal" MaxVal="@sendDataMaxVal" ExpTimeMSec="1000"></ProgressDisplay>
|
||||
<ProgressDisplay Title="Salvataggio ed invio richiesta" CurrVal="@sendDataVal" NextVal="@sendDataNextVal" MaxVal="@sendDataMaxVal" ExpTimeMSec="1000"></ProgressDisplay>
|
||||
}
|
||||
@if (ListRecords == null)
|
||||
{
|
||||
<LoadingDataSmall></LoadingDataSmall>
|
||||
<LoadingData DisplaySize="LoadingData.CtrlSize.Small"></LoadingData>
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -6,11 +6,11 @@ else
|
||||
{
|
||||
@if (isSendingData)
|
||||
{
|
||||
<ProgressDisplay Title="Salvataggio ed invio richiesta" CurrVal="@sendDataVal" MaxVal="@sendDataMaxVal" ExpTimeMSec="1000"></ProgressDisplay>
|
||||
<ProgressDisplay Title="Salvataggio ed invio richiesta" CurrVal="@sendDataVal" NextVal="@sendDataNextVal" MaxVal="@sendDataMaxVal" ExpTimeMSec="1000"></ProgressDisplay>
|
||||
}
|
||||
@if (ListRecords == null)
|
||||
{
|
||||
<LoadingDataSmall></LoadingDataSmall>
|
||||
<LoadingData DisplaySize="LoadingData.CtrlSize.Small"></LoadingData>
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<LoadingDataSmall></LoadingDataSmall>
|
||||
<LoadingData DisplaySize="LoadingData.CtrlSize.Small"></LoadingData>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -79,7 +79,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<LoadingDataSmall></LoadingDataSmall>
|
||||
<LoadingData DisplaySize="LoadingData.CtrlSize.Small"></LoadingData>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using EgwCoreLib.Utils;
|
||||
using GPW.CORE.Data;
|
||||
using GPW.CORE.Data.DbModels;
|
||||
using GPW.CORE.Data.DTO;
|
||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||
@@ -51,6 +52,11 @@ namespace GPW.CORE.WRKLOG.Data
|
||||
{
|
||||
dbController = new CORE.Data.Controllers.GPWController(configuration);
|
||||
}
|
||||
|
||||
// init datapipe...
|
||||
mPipeTimb = new MessagePipe(redisConn, Const.rPipeChTimb);
|
||||
mPipeRich = new MessagePipe(redisConn, Const.rPipeChRich);
|
||||
|
||||
_logger.LogInformation("Avviata classe GpwDataService");
|
||||
}
|
||||
|
||||
@@ -60,6 +66,16 @@ namespace GPW.CORE.WRKLOG.Data
|
||||
|
||||
public string CodApp { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Pipe messaggi richieste
|
||||
/// </summary>
|
||||
public MessagePipe mPipeRich { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Pipe messaggi timbrature
|
||||
/// </summary>
|
||||
public MessagePipe mPipeTimb { get; set; } = null!;
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Public Methods
|
||||
@@ -754,6 +770,48 @@ namespace GPW.CORE.WRKLOG.Data
|
||||
Log.Debug($"DailyDetails | {source} in: {ts.TotalMilliseconds} ms");
|
||||
return dbResult;
|
||||
}
|
||||
/// <summary>
|
||||
/// Recupera l'elenco dei dettaglio giornaliero attività di tutti i dipendenti, dato giorno riferimento
|
||||
/// </summary>
|
||||
/// <param name="dtRif">Data di riferimento</param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<DailyDataDTO>> DailyDetailAllDip(DateTime dtRif)
|
||||
{
|
||||
string source = "DB";
|
||||
List<DailyDataDTO>? dbResult = new List<DailyDataDTO>();
|
||||
string currKey = $"{rKeyDailyData}:ALL:{dtRif.ToString("yyyy-MM-dd")}";
|
||||
Stopwatch stopWatch = new Stopwatch();
|
||||
stopWatch.Start();
|
||||
string? rawData = await redisDb.StringGetAsync(currKey);
|
||||
if (!string.IsNullOrEmpty(rawData))
|
||||
{
|
||||
source = "REDIS";
|
||||
var tempResult = JsonConvert.DeserializeObject<List<DailyDataDTO>>(rawData);
|
||||
if (tempResult == null)
|
||||
{
|
||||
dbResult = new List<DailyDataDTO>();
|
||||
}
|
||||
else
|
||||
{
|
||||
dbResult = tempResult;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dbResult = dbController.DailyDetailAllDip(dtRif);
|
||||
rawData = JsonConvert.SerializeObject(dbResult, JSSettings);
|
||||
await redisDb.StringSetAsync(currKey, rawData, FastCache);
|
||||
}
|
||||
if (dbResult == null)
|
||||
{
|
||||
dbResult = new List<DailyDataDTO>();
|
||||
}
|
||||
stopWatch.Stop();
|
||||
TimeSpan ts = stopWatch.Elapsed;
|
||||
Log.Debug($"DailyDetailAllDip | {source} in: {ts.TotalMilliseconds} ms");
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
|
||||
public string DeriptData(string encData)
|
||||
{
|
||||
@@ -907,6 +965,48 @@ namespace GPW.CORE.WRKLOG.Data
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Righe presenze giornaliere
|
||||
/// </summary>
|
||||
/// <param name="dtRif">DataOra riferimento per richiesta presenze</param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<StatsDayPresModel>> PresenzeDay(DateTime dtRif)
|
||||
{
|
||||
string source = "DB";
|
||||
List<StatsDayPresModel> dbResult = new List<StatsDayPresModel>();
|
||||
string currKey = $"{rKeyStatPresDay}:{dtRif:yyyy-MM-dd}";
|
||||
Stopwatch stopWatch = new Stopwatch();
|
||||
stopWatch.Start();
|
||||
string? rawData = await redisDb.StringGetAsync(currKey);
|
||||
if (!string.IsNullOrEmpty(rawData))
|
||||
{
|
||||
source = "REDIS";
|
||||
var tempResult = JsonConvert.DeserializeObject<List<StatsDayPresModel>>(rawData);
|
||||
if (tempResult == null)
|
||||
{
|
||||
dbResult = new List<StatsDayPresModel>();
|
||||
}
|
||||
else
|
||||
{
|
||||
dbResult = tempResult;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dbResult = dbController.PresenzeDay(dtRif);
|
||||
rawData = JsonConvert.SerializeObject(dbResult, JSSettings);
|
||||
await redisDb.StringSetAsync(currKey, rawData, FastCache);
|
||||
}
|
||||
if (dbResult == null)
|
||||
{
|
||||
dbResult = new List<StatsDayPresModel>();
|
||||
}
|
||||
stopWatch.Stop();
|
||||
TimeSpan ts = stopWatch.Elapsed;
|
||||
Log.Debug($"PresenzeDay | {source} in: {ts.TotalMilliseconds} ms");
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
public async Task<bool> RegAttDelete(RegAttivitaModel currItem)
|
||||
{
|
||||
bool answ = false;
|
||||
@@ -1447,15 +1547,10 @@ namespace GPW.CORE.WRKLOG.Data
|
||||
protected const string rKeyCalcOreFase = $"{redisBaseAddr}:Cache:CalcOreFase";
|
||||
|
||||
protected const string rKeyCalcOreProj = $"{redisBaseAddr}:Cache:CalcOreProj";
|
||||
|
||||
protected const string rKeyCalendari = $"{redisBaseAddr}:Cache:Calendari";
|
||||
|
||||
protected const string rKeyCliAll = $"{redisBaseAddr}:Cache:CliAll";
|
||||
|
||||
protected const string rKeyConfig = $"{redisBaseAddr}:Cache:Config";
|
||||
|
||||
protected const string rKeyDailyData = $"{redisBaseAddr}:Cache:DailyData";
|
||||
|
||||
protected const string rKeyDipendenti = $"{redisBaseAddr}:Cache:Dipendenti";
|
||||
protected const string rKeyFasiAll = $"{redisBaseAddr}:Cache:FasiAll";
|
||||
protected const string rKeyFasiByProj = $"{redisBaseAddr}:Cache:FasiByProj";
|
||||
@@ -1467,7 +1562,7 @@ namespace GPW.CORE.WRKLOG.Data
|
||||
protected const string rKeyProjAll = $"{redisBaseAddr}:Cache:ProjAll";
|
||||
protected const string rKeyReportData = $"{redisBaseAddr}:Cache:ReportData";
|
||||
protected const string rKeyRilTemp = $"{redisBaseAddr}:Cache:RilTemp";
|
||||
|
||||
protected const string rKeyStatPresDay = $"{redisBaseAddr}:Cache:StatPresDay";
|
||||
protected const string rKeyVC19 = $"{redisBaseAddr}:Cache:VC19";
|
||||
|
||||
protected const string rKeyVetoIns = $"{redisBaseAddr}:Cache:VetoInsert";
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Version>3.0.2312.0618</Version>
|
||||
<Version>3.0.2403.0715</Version>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
@@ -32,14 +32,14 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BlazorCalendar" Version="2.5.3" />
|
||||
<PackageReference Include="EgwCoreLib.Razor" Version="1.4.2307.3111" />
|
||||
<PackageReference Include="EgwCoreLib.Utils" Version="1.4.2307.3111" />
|
||||
<PackageReference Include="EgwCoreLib.Razor" Version="1.5.2402.2411" />
|
||||
<PackageReference Include="EgwCoreLib.Utils" Version="1.5.2402.2411" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.Negotiate" Version="6.0.14" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="6.0.14" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NLog" Version="5.2.2" />
|
||||
<PackageReference Include="RestSharp" Version="108.0.3" />
|
||||
<PackageReference Include="StackExchange.Redis" Version="2.6.96" />
|
||||
<PackageReference Include="StackExchange.Redis" Version="2.7.27" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
await Task.Delay(1);
|
||||
|
||||
// passo a pagina home
|
||||
NavManager.NavigateTo("");
|
||||
NavManager.NavigateTo("", true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<LoadingDataSmall></LoadingDataSmall>
|
||||
<LoadingData DisplaySize="LoadingData.CtrlSize.Small"></LoadingData>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
@page "/Presenze"
|
||||
@attribute [Authorize]
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header table-primary py-1">
|
||||
<div class="row">
|
||||
<h3>Presenze</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row detPresenze">
|
||||
<div class="col-12">
|
||||
<DayHoriz IsTitle="true" StartHour="@startHour" EndHour="@endHour" ListFasi="@ListFasi" IdxDipSel="@IdxDipendente" MultiUser="true" DtRif="@DtSelected"></DayHoriz>
|
||||
</div>
|
||||
@if (ListRecords == null)
|
||||
{
|
||||
@for (int i = 0; i < 7; i++)
|
||||
{
|
||||
<div class="col-12 my-3">
|
||||
<div class="placeholder-glow">
|
||||
<span class="placeholder col-6 mb-1"></span>
|
||||
<span class="placeholder col-5 mb-1"></span>
|
||||
<span class="placeholder fs-1 col-6"></span>
|
||||
<span class="placeholder fs-1 col-5"></span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@foreach (var currItem in ListRecords)
|
||||
{
|
||||
<div class="col-12">
|
||||
<DayHoriz DayDTO="@currItem" StartHour="@startHour" EndHour="@endHour" ListFasi="@ListFasi" IdxDipSel="@currItem.IdxDipendente" MultiUser="true"></DayHoriz>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,223 @@
|
||||
using GPW.CORE.Data.DbModels;
|
||||
using GPW.CORE.Data.DTO;
|
||||
using GPW.CORE.WRKLOG.Data;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace GPW.CORE.WRKLOG.Pages
|
||||
{
|
||||
public partial class Presenze : IDisposable
|
||||
{
|
||||
#region Public Methods
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
UITimer?.Dispose();
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#region Protected Fields
|
||||
|
||||
protected DateTime lastRefresh = DateTime.Now;
|
||||
|
||||
/// <summary>
|
||||
/// Timer per refresh dati
|
||||
///
|
||||
/// https://stackoverflow.com/questions/63060065/blazor-timer-call-async-api-task-to-update-ui https://www.janduniec.blog/index.php/100/timers-in-blazor/
|
||||
/// </summary>
|
||||
protected System.Timers.Timer UITimer = new System.Timers.Timer();
|
||||
|
||||
#endregion Protected Fields
|
||||
|
||||
#region Protected Properties
|
||||
|
||||
[Inject]
|
||||
protected MessageService AppMServ { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected GpwDataService GDataServ { get; set; } = null!;
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private int _endHour = 18;
|
||||
|
||||
private int _startHour = 8;
|
||||
|
||||
private DateTime DtSelected = DateTime.Today;
|
||||
|
||||
private int IdxDipendente = 0;
|
||||
|
||||
private List<AnagFasiModel> ListFasi = new List<AnagFasiModel>();
|
||||
|
||||
private List<DailyDataDTO>? ListRecords = null;
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Private Properties
|
||||
|
||||
private int endHour
|
||||
{
|
||||
get => _endHour;
|
||||
set
|
||||
{
|
||||
// fix --> max 24...
|
||||
_endHour = value < 25 ? value : 24;
|
||||
}
|
||||
}
|
||||
|
||||
private bool isLoading { get; set; } = false;
|
||||
|
||||
private int startHour
|
||||
{
|
||||
get => _startHour;
|
||||
set
|
||||
{
|
||||
// fix --> MIN 0...
|
||||
_startHour = value > 0 ? value : 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private void checkHourRange()
|
||||
{
|
||||
int minHour = 12;
|
||||
int maxHour = 14;
|
||||
int currStart = 12;
|
||||
int currEnd = 12;
|
||||
int roundMin = 30;
|
||||
//int extraEnd = 30;
|
||||
if (ListRecords != null)
|
||||
{
|
||||
// per ogni giornata
|
||||
foreach (var giornata in ListRecords)
|
||||
{
|
||||
if (giornata.ListTimbr != null)
|
||||
{
|
||||
var minRecTimb = giornata.ListTimbr
|
||||
.Where(x => x.Entrata == true)
|
||||
.OrderBy(x => x.DataOra)
|
||||
.FirstOrDefault();
|
||||
if (minRecTimb != null)
|
||||
{
|
||||
if (minHour > minRecTimb.DataOra.AddMinutes(roundMin / 3).Hour)
|
||||
{
|
||||
minHour = minRecTimb.DataOra.AddMinutes(roundMin / 3).Hour;
|
||||
}
|
||||
}
|
||||
var maxRecTimb = giornata.ListTimbr
|
||||
.Where(x => x.Entrata == false)
|
||||
.OrderByDescending(x => x.DataOra)
|
||||
.FirstOrDefault();
|
||||
if (maxRecTimb != null)
|
||||
{
|
||||
if (maxHour < maxRecTimb.DataOra.AddMinutes(-roundMin / 3).Hour)
|
||||
{
|
||||
maxHour = maxRecTimb.DataOra.AddMinutes(-roundMin / 3).Hour + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (giornata.ListRA != null)
|
||||
{
|
||||
var minRecRa = giornata.ListRA
|
||||
.OrderBy(x => x.Inizio)
|
||||
.FirstOrDefault();
|
||||
if (minRecRa != null)
|
||||
{
|
||||
// verifico se cambia giorno inizio/fine --> seleziono la mezzanotte
|
||||
currStart = minRecRa.Inizio.AddMinutes(-roundMin).Date.Equals(minRecRa.Fine.Date) ? minRecRa.Inizio.AddMinutes(-roundMin).Hour : 0;
|
||||
if (minHour > currStart)
|
||||
{
|
||||
minHour = currStart;
|
||||
}
|
||||
}
|
||||
var maxRecRa = giornata.ListRA
|
||||
.OrderByDescending(x => x.Fine)
|
||||
.FirstOrDefault();
|
||||
if (maxRecRa != null)
|
||||
{
|
||||
// verifico se cambia giorno inizio/fine --> seleziono la mezzanotte
|
||||
currEnd = maxRecRa.Inizio.Date.Equals(maxRecRa.Fine.AddMinutes(roundMin).Date) ? maxRecRa.Fine.AddMinutes(roundMin).Hour + 1 : 24;
|
||||
if (maxHour < currEnd)
|
||||
{
|
||||
maxHour = currEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
startHour = minHour;// - 1;
|
||||
checkOrarioDip();
|
||||
// minimo 6 h... x cui "allungo" verso fine
|
||||
if (maxHour - minHour < AppMServ.orarioDip)
|
||||
{
|
||||
minHour--;
|
||||
maxHour = minHour + AppMServ.orarioDip;
|
||||
}
|
||||
endHour = maxHour;// + 1;
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
ListRecords = null;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
await Task.Delay(1);
|
||||
|
||||
await TryReload();
|
||||
// avvio un timer infinito x refresh pagina COMUNQUE ogni 60 sec anche non succedesse nulla...
|
||||
UITimer = new System.Timers.Timer
|
||||
{
|
||||
Interval = 1000 * 60,
|
||||
AutoReset = true,
|
||||
Enabled = true
|
||||
};
|
||||
UITimer.Elapsed += async (s, ea) => await TryReload();
|
||||
}
|
||||
|
||||
protected async Task TryReload()
|
||||
{
|
||||
// effettuo reload SOLO SE no ho editing in corso...
|
||||
await ReloadData();
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private void checkOrarioDip()
|
||||
{
|
||||
// calcolo minimo da cod orario dipendente
|
||||
if (AppMServ.orarioDip == 0)
|
||||
{
|
||||
AnagOrariModel? schemaOrario = null;
|
||||
// recupero da DB schema settimanale...
|
||||
var pUpd = Task.Run(async () =>
|
||||
{
|
||||
schemaOrario = await GDataServ.AnagOrarioByDip(AppMServ.IdxDipendente);
|
||||
});
|
||||
pUpd.Wait();
|
||||
if (schemaOrario != null)
|
||||
{
|
||||
AppMServ.orarioDip = (int)(Math.Ceiling(schemaOrario.oreOrdSett / 5));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ReloadData()
|
||||
{
|
||||
isLoading = true;
|
||||
UITimer.Stop();
|
||||
ListRecords = await GDataServ.DailyDetailAllDip(DtSelected);
|
||||
await Task.Delay(1);
|
||||
checkHourRange();
|
||||
await Task.Delay(1);
|
||||
lastRefresh = DateTime.Now;
|
||||
UITimer.Start();
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
.detPresenze {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
.detPresenze {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
.detPresenze{font-size:.8em;}
|
||||
@@ -144,7 +144,7 @@ namespace GPW.CORE.WRKLOG.Pages
|
||||
|
||||
protected void ResetData()
|
||||
{
|
||||
//DataService.rollBackEdit(currRecord);
|
||||
//GDataServ.rollBackEdit(currRecord);
|
||||
}
|
||||
|
||||
protected void Select(DipendentiModel selRecord)
|
||||
|
||||
@@ -90,31 +90,52 @@ else if (ListTimbr != null)
|
||||
}
|
||||
else
|
||||
{
|
||||
<LoadingDataSmall></LoadingDataSmall>
|
||||
<div class="row">
|
||||
@for (int i = 0; i < 5; i++)
|
||||
{
|
||||
<div class="col px-1">
|
||||
<div class="placeholder-glow">
|
||||
<span class="placeholder fs-3 col-12 mb-1"></span>
|
||||
<span class="placeholder fs-3 col-6"></span>
|
||||
<span class="placeholder fs-3 col-5"></span>
|
||||
<span class="placeholder col-12"></span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if (ListRecords == null)
|
||||
{
|
||||
<LoadingData></LoadingData>
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<DayHoriz IsTitle="true" StartHour="@startHour" EndHour="@endHour" ListFasi="@ListFasi" IdxDipSel="@IdxDipendente"></DayHoriz>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<DayHoriz IsTitle="true" StartHour="@startHour" EndHour="@endHour" ListFasi="@ListFasi" IdxDipSel="@IdxDipendente"></DayHoriz>
|
||||
</div>
|
||||
@if (ListRecords == null)
|
||||
{
|
||||
@for (int i = 0; i < 7; i++)
|
||||
{
|
||||
<div class="col-12 my-3">
|
||||
<div class="placeholder-glow">
|
||||
<span class="placeholder col-6 mb-1"></span>
|
||||
<span class="placeholder col-5 mb-1"></span>
|
||||
<span class="placeholder fs-1 col-6"></span>
|
||||
<span class="placeholder fs-1 col-5"></span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@foreach (var currItem in ListRecords)
|
||||
{
|
||||
<div class="col-12">
|
||||
<DayHoriz DayDTO="@currItem" StartHour="@startHour" EndHour="@endHour" ListFasi="@ListFasi" ItemSelected="ReportSelect" ItemUpdated="UpdRegAttData" IdxDipSel="@IdxDipendente" PeriodSelected="PeriodoSelect" ReqTempList="ShowTempRil" ReqDayAgenda="ShowDayAgenda"></DayHoriz>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer py-1">
|
||||
<div class="d-flex justify-content-between">
|
||||
@@ -125,9 +146,6 @@ else if (ListTimbr != null)
|
||||
<i class="fas fa-angle-double-right"></i>
|
||||
<input @bind="endHour" style="width: 3em;" type="number" />
|
||||
</div>
|
||||
<div class="py-1 px-2">
|
||||
<span>@lastRefresh.ToString("HH:mm:ss")</span> <i class="far fa-clock"></i>
|
||||
</div>
|
||||
<div class="py-1 px-2">
|
||||
@if (clonedRA != null)
|
||||
{
|
||||
@@ -144,12 +162,10 @@ else if (ListTimbr != null)
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="py-1 px-2">
|
||||
<small>last update: @lastRefresh.ToString("HH:mm:ss")</small> <i class="far fa-clock"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="my-4"> </div>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using GPW.CORE.Data.DTO;
|
||||
using GPW.CORE.WRKLOG.Data;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace GPW.CORE.WRKLOG.Pages
|
||||
{
|
||||
@@ -12,26 +13,35 @@ namespace GPW.CORE.WRKLOG.Pages
|
||||
///
|
||||
/// modale: vedere qui: https://gist.github.com/conficient/ba98d1662c659e170ec16650acea05c8
|
||||
/// </summary>
|
||||
//[Authorize(Roles = "SuperAdmin, Admin")]
|
||||
public partial class WeekPlan : IDisposable
|
||||
{
|
||||
#region Private Fields
|
||||
#region Public Properties
|
||||
|
||||
private int _endHour = 14;
|
||||
private int _startHour = 12;
|
||||
public RegAttivitaModel? clonedRA
|
||||
{
|
||||
get
|
||||
{
|
||||
return AppMServ.clonedRA;
|
||||
}
|
||||
set
|
||||
{
|
||||
AppMServ.clonedRA = value;
|
||||
}
|
||||
}
|
||||
|
||||
private RegAttivitaModel? currRecord = null;
|
||||
private DateTime DtSelected = DateTime.Today;
|
||||
private List<AnagFasiModel> ListFasi = new List<AnagFasiModel>();
|
||||
private List<DailyDataDTO>? ListRecords = null;
|
||||
private List<TimbratureModel>? ListTimbr = null;
|
||||
private DailyDataDTO? SelDayDTO = null;
|
||||
private bool selPeriod = false;
|
||||
private bool showDay = false;
|
||||
private bool showTemp = false;
|
||||
private List<WeekStatDTO>? weekStatList = null;
|
||||
#endregion Public Properties
|
||||
|
||||
#endregion Private Fields
|
||||
#region Public Methods
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
AppMServ.EA_SearchUpdated -= OnSearchUpdated;
|
||||
GDataServ.mPipeTimb.EA_NewMessage -= MPipeTimb_EA_NewMessage;
|
||||
GDataServ.mPipeRich.EA_NewMessage -= MPipeRich_EA_NewMessage;
|
||||
UITimer?.Dispose();
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#region Protected Fields
|
||||
|
||||
@@ -40,57 +50,12 @@ namespace GPW.CORE.WRKLOG.Pages
|
||||
/// <summary>
|
||||
/// Timer per refresh dati
|
||||
///
|
||||
/// https://stackoverflow.com/questions/63060065/blazor-timer-call-async-api-task-to-update-ui
|
||||
/// https://www.janduniec.blog/index.php/100/timers-in-blazor/
|
||||
/// https://stackoverflow.com/questions/63060065/blazor-timer-call-async-api-task-to-update-ui https://www.janduniec.blog/index.php/100/timers-in-blazor/
|
||||
/// </summary>
|
||||
protected System.Timers.Timer UITimer = new System.Timers.Timer();
|
||||
|
||||
#endregion Protected Fields
|
||||
|
||||
#region Private Properties
|
||||
|
||||
private int endHour
|
||||
{
|
||||
get => _endHour;
|
||||
set
|
||||
{
|
||||
// fix --> max 24...
|
||||
_endHour = value < 25 ? value : 24;
|
||||
}
|
||||
}
|
||||
|
||||
private bool isLoading { get; set; } = false;
|
||||
|
||||
private double periodoClonato
|
||||
{
|
||||
get
|
||||
{
|
||||
double answ = 8;
|
||||
// se ho record clonato --> uso quello
|
||||
if (clonedRA != null)
|
||||
{
|
||||
answ = clonedRA.Durata.TotalHours;
|
||||
}
|
||||
else
|
||||
{
|
||||
answ = endHour - startHour;
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
|
||||
private int startHour
|
||||
{
|
||||
get => _startHour;
|
||||
set
|
||||
{
|
||||
// fix --> MIN 0...
|
||||
_startHour = value > 0 ? value : 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#region Protected Properties
|
||||
|
||||
protected string actionCss
|
||||
@@ -134,7 +99,7 @@ namespace GPW.CORE.WRKLOG.Pages
|
||||
}
|
||||
|
||||
[Inject]
|
||||
protected GpwDataService DataService { get; set; } = null!;
|
||||
protected GpwDataService GDataServ { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Dipendente corrente
|
||||
@@ -172,158 +137,6 @@ namespace GPW.CORE.WRKLOG.Pages
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public RegAttivitaModel? clonedRA
|
||||
{
|
||||
get
|
||||
{
|
||||
return AppMServ.clonedRA;
|
||||
}
|
||||
set
|
||||
{
|
||||
AppMServ.clonedRA = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private void checkHourRange()
|
||||
{
|
||||
int minHour = 12;
|
||||
int maxHour = 14;
|
||||
int currStart = 12;
|
||||
int currEnd = 12;
|
||||
int roundMin = 30;
|
||||
//int extraEnd = 30;
|
||||
if (ListRecords != null)
|
||||
{
|
||||
// per ogni giornata
|
||||
foreach (var giornata in ListRecords)
|
||||
{
|
||||
if (giornata.ListTimbr != null)
|
||||
{
|
||||
var minRecTimb = giornata.ListTimbr
|
||||
.Where(x => x.Entrata == true)
|
||||
.OrderBy(x => x.DataOra)
|
||||
.FirstOrDefault();
|
||||
if (minRecTimb != null)
|
||||
{
|
||||
if (minHour > minRecTimb.DataOra.AddMinutes(roundMin / 3).Hour)
|
||||
{
|
||||
minHour = minRecTimb.DataOra.AddMinutes(roundMin / 3).Hour;
|
||||
}
|
||||
}
|
||||
var maxRecTimb = giornata.ListTimbr
|
||||
.Where(x => x.Entrata == false)
|
||||
.OrderByDescending(x => x.DataOra)
|
||||
.FirstOrDefault();
|
||||
if (maxRecTimb != null)
|
||||
{
|
||||
if (maxHour < maxRecTimb.DataOra.AddMinutes(-roundMin / 3).Hour)
|
||||
{
|
||||
maxHour = maxRecTimb.DataOra.AddMinutes(-roundMin / 3).Hour + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (giornata.ListRA != null)
|
||||
{
|
||||
var minRecRa = giornata.ListRA
|
||||
.OrderBy(x => x.Inizio)
|
||||
.FirstOrDefault();
|
||||
if (minRecRa != null)
|
||||
{
|
||||
// verifico se cambia giorno inizio/fine --> seleziono la mezzanotte
|
||||
currStart = minRecRa.Inizio.AddMinutes(-roundMin).Date.Equals(minRecRa.Fine.Date) ? minRecRa.Inizio.AddMinutes(-roundMin).Hour : 0;
|
||||
if (minHour > currStart)
|
||||
{
|
||||
minHour = currStart;
|
||||
}
|
||||
}
|
||||
var maxRecRa = giornata.ListRA
|
||||
.OrderByDescending(x => x.Fine)
|
||||
.FirstOrDefault();
|
||||
if (maxRecRa != null)
|
||||
{
|
||||
// verifico se cambia giorno inizio/fine --> seleziono la mezzanotte
|
||||
currEnd = maxRecRa.Inizio.Date.Equals(maxRecRa.Fine.AddMinutes(roundMin).Date) ? maxRecRa.Fine.AddMinutes(roundMin).Hour + 1 : 24;
|
||||
if (maxHour < currEnd)
|
||||
{
|
||||
maxHour = currEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
startHour = minHour;// - 1;
|
||||
checkOrarioDip();
|
||||
// minimo 6 h... x cui "allungo" verso fine
|
||||
if (maxHour - minHour < AppMServ.orarioDip)
|
||||
{
|
||||
minHour--;
|
||||
maxHour = minHour + AppMServ.orarioDip;
|
||||
}
|
||||
endHour = maxHour;// + 1;
|
||||
}
|
||||
|
||||
private void checkOrarioDip()
|
||||
{
|
||||
// calcolo minimo da cod orario dipendente
|
||||
if (AppMServ.orarioDip == 0)
|
||||
{
|
||||
AnagOrariModel? schemaOrario = null;
|
||||
// recupero da DB schema settimanale...
|
||||
var pUpd = Task.Run(async () =>
|
||||
{
|
||||
schemaOrario = await DataService.AnagOrarioByDip(AppMServ.IdxDipendente);
|
||||
});
|
||||
pUpd.Wait();
|
||||
if (schemaOrario != null)
|
||||
{
|
||||
AppMServ.orarioDip = (int)(Math.Ceiling(schemaOrario.oreOrdSett / 5));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reinit dei dati
|
||||
/// </summary>
|
||||
/// <param name="dateReset"></param>
|
||||
/// <returns></returns>
|
||||
private async Task InitData(bool dateReset)
|
||||
{
|
||||
isLoading = true;
|
||||
if (dateReset)
|
||||
{
|
||||
TargetDate = DateTime.Today;
|
||||
}
|
||||
weekStatList = await DataService.LastWeeks(IdxDipendente, TargetDate, 4);
|
||||
if (dateReset)
|
||||
{
|
||||
currWeekNum = weekStatList.Last().WeekNumber;
|
||||
}
|
||||
currYear = weekStatList.Last().Anno;
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
private async Task ReloadData()
|
||||
{
|
||||
isLoading = true;
|
||||
UITimer.Stop();
|
||||
ListRecords = await DataService.DailyDetails(IdxDipendente, currWeekSel.inizio, currWeekSel.fine);
|
||||
await Task.Delay(1);
|
||||
checkHourRange();
|
||||
await Task.Delay(1);
|
||||
lastRefresh = DateTime.Now;
|
||||
UITimer.Start();
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected async Task MoveWeek(int numWeek)
|
||||
@@ -354,6 +167,9 @@ namespace GPW.CORE.WRKLOG.Pages
|
||||
};
|
||||
UITimer.Elapsed += async (s, ea) => await TryReload();
|
||||
AppMServ.EA_SearchUpdated += OnSearchUpdated;
|
||||
// aggiungo gestione notifica messaggi timbrature...
|
||||
GDataServ.mPipeTimb.EA_NewMessage += MPipeTimb_EA_NewMessage;
|
||||
GDataServ.mPipeRich.EA_NewMessage += MPipeRich_EA_NewMessage;
|
||||
}
|
||||
|
||||
protected void OnSearchUpdated()
|
||||
@@ -362,9 +178,6 @@ namespace GPW.CORE.WRKLOG.Pages
|
||||
pUpd.Wait();
|
||||
}
|
||||
|
||||
#if false
|
||||
//protected void PeriodoSelect(List<TimbratureModel> newList)
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Indico item selezionato
|
||||
/// </summary>
|
||||
@@ -539,13 +352,230 @@ namespace GPW.CORE.WRKLOG.Pages
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Public Methods
|
||||
#region Private Fields
|
||||
|
||||
public void Dispose()
|
||||
private int _endHour = 18;
|
||||
|
||||
private int _startHour = 8;
|
||||
|
||||
private RegAttivitaModel? currRecord = null;
|
||||
|
||||
private DateTime DtSelected = DateTime.Today;
|
||||
|
||||
private List<AnagFasiModel> ListFasi = new List<AnagFasiModel>();
|
||||
|
||||
private List<DailyDataDTO>? ListRecords = null;
|
||||
|
||||
private List<TimbratureModel>? ListTimbr = null;
|
||||
|
||||
private DailyDataDTO? SelDayDTO = null;
|
||||
|
||||
private bool selPeriod = false;
|
||||
|
||||
private bool showDay = false;
|
||||
|
||||
private bool showTemp = false;
|
||||
|
||||
private List<WeekStatDTO>? weekStatList = null;
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Private Properties
|
||||
|
||||
private int endHour
|
||||
{
|
||||
UITimer?.Dispose();
|
||||
get => _endHour;
|
||||
set
|
||||
{
|
||||
// fix --> max 24...
|
||||
_endHour = value < 25 ? value : 24;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
private bool isLoading { get; set; } = false;
|
||||
|
||||
private double periodoClonato
|
||||
{
|
||||
get
|
||||
{
|
||||
double answ = 8;
|
||||
// se ho record clonato --> uso quello
|
||||
if (clonedRA != null)
|
||||
{
|
||||
answ = clonedRA.Durata.TotalHours;
|
||||
}
|
||||
else
|
||||
{
|
||||
answ = endHour - startHour;
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
|
||||
private int startHour
|
||||
{
|
||||
get => _startHour;
|
||||
set
|
||||
{
|
||||
// fix --> MIN 0...
|
||||
_startHour = value > 0 ? value : 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private void checkHourRange()
|
||||
{
|
||||
int minHour = 12;
|
||||
int maxHour = 14;
|
||||
int currStart = 12;
|
||||
int currEnd = 12;
|
||||
int roundMin = 30;
|
||||
//int extraEnd = 30;
|
||||
if (ListRecords != null)
|
||||
{
|
||||
// per ogni giornata
|
||||
foreach (var giornata in ListRecords)
|
||||
{
|
||||
if (giornata.ListTimbr != null)
|
||||
{
|
||||
var minRecTimb = giornata.ListTimbr
|
||||
.Where(x => x.Entrata == true)
|
||||
.OrderBy(x => x.DataOra)
|
||||
.FirstOrDefault();
|
||||
if (minRecTimb != null)
|
||||
{
|
||||
if (minHour > minRecTimb.DataOra.AddMinutes(roundMin / 3).Hour)
|
||||
{
|
||||
minHour = minRecTimb.DataOra.AddMinutes(roundMin / 3).Hour;
|
||||
}
|
||||
}
|
||||
var maxRecTimb = giornata.ListTimbr
|
||||
.Where(x => x.Entrata == false)
|
||||
.OrderByDescending(x => x.DataOra)
|
||||
.FirstOrDefault();
|
||||
if (maxRecTimb != null)
|
||||
{
|
||||
if (maxHour < maxRecTimb.DataOra.AddMinutes(-roundMin / 3).Hour)
|
||||
{
|
||||
maxHour = maxRecTimb.DataOra.AddMinutes(-roundMin / 3).Hour + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (giornata.ListRA != null)
|
||||
{
|
||||
var minRecRa = giornata.ListRA
|
||||
.OrderBy(x => x.Inizio)
|
||||
.FirstOrDefault();
|
||||
if (minRecRa != null)
|
||||
{
|
||||
// verifico se cambia giorno inizio/fine --> seleziono la mezzanotte
|
||||
currStart = minRecRa.Inizio.AddMinutes(-roundMin).Date.Equals(minRecRa.Fine.Date) ? minRecRa.Inizio.AddMinutes(-roundMin).Hour : 0;
|
||||
if (minHour > currStart)
|
||||
{
|
||||
minHour = currStart;
|
||||
}
|
||||
}
|
||||
var maxRecRa = giornata.ListRA
|
||||
.OrderByDescending(x => x.Fine)
|
||||
.FirstOrDefault();
|
||||
if (maxRecRa != null)
|
||||
{
|
||||
// verifico se cambia giorno inizio/fine --> seleziono la mezzanotte
|
||||
currEnd = maxRecRa.Inizio.Date.Equals(maxRecRa.Fine.AddMinutes(roundMin).Date) ? maxRecRa.Fine.AddMinutes(roundMin).Hour + 1 : 24;
|
||||
if (maxHour < currEnd)
|
||||
{
|
||||
maxHour = currEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
startHour = minHour;// - 1;
|
||||
checkOrarioDip();
|
||||
// minimo 6 h... x cui "allungo" verso fine
|
||||
if (maxHour - minHour < AppMServ.orarioDip)
|
||||
{
|
||||
minHour--;
|
||||
maxHour = minHour + AppMServ.orarioDip;
|
||||
}
|
||||
endHour = maxHour;// + 1;
|
||||
}
|
||||
|
||||
private void checkOrarioDip()
|
||||
{
|
||||
// calcolo minimo da cod orario dipendente
|
||||
if (AppMServ.orarioDip == 0)
|
||||
{
|
||||
AnagOrariModel? schemaOrario = null;
|
||||
// recupero da DB schema settimanale...
|
||||
var pUpd = Task.Run(async () =>
|
||||
{
|
||||
schemaOrario = await GDataServ.AnagOrarioByDip(AppMServ.IdxDipendente);
|
||||
});
|
||||
pUpd.Wait();
|
||||
if (schemaOrario != null)
|
||||
{
|
||||
AppMServ.orarioDip = (int)(Math.Ceiling(schemaOrario.oreOrdSett / 5));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ForceReload()
|
||||
{
|
||||
await GDataServ.FlushRedisCache();
|
||||
await InitData(false);
|
||||
await TryReload();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reinit dei dati
|
||||
/// </summary>
|
||||
/// <param name="dateReset"></param>
|
||||
/// <returns></returns>
|
||||
private async Task InitData(bool dateReset)
|
||||
{
|
||||
isLoading = true;
|
||||
if (dateReset)
|
||||
{
|
||||
TargetDate = DateTime.Today;
|
||||
}
|
||||
weekStatList = await GDataServ.LastWeeks(IdxDipendente, TargetDate, 4);
|
||||
if (dateReset)
|
||||
{
|
||||
currWeekNum = weekStatList.Last().WeekNumber;
|
||||
}
|
||||
currYear = weekStatList.Last().Anno;
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
private async void MPipeRich_EA_NewMessage(object? sender, EventArgs e)
|
||||
{
|
||||
await ForceReload();
|
||||
}
|
||||
|
||||
private async void MPipeTimb_EA_NewMessage(object? sender, EventArgs e)
|
||||
{
|
||||
await ForceReload();
|
||||
}
|
||||
|
||||
private async Task ReloadData()
|
||||
{
|
||||
isLoading = true;
|
||||
UITimer.Stop();
|
||||
ListRecords = await GDataServ.DailyDetails(IdxDipendente, currWeekSel.inizio, currWeekSel.fine);
|
||||
await Task.Delay(1);
|
||||
checkHourRange();
|
||||
await Task.Delay(1);
|
||||
lastRefresh = DateTime.Now;
|
||||
UITimer.Start();
|
||||
isLoading = false;
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
|
||||
}
|
||||
}
|
||||
@@ -29,32 +29,50 @@
|
||||
<a class="dismiss">🗙</a>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="_framework/blazor.server.js" autostart="false"></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({
|
||||
reconnectionOptions: {
|
||||
maxRetries: 300,
|
||||
retryIntervalMilliseconds: 2000
|
||||
maxRetries: 3600,
|
||||
retryIntervalMilliseconds: 1000
|
||||
},
|
||||
}).then(() => {
|
||||
Blazor.defaultReconnectionHandler._reconnectCallback = function (d) {
|
||||
console.log("Client reconnected, waiting 5 sec and reload!");
|
||||
setTimeout(function () {
|
||||
document.location.reload();
|
||||
}, 2000);
|
||||
}
|
||||
});
|
||||
</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({
|
||||
reconnectionOptions: {
|
||||
maxRetries: 1500,
|
||||
retryIntervalMilliseconds: 4000
|
||||
},
|
||||
reconnectionHandler: {
|
||||
onConnectionDown: (options, error) => console.error(error),
|
||||
onConnectionUp: () => console.log("Connection up!,restarting!")
|
||||
}
|
||||
}).then(() => {
|
||||
Object.defineProperty(Blazor.defaultReconnectionHandler, '_reconnectionDisplay', {
|
||||
get() {
|
||||
return this.__reconnectionDisplay;
|
||||
},
|
||||
set(value) {
|
||||
this.__reconnectionDisplay = {
|
||||
show: () => value.show(),
|
||||
update: (d) => value.update(d),
|
||||
rejected: (d) => document.location.reload()
|
||||
}
|
||||
Object.defineProperty(Blazor.defaultReconnectionHandler, '_reconnectionDisplay', {
|
||||
get() {
|
||||
return this.__reconnectionDisplay;
|
||||
},
|
||||
set(value) {
|
||||
this.__reconnectionDisplay = {
|
||||
show: () => value.show(),
|
||||
update: (d) => value.update(d),
|
||||
rejected: (d) => document.location.reload()
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@*Gestione ricollegamento successivo: https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/signalr?view=aspnetcore-6.0*@
|
||||
<script>Blazor.defaultReconnectionHandler._reconnectCallback = function (d) { document.location.reload(); }</script>
|
||||
});
|
||||
</script> *@
|
||||
|
||||
<script src="lib/Chart.js/chart.js"></script>
|
||||
<script src="lib/luxon/luxon.js"></script>
|
||||
<script src="lib/chartjs-adapter-luxon/chartjs-adapter-luxon.js"></script>
|
||||
|
||||
@@ -7,18 +7,37 @@
|
||||
@inject AuthenticationStateProvider AuthenticationStateProvider
|
||||
|
||||
<AuthorizeView>
|
||||
<div class="d-flex">
|
||||
<div class="px-1"><b>@userName</b></div>
|
||||
<div class="d-flex justify-content-between w-100">
|
||||
<div class="px-1">
|
||||
<button class="btn btn-sm btn-outline-dark" @onclick="() => DoReloadUtente()">
|
||||
<i class="fas fa-user @cssActive" title="Attivazione Utente"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="px-1">
|
||||
<button class="btn btn-sm btn-outline-dark" @onclick="() => DoVerifyActiv()">
|
||||
<i class="fas fa-address-card @cssLicOk" title="Licenza assegnata"></i>
|
||||
</button>
|
||||
<div class="d-flex">
|
||||
<div class="px-1"><b>@userName</b></div>
|
||||
<div class="px-1">
|
||||
<button class="btn btn-sm btn-outline-dark" @onclick="() => DoReloadUtente()">
|
||||
<i class="fas fa-user @cssActive" title="Attivazione Utente"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="px-1">
|
||||
<button class="btn btn-sm btn-outline-dark" @onclick="() => DoVerifyActiv()">
|
||||
<i class="fas fa-address-card @cssLicOk" title="Licenza assegnata"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@if (isAdmin)
|
||||
{
|
||||
<div class="px-1">
|
||||
<NavLink class="btn btn-info btn-sm mb-0 py-1" href="Presenze">
|
||||
@if (!string.IsNullOrEmpty(lblDisplay))
|
||||
{
|
||||
@lblDisplay
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>Presenti: @numPres di @numTot</span>
|
||||
}
|
||||
</NavLink>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</AuthorizeView>
|
||||
|
||||
|
||||
@@ -1,13 +1,30 @@
|
||||
using GPW.CORE.Data;
|
||||
using GPW.CORE.Data.DbModels;
|
||||
using GPW.CORE.WRKLOG.Data;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using Microsoft.AspNetCore.Components.Routing;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace GPW.CORE.WRKLOG.Shared
|
||||
{
|
||||
public partial class LoginDisplay
|
||||
public partial class LoginDisplay : IDisposable
|
||||
{
|
||||
#region Public Methods
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GDataServ.mPipeTimb.EA_NewMessage -= MPipeTimb_EA_NewMessage;
|
||||
GDataServ.mPipeRich.EA_NewMessage -= MPipeRich_EA_NewMessage;
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#region Protected Properties
|
||||
|
||||
[Inject]
|
||||
protected IConfiguration config { get; set; } = null!;
|
||||
|
||||
protected string cssActive { get => AppMServ.IsActive ? "text-success" : "text-danger"; }
|
||||
|
||||
protected string cssLicOk { get => AppMServ.PayloadOk ? "text-success" : "text-danger"; }
|
||||
@@ -111,13 +128,13 @@ namespace GPW.CORE.WRKLOG.Shared
|
||||
{
|
||||
userName = $"{user.Identity.Name}";
|
||||
// cerco su DB
|
||||
var listaDip = await GDataServ.DipendentiGetAll();
|
||||
DipendentiModel? rigaDip = listaDip.Where(x => $"{x.Dominio.Trim()}\\{x.Utente.Trim()}".ToLower() == userName.Trim().ToLower()).FirstOrDefault();
|
||||
DipendentiModel? rigaDip = ListaDip.Where(x => $"{x.Dominio.Trim()}\\{x.Utente.Trim()}".ToLower() == userName.Trim().ToLower()).FirstOrDefault();
|
||||
if (rigaDip != null)
|
||||
{
|
||||
// salvo riga info dipendente
|
||||
AppMServ.RigaDip = rigaDip;
|
||||
userName = $"{rigaDip.Cognome} {rigaDip.Nome}";
|
||||
idxDipendente = rigaDip.IdxDipendente;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -128,6 +145,13 @@ namespace GPW.CORE.WRKLOG.Shared
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
// aggiungo gestione notifica messaggi timbrature...
|
||||
GDataServ.mPipeTimb.EA_NewMessage += MPipeTimb_EA_NewMessage;
|
||||
GDataServ.mPipeRich.EA_NewMessage += MPipeRich_EA_NewMessage;
|
||||
// leggo lista dip
|
||||
ListaDip = await GDataServ.DipendentiGetAll();
|
||||
numTot = ListaDip.Count(x => x.Attivo == true);
|
||||
|
||||
//effettuo eventuale recupero dati dipendente
|
||||
if (AppMServ.RigaDip == null)
|
||||
{
|
||||
@@ -136,6 +160,9 @@ namespace GPW.CORE.WRKLOG.Shared
|
||||
|
||||
// verifica attivazione
|
||||
await VerifyActiv();
|
||||
|
||||
// verifica rpesenza personale
|
||||
await VerifPresenze(false);
|
||||
}
|
||||
|
||||
protected async Task VerifyActiv()
|
||||
@@ -146,21 +173,126 @@ namespace GPW.CORE.WRKLOG.Shared
|
||||
await checkActivations();
|
||||
// verifico e salvo dati attivazione dipendente...
|
||||
await checkUserLicense();
|
||||
|
||||
// verifica admin
|
||||
checkAdmin();
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private int idxDipendente = 0;
|
||||
|
||||
private bool isAdmin = false;
|
||||
|
||||
private List<DipendentiModel> ListaDip = new List<DipendentiModel>();
|
||||
|
||||
private List<StatsDayPresModel> ListaPres = new List<StatsDayPresModel>();
|
||||
|
||||
private List<string> ListIdxAdmin = new List<string>();
|
||||
|
||||
private int numPres = 0;
|
||||
|
||||
private int numTot = 0;
|
||||
|
||||
private string userName = "";
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Private Properties
|
||||
|
||||
private string lblDisplay { get; set; } = "";
|
||||
|
||||
[Inject]
|
||||
private NavigationManager NavManager { get; set; } = null!;
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private void checkAdmin()
|
||||
{
|
||||
// leggo elenco admin
|
||||
string rawData = config.GetValue<string>("ServerConf:AdmList");
|
||||
if (!string.IsNullOrEmpty(rawData))
|
||||
{
|
||||
ListIdxAdmin = rawData.Split(',').ToList();
|
||||
}
|
||||
isAdmin = ListIdxAdmin.Contains($"{idxDipendente}");
|
||||
}
|
||||
|
||||
private async void MPipeRich_EA_NewMessage(object? sender, EventArgs e)
|
||||
{
|
||||
await processMessage(e);
|
||||
}
|
||||
|
||||
private async void MPipeTimb_EA_NewMessage(object? sender, EventArgs e)
|
||||
{
|
||||
await processMessage(e);
|
||||
}
|
||||
|
||||
private async Task processMessage(EventArgs e)
|
||||
{
|
||||
PubSubEventArgs currArgs = (PubSubEventArgs)e;
|
||||
// conversione on-the-fly List<string> --> allarmi
|
||||
if (!string.IsNullOrEmpty(currArgs.newMessage))
|
||||
{
|
||||
try
|
||||
{
|
||||
TimbratureModel? timbData = JsonConvert.DeserializeObject<TimbratureModel>(currArgs.newMessage);
|
||||
if (timbData != null)
|
||||
{
|
||||
// solo se admin
|
||||
if (isAdmin)
|
||||
{
|
||||
updateDisplay(timbData);
|
||||
await InvokeAsync(StateHasChanged);
|
||||
await ResetMessage(6);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Chiama reset messaggio dopo un periodo di sec richiesto...
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task ResetMessage(int numSec)
|
||||
{
|
||||
// chiudo visualizzazione stato update
|
||||
await Task.Delay(numSec * 1000);
|
||||
lblDisplay = "";
|
||||
await VerifPresenze(true);
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private void updateDisplay(TimbratureModel timbData)
|
||||
{
|
||||
string tipo = timbData.Entrata ?? true ? "IN" : "OUT";
|
||||
string dipData = $"Dip: {timbData.IdxDipendente}";
|
||||
//cerco dip...
|
||||
var currDip = ListaDip.Find(x => x.IdxDipendente == timbData.IdxDipendente);
|
||||
if (currDip != null)
|
||||
{
|
||||
dipData = $"{currDip.Cognome} {currDip.Nome} ({timbData.IdxDipendente})";
|
||||
}
|
||||
lblDisplay = $"{tipo} | {dipData} | {timbData.DataOra:HH:mm:ss}";
|
||||
}
|
||||
|
||||
private async Task VerifPresenze(bool resetCache)
|
||||
{
|
||||
if (resetCache)
|
||||
{
|
||||
await GDataServ.FlushRedisCache();
|
||||
}
|
||||
ListaPres = await GDataServ.PresenzeDay(DateTime.Now);
|
||||
numPres = ListaPres.Sum(x => x.IsPresent);
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
||||
@@ -1,85 +1,74 @@
|
||||
.page {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.page {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.sidebar,
|
||||
.sidebarSmall {
|
||||
background-image: linear-gradient(180deg, rgb(5, 39, 103) 20%, #3aa6ff 90%);
|
||||
background-image: linear-gradient(180deg, #052767 20%, #3aa6ff 90%);
|
||||
}
|
||||
|
||||
.top-row {
|
||||
background-color: #f7f7f7;
|
||||
border-bottom: 1px solid #d6d5d5;
|
||||
justify-content: flex-end;
|
||||
height: 3.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #f7f7f7;
|
||||
border-bottom: 1px solid #d6d5d5;
|
||||
/*justify-content: flex-end;*/
|
||||
height: 3.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.top-row ::deep a,
|
||||
.top-row .btn-link {
|
||||
white-space: nowrap;
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
.top-row a:first-child {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.top-row ::deep a, .top-row .btn-link {
|
||||
white-space: nowrap;
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
|
||||
.top-row a:first-child {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.bottom-row {
|
||||
color: #dedede;
|
||||
background-color: #000000;
|
||||
height: 2rem;
|
||||
align-items: center;
|
||||
color: #dedede;
|
||||
background-color: #000000;
|
||||
height: 2rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@media (max-width: 640.98px) {
|
||||
.top-row:not(.auth) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.top-row.auth {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.top-row a, .top-row .btn-link {
|
||||
margin-left: 0;
|
||||
}
|
||||
.top-row:not(.auth) {
|
||||
display: none;
|
||||
}
|
||||
.top-row.auth {
|
||||
justify-content: space-between;
|
||||
}
|
||||
.top-row a,
|
||||
.top-row .btn-link {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 641px) {
|
||||
.page {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 13.5rem;
|
||||
height: 100vh;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.sidebarSmall {
|
||||
width: 4.5rem;
|
||||
height: 100vh;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.top-row {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.top-row, article {
|
||||
padding-left: 0.5rem !important;
|
||||
padding-right: 0.5rem !important;
|
||||
}
|
||||
}
|
||||
.page {
|
||||
flex-direction: row;
|
||||
}
|
||||
.sidebar {
|
||||
width: 13.5rem;
|
||||
height: 100vh;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
.sidebarSmall {
|
||||
width: 4.5rem;
|
||||
height: 100vh;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
.top-row {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
.top-row,
|
||||
article {
|
||||
padding-left: 0.5rem !important;
|
||||
padding-right: 0.5rem !important;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
.page {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.sidebar,
|
||||
.sidebarSmall {
|
||||
background-image: linear-gradient(180deg, rgb(5, 39, 103) 20%, #3aa6ff 90%);
|
||||
}
|
||||
|
||||
.top-row {
|
||||
background-color: #f7f7f7;
|
||||
border-bottom: 1px solid #d6d5d5;
|
||||
/*justify-content: flex-end;*/
|
||||
height: 3.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.top-row ::deep a, .top-row .btn-link {
|
||||
white-space: nowrap;
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
|
||||
.top-row a:first-child {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.bottom-row {
|
||||
color: #dedede;
|
||||
background-color: #000000;
|
||||
height: 2rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@media (max-width: 640.98px) {
|
||||
.top-row:not(.auth) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.top-row.auth {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.top-row a, .top-row .btn-link {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 641px) {
|
||||
.page {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 13.5rem;
|
||||
height: 100vh;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.sidebarSmall {
|
||||
width: 4.5rem;
|
||||
height: 100vh;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.top-row {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.top-row, article {
|
||||
padding-left: 0.5rem !important;
|
||||
padding-right: 0.5rem !important;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
.page{position:relative;display:flex;flex-direction:column;}main{flex:1;}.sidebar,.sidebarSmall{background-image:linear-gradient(180deg,#052767 20%,#3aa6ff 90%);}.top-row{background-color:#f7f7f7;border-bottom:1px solid #d6d5d5;height:3.5rem;display:flex;align-items:center;}.top-row ::deep a,.top-row .btn-link{white-space:nowrap;margin-left:1.5rem;}.top-row a:first-child{overflow:hidden;text-overflow:ellipsis;}.bottom-row{color:#dedede;background-color:#000;height:2rem;align-items:center;}@media(max-width:640.98px){.top-row:not(.auth){display:none;}.top-row.auth{justify-content:space-between;}.top-row a,.top-row .btn-link{margin-left:0;}}@media(min-width:641px){.page{flex-direction:row;}.sidebar{width:13.5rem;height:100vh;position:sticky;top:0;}.sidebarSmall{width:4.5rem;height:100vh;position:sticky;top:0;}.top-row{position:sticky;top:0;z-index:1;}.top-row,article{padding-left:.5rem!important;padding-right:.5rem!important;}}
|
||||
@@ -28,6 +28,9 @@
|
||||
"InfoMal": "samuele.locatelli@egalware.com",
|
||||
"InfoRich": "samuele.locatelli@egalware.com"
|
||||
},
|
||||
"ServerConf": {
|
||||
"AdmList": "1,6"
|
||||
},
|
||||
"AdmApp": {
|
||||
"LinkMal": "https://office.egalware.com/GPW/ADMIN/malattia",
|
||||
"LinkRich": "https://office.egalware.com/GPW/ADMIN/richiesteDip"
|
||||
|
||||
@@ -10,5 +10,13 @@
|
||||
{
|
||||
"outputFile": "wwwroot/css/BlazorCal.css",
|
||||
"inputFile": "wwwroot/css/BlazorCal.less"
|
||||
},
|
||||
{
|
||||
"outputFile": "Shared/MainLayout.razor.css",
|
||||
"inputFile": "Shared/MainLayout.razor.less"
|
||||
},
|
||||
{
|
||||
"outputFile": "Pages/Presenze.razor.css",
|
||||
"inputFile": "Pages/Presenze.razor.less"
|
||||
}
|
||||
]
|
||||
@@ -1,6 +1,6 @@
|
||||
<body>
|
||||
<i>GPW - Gestione Presenze Web</i>
|
||||
<h4>Versione: 3.0.2312.0708</h4>
|
||||
<h4>Versione: 3.0.2403.0715</h4>
|
||||
<br /> Note di rilascio:
|
||||
<ul>
|
||||
<li>
|
||||
|
||||
@@ -1 +1 @@
|
||||
3.0.2312.0708
|
||||
3.0.2403.0715
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<item>
|
||||
<version>3.0.2312.0708</version>
|
||||
<url>http://nexus.steamware.net/repository/SWS/GPW/stable/GPW.Smart.zip</url>
|
||||
<version>3.0.2403.0715</version>
|
||||
<url>http://nexus.steamware.net/repository/SWS/GPW/stable/GPW.UI.zip</url>
|
||||
<changelog>http://nexus.steamware.net/repository/SWS/GPW/stable/ChangeLog.html</changelog>
|
||||
<mandatory>false</mandatory>
|
||||
</item>
|
||||
|
||||
Reference in New Issue
Block a user