Compare commits

...

79 Commits

Author SHA1 Message Date
Samuele Locatelli 871a0c8ca5 Merge branch 'release/MonCleanup' 2022-07-12 19:05:53 +02:00
Samuele Locatelli 78cb17d8fc Cleanup MP/MON 2022-07-12 19:05:30 +02:00
Samuele Locatelli 22ff799204 Merge tag 'MonWithRedisChannels' into develop
Gestioen con redis channels (da ripulire...)
2022-07-12 18:45:32 +02:00
Samuele Locatelli a26408a21c Merge branch 'release/MonWithRedisChannels' 2022-07-12 18:45:18 +02:00
Samuele Locatelli ee043f81be Update MON:
- gestione tramite REDIS CHANNEL
- refresh sincrono
2022-07-12 18:44:57 +02:00
Samuele Locatelli 97741b4973 refresh libs 2022-07-12 18:44:35 +02:00
Samuele Locatelli 544c977740 Merge tag 'UpdateMonStandard' into develop
Update comportamento monitor standard
2022-07-12 17:10:37 +02:00
Samuele Locatelli dc38127291 Merge branch 'release/UpdateMonStandard' 2022-07-12 17:10:23 +02:00
Samuele Locatelli 8e7bdf2b77 Refresh bootstrap libs 2022-07-12 17:09:53 +02:00
Samuele Locatelli 7e922555b1 refresh MON principale 2022-07-12 17:08:48 +02:00
Samuele Locatelli acbbd5c9e6 Cambio metodi DB : asNoTracking 2022-07-12 17:08:19 +02:00
Samuele Locatelli 77f06c465e Update metodi WASM Server 2022-07-12 17:07:56 +02:00
Samuele Locatelli 4bfba522ce Complto review WASM client 2022-07-12 17:07:44 +02:00
Samuele Locatelli cbbdc8e8d8 Fix blink WASM client 2022-07-12 17:07:10 +02:00
Samuele Locatelli e8e3d63d09 Implementato dispose classe server 2022-07-11 18:46:53 +02:00
Samuele E. Locatelli 9dc73936da ancora pub profiles 2022-07-09 18:26:21 +02:00
Samuele E. Locatelli a2afeab317 refresh publish profiles 2022-07-09 18:26:15 +02:00
Samuele E. Locatelli 2c62abdf73 ancora refresh yaml e versione WASM 2022-07-09 18:21:04 +02:00
Samuele E. Locatelli d17cb03c7b Setup pubblicazione sito + test yaml (da validare) 2022-07-09 18:20:55 +02:00
Samuele Locatelli c749f10a8a UPdate MON da provare 2022-07-09 13:13:12 +02:00
Samuele Locatelli f2973cb0be Update refresh sincronizzato 2022-07-09 10:30:08 +02:00
Samuele Locatelli 8f2afd8ab5 MON Server / WASM
- fine tuning cache
- test velocità recupero dati
2022-07-09 09:53:21 +02:00
Samuele Locatelli 1d46b75608 Merge branch 'Feature/WASM' into develop 2022-07-08 19:53:00 +02:00
Samuele Locatelli 7c28833874 Update con cache REDIS x non chiamare sempre DB 2022-07-08 19:52:50 +02:00
Samuele Locatelli 1a019f1c72 refresh WASM 2022-07-08 19:51:24 +02:00
Samuele Locatelli cae553c47f Update progetto WASM con inclusione index page 2022-07-08 18:49:32 +02:00
Samuele Locatelli 7634fc42ba Bozza riscrittura WASM applicazione MON 2022-07-08 17:27:08 +02:00
Samuele Locatelli c24935afce WASM
- aggiunta preliminare progetto Web Assembly
2022-07-08 17:05:53 +02:00
Samuele Locatelli 2c4ce635c0 Merge tag 'FixPrerenderMonAndStressTest' into develop
Fix stress test e server prerender
2022-07-08 10:01:41 +02:00
Samuele Locatelli a4b01773ea Merge branch 'release/FixPrerenderMonAndStressTest' 2022-07-08 10:01:33 +02:00
Samuele Locatelli b076148e65 MON:
- Update con log esteso
- evitato server prerender x raddoppio pagina
- test stress (disabilitato)
2022-07-08 10:01:03 +02:00
Samuele Locatelli 02369f87f7 Merge tag 'UpgradeMapoCoreAll' into develop
Upgrade all MAPO-CORE
2022-07-07 18:58:43 +02:00
Samuele Locatelli 4b04feedff Merge branch 'release/UpgradeMapoCoreAll' 2022-07-07 18:58:34 +02:00
Samuele Locatelli e99def8664 Update LAND x refresh pagina 2022-07-07 18:57:34 +02:00
Samuele Locatelli a8744cfc56 Refresh STATS
- page reload
- Nuget upgrade
2022-07-07 18:52:53 +02:00
Samuele Locatelli 03761b81ec Merge tag 'UpgradeMapoMon' into develop
Update mapo MON x verificare reboot da Jetco
2022-07-07 18:49:28 +02:00
Samuele Locatelli dd4f403b7a Merge branch 'release/UpgradeMapoMon' 2022-07-07 18:49:16 +02:00
Samuele Locatelli c7d1ca046c Update/refresh MON:
- cambio logica reload blazor x MON
- update nuget vari
- rimozione warnings
2022-07-07 18:48:33 +02:00
Samuele Locatelli 2c3494f9f0 Merge tag 'UpdateAboutColorCheck' into develop
Update comportamento colori x About page e check licenze
2022-07-06 13:31:10 +02:00
Samuele Locatelli 7dc0aef175 Merge branch 'release/UpdateAboutColorCheck' 2022-07-06 13:30:49 +02:00
Samuele Locatelli e2afe6a586 Update display a + colori x check licenze 2022-07-06 13:30:22 +02:00
Samuele Locatelli e3ed9a7f35 Merge tag 'FixAboutPageError' into develop
Sistemato About page e suo errore x licenze cannate
2022-07-06 10:11:29 +02:00
Samuele Locatelli db003d2bc3 Merge branch 'release/FixAboutPageError' 2022-07-06 10:11:16 +02:00
Samuele Locatelli c203ab6eb3 Fix comportamento pagina About x check licenze 2022-07-06 10:10:50 +02:00
Samuele Locatelli c10633b6f1 Merge branch 'develop' 2022-07-05 10:00:30 +02:00
Samuele Locatelli a9fd0e2f83 Ancora fix sel reparto 2022-07-05 10:00:21 +02:00
Samuele Locatelli 112c73aea1 Merge tag 'FixSelReprtoAndSelEnabled' into develop
Fix: esclusi i gruppi con sel enabled se NON fossero tipo REPARTO
2022-07-05 09:57:19 +02:00
Samuele Locatelli 9e8e885ef9 Merge branch 'release/FixSelReprtoAndSelEnabled' 2022-07-05 09:56:59 +02:00
Samuele Locatelli 1f964ded92 Fix selezione gruppi
- prende SOLO reparto
- escluso gruppi con selEnabled
2022-07-05 09:56:28 +02:00
Samuele Locatelli eeba41cb5c Merge tag 'FixQrCodeJsConsoleLog' into develop
Eliminato console log inutile
2022-07-04 19:14:20 +02:00
Samuele Locatelli c418812ba2 Merge branch 'release/FixQrCodeJsConsoleLog' 2022-07-04 19:14:10 +02:00
Samuele Locatelli 6169d8cfcc Correzione jscript: niente console log 2022-07-04 19:13:28 +02:00
Samuele Locatelli 75596c61bc Merge tag 'FixQrUserDisplay' into develop
Fix comportamento display QrCode user
2022-07-04 19:12:39 +02:00
Samuele Locatelli b51e164c18 Merge branch 'release/FixQrUserDisplay' 2022-07-04 19:12:24 +02:00
Samuele Locatelli c35d625c36 Gestioen QRCode filt
- completata correzione selezione con distinct
- fix join come richeista Gian
2022-07-04 19:11:55 +02:00
Samuele Locatelli c893ce4d44 refresh pagina QR Card utenti 2022-07-04 18:48:58 +02:00
Samuele Locatelli c47fb1787c Aggiunta helper js x qrcode 2022-07-04 18:48:48 +02:00
Samuele Locatelli aca61c24dc Filtro gruppi:
- add componente filtro gruppi
- add meccanismo mesageService
2022-07-04 18:48:37 +02:00
Samuele Locatelli 167c9d89d4 Aggiunto modelli accesso dati x filtro QRCode utenti 2022-07-04 18:48:03 +02:00
Samuele Locatelli 2295f12958 Merge tag 'UpdateDisplayMonOverride' into develop
Update x MONitor: gestione override info x parameti FLog
2022-06-06 16:45:43 +02:00
Samuele Locatelli 9762628abc Merge branch 'release/UpdateDisplayMonOverride' 2022-06-06 16:45:23 +02:00
Samuele Locatelli a7918e1a89 Update con gestione override display da conf JSon 2022-06-06 16:42:49 +02:00
Samuele E. Locatelli 7a8e05462c Da testare: metodi redis da mostrare 2022-06-04 18:09:29 +02:00
Samuele E. Locatelli aaeae6e99e Riorganizzazione classe con CodeMaid 2022-06-04 17:44:37 +02:00
Samuele E. Locatelli 533f3f4f8f Update: spostao da DTO a conf la parte setup IOB + metodi ad avvio class MpDataService 2022-06-04 17:42:03 +02:00
Samuele E. Locatelli 5135987f1b Inizio update x gestione override dati in MON 2022-06-03 19:01:00 +02:00
Samuele Locatelli 458d788a13 Merge tag 'FixDownloadCsvOnDataPager' into develop
Fix gestione download csv da datapager (sparito in refactoring...)
2022-05-23 11:11:51 +02:00
Samuele Locatelli e842228baf Merge branch 'release/FixDownloadCsvOnDataPager' 2022-05-23 11:11:27 +02:00
Samuele Locatelli 25d2ada96e Fix errore eliminazione download csv da datapager 2022-05-23 11:10:04 +02:00
Samuele Locatelli f22933f925 Merge branch 'develop' 2022-05-03 14:49:30 +02:00
Samuele Locatelli 009b5f6452 Update x nuovo installer MON da testare 2022-05-03 14:49:22 +02:00
Samuele Locatelli 94c72b7e11 Merge tag 'FixSetupCssSemaforoAssente' into develop
Correzione mON nuovo: se manca colore semaforo x una macchina si pianta
--> metto nero (tipicamente al setup)
2022-05-02 19:06:09 +02:00
Samuele Locatelli 11a1925660 Merge branch 'release/FixSetupCssSemaforoAssente' 2022-05-02 19:05:10 +02:00
Samuele Locatelli 6ce8386248 Fix x caso colore semaforo assente (es setup iniziale) --> mette NERO 2022-05-02 19:04:26 +02:00
Samuele Locatelli 1739dcf38a Merge tag 'AddCheckLicMapo' into develop
Aggiunto controllo licenze in pagina about
2022-04-26 12:15:35 +02:00
Samuele Locatelli 1a42d581d4 Merge branch 'release/AddCheckLicMapo' 2022-04-26 12:15:22 +02:00
Samuele Locatelli 625433a3af Update visualizzazione licenze x MAPO 2022-04-26 12:14:52 +02:00
Samuele Locatelli 782a01a4b0 UIpdate pagina about x check licenze e server 2022-04-23 09:50:15 +02:00
Samuele Locatelli e65105b305 Merge tag 'FixDeployMaster' into develop
Sistemazione ciclo deploy su Master + fix vers number
2022-04-14 16:53:34 +02:00
2030 changed files with 113471 additions and 41817 deletions
+112 -2
View File
@@ -1,5 +1,6 @@
variables:
NEXUS_PATH: 'MP-STATS'
PROJ_PATH: ''
APP_NAME: 'MP.Stats'
SOL_NAME: 'MP-STATS'
@@ -120,6 +121,20 @@ MON:build:
script:
- dotnet build $env:APP_NAME/$env:APP_NAME.csproj
WAMON:build:
stage: build
tags:
- win
variables:
PROJ_PATH: MP.WASM.Mon\Server
APP_NAME: MP.WASM.Mon.Server
SOL_NAME: MP-WAMON
before_script:
- *nuget-fix
- dotnet restore "$env:SOL_NAME.sln"
script:
- dotnet build $env:PROJ_PATH/$env:APP_NAME.csproj
LAND:test:
stage: test
tags:
@@ -184,6 +199,23 @@ MON:test:
script:
- dotnet test $env:APP_NAME/$env:APP_NAME.csproj
WAMON:test:
stage: test
tags:
- win
variables:
PROJ_PATH: MP.WASM.Mon\Server
APP_NAME: MP.WASM.Mon.Server
SOL_NAME: MP-WAMON
before_script:
- *nuget-fix
- dotnet restore "$env:SOL_NAME.sln"
only:
- develop
needs: ["WAMON:build"]
script:
- dotnet test $env:PROJ_PATH/$env:APP_NAME.csproj
LAND:IIS01:deploy:
stage: deploy
tags:
@@ -248,6 +280,23 @@ MON:IIS01:deploy:
script:
- dotnet publish -p:PublishProfile=IIS01.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=viadante16 -p:AllowUntrustedCertificate=true $env:APP_NAME/$env:APP_NAME.csproj
WAMON:IIS01:deploy:
stage: deploy
tags:
- win
variables:
PROJ_PATH: MP.WASM.Mon\Server
APP_NAME: MP.WASM.Mon.Server
SOL_NAME: MP-WAMON
before_script:
- *nuget-fix
- dotnet restore "$env:SOL_NAME.sln"
only:
- develop
needs: ["WAMON:test"]
script:
- dotnet publish -p:PublishProfile=IIS01.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=viadante16 -p:AllowUntrustedCertificate=true $env:PROJ_PATH/$env:APP_NAME.csproj
LAND:IIS02:deploy:
stage: deploy
tags:
@@ -316,6 +365,24 @@ MON:IIS02:deploy:
- dotnet publish -p:PublishProfile=IIS02.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=viadante16 -p:AllowUntrustedCertificate=true $env:APP_NAME/$env:APP_NAME.csproj
- dotnet publish -p:PublishProfile=IIS03.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=viadante16 -p:AllowUntrustedCertificate=true $env:APP_NAME/$env:APP_NAME.csproj
WAMON:IIS02:deploy:
stage: deploy
tags:
- win
variables:
PROJ_PATH: MP.WASM.Mon\Server
APP_NAME: MP.WASM.Mon.Server
SOL_NAME: MP-WAMON
before_script:
- *nuget-fix
- dotnet restore "$env:SOL_NAME.sln"
only:
- master
needs: ["WAMON:build"]
script:
- dotnet publish -p:PublishProfile=IIS02.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=viadante16 -p:AllowUntrustedCertificate=true $env:PROJ_PATH/$env:APP_NAME.csproj
- dotnet publish -p:PublishProfile=IIS03.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=viadante16 -p:AllowUntrustedCertificate=true $env:PROJ_PATH/$env:APP_NAME.csproj
LAND:installer:
stage: installer
tags:
@@ -400,6 +467,28 @@ MON:installer:
- *hashBuild
- *nexusUpload
WAMON:installer:
stage: installer
tags:
- win
variables:
PROJ_PATH: MP.WASM.Mon\Server
APP_NAME: MP.WASM.Mon.Server
SOL_NAME: MP-WAMON
NEXUS_PATH: MP-WAMON
before_script:
- *nuget-fix
- dotnet restore "$env:SOL_NAME.sln"
only:
- develop
- master
needs: ["WAMON:build"]
script:
- dotnet publish -p:PublishProfile=IISProfile.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release $env:PROJ_PATH/$env:APP_NAME.csproj -o:publish
# qui il deploy su nexus...
- *hashBuild
- *nexusUpload
LAND:release:
stage: release
tags:
@@ -484,8 +573,6 @@ MON:release:
- *nuget-fix
- dotnet restore "$env:SOL_NAME.sln"
only:
#- feature/Deploy_CI_CD
# - master
- tags
except:
- branches
@@ -495,3 +582,26 @@ MON:release:
- publish/
script:
- dotnet publish -c Release -o ./publish $env:APP_NAME/$env:APP_NAME.csproj
WAMON:release:
stage: release
tags:
- win
variables:
PROJ_PATH: MP.WASM.Mon\Server
APP_NAME: MP.WASM.Mon.Server
SOL_NAME: MP-WAMON
NEXUS_PATH: MP-WAMON
before_script:
- *nuget-fix
- dotnet restore "$env:SOL_NAME.sln"
only:
- tags
except:
- branches
needs: ["WAMON:build"]
artifacts:
paths:
- publish/
script:
- dotnet publish -c Release -o ./publish $env:PROJ_PATH/$env:APP_NAME.csproj
+8 -1
View File
@@ -30,7 +30,14 @@ namespace Egw.Core
{
string passPhrase = string.Format("{0}|{1}", cliente.PadLeft(50, ':'), applicativo);
plainAuthKey = SteamCrypto.DecryptString(authKey, passPhrase); // uso combinazione cliente+applicativo come passphrase!
answ = Convert.ToDateTime(plainAuthKey.Replace(string.Format("{0}#{1}-", cliente, applicativo.PadLeft(20, '-')), "").Replace(string.Format("%{0}%", licenze), ""));
string datePart = plainAuthKey.Replace($"{cliente}#{applicativo.PadLeft(20, '-')}-", "").Replace($"%{licenze}%", "");
//string datePart = plainAuthKey.Replace(string.Format("{0}#{1}-", cliente, applicativo.PadLeft(20, '-')), "").Replace(string.Format("%{0}%", licenze), "");
// se non avesse "bonificato" la parte num licenze (es non corrisponde al max) forzo il trim
if (datePart.Contains("%"))
{
datePart = datePart.Substring(0, datePart.IndexOf("%"));
}
answ = Convert.ToDateTime(datePart);
}
catch (Exception exc)
{
+43
View File
@@ -0,0 +1,43 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.32126.317
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MP.Data", "MP.Data\MP.Data.csproj", "{10BA8450-301D-49C7-8E1E-21B7469C225C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MP.Mon", "MP.Mon\MP.Mon.csproj", "{7780FA7A-3597-4098-81C1-DC9AD6AE7A98}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MP.WASM.Mon.Server", "MP.WASM.Mon\Server\MP.WASM.Mon.Server.csproj", "{4A98B7F4-4EC6-4284-9D6C-63203DB981B1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MP.WASM.Mon.Client", "MP.WASM.Mon\Client\MP.WASM.Mon.Client.csproj", "{9BF7BDE7-016A-458C-8791-494FD4204301}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{10BA8450-301D-49C7-8E1E-21B7469C225C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{10BA8450-301D-49C7-8E1E-21B7469C225C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{10BA8450-301D-49C7-8E1E-21B7469C225C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{10BA8450-301D-49C7-8E1E-21B7469C225C}.Release|Any CPU.Build.0 = Release|Any CPU
{7780FA7A-3597-4098-81C1-DC9AD6AE7A98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7780FA7A-3597-4098-81C1-DC9AD6AE7A98}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7780FA7A-3597-4098-81C1-DC9AD6AE7A98}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7780FA7A-3597-4098-81C1-DC9AD6AE7A98}.Release|Any CPU.Build.0 = Release|Any CPU
{4A98B7F4-4EC6-4284-9D6C-63203DB981B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4A98B7F4-4EC6-4284-9D6C-63203DB981B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4A98B7F4-4EC6-4284-9D6C-63203DB981B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4A98B7F4-4EC6-4284-9D6C-63203DB981B1}.Release|Any CPU.Build.0 = Release|Any CPU
{9BF7BDE7-016A-458C-8791-494FD4204301}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9BF7BDE7-016A-458C-8791-494FD4204301}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9BF7BDE7-016A-458C-8791-494FD4204301}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9BF7BDE7-016A-458C-8791-494FD4204301}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {632D11D1-088B-4795-97E5-048534002558}
EndGlobalSection
EndGlobal
+33
View File
@@ -54,7 +54,9 @@ namespace MP.AppAuth
#region Public Properties
public virtual DbSet<AnagraficaGruppi> DbSetAnagraficaGruppi { get; set; }
public virtual DbSet<AnagraficaOperatori> DbSetAnagOpr { get; set; }
public virtual DbSet<Gruppi2Operatori> DbSetGruppi2Oper { get; set; }
public virtual DbSet<UpdMan> DbSetUpdMan { get; set; }
public virtual DbSet<Vocabolario> DbSetVocabolario { get; set; }
@@ -103,6 +105,37 @@ namespace MP.AppAuth
.HasMaxLength(500);
});
modelBuilder.Entity<AnagraficaGruppi>(entity =>
{
entity.HasKey(e => e.CodGruppo);
entity.ToTable("AnagraficaGruppi");
entity.Property(e => e.CodGruppo).HasMaxLength(50);
entity.Property(e => e.DescrGruppo)
.IsRequired()
.HasMaxLength(250)
.HasDefaultValueSql("('')");
entity.Property(e => e.SelEnabled).HasComment("Indica se sia selezionabile a livello di tendina x inserimento BCode");
entity.Property(e => e.TipoGruppo)
.IsRequired()
.HasMaxLength(50)
.HasDefaultValueSql("('REPARTO')")
.HasComment("tipo gruppo: reparto (es x gestione operatori assegnati), GRUPPO FASE (es macchien che fanno lo stesso tipo di lavoro), ...");
});
modelBuilder.Entity<Gruppi2Operatori>(entity =>
{
entity.HasKey(e => new { e.MatrOpr, e.CodGruppo });
entity.ToTable("Gruppi2Operatori");
entity.Property(e => e.CodGruppo).HasMaxLength(50);
});
//
modelBuilder.Seed();
@@ -31,6 +31,38 @@ namespace MP.AppAuth.Controllers
#region Public Methods
/// <summary>
/// Elenco Record x Gruppi
/// </summary>
/// <returns></returns>
public List<Models.AnagraficaGruppi> AnagGruppiFilt(string codTipo)
{
List<Models.AnagraficaGruppi> dbResult = new List<Models.AnagraficaGruppi>();
using (AppAuthContext localDbCtx = new AppAuthContext(_configuration))
{
dbResult = localDbCtx
.DbSetAnagraficaGruppi
.Where(x => x.TipoGruppo == codTipo)
.ToList();
}
return dbResult;
}
/// <summary>
/// Elenco Record x Gruppi
/// </summary>
/// <returns></returns>
public List<Models.AnagraficaGruppi> AnagGruppiGetAll()
{
List<Models.AnagraficaGruppi> dbResult = new List<Models.AnagraficaGruppi>();
using (AppAuthContext localDbCtx = new AppAuthContext(_configuration))
{
dbResult = localDbCtx
.DbSetAnagraficaGruppi
.ToList();
}
return dbResult;
}
public List<Models.AnagraficaOperatori> AnagOpGetAll(string searchVal)
{
List<Models.AnagraficaOperatori> dbResult = new List<Models.AnagraficaOperatori>();
@@ -53,6 +85,41 @@ namespace MP.AppAuth.Controllers
// ritorno
return dbResult;
}
public List<Models.AnagraficaOperatori> AnagOpByGruppoGetFilt(string codGruppo, string searchVal)
{
List<Models.AnagraficaOperatori> dbResult = new List<Models.AnagraficaOperatori>();
using (AppAuthContext localDbCtx = new AppAuthContext(_configuration))
{
if (!string.IsNullOrEmpty(searchVal))
{
dbResult = localDbCtx
.DbSetGruppi2Oper
.Where(x => x.CodGruppo == codGruppo || string.IsNullOrEmpty(codGruppo))
.Join(
localDbCtx.DbSetAnagOpr.Where(x => x.Cognome.Contains(searchVal) || x.Nome.Contains(searchVal)),
gruppo => gruppo.MatrOpr,
operatore => operatore.MatrOpr,
(gruppo, operatore) => operatore
)
.ToList();
}
else
{
dbResult = localDbCtx
.DbSetGruppi2Oper
.Where(x => x.CodGruppo == codGruppo || string.IsNullOrEmpty(codGruppo))
.Join(
localDbCtx.DbSetAnagOpr,
gruppo => gruppo.MatrOpr,
operatore => operatore.MatrOpr,
(gruppo, operatore) => operatore
)
.ToList();
}
}
// ritorno
return dbResult;
}
public void Dispose()
{
+14 -13
View File
@@ -2,22 +2,17 @@
using NLog;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MP.AppAuth.Controllers
{
public class MPController : IDisposable
{
#region Private Fields
#region Public Fields
private static IConfiguration _configuration;
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
public static AppAuth.Controllers.MPController dbController;
#endregion Private Fields
#endregion Public Fields
#region Public Constructors
@@ -31,12 +26,6 @@ namespace MP.AppAuth.Controllers
#region Public Methods
public void Dispose()
{
// Clear database controller
dbController.Dispose();
}
/// <summary>
/// Elenco Record x AnagKeyValue
@@ -54,7 +43,19 @@ namespace MP.AppAuth.Controllers
return dbResult;
}
public void Dispose()
{
// Clear database controller
dbController.Dispose();
}
#endregion Public Methods
#region Private Fields
private static IConfiguration _configuration;
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
#endregion Private Fields
}
}
+6 -6
View File
@@ -9,18 +9,18 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.10">
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.6">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.10">
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.6">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="NLog" Version="4.7.11" />
<PackageReference Include="NLog" Version="5.0.1" />
</ItemGroup>
<ItemGroup>
+15
View File
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
#nullable disable
namespace MP.AppAuth.Models
{
public partial class AnagraficaGruppi
{
public string CodGruppo { get; set; }
public string TipoGruppo { get; set; }
public string DescrGruppo { get; set; }
public bool SelEnabled { get; set; }
}
}
+13
View File
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
#nullable disable
namespace MP.AppAuth.Models
{
public partial class Gruppi2Operatori
{
public int MatrOpr { get; set; }
public string CodGruppo { get; set; }
}
}
+3 -1
View File
@@ -71,7 +71,7 @@ namespace MP.AppAuth
public virtual DbSet<ListValue> ListValues { get; set; }
public virtual DbSet<Macchine> Macchines { get; set; }
public virtual DbSet<UpdMan> UpdMan { get; set; }
public virtual DbSet<Vocabolario> Vocabolario { get; set; }
public virtual DbSet<Vocabolario> DbSetVocabolario { get; set; }
#endregion Public Properties
@@ -503,6 +503,8 @@ namespace MP.AppAuth
.HasMaxLength(500);
});
OnModelCreatingPartial(modelBuilder);
}
+19
View File
@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MP.Data.Conf
{
/// <summary>
/// Struttura conf del file conf TAG x IOB
/// </summary>
public class IobTags
{
/// <summary>
/// Oggetto dizionario di configurazione x IOB
/// </summary>
public Dictionary<string, List<TagData>> IobSetup = new Dictionary<string, List<TagData>>();
}
}
+44
View File
@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MP.Data.Conf
{
/// <summary>
/// Item da mostrare nei blocchi MON degli impianti come override ai dati MSE
/// </summary>
public class TagData
{
/// <summary>
/// Indice della colonna (ordine) del dato
/// </summary>
public int ColNum { get; set; } = 0;
/// <summary>
/// Indice della riga del dato
/// </summary>
public int RowNum { get; set; } = 0;
/// <summary>
/// Override CSS (es fontSmall)
/// </summary>
public string TagCss { get; set; } = "";
/// <summary>
/// Etichetta da mostrare
/// </summary>
public string TagName { get; set; } = "";
/// <summary>
/// Indicazione della chiave REDIS dove recuperare il tag indicato (già in formato string)
/// </summary>
public string TagLocation { get; set; } = "";
/// <summary>
/// Clone dell'oggetto
/// </summary>
/// <returns></returns>
public TagData Clone()
{
return (TagData)this.MemberwiseClone();
}
}
}
+21
View File
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MP.Data
{
public class Constants
{
// dati conf REDIS Cache
public static readonly string BASE_HASH = "MAPO";
// REDIS KEY Dati correnti
public static readonly string CONF_MON_KEY = $"{BASE_HASH}:Conf:MonDispData";
public static readonly string ACT_MSE_DATA_KEY = $"{BASE_HASH}:Current:MSE";
public static readonly string ACT_BLINK_KEY = $"{BASE_HASH}:Current:Blink";
}
}
+4
View File
@@ -43,6 +43,7 @@ namespace MP.Data.Controllers
{
dbResult = dbCtx
.DbSetArticoli
.AsNoTracking()
.Where(x => x.CodArticolo.Contains(searchVal) || x.DescArticolo.Contains(searchVal) || x.Disegno.Contains(searchVal) || string.IsNullOrEmpty(searchVal))
.OrderBy(x => x.CodArticolo)
.Take(numRecord)
@@ -66,6 +67,7 @@ namespace MP.Data.Controllers
{
dbResult = dbCtx
.DbSetMacchine
.AsNoTracking()
.OrderBy(x => x.IdxMacchina)
.ToList();
}
@@ -83,6 +85,7 @@ namespace MP.Data.Controllers
{
dbResult = dbCtx
.DbSetConfig
.AsNoTracking()
.OrderBy(x => x.Chiave)
.ToList();
}
@@ -103,6 +106,7 @@ namespace MP.Data.Controllers
dbResult = dbCtx
.DbSetMSE
.FromSqlRaw("EXEC stp_MSE_getData @maxAgeSec", maxAgeSec)
.AsNoTracking()
.ToList();
}
return dbResult;
+6 -6
View File
@@ -12,14 +12,14 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.4">
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.6">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="6.0.4" />
<PackageReference Include="NLog" Version="4.7.15" />
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="6.0.6" />
<PackageReference Include="NLog" Version="5.0.1" />
</ItemGroup>
</Project>
+135
View File
@@ -0,0 +1,135 @@
using NLog;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MP.Data
{
public class MessagePipe
{
#region Private Fields
private bool enableLog = false;
private IConnectionMultiplexer redis;
private IDatabase? redisDb;
#endregion Private Fields
#region Protected Fields
protected static Logger Log = LogManager.GetCurrentClassLogger();
#endregion Protected Fields
#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 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) =>
{
Log.Trace($"ch {channel} | {message}");
// messaggio
PubSubEventArgs mea = new PubSubEventArgs(message);
// se qualcuno ascolta sollevo evento nuovo valore...
if (EA_NewMessage != null)
{
EA_NewMessage(this, mea);
}
});
Log.Info($"Subscribed {_channel}");
}
#endregion Private Methods
#region Public Methods
public bool saveAndSendMessage(string memKey, string message)
{
bool answ = false;
// invio notifica tramite il canale richiesto
answ = sendMessage(message);
if (redisDb != null)
{
redisDb.StringSetAsync(memKey, message);
if (enableLog)
{
Log.Info($"Redis Cache Key: {memKey}");
}
}
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
/// <summary>
/// Invio messaggio sul canale + salvataggio in cache REDIS
/// </summary>
/// <param name="memKey">Chiave REDIS x salvare valore</param>
/// <param name="message"></param>
}
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
}
}
+20
View File
@@ -0,0 +1,20 @@
<div class="row">
<div class="col-6">
Gruppi
</div>
<div class="col-6 text-right">
<select @bind="@groupName" class="form-control form-control-sm">
<option value="">--- Tutti ---</option>
@if (ListGroups != null)
{
@foreach (var item in ListGroups)
{
<option value="@item.CodGruppo">@item.DescrGruppo</option>
}
}
</select>
</div>
</div>
+54
View File
@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using System.Net.Http;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.Web.Virtualization;
using Microsoft.JSInterop;
using MP.Land;
using MP.Land.Shared;
using MP.AppAuth.Models;
using MP.Land.Data;
namespace MP.Land.Components
{
public partial class CmpGroupFilt
{
[Inject]
protected MessageService AppMService { get; set; }
[Inject]
protected AppAuthService DataService { get; set; }
private List<AnagraficaGruppi> ListGroups;
private string groupName
{
get
{
return AppMService.CodGruppo;
}
set
{
AppMService.CodGruppo = value;
}
}
protected override async Task OnInitializedAsync()
{
await ReloadData();
}
private async Task ReloadData()
{
// carico i gruppi
ListGroups = await DataService.AnagGruppiFilt("REPARTO");
}
}
}
+3 -3
View File
@@ -42,9 +42,9 @@
{
<div class="input-group input-group-sm">
<select @bind="@PageSize" class="form-control form-control-sm">
<option value="2">2</option>
<option value="4">4</option>
<option value="10">10</option>
<option value="3">3</option>
<option value="6">6</option>
<option value="9">9</option>
</select>
</div>
}
+1 -1
View File
@@ -71,7 +71,7 @@ namespace MP.Land.Components
protected int _numPage { get; set; } = 1;
protected int _numRecord { get; set; } = 4;
protected int _numRecord { get; set; } = 6;
protected int percLoading { get; set; } = 0;
+1 -1
View File
@@ -31,7 +31,7 @@
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender)
if (firstRender)
{
await JSRuntime.InvokeVoidAsync("clearContent", $"qrCodeImg_{CurrItem.MatrOpr}");
await JSRuntime.InvokeVoidAsync("displayQr", $"qrCodeImg_{CurrItem.MatrOpr}", rawCode);
+40
View File
@@ -129,6 +129,46 @@ namespace MP.Land.Data
#region Public Methods
public async Task<List<AppAuth.Models.AnagraficaGruppi>> AnagGruppiAll()
{
List<AppAuth.Models.AnagraficaGruppi> dbResult = new List<AppAuth.Models.AnagraficaGruppi>();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.AnagGruppiGetAll();
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per AnagGruppiAll: {ts.TotalMilliseconds} ms");
return await Task.FromResult(dbResult);
}
public async Task<List<AppAuth.Models.AnagraficaGruppi>> AnagGruppiFilt(string codTipo)
{
List<AppAuth.Models.AnagraficaGruppi> dbResult = new List<AppAuth.Models.AnagraficaGruppi>();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
dbResult = dbController.AnagGruppiFilt(codTipo);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per AnagGruppiFilt: {ts.TotalMilliseconds} ms");
return await Task.FromResult(dbResult);
}
public async Task<List<AppAuth.Models.AnagraficaOperatori>> AnagOperByGroupList(string codGruppo, string searchVal)
{
List<AppAuth.Models.AnagraficaOperatori> dbResult = new List<AppAuth.Models.AnagraficaOperatori>();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
var rawData = dbController
.AnagOpByGruppoGetFilt(codGruppo, searchVal);
dbResult = rawData
.GroupBy(user => user.MatrOpr)
.Select(grp => grp.First())
.ToList();
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Trace($"Effettuata lettura da DB per AnagOperByGroupList: {ts.TotalMilliseconds} ms");
return await Task.FromResult(dbResult);
}
public async Task<List<AppAuth.Models.AnagraficaOperatori>> AnagOperList(string searchVal)
{
List<AppAuth.Models.AnagraficaOperatori> dbResult = new List<AppAuth.Models.AnagraficaOperatori>();
+181 -51
View File
@@ -28,6 +28,12 @@ namespace MP.Land.Data
/// URL dell'API x chiamate gestione licenze
/// </summary>
private static string apiUrl = "https://liman.egalware.com/ELM.API/";
//private static string apiUrl = "https://localhost:44351/";
/// <summary>
/// Chiave redis x info della licenza
/// </summary>
private static string rkeyAppInfo = "LongCache:AppInfo";
private readonly IDistributedCache distributedCache;
@@ -120,10 +126,26 @@ namespace MP.Land.Data
public DateTime infoExpiry { get; set; } = DateTime.Today.AddDays(1);
/// <summary>
/// Codice cliente/installazione
/// </summary>
public string Installazione { get; set; } = "";
/// <summary>
/// Master key licenza principale
/// </summary>
public string MasterKey { get; set; } = "";
/// <summary>
/// Numero licenze da DB
/// </summary>
public int NumLicDb { get; set; } = -1;
/// <summary>
/// Numero licenze da auth remota
/// </summary>
public int NumLicRemote { get; set; } = -1;
public bool ValidData
{
get
@@ -160,7 +182,7 @@ namespace MP.Land.Data
RestClient client = new RestClient(apiUrl);
//client.Authenticator = new HttpBasicAuthenticator("username", "password");
string MKeyEnc = HttpUtility.UrlEncode(MasterKey);
var request = new RestRequest($"/api/attivazioni/?chiave={MKeyEnc}", Method.Get);
var request = new RestRequest($"api/attivazioni/?chiave={MKeyEnc}", Method.Get);
var response = await client.GetAsync(request);
// controllo risposta
if (response.StatusCode == System.Net.HttpStatusCode.OK)
@@ -172,6 +194,29 @@ namespace MP.Land.Data
return await Task.FromResult(answ);
}
/// <summary>
/// Recupera info licenza da remoto
/// </summary>
private async Task<List<LiManObj.ApplicativoDTO>> OnlineAppInfo()
{
List<LiManObj.ApplicativoDTO> answ = new List<LiManObj.ApplicativoDTO>();
// cerco online
RestClient client = new RestClient(apiUrl);
string MKeyEnc = HttpUtility.UrlEncode(MasterKey);
//string mKey = System.Net.WebUtility.UrlEncode(MasterKey);
string reqUrl = $"api/licenza/{Installazione}?CodApp={Applicazione}&Chiave={MKeyEnc}";
var request = new RestRequest(reqUrl, Method.Get);
var response = await client.GetAsync(request);
// controllo risposta
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
// verifico risposta
string rawData = $"{response.Content}";
answ = JsonConvert.DeserializeObject<List<LiManObj.ApplicativoDTO>?>(rawData);
}
return await Task.FromResult(answ);
}
private void ReportUpdated()
{
if (EA_InfoUpdated != null)
@@ -184,6 +229,25 @@ namespace MP.Land.Data
#region Protected Methods
/// <summary>
/// Cerca di recuperare valore INT da elenco AKV
/// </summary>
/// <param name="varReq">Chiave AKV richiesta</param>
/// <returns></returns>
protected int getAVKInt(string varReq)
{
int answ = -9999;
if (AKVList != null && AKVList.Count > 0)
{
var currRec = AKVList.Where(x => x.NomeVar == varReq).FirstOrDefault();
if (currRec != null)
{
answ = currRec.ValInt ?? 0;
}
}
return answ;
}
/// <summary>
/// Cerca di recuperare valore string da elenco AKV
/// </summary>
@@ -285,55 +349,6 @@ namespace MP.Land.Data
return await Task.FromResult(dbResult);
}
/// <summary>
/// Init della classe con variabili di base da Redis/DB
/// </summary>
public bool InitAkv()
{
bool fatto = false;
Applicazione = "MAPO";
Installazione = getAVKStr("Installazione");
MasterKey = getAVKStr(Applicazione);
fatto = !string.IsNullOrEmpty($"{Installazione}{MasterKey}");
return fatto;
}
/// <summary>
/// Init della classe con variabili di base da Redis/DB
/// </summary>
public async Task<bool> RefreshLicense()
{
bool fatto = false;
var onlineAct = await OnlineActivationList();
if (onlineAct != null)
{
if (onlineAct.Count > 0)
{
// scadenza info a 15 gg...
int numDays = 15;
infoExpiry = DateTime.Now.AddDays(numDays);
ActivList = onlineAct;
fatto = await setActivList(onlineAct, numDays);
}
}
await Task.Delay(1);
return fatto;
}
public async Task<bool> setActivList(List<LiManObj.AttivazioneDTO> newActList, int numDays)
{
bool fatto = false;
string cacheKey = $"{rKeyAttByLic}:{MasterKey}";
var rawData = JsonConvert.SerializeObject(newActList);
await setRSV(cacheKey, rawData, numDays * cacheFact * 24);
fatto = true;
if (EA_InfoUpdated != null)
{
EA_InfoUpdated?.Invoke();
}
return fatto;
}
/// <summary>
/// Verifica attivazione licenza
/// </summary>
@@ -363,6 +378,121 @@ namespace MP.Land.Data
return answ;
}
/// <summary>
/// Stato server gestione licenze
/// </summary>
public async Task<string> checkLimanServer()
{
string answ = "ND";
// cerco online
RestClient client = new RestClient(apiUrl);
var request = new RestRequest($"api/health", Method.Get);
var response = await client.GetAsync(request);
// controllo risposta
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
// verifico risposta
answ = response.Content.Replace("\"", "");
}
return await Task.FromResult(answ);
}
/// <summary>
/// Init della classe con variabili di base da Redis/DB
/// </summary>
public bool InitAkv()
{
bool fatto = false;
Applicazione = "MAPO";
Installazione = getAVKStr("Installazione");
MasterKey = getAVKStr(Applicazione);
NumLicDb = getAVKInt(Applicazione);
fatto = !string.IsNullOrEmpty($"{Installazione}{MasterKey}");
return fatto;
}
public async Task<List<LiManObj.ApplicativoDTO>> LicAppCache()
{
List<LiManObj.ApplicativoDTO> dbResult = new List<LiManObj.ApplicativoDTO>();
string cacheKey = $"{rkeyAppInfo}:{MasterKey}";
trackCache(cacheKey);
string rawData = await getRSV(cacheKey);
if (!string.IsNullOrEmpty(rawData))
{
var cacheRes = JsonConvert.DeserializeObject<List<LiManObj.ApplicativoDTO>?>(rawData);
if (cacheRes != null)
{
dbResult = cacheRes;
}
}
return await Task.FromResult(dbResult);
}
/// <summary>
/// Init della classe con variabili di base da Redis/DB
/// </summary>
public async Task<bool> RefreshLicense()
{
bool fatto = false;
// scadenza info a 15 gg...
int numDays = 15;
// dati applicativo
var appData = await OnlineAppInfo();
if (appData != null)
{
if (appData.Count > 0)
{
fatto = await setAppInfo(appData, numDays);
// salvo info licenza...
NumLicRemote = appData[0].NumLicenze;
}
}
// dati attivazioni
var onlineAct = await OnlineActivationList();
if (onlineAct != null)
{
if (onlineAct.Count > 0)
{
infoExpiry = DateTime.Now.AddDays(numDays);
ActivList = onlineAct;
fatto = await setActivList(onlineAct, numDays);
}
}
await Task.Delay(1);
return fatto;
}
public async Task<bool> setActivList(List<LiManObj.AttivazioneDTO> newActList, int numDays)
{
bool fatto = false;
string cacheKey = $"{rKeyAttByLic}:{MasterKey}";
var rawData = JsonConvert.SerializeObject(newActList);
await setRSV(cacheKey, rawData, numDays * cacheFact * 24);
fatto = true;
if (EA_InfoUpdated != null)
{
EA_InfoUpdated?.Invoke();
}
return fatto;
}
public async Task<bool> setAppInfo(List<LiManObj.ApplicativoDTO> newAppInfo, int numDays)
{
bool fatto = false;
string cacheKey = $"{rkeyAppInfo}:{MasterKey}";
var rawData = JsonConvert.SerializeObject(newAppInfo);
await setRSV(cacheKey, rawData, numDays * cacheFact * 24);
fatto = true;
if (EA_InfoUpdated != null)
{
EA_InfoUpdated?.Invoke();
}
return fatto;
}
#endregion Public Methods
}
}
}
+15
View File
@@ -106,6 +106,21 @@ namespace MP.Land.Data
}
}
protected string _groupName { get; set; } = "";
public string CodGruppo
{
get => _groupName;
set
{
if (_groupName != value)
{
_groupName = value;
ReportFilter();
}
}
}
#endregion Public Properties
#region Private Methods
+1 -1
View File
@@ -44,7 +44,7 @@ namespace MP.Land.Data
public bool OnlyMod { get; set; } = false;
public bool OnlyNoTag { get; set; } = false;
public int PageNum { get; set; } = 1;
public int PageSize { get; set; } = 4;
public int PageSize { get; set; } = 6;
public string SearchVal { get; set; } = "";
public string Tag { get; set; } = "";
+5 -5
View File
@@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>MP.Land</RootNamespace>
<Version>6.15.2204.1216</Version>
<Version>6.15.2207.0718</Version>
</PropertyGroup>
<ItemGroup>
@@ -45,14 +45,14 @@
<ItemGroup>
<PackageReference Include="DiffMatchPatch" Version="1.0.3" />
<PackageReference Include="Majorsoft.Blazor.Components.Debounce" Version="1.5.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.10">
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.6">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="5.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="5.0.2" />
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="6.0.6" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="6.0.6" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NLog.Web.AspNetCore" Version="4.14.0" />
<PackageReference Include="NLog.Web.AspNetCore" Version="5.0.0" />
<PackageReference Include="RestSharp" Version="107.1.2" />
</ItemGroup>
+59 -15
View File
@@ -2,9 +2,10 @@
@using MP.Land.Data
@inject MessageService AppMService
@inject LicenseService LicServ
<div class="row mx-2">
<div class="col-12 col-lg-8 offset-lg-2">
<div class="col-12 col-lg-10 offset-lg-1">
<div class="card">
<div class="card-header text-center">
<div class="row">
@@ -28,28 +29,71 @@
<img src="img/LogoMapoFull.png" class="img-fluid" />
</div>
<div class="col-lg-3"></div>
<div class="col-12">
<div class="col-6">
<h4 class="card-title">@Messaggio</h4>
<br />
<p>MoonPro / MAPO sono una suite di applicazioni e dispositivi hw dedicati per l'IOT,l'industry 4.0 e la gestione automatizzata dei processi produttivi.</p>
<hr />
<p>Per maggiori informazioni <a href="http://www.steamware.net/iot" target="_blank">visita il link</a> sul nostro sito.</p>
</div>
<div class="col-6 text-right">
<div runat="server" id="divCheck" class="@mainCss">
<h4>Info installazione</h4>
<hr />
<div class="d-flex justify-content-between @remSrvCss">
<div class="px-2">
<i class="fa fa-server" aria-hidden="true"></i> Remote Server:
</div>
<div class="px-2">
<b>@ServerStatus</b>
</div>
</div>
<div class="d-flex justify-content-between">
<div class="px-2">
<i class="fa fa-certificate" aria-hidden="true"></i> Cliente:
</div>
<div class="px-2">
<b>@Installazione</b>
</div>
</div>
<div class="d-flex justify-content-between">
<div class="px-2">
<i class="fa fa-desktop" aria-hidden="true"></i> App:
</div>
<div class="px-2">
<b>@Applicazione</b>
</div>
</div>
<div class="d-flex justify-content-between @licenseCss">
<div class="px-2">
<i class="fa fa-users" aria-hidden="true"></i> Licenze:
</div>
<div class="px-2">
<b title="# Licenze locali / # Licenze Remote">@Licenze</b>
</div>
</div>
<div class="d-flex justify-content-between @expDateCss">
<div class="px-2">
<i class="far fa-calendar-check" aria-hidden="true"></i> Scadenza:
</div>
<div class="px-2">
<b>@($"{Scadenza:yyyy/MM/dd}")</b>
</div>
</div>
<div class="d-flex justify-content-between @licenseCss">
<div class="px-2">
<i class="fa fa-key" aria-hidden="true"></i> Key
</div>
<div class="px-2">
<span Font-Size="0.6em" class="small">@MastKey</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@code {
protected string Titolo = "";
protected string Messaggio = "";
protected override void OnInitialized()
{
Titolo = "MES | SCADA | IOT";
Messaggio = "Soluzione integrata per la gestione della produzione";
AppMService.ShowSearch = false;
AppMService.PageName = "About";
AppMService.PageIcon = "fas fa-info-circle pr-2";
}
}
+90
View File
@@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using System.Net.Http;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.Web.Virtualization;
using Microsoft.JSInterop;
using MP.Land;
using MP.Land.Shared;
using MP.Land.Data;
using NLog;
namespace MP.Land.Pages
{
public partial class About
{
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
private string Titolo = "";
private string Messaggio = "";
private string ServerStatus = "SrvState";
private string Installazione = "Inst";
private string Applicazione = "App";
private string Licenze = "#";
private DateTime Scadenza = DateTime.Today;
private string MastKey = "########################";
private string mainCss = "alert alert-info";
private string remSrvCss = "bg-warning text-secondary";
private string expDateCss = "bg-warning text-secondary";
private string licenseCss = "bg-warning text-secondary";
protected override async Task OnInitializedAsync()
{
updatePageHead();
await reloadLicenseData();
}
private async Task reloadLicenseData()
{
int cDelay = 5;
// recupero dati
await Task.Delay(cDelay);
try
{
LicServ.InitAkv();
// verifico stati
ServerStatus = await LicServ.checkLimanServer();
Installazione = LicServ.Installazione;
Applicazione = LicServ.Applicazione;
MastKey = LicServ.MasterKey;
await Task.Delay(cDelay);
var fatto = await LicServ.RefreshLicense();
await Task.Delay(cDelay);
Licenze = $"{LicServ.NumLicDb}/{LicServ.NumLicRemote}";
licenseCss = "";
}
catch(Exception exc)
{
licenseCss = "bg-dark text-warning";
Log.Error($"Eccezione in reloadLicenseData:{Environment.NewLine}{exc}");
}
bool okRemoteSrv = ServerStatus == "OK";
bool okScadenza = LicServ.checkLicenseActive(LicServ.MasterKey);
bool okNumLic = (LicServ.NumLicDb <= LicServ.NumLicRemote);
// aggiornamento css secondo status colore da check
mainCss = okNumLic ? "alert alert-success shadowBox" : "alert alert-warning shadowBox";
expDateCss = okScadenza ? "" : "bg-danger text-warning";
remSrvCss = okRemoteSrv ? "" : "bg-danger text-warning";
await Task.Delay(cDelay);
}
private void updatePageHead()
{
Titolo = "MES | SCADA | IOT";
Messaggio = "Soluzione integrata per la gestione della produzione";
AppMService.ShowSearch = false;
AppMService.PageName = "About";
AppMService.PageIcon = "fas fa-info-circle pr-2";
}
}
}
+2
View File
@@ -5,6 +5,7 @@
<div class="card">
<div class="card-body">
<CmpGroupFilt></CmpGroupFilt>
@if (ListRecords == null)
{
<LoadingData></LoadingData>
@@ -15,6 +16,7 @@
}
else
{
<div class="row">
@foreach (var item in ListRecords)
{
+93 -66
View File
@@ -11,12 +11,14 @@ namespace MP.Land.Pages
{
public partial class UserQr : IDisposable
{
#region Private Fields
#region Public Methods
private List<AnagraficaOperatori> ListRecords;
private List<AnagraficaOperatori> SearchRecords;
public void Dispose()
{
AppMService.EA_SearchUpdated -= OnSeachUpdated;
}
#endregion Private Fields
#endregion Public Methods
#region Protected Fields
@@ -25,39 +27,6 @@ namespace MP.Land.Pages
#endregion Protected Fields
#region Private Properties
[Inject]
private IConfiguration Configuration { get; set; }
private int currPage
{
get
{
return AppMService.SelFilter.PageNum;
}
set
{
AppMService.SelFilter.PageNum = value;
}
}
private bool isLoading { get; set; } = false;
private int numRecord
{
get
{
return AppMService.SelFilter.PageSize;
}
set
{
AppMService.SelFilter.PageSize = value;
}
}
#endregion Private Properties
#region Protected Properties
[Inject]
@@ -78,18 +47,6 @@ namespace MP.Land.Pages
#endregion Protected Properties
#region Private Methods
private async void OnSeachUpdated()
{
ListRecords = null;
currPage = 1;
await Task.Delay(1);
await ReloadData();
}
#endregion Private Methods
#region Protected Methods
protected override async Task OnInitializedAsync()
@@ -99,6 +56,7 @@ namespace MP.Land.Pages
AppMService.PageIcon = "fas fa-qrcode pr-2";
await ReloadData();
AppMService.EA_SearchUpdated += OnSeachUpdated;
AppMService.EA_FilterUpdated += OnFilterUpdated;
}
protected async Task PagerReloadNum(int newNum)
@@ -117,19 +75,6 @@ namespace MP.Land.Pages
isLoading = false;
}
protected async Task ReloadData()
{
isLoading = true;
// importante altrimenti NON mostra update UI
await Task.Delay(1);
SearchRecords = await DataService.AnagOperList(AppMService.SearchVal);
ListRecords = SearchRecords.Skip((currPage - 1) * numRecord).Take(numRecord).ToList();
totalCount = SearchRecords.Count();
await Task.Delay(1);
isLoading = false;
StateHasChanged();
}
protected MarkupString traduci(string lemma)
{
MarkupString answ;
@@ -142,13 +87,95 @@ namespace MP.Land.Pages
#endregion Protected Methods
#region Public Methods
#region Private Fields
public void Dispose()
private List<AnagraficaOperatori> ListRecords;
private List<AnagraficaOperatori> SearchRecords;
#endregion Private Fields
#region Private Properties
[Inject]
private IConfiguration Configuration { get; set; }
private int currPage
{
AppMService.EA_SearchUpdated -= OnSeachUpdated;
get
{
return AppMService.SelFilter.PageNum;
}
set
{
AppMService.SelFilter.PageNum = value;
}
}
#endregion Public Methods
private string groupName
{
get
{
return AppMService.CodGruppo;
}
}
private bool isLoading { get; set; } = false;
private int numRecord
{
get
{
return AppMService.SelFilter.PageSize;
}
set
{
AppMService.SelFilter.PageSize = value;
}
}
#endregion Private Properties
#region Private Methods
private async void OnFilterUpdated()
{
ListRecords = null;
currPage = 1;
await Task.Delay(1);
await ReloadData();
}
private async void OnSeachUpdated()
{
ListRecords = null;
currPage = 1;
await Task.Delay(1);
await ReloadData();
}
private async Task ReloadData()
{
isLoading = true;
// importante altrimenti NON mostra update UI
await Task.Delay(1);
// se ho selezionato qualcosa cerco x gruppo
//if (groupName != "")
//{
SearchRecords = await DataService.AnagOperByGroupList(groupName, AppMService.SearchVal);
//}
//else
//{
// //altrimenti TUTTI
// SearchRecords = await DataService.AnagOperList(AppMService.SearchVal);
//}
ListRecords = SearchRecords.Skip((currPage - 1) * numRecord).Take(numRecord).ToList();
totalCount = SearchRecords.Count();
await Task.Delay(1);
isLoading = false;
StateHasChanged();
}
#endregion Private Methods
}
}
+25 -31
View File
@@ -36,11 +36,30 @@
<a class="dismiss">🗙</a>
</div>
@* Riconnessione server app: https://www.syncfusion.com/faq/how-do-i-reconnect-blazor-server-side-automatically *@
@*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.defaultReconnectionHandler._reconnectCallback = function (d) {
document.location.reload();
}
//Blazor.start().then(() => {
// Blazor.defaultReconnectionHandler._reconnectionDisplay = {
// show: () => { },
// update: (d) => { },
// rejected: (d) => document.location.reload()
// };
//});
Blazor.start().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()
}
}
});
});
</script>
<!-- inside of body section and after the div/app tag -->
@@ -50,33 +69,8 @@
<script src="font-awesome/js/all.min.js"></script>
<script src="_framework/blazor.server.js"></script>
<script type="text/javascript" src="~/lib/qrcode.js"></script>
<script type="text/javascript">
function clearContent(elementID) {
console.log(elementID);
document.getElementById(elementID).innerHTML = "";
}
// gestione qrcode... da https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity-enable-qrcodes?view=aspnetcore-5.0
//var qrcode = new QRCode("qrCodeImg");
function displayQr(elementName, rawData) {
console.log(elementName);
try {
if (elementName != "" && rawData != "") {
qrcode = new QRCode(document.getElementById(elementName),
{
text: rawData,
width: 200,
height: 200
});
//qrcode = new QRCode(document.getElementById(elementName));
//qrcode.clear();
//qrcode.makeCode(rawData);
}
}
catch
{ }
}
</script>
<script type="text/javascript" src="~/lib/qrHelper.js"></script>
</body>
</html>
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>Modulo gestione Programmi MAPO</i>
<h4>Versione: 6.15.2204.1216</h4>
<h4>Versione: 6.15.2207.0718</h4>
<br />
Note di rilascio:
<ul>
+1 -1
View File
@@ -1 +1 @@
6.15.2204.1216
6.15.2207.0718
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>6.15.2204.1216</version>
<version>6.15.2207.0718</version>
<url>https://nexus.steamware.net/repository/SWS/MP-LAND/stable/LAST/MP.Land.zip</url>
<changelog>https://nexus.steamware.net/repository/SWS/MP-LAND/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>
+2 -2
View File
@@ -18,8 +18,8 @@
"Redis": "localhost:6379,defaultDatabase=1,keepAlive=180,asyncTimeout=5000"
}
//"ConnectionStrings": {
// "DefaultConnection": "Server=SQL2016PROD;Database=Valvital_MoonPro_Prod;Trusted_Connection=True;MultipleActiveResultSets=true",
// "MP.Land": "Server=SQL2016PROD;Database=Valvital_MoonPro_Prod;User ID=sa;Password=keyhammer16;integrated security=False;MultipleActiveResultSets=True;App=MP.Land;",
// "DefaultConnection": "Server=SQL2016PROD;Database=Jetco_MoonPro_Prod;Trusted_Connection=True;MultipleActiveResultSets=true",
// "MP.Land": "Server=SQL2016PROD;Database=Jetco_MoonPro_Prod;User ID=sa;Password=keyhammer16;integrated security=False;MultipleActiveResultSets=True;App=MP.Land;",
// "Redis": "localhost:6379,defaultDatabase=11,keepAlive=180,asyncTimeout=5000"
//}
}
+50 -4
View File
@@ -63,6 +63,52 @@ a,
.footer {
line-height: 1.8em;
}
.textTrim {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.maxChar {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.max5Char {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 5rem;
}
.max10Char {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 10rem;
}
.max20Char {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 20rem;
}
.max30Char {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 30rem;
}
.max40Char {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 40rem;
}
.max50Char {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 50rem;
}
/*------------------------------------------------------------------
[ Shortcuts / .shortcuts ]
*/
@@ -76,7 +122,7 @@ a,
min-width: 9rem;
min-height: 5rem;
display: inline-block;
padding: 0.66666667rem 0;
padding: 2rem/3 0;
margin: 0 2px 1em;
vertical-align: top;
text-decoration: none;
@@ -89,13 +135,13 @@ a,
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffeeeeee', GradientType=0);
border: 1px solid #ddd;
box-sizing: border-box;
border-radius: 0.5rem;
border-radius: 1rem/2;
}
.shortcuts .shortcut-sm {
min-width: 4.5rem;
min-height: 3rem;
display: inline-block;
padding: 0.25rem 0;
padding: 1rem/4 0;
margin: 0 2px 1em;
vertical-align: top;
text-decoration: none;
@@ -108,7 +154,7 @@ a,
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffeeeeee', GradientType=0);
border: 1px solid #ddd;
box-sizing: border-box;
border-radius: 0.5rem;
border-radius: 1rem/2;
}
.shortcuts .shortcut .shortcut-icon {
width: 100%;
+44
View File
@@ -63,6 +63,50 @@ a, .btn-link {
line-height: 1.8em;
}
.textTrim {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.maxChar {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.max5Char {
.maxChar;
width: 5rem;
}
.max10Char {
.maxChar;
width: 10rem;
}
.max20Char {
.maxChar;
width: 20rem;
}
.max30Char {
.maxChar;
width: 30rem;
}
.max40Char {
.maxChar;
width: 40rem;
}
.max50Char {
.maxChar;
width: 50rem;
}
/*------------------------------------------------------------------
[ Shortcuts / .shortcuts ]
*/
+1 -1
View File
@@ -1 +1 @@
@import url('open-iconic/font/css/open-iconic-bootstrap.min.css');@import url('fonts.min.css');h1,h2,h3,h4,h5,h6,b,display-1,display-2,display-3,display-4{font-family:'Lato',sans-serif}html,body,.textCondensed{font-family:'Roboto Condensed',sans-serif}a,.btn-link{color:#0366d6}.btn-primary{color:#fff;background-color:#1b6ec2;border-color:#1861ac}.content{padding-top:1.1rem}.valid.modified:not([type=checkbox]){outline:1px solid #26b050}.invalid{outline:1px solid #f00}.validation-message{color:#f00}.textStriked{text-decoration:line-through}#blazor-error-ui{background:#ffffe0;bottom:0;box-shadow:0 -1px 2px rgba(0,0,0,.2);display:none;left:0;padding:.6rem 1.25rem .7rem 1.25rem;position:fixed;width:100%;z-index:1000}#blazor-error-ui .dismiss{cursor:pointer;position:absolute;right:.75rem;top:.5rem}.footer{line-height:1.8em}.shortcuts{text-align:center}.shortcuts .shortcut-icon{font-size:2rem}.shortcuts .shortcut{min-width:9rem;min-height:5rem;display:inline-block;padding:.66666667rem 0;margin:0 2px 1em;vertical-align:top;text-decoration:none;background:#f3f3f3;background-image:-webkit-gradient(linear,left 0%,left 100%,from(#fff),to(#eee));background-image:-webkit-linear-gradient(top,#fff,0%,#eee,100%);background-image:-moz-linear-gradient(top,#fff 0%,#eee 100%);background-image:linear-gradient(to bottom,#fff 0%,#eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffeeeeee',GradientType=0);border:1px solid #ddd;box-sizing:border-box;border-radius:.5rem}.shortcuts .shortcut-sm{min-width:4.5rem;min-height:3rem;display:inline-block;padding:.25rem 0;margin:0 2px 1em;vertical-align:top;text-decoration:none;background:#f3f3f3;background-image:-webkit-gradient(linear,left 0%,left 100%,from(#fff),to(#eee));background-image:-webkit-linear-gradient(top,#fff,0%,#eee,100%);background-image:-moz-linear-gradient(top,#fff 0%,#eee 100%);background-image:linear-gradient(to bottom,#fff 0%,#eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffeeeeee',GradientType=0);border:1px solid #ddd;box-sizing:border-box;border-radius:.5rem}.shortcuts .shortcut .shortcut-icon{width:100%;margin-top:0;margin-bottom:0;font-size:2rem;color:#333}.shortcuts .shortcut-sm .shortcut-icon{width:100%;margin-top:0;margin-bottom:0;font-size:2rem;color:#333}.shortcuts .shortcut:hover{background:#e8e8e8;background-image:-webkit-gradient(linear,left 0%,left 100%,from(#fafafa),to(#e1e1e1));background-image:-webkit-linear-gradient(top,#fafafa,0%,#e1e1e1,100%);background-image:-moz-linear-gradient(top,#fafafa 0%,#e1e1e1 100%);background-image:linear-gradient(to bottom,#fafafa 0%,#e1e1e1 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa',endColorstr='#ffe1e1e1',GradientType=0)}.shortcuts .shortcut-sm:hover{background:#e8e8e8;background-image:-webkit-gradient(linear,left 0%,left 100%,from(#fafafa),to(#e1e1e1));background-image:-webkit-linear-gradient(top,#fafafa,0%,#e1e1e1,100%);background-image:-moz-linear-gradient(top,#fafafa 0%,#e1e1e1 100%);background-image:linear-gradient(to bottom,#fafafa 0%,#e1e1e1 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa',endColorstr='#ffe1e1e1',GradientType=0)}.shortcuts .shortcut:active{box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.shortcuts .shortcut-sm:active{box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.shortcuts .shortcut:hover .shortcut-icon{color:#c93}.shortcuts .shortcut-sm:hover .shortcut-icon{color:#666}.shortcuts .shortcut-label{display:block;margin-top:.75em;font-weight:400;color:#666}@media(max-width:640px){.shortcuts .shortcut{min-width:8rem;min-height:4rem}body{font-size:.8em}}
@import url('open-iconic/font/css/open-iconic-bootstrap.min.css');@import url('fonts.min.css');h1,h2,h3,h4,h5,h6,b,display-1,display-2,display-3,display-4{font-family:'Lato',sans-serif}html,body,.textCondensed{font-family:'Roboto Condensed',sans-serif}a,.btn-link{color:#0366d6}.btn-primary{color:#fff;background-color:#1b6ec2;border-color:#1861ac}.content{padding-top:1.1rem}.valid.modified:not([type=checkbox]){outline:1px solid #26b050}.invalid{outline:1px solid #f00}.validation-message{color:#f00}.textStriked{text-decoration:line-through}#blazor-error-ui{background:#ffffe0;bottom:0;box-shadow:0 -1px 2px rgba(0,0,0,.2);display:none;left:0;padding:.6rem 1.25rem .7rem 1.25rem;position:fixed;width:100%;z-index:1000}#blazor-error-ui .dismiss{cursor:pointer;position:absolute;right:.75rem;top:.5rem}.footer{line-height:1.8em}.textTrim{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.maxChar{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.max5Char{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:5rem}.max10Char{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:10rem}.max20Char{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:20rem}.max30Char{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:30rem}.max40Char{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:40rem}.max50Char{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:50rem}.shortcuts{text-align:center}.shortcuts .shortcut-icon{font-size:2rem}.shortcuts .shortcut{min-width:9rem;min-height:5rem;display:inline-block;padding:2rem/3 0;margin:0 2px 1em;vertical-align:top;text-decoration:none;background:#f3f3f3;background-image:-webkit-gradient(linear,left 0%,left 100%,from(#fff),to(#eee));background-image:-webkit-linear-gradient(top,#fff,0%,#eee,100%);background-image:-moz-linear-gradient(top,#fff 0%,#eee 100%);background-image:linear-gradient(to bottom,#fff 0%,#eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffeeeeee',GradientType=0);border:1px solid #ddd;box-sizing:border-box;border-radius:1rem/2}.shortcuts .shortcut-sm{min-width:4.5rem;min-height:3rem;display:inline-block;padding:1rem/4 0;margin:0 2px 1em;vertical-align:top;text-decoration:none;background:#f3f3f3;background-image:-webkit-gradient(linear,left 0%,left 100%,from(#fff),to(#eee));background-image:-webkit-linear-gradient(top,#fff,0%,#eee,100%);background-image:-moz-linear-gradient(top,#fff 0%,#eee 100%);background-image:linear-gradient(to bottom,#fff 0%,#eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffeeeeee',GradientType=0);border:1px solid #ddd;box-sizing:border-box;border-radius:1rem/2}.shortcuts .shortcut .shortcut-icon{width:100%;margin-top:0;margin-bottom:0;font-size:2rem;color:#333}.shortcuts .shortcut-sm .shortcut-icon{width:100%;margin-top:0;margin-bottom:0;font-size:2rem;color:#333}.shortcuts .shortcut:hover{background:#e8e8e8;background-image:-webkit-gradient(linear,left 0%,left 100%,from(#fafafa),to(#e1e1e1));background-image:-webkit-linear-gradient(top,#fafafa,0%,#e1e1e1,100%);background-image:-moz-linear-gradient(top,#fafafa 0%,#e1e1e1 100%);background-image:linear-gradient(to bottom,#fafafa 0%,#e1e1e1 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa',endColorstr='#ffe1e1e1',GradientType=0)}.shortcuts .shortcut-sm:hover{background:#e8e8e8;background-image:-webkit-gradient(linear,left 0%,left 100%,from(#fafafa),to(#e1e1e1));background-image:-webkit-linear-gradient(top,#fafafa,0%,#e1e1e1,100%);background-image:-moz-linear-gradient(top,#fafafa 0%,#e1e1e1 100%);background-image:linear-gradient(to bottom,#fafafa 0%,#e1e1e1 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffafafa',endColorstr='#ffe1e1e1',GradientType=0)}.shortcuts .shortcut:active{box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.shortcuts .shortcut-sm:active{box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.shortcuts .shortcut:hover .shortcut-icon{color:#c93}.shortcuts .shortcut-sm:hover .shortcut-icon{color:#666}.shortcuts .shortcut-label{display:block;margin-top:.75em;font-weight:400;color:#666}@media(max-width:640px){.shortcuts .shortcut{min-width:8rem;min-height:4rem}body{font-size:.8em}}
+21
View File
@@ -0,0 +1,21 @@
function clearContent(elementID) {
//console.log("Remove " + elementID);
document.getElementById(elementID).innerHTML = "";
}
// gestione qrcode... da https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity-enable-qrcodes?view=aspnetcore-5.0
//var qrcode = new QRCode("qrCodeImg");
function displayQr(elementName, rawData) {
//console.log("Add " + elementName);
try {
if (elementName != "" && rawData != "") {
qrcode = new QRCode(document.getElementById(elementName),
{
text: rawData,
width: 200,
height: 200
});
}
}
catch
{ }
}
-38
View File
@@ -7,41 +7,3 @@
</div>
</div>
@code {
Version version = typeof(Program).Assembly.GetName().Version;
protected override async Task OnInitializedAsync()
{
StartTimer();
}
public void Dispose()
{
aTimer.Stop();
aTimer.Dispose();
}
private static System.Timers.Timer aTimer;
public void StartTimer()
{
int tOutPeriod = 1000;
//int.TryParse(Configuration["ReloadStatusTimer"], out tOutPeriod);
aTimer = new System.Timers.Timer(tOutPeriod);
aTimer.Elapsed += ElapsedTimer;
aTimer.Enabled = true;
aTimer.Start();
}
public void ElapsedTimer(Object source, System.Timers.ElapsedEventArgs e)
{
var pUpd = Task.Run(async () =>
{
//await ReloadData();
await Task.Delay(1);
await InvokeAsync(StateHasChanged);
});
pUpd.Wait();
}
}
+58
View File
@@ -0,0 +1,58 @@
using NLog;
namespace MP.Mon.Components
{
public partial class CmpFooter
{
#region Public Methods
public void Dispose()
{
//aTimer.Elapsed -= ElapsedTimer;
aTimer.Stop();
aTimer.Dispose();
}
public void ElapsedTimer(object? source, System.Timers.ElapsedEventArgs e)
{
var pUpd = Task.Run(async () =>
{
await Task.Delay(1);
await InvokeAsync(() => StateHasChanged());
});
pUpd.Wait();
//Log.Trace($"Elapsed Timer Footer");
}
public void StartTimer()
{
int tOutPeriod = 5000;
//int.TryParse(Configuration["ReloadStatusTimer"], out tOutPeriod);
aTimer = new System.Timers.Timer(tOutPeriod);
aTimer.Elapsed += ElapsedTimer;
aTimer.Enabled = true;
aTimer.Start();
}
#endregion Public Methods
#region Protected Methods
protected override void OnInitialized()
{
var currAssembly = typeof(Program).Assembly.GetName();
version = currAssembly.Version != null ? currAssembly.Version : new Version();
StartTimer();
}
#endregion Protected Methods
#region Private Fields
private static System.Timers.Timer aTimer = null!;
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
private Version version = null!;
#endregion Private Fields
}
}
+2 -2
View File
@@ -1,12 +1,12 @@
<div class="px-2">
<img class="logoImg img-fluid" src="images/LogoMapo.png" width="80" />
<img class="logoImg img-fluid" src="images/LogoMapo.png" height="24" />
<span class="mainHead p-3"><b><span style="color: #DEDEDE;">MP MON</span>itor</b></span>
</div>
<div class="px-2">
<span id="text-white text-right">
@($"{DateTime.Now:dddd dd MMMM yyyy}")
</span>
<img class="logoImg img-fluid" src="images/logoCliente.png" width="32" />
<img class="logoImg img-fluid" src="images/logoCliente.png" height="24" />
EgalWare
</div>
+92 -29
View File
@@ -9,44 +9,107 @@
<div class="d-flex mb-1 ui-title justify-content-center align-items-center text-uppercase">
@CurrRecord.Nome
</div>
<div class="d-flex justify-content-between pt-0 pb-2 px-1 fontSmall text-uppercase">
<div class="px-1 pe-0">Art</div>
<div class="px-1 ps-0 ui-art">
@if (showArt == "CodArticolo")
@if (hasRow(1))
{
<div class="d-flex justify-content-between pt-0 pb-0 px-1">
@foreach (var item in rowValues(1))
{
<span>@CurrRecord.CodArticolo</span>
<div class="px-1 @item.TagCss">@item.TagName: <b>@currVal(item.TagLocation)</b></div>
}
else
{
if (string.IsNullOrEmpty(CurrRecord.Disegno))
</div>
}
else
{
<div class="d-flex justify-content-between pt-0 pb-2 px-1 fontSmall text-uppercase">
<div class="px-1 pe-0">Art</div>
<div class="px-1 ps-0 ui-art">
@if (showArt == "CodArticolo")
{
<span>[@CurrRecord.CodArticolo]</span>
<span>@CurrRecord.CodArticolo</span>
}
else
{
<span>@CurrRecord.Disegno</span>
if (string.IsNullOrEmpty(CurrRecord.Disegno))
{
<span>[@CurrRecord.CodArticolo]</span>
}
else
{
<span>@CurrRecord.Disegno</span>
}
}
</div>
</div>
}
@if (hasRow(2))
{
<div class="d-flex justify-content-between pt-0 pb-0 px-1">
@foreach (var item in rowValues(2))
{
<div class="px-1 @item.TagCss">@item.TagName: <b>@currVal(item.TagLocation)</b></div>
}
</div>
</div>
<div class="d-flex justify-content-between pt-0 pb-2 px-1 fontSmall">
<div class="px-1 text-uppercase"><b>@CurrRecord.DescrizioneStato</b></div>
<div class="px-1 ps-0">@getMinSec((decimal)CurrRecord.Durata)</div>
</div>
<div class="d-flex justify-content-between pt-0 pb-2 px-1 fontSmall text-uppercase">
@*<div class="col-6 pe-0">OEE</div>
<div class="col-6 ps-0">xx%</div>*@
<div class="px-1 pe-0">TCiclo</div>
<div class="px-1 ps-0">std: @getMinSec(@CurrRecord.TCAssegnato)</div>
<div class="px-1 ps-0">act: @getMinSec(@CurrRecord.TCLavRT)</div>
</div>
<div class="d-flex justify-content-between pt-0 pb-0 px-1 fontSmall1 text-uppercase">
@*<div class="px-1 pe-0">Pezzi</div>
<div class="px-1 ps-0">prod: @CurrRecord.PezziProd</div>
<div class="px-1 ps-0">ord: @CurrRecord.NumPezzi</div>*@
<div class="px-1 pe-0">Pezzi<sub>(prod/ord)</sub></div>
<div class="px-1 ps-0">@CurrRecord.PezziProd / @CurrRecord.NumPezzi</div>
</div>
}
else
{
<div class="d-flex justify-content-between pt-0 pb-2 px-1 fontSmall">
<div class="px-1 text-uppercase"><b>@CurrRecord.DescrizioneStato</b></div>
<div class="px-1 ps-0">@getMinSec(getDecimal(@CurrRecord.Durata))</div>
</div>
}
@if (hasRow(3))
{
<div class="d-flex justify-content-between pt-0 pb-0 px-1">
@foreach (var item in rowValues(3))
{
<div class="px-1 @item.TagCss">@item.TagName: <b>@currVal(item.TagLocation)</b></div>
}
</div>
}
else
{
<div class="d-flex justify-content-between pt-0 pb-2 px-1 fontSmall text-uppercase">
@*<div class="col-6 pe-0">OEE</div>
<div class="col-6 ps-0">xx%</div>*@
<div class="px-1 pe-0">TCiclo</div>
<div class="px-1 ps-0">std: @getMinSec(@CurrRecord.TCAssegnato)</div>
<div class="px-1 ps-0">act: @getMinSec(@CurrRecord.TCLavRT)</div>
</div>
}
@if (hasRow(4))
{
<div class="d-flex justify-content-between pt-0 pb-0 px-1">
@foreach (var item in rowValues(4))
{
<div class="px-1 @item.TagCss">@item.TagName: <b>@currVal(item.TagLocation)</b></div>
}
</div>
}
else
{
<div class="d-flex justify-content-between pt-0 pb-0 px-1 fontSmall1 text-uppercase">
<div class="px-1 pe-0">Pezzi<sub>(prod/ord)</sub></div>
<div class="px-1 ps-0">@CurrRecord.PezziProd / @CurrRecord.NumPezzi</div>
</div>
}
@if (hasRow(5))
{
<div class="d-flex justify-content-between pt-0 pb-0 px-1">
@foreach (var item in rowValues(5))
{
<div class="px-1 @item.TagCss">@item.TagName: <b>@currVal(item.TagLocation)</b></div>
}
</div>
}
@if (hasRow(6))
{
<div class="d-flex justify-content-between pt-0 pb-0 px-1">
@foreach (var item in rowValues(6))
{
<div class="px-1 @item.TagCss">@item.TagName: <b>@currVal(item.TagLocation)</b></div>
}
</div>
}
</div>
<div class="@cssComStatus(CurrRecord.Semaforo, CurrRecord.LastUpdate) p-1">
<div class="row fontSmaller mt-1">
+229 -77
View File
@@ -1,59 +1,212 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using System.Net.Http;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.Web.Virtualization;
using Microsoft.JSInterop;
using MP.Mon;
using MP.Mon.Shared;
using MP.Mon.Components;
using MP.Data.Conf;
using MP.Data.DatabaseModels;
using NLog;
namespace MP.Mon.Components
{
public partial class DetailMSE
{
#region Public Properties
protected string baseCss = "sem";
protected bool dataLoaded { get; set; } = false;
protected int kaFactor = 60 / 2;
[Parameter]
public MappaStatoExpl? CurrRecord { get; set; } = null;
[Parameter]
public List<TagData>? currTagConf { get; set; } = null;
[Parameter]
public Dictionary<string, string> currTagVal { get; set; } = new Dictionary<string, string>();
[Parameter]
public bool doAnimate { get; set; } = true;
[Parameter]
public string showArt { get; set; } = "";
public bool doBlink { get; set; } = false;
[Parameter]
public int keepAliveMin { get; set; } = 5;
[Parameter]
public MappaStatoExpl? CurrRecord { get; set; } = null;
private string cssStatus(string codSemaforo)
[Parameter]
public string showArt { get; set; } = "";
#endregion Public Properties
#region Public Methods
public void Dispose()
{
string codColore = codSemaforo.Substring(1, 2);
string answ = $"{baseCss}{codColore}";
if (doAnimate && codColore != "Ve")
aTimer.Elapsed -= ElapsedTimer;
aTimer.Stop();
aTimer.Dispose();
}
public void ElapsedTimer(object? source, System.Timers.ElapsedEventArgs e)
{
var pUpd = Task.Run(async () =>
{
// blink se secondo pari...
DateTime adesso = DateTime.Now;
int resto = 0;
Math.DivRem(adesso.Second, 2, out resto);
if (resto == 0)
await Task.Delay(1);
// verifica variazione x blink...
bool needUpdate = false;
if (CurrRecord == null)
{
answ += "_b";
needUpdate = true;
}
else
{
if (OldRecord == null)
{
needUpdate = true;
}
else
{
if (!CurrRecord.Semaforo.Equals(OldRecord.Semaforo) || CurrRecord.Semaforo != "sVe")
{
needUpdate = true;
}
}
}
if (needUpdate)
{
if (false)
{
Log.Trace($"Elapsed Timer {CurrRecord?.CodMacchina}");
}
await InvokeAsync(() => StateHasChanged());
}
OldRecord = CurrRecord;
});
pUpd.Wait();
}
public void StartTimer()
{
int tOutPeriod = 1000;
//int.TryParse(Configuration["ReloadStatusTimer"], out tOutPeriod);
aTimer = new System.Timers.Timer(tOutPeriod);
aTimer.Elapsed += ElapsedTimer;
aTimer.Enabled = true;
aTimer.Start();
}
#endregion Public Methods
#region Protected Fields
protected string baseCss = "sem";
protected int kaFactor = 60 / 2;
#endregion Protected Fields
#region Protected Properties
protected string codIOB
{
get
{
string answ = "";
if (CurrRecord != null)
{
answ = CurrRecord.IdxMacchina;
}
return answ;
}
}
protected bool dataLoaded { get; set; } = false;
#endregion Protected Properties
#region Protected Methods
/// <summary>
/// restituisce il valore data la tagLocation
/// </summary>
/// <param name="tagLocation"></param>
/// <returns></returns>
protected string currVal(string tagLocation)
{
string answ = "";
if (currTagVal.ContainsKey(tagLocation))
{
answ = currTagVal[tagLocation];
}
return answ;
}
/// <summary>
/// Verifica se ci sia un override per la riga indicata
/// </summary>
/// <param name="numRow"></param>
/// <returns></returns>
protected bool hasRow(int numRow)
{
bool answ = false;
if (currTagConf != null)
{
if (currTagConf.Count > 0)
{
var currVals = rowValues(numRow);
answ = currVals.Count > 0;
}
}
return answ;
}
protected override async Task OnInitializedAsync()
{
//StartTimer();
Random rnd = new Random();
await Task.Delay(rnd.Next(5));
setupConf();
dataLoaded = true;
}
/// <summary>
/// Restituisce (se presenti) valori di override per la riga indicata
/// </summary>
/// <param name="numRow"></param>
/// <returns></returns>
protected List<TagData> rowValues(int numRow)
{
List<TagData>? rowVals = null;
if (currTagConf != null)
{
if (currTagConf.Count > 0)
{
//cerco solo la riga corrente...
rowVals = currTagConf.Where(x => x.RowNum == numRow).ToList();
}
}
if (rowVals == null)
{
rowVals = new List<TagData>();
}
return rowVals;
}
#endregion Protected Methods
#region Private Fields
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
#endregion Private Fields
#region Private Properties
private static System.Timers.Timer aTimer { get; set; } = null!;
/// <summary>
/// Valore precedente x calcolo variazione
/// </summary>
private MappaStatoExpl? OldRecord { get; set; } = null;
#endregion Private Properties
#region Private Methods
private string cssComStatus(string semaforo, DateTime? lastUpdateN)
{
DateTime lastUpdate = lastUpdateN.HasValue ? (DateTime)lastUpdateN : DateTime.Now.AddHours(-1);
@@ -72,18 +225,56 @@ namespace MP.Mon.Components
}
return answ;
}
protected override async Task OnInitializedAsync()
private string cssStatus(string codSemaforo)
{
StartTimer();
Random rnd = new Random();
//await Task.Delay(rnd.Next(500));
dataLoaded = true;
setupConf();
// se vuoto --> mostra nero!
if (string.IsNullOrEmpty(codSemaforo))
{
codSemaforo = "sNe";
}
string codColore = codSemaforo.Substring(1, 2);
string answ = $"{baseCss}{codColore}";
if (doAnimate && codColore != "Ve")
{
if (doBlink)
{
answ += "_b";
}
}
return answ;
}
private decimal getDecimal(object? rawData)
{
decimal answ = 0;
if (rawData != null)
{
decimal.TryParse($"{rawData}", out answ);
}
return answ;
}
private string getMinSec(decimal? currTimeMin)
{
string answ = "nd";
TimeSpan tSpan = new TimeSpan(0);
try
{
double cTimeMin = currTimeMin != null ? (double)currTimeMin : 0;
tSpan = TimeSpan.FromMinutes(cTimeMin);
answ = $"{tSpan:mm}:{tSpan:ss}";
}
catch
{ }
return answ;
}
private void setupConf()
{
//baseCss = doAnimate ? "semBlink" : "sem";
}
private bool showComErr(DateTime? lastUpdateN)
{
DateTime lastUpdate = lastUpdateN.HasValue ? (DateTime)lastUpdateN : DateTime.Now.AddHours(-1);
@@ -95,45 +286,6 @@ namespace MP.Mon.Components
return answ;
}
private string getMinSec(decimal? currTimeMin)
{
string answ = "nd";
TimeSpan tSpan = new TimeSpan(0);
try
{
tSpan = TimeSpan.FromMinutes((double)currTimeMin);
answ = $"{tSpan:mm}:{tSpan:ss}";
}
catch
{ }
return answ;
}
public void Dispose()
{
aTimer.Stop();
aTimer.Dispose();
}
private static System.Timers.Timer aTimer = new System.Timers.Timer(60 * 1000);
public void StartTimer()
{
int tOutPeriod = 1000;
//int.TryParse(Configuration["ReloadStatusTimer"], out tOutPeriod);
aTimer = new System.Timers.Timer(tOutPeriod);
aTimer.Elapsed += ElapsedTimer;
aTimer.Enabled = true;
aTimer.Start();
}
public void ElapsedTimer(Object source, System.Timers.ElapsedEventArgs e)
{
var pUpd = Task.Run(async () =>
{
await Task.Delay(1);
await InvokeAsync(StateHasChanged);
});
pUpd.Wait();
}
#endregion Private Methods
}
}
+5
View File
@@ -0,0 +1,5 @@
{
"IobSetup": {
"***": []
}
}
+90
View File
@@ -0,0 +1,90 @@
{
"IobSetup": {
"***": [
{
"ColNum": 1,
"RowNum": 5,
"TagCss": "fontSmall",
"TagName": "Feed Over",
"TagLocation": "MoonPro:SQL2016DEV:MoonPro:FLOG:***:FEED_OVER"
},
{
"ColNum": 2,
"RowNum": 5,
"TagCss": "fontSmall",
"TagName": "Rapid Over",
"TagLocation": "MoonPro:SQL2016DEV:MoonPro:FLOG:***:RAPID_OVER"
}
],
"SIMUL_01": [
{
"ColNum": 1,
"RowNum": 6,
"TagCss": "fontSmall",
"TagName": "Power",
"TagLocation": "MoonPro:SQL2016DEV:MoonPro:FLOG:SIMUL_01:POWER_01"
}
],
"SIMUL_02": [
{
"ColNum": 1,
"RowNum": 6,
"TagCss": "fontSmall",
"TagName": "Power",
"TagLocation": "MoonPro:SQL2016DEV:MoonPro:FLOG:SIMUL_02:POWER_01"
}
],
"GIACO_ICOEL_001": [
{
"ColNum": 1,
"RowNum": 1,
"TagName": "Vel",
"TagLocation": "FluxData:TonnOra"
},
{
"ColNum": 2,
"RowNum": 1,
"TagName": "Vel",
"TagLocation": "FluxData:PezziMin"
},
{
"ColNum": 1,
"RowNum": 2,
"TagName": "Batch SX",
"TagLocation": "FluxData:BatchL1"
},
{
"ColNum": 2,
"RowNum": 2,
"TagName": "Batch DX",
"TagLocation": "FluxData:BatchL2"
}
],
"GIACO_ICOEL_002": [
{
"ColNum": 1,
"RowNum": 1,
"TagName": "Vel",
"TagLocation": "FluxData:TonnOra"
},
{
"ColNum": 2,
"RowNum": 1,
"TagName": "Vel",
"TagLocation": "FluxData:PezziMin"
},
{
"ColNum": 1,
"RowNum": 2,
"TagName": "Batch SX",
"TagLocation": "FluxData:BatchL1"
},
{
"ColNum": 2,
"RowNum": 2,
"TagName": "Batch DX",
"TagLocation": "FluxData:BatchL2"
}
]
}
}
+254 -22
View File
@@ -1,29 +1,30 @@
using MP.Data.DatabaseModels;
using MP.Data;
using MP.Data.Conf;
using MP.Data.DatabaseModels;
using Newtonsoft.Json;
using NLog;
using StackExchange.Redis;
using System.Diagnostics;
using System.Text;
namespace MP.Mon.Data
{
public class MpDataService : IDisposable
{
#region Private Fields
private static IConfiguration _configuration;
private static ILogger<MpDataService> _logger;
#endregion Private Fields
#region Public Fields
public static MP.Data.Controllers.MpMonController dbController;
#endregion Public Fields
#region Public Constructors
public MpDataService(IConfiguration configuration, ILogger<MpDataService> logger)
{
_logger = logger;
_configuration = configuration;
// setup compoenti REDIS
redisConn = ConnectionMultiplexer.Connect(_configuration.GetConnectionString("Redis"));
redisDb = redisConn.GetDatabase();
// setup canali pub/sub
dataPipe = new MessagePipe(redisConn, Constants.ACT_MSE_DATA_KEY);
blinkPipe = new MessagePipe(redisConn, Constants.ACT_BLINK_KEY);
// conf DB
string connStr = _configuration.GetConnectionString("Mp.Mon");
if (string.IsNullOrEmpty(connStr))
@@ -35,13 +36,33 @@ namespace MP.Mon.Data
dbController = new MP.Data.Controllers.MpMonController(configuration);
StringBuilder sb = new StringBuilder();
sb.AppendLine($"DbController OK");
//sb.AppendLine($"CST: {dbController.CustomersCount()} | CNT: {dbController.CountersCount()} | BSK: {dbController.BasketsCount()} | NGT: {dbController.NegotiationsCount()} | DOC: {dbController.DocsCount()} | ITM: {dbController.ItemsCount()} | RES: {dbController.ResourcesCount()}");
_logger.LogInformation(sb.ToString());
}
// setup conf IOB da dizionario
tryLoadIobTags();
// avvio timers...
startTimers();
}
#endregion Public Constructors
#region Public Properties
public static MP.Data.Controllers.MpMonController dbController { get; set; } = null!;
public MessagePipe blinkPipe { get; set; } = null!;
/// <summary>
/// Dizionario dei tag configurati per IOB
/// </summary>
public Dictionary<string, List<TagData>> currTagConf { get; set; } = new Dictionary<string, List<TagData>>();
public MessagePipe dataPipe { get; set; } = null!;
#endregion Public Properties
#region Public Methods
public Task<List<ConfigModel>> ConfigGetAll()
@@ -55,21 +76,232 @@ namespace MP.Mon.Data
dbController.Dispose();
}
public Task<List<Macchine>> MacchineGetAll()
/// <summary>
/// Richiesta attivazione --&gt; sposto avanti 1 minuto il periodo limite x fast running
/// </summary>
public void doActivate()
{
return Task.FromResult(dbController.MacchineGetAll().ToList());
fastLimit = DateTime.Now.AddMinutes(1);
}
public Task<List<MappaStatoExpl>> MseGetAll()
/// <summary>
/// Elenco setup dei tag conf correnti
/// </summary>
/// <returns></returns>
public Task<Dictionary<string, List<TagData>>> getAllTags()
{
var dbResult = dbController.MseGetAll();
if (dbResult == null)
return Task.FromResult(currTagConf);
}
/// <summary>
/// restituisce il valore da REDIS associato al tag richeisto
/// </summary>
/// <param name="redKey">Chiave in cui cercare il valore</param>
/// <returns></returns>
public string getTagConf(string redKey)
{
string outVal = "";
// cerco in REDIS la conf x l'IOB
var rawData = redisDb.StringGet(redKey);
if (!string.IsNullOrEmpty(rawData))
{
dbResult = new List<MappaStatoExpl>();
outVal = $"{rawData}";
}
return Task.FromResult(dbResult);
return outVal;
}
public Task<List<Macchine>> MacchineGetAll()
{
return Task.FromResult(dbController.MacchineGetAll());
}
public async Task<List<MappaStatoExpl>> MseGetAll()
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
List<MappaStatoExpl> result = new List<MappaStatoExpl>();
// cerco in redis...
var rawData = await redisDb.StringGetAsync(redisMseKey);
if (!string.IsNullOrEmpty(rawData))
{
result = JsonConvert.DeserializeObject<List<MappaStatoExpl>>(rawData);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"Read from REDIS: {ts.TotalMilliseconds}ms");
}
else
{
result = await Task.FromResult(dbController.MseGetAll());
// serializzp e salvo...
rawData = JsonConvert.SerializeObject(result);
await redisDb.StringSetAsync(redisMseKey, rawData, TimeSpan.FromSeconds(2));
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"Read from DB: {ts.TotalMilliseconds}ms");
}
if (result == null)
{
result = new List<MappaStatoExpl>();
}
return result;
}
#endregion Public Methods
#region Private Fields
private static IConfiguration _configuration = null!;
private static ILogger<MpDataService> _logger = null!;
private static System.Timers.Timer fastTimer = new System.Timers.Timer(4000);
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
/// <summary>
/// Limite in formato data-ora per inviare dati rapidamente (incrementato come now + 1 min
/// ad ogni chiamata client)
/// </summary>
private DateTime fastLimit = DateTime.Now;
private int fastRefreshMs = 1000;
/// <summary>
/// Oggetto per connessione a REDIS
/// </summary>
private ConnectionMultiplexer redisConn = null!;
//ISubscriber sub = redis.GetSubscriber();
/// <summary>
/// Oggetto DB redis da impiegare x chiamate R/W
/// </summary>
private IDatabase redisDb = null!;
private string redisMseKey = "MP:MON:Cache:MSE";
#endregion Private Fields
#region Private Methods
private void ElapsedFastTimer(object? source, System.Timers.ElapsedEventArgs e)
{
var pUpd = Task.Run(async () =>
{
// secondi pari --> blink, secondi dispari --> ricarica
DateTime adesso = DateTime.Now;
int resto = 0;
Math.DivRem(adesso.Second, 2, out resto);
if (resto == 0)
{
// invio in channel blink il segnale
blinkPipe.sendMessage("true");
Log.Debug("Elapsed Fast Timer Blink");
}
else
{
// invio in channel blink segnale false
blinkPipe.sendMessage("false");
// rileggo dati...
var newData = await MseGetAll();
// invio tramite la pipe...
dataPipe.sendMessage(JsonConvert.SerializeObject(newData));
Log.Debug("Elapsed Fast Timer reload");
}
});
pUpd.Wait();
}
private void startTimers()
{
fastTimer = new System.Timers.Timer(fastRefreshMs);
fastTimer.Elapsed += ElapsedFastTimer;
fastTimer.Enabled = true;
fastTimer.Start();
}
/// <summary>
/// Prova a caricare da file la conf degli IOB se presente
/// </summary>
private void tryLoadIobTags()
{
Dictionary<string, List<TagData>> currConf = new Dictionary<string, List<TagData>>();
string strExeFilePath = System.Reflection.Assembly.GetExecutingAssembly().Location;
if (!string.IsNullOrEmpty(strExeFilePath))
{
string? strWorkPath = Path.GetDirectoryName(strExeFilePath);
if (!string.IsNullOrEmpty(strWorkPath))
{
string filePath = $"{strWorkPath}/Conf/iobTagsConf.json";
if (File.Exists(filePath))
{
string rawData = File.ReadAllText(filePath);
if (!string.IsNullOrEmpty(rawData))
{
var fileConfData = JsonConvert.DeserializeObject<IobTags>(rawData);
if (fileConfData != null)
{
// effettuo esplosione conf SE contenesse il valore "***" = tutti
// gli IOB
if (fileConfData.IobSetup.ContainsKey("***"))
{
// recupero elenco macchine...
var elencoMacc = dbController.MacchineGetAll();
// x ogni macchina creo le righe standard da conf...
var baseConf = fileConfData.IobSetup.Where(x => x.Key == "***").FirstOrDefault();
foreach (var item in elencoMacc)
{
if (!string.IsNullOrEmpty(item.IdxMacchina))
{
// converto i valori x la macchina corrente... clono in
// nuovo oggetto
var specVal = baseConf.Value.Select(i => i.Clone()).ToList();
// sostituisco segnaposto
foreach (var singleVal in specVal)
{
singleVal.TagLocation = singleVal.TagLocation.Replace("***", item.IdxMacchina);
}
// ora aggiungo eventuali valori in override...
if (fileConfData.IobSetup.ContainsKey(item.IdxMacchina))
{
var otConf = fileConfData.IobSetup.Where(x => x.Key == item.IdxMacchina).FirstOrDefault();
//verifico x ogni valore other...
foreach (var otTag in otConf.Value)
{
var ovrTag = specVal.Where(x => x.ColNum == otTag.ColNum && x.RowNum == otTag.RowNum).FirstOrDefault();
// se contiene --> sovrascrivo
if (ovrTag != null)
{
//ovrTag = otTag.Clone();
specVal.Remove(ovrTag);
specVal.Add(otTag.Clone());
}
// se non contiene --> aggiungo
else
{
specVal.Add(otTag);
}
}
}
currConf.Add(item.IdxMacchina, specVal);
}
}
}
// altrimenti copio ed ho finito
else
{
currConf = fileConfData.IobSetup;
}
}
}
}
if (currConf != null)
{
currTagConf = currConf;
}
}
}
}
#endregion Private Methods
}
}
+15 -3
View File
@@ -4,7 +4,7 @@
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<Version>6.15.2204.1416</Version>
<Version>6.15.2207.1219</Version>
</PropertyGroup>
<ItemGroup>
@@ -30,13 +30,25 @@
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NLog" Version="4.7.15" />
<PackageReference Include="StackExchange.Redis" Version="2.5.61" />
<PackageReference Include="NLog" Version="5.0.1" />
<PackageReference Include="StackExchange.Redis" Version="2.6.48" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MP.Data\MP.Data.csproj" />
</ItemGroup>
<ItemGroup>
<Content Update="Conf\iobTagsConf.office.json">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<None Update="logs\.placeholder">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="powershell.exe -ExecutionPolicy Unrestricted -NoProfile -NonInteractive -File $(ProjectDir)\post-build.ps1 -ProjectDir $(ProjectDir) -ProjectPath $(ProjectPath)" />
</Target>
+2 -2
View File
@@ -29,7 +29,7 @@
layout="${longdate} ${uppercase:${level}} ${message}" />
-->
<target xsi:type="File" name="fileTarget" fileName="${basedir}/logs/${shortdate}.log" layout="${longdate} | ${uppercase:${level}} | ${logger:shortName=false} | ${message}" />
<target xsi:type="ColoredConsole" name="consoleTarget" layout="${longdate} | ${uppercase:${level}} | ${logger:shortName=true}| ${message}" />
<target xsi:type="ColoredConsole" name="consoleTarget" layout="${longdate} | ${uppercase:${level}} | ${logger:shortName=true} | ${message}" />
</targets>
<rules>
@@ -39,7 +39,7 @@
Write all events with minimal level of Debug (So Debug, Info, Warn, Error and Fatal, but not Trace) to "f"
<logger name="*" minlevel="Debug" writeTo="f" />
-->
<logger name="*" minlevel="Trace" writeTo="consoleTarget" />
<logger name="*" minlevel="Debug" writeTo="consoleTarget" />
<!--<logger name="Microsoft.*" maxlevel="Info" final="true" />-->
<logger name="*" minlevel="Info" writeTo="fileTarget" />
</rules>
+8 -11
View File
@@ -2,18 +2,17 @@
<PageTitle>Index</PageTitle>
<PageTitle>MP MON</PageTitle>
<div class="row statusMap mx-1 my-1">
@if (ListMSE == null)
@if (listMSE == null)
{
<div class="col-12">
<LoadingData></LoadingData>
</div>
}
else if (ListMSE.Count == 0)
else if (listMSE.Count == 0)
{
<div class="col-12">
<div class="alert alert-warning">
@@ -24,23 +23,21 @@
else
{
int currIdx = 0;
foreach (var macchina in ListMSE)
foreach (var recordIob in listMSE)
{
<DetailMSE CurrRecord="@macchina" doAnimate="@doAnimate" keepAliveMin="@keepAliveMin" showArt="@showArt"></DetailMSE>
<DetailMSE CurrRecord="@recordIob" currTagConf="@getIobTag(recordIob.IdxMacchina)" currTagVal="@getTagVal(recordIob.IdxMacchina)" doAnimate="@doAnimate" keepAliveMin="@keepAliveMin" showArt="@showArt" doBlink="@doBlink"></DetailMSE>
currIdx++;
if (currIdx >= maxCol)
{
currIdx = 0;
@((MarkupString)"</div><div class=\"row statusMap mx-1 my-1\">")
;
@((MarkupString)"</div><div class=\"row statusMap mx-1 my-1\">");
}
}
// controllo se devo "chiudere riga...
int currNum = (currIdx % maxCol);
while (currNum < (maxCol))
{
@((MarkupString)"<div class=\"col machBlock\">&nbsp;</div>")
;
@((MarkupString)"<div class=\"col machBlock\">&nbsp;</div>");
currNum++;
}
+196 -98
View File
@@ -1,62 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using System.Net.Http;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.Web.Virtualization;
using Microsoft.JSInterop;
using MP.Mon;
using MP.Mon.Shared;
using MP.Mon.Components;
using MP.Data;
using MP.Data.Conf;
using MP.Data.DatabaseModels;
using MP.Mon.Components;
using MP.Mon.Data;
using Newtonsoft.Json;
using NLog;
namespace MP.Mon.Pages
{
public partial class Index : IDisposable
{
protected List<MappaStatoExpl>? ListMSE = null;
List<ConfigModel>? CurrConfig = null;
#region Public Methods
public void Dispose()
{
disposeTimers();
}
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
public async void ElapsedSlowTimer(object? source, System.Timers.ElapsedEventArgs e)
{
listMSE = null;
await Task.Delay(1);
Log.Info("Elapsed Slow Timer --> full page reload");
// dispongo i vari timers...
disposeTimers();
await Task.Delay(1);
// reload pagina
NavManager.NavigateTo(NavManager.Uri);
}
protected int keepAliveMin = 1;
public void StartTimer()
{
// timer lento
slowTimer = new System.Timers.Timer(slowRefreshMs);
slowTimer.Elapsed += ElapsedSlowTimer;
slowTimer.Enabled = true;
slowTimer.Start();
}
protected int maxCol = 4;
#endregion Public Methods
#region Protected Fields
protected bool doAnimate = true;
protected int fastRefreshMs = 1000;
protected int keepAliveMin = 1;
protected int maxCol = 6;
protected string showArt = "";
protected int slowRefreshSec = 300;
protected int fastRefreshSec = 10;
#endregion Protected Fields
protected int slowRefreshMs
{
get => 1000 * slowRefreshSec;
}
protected int fastRefreshMs
{
get => 1000 * fastRefreshSec;
}
protected override async Task OnInitializedAsync()
{
await setupConf();
await ReloadData();
StartTimer();
}
#region Protected Properties
[Inject]
protected MpDataService MMDataService { get; set; } = null!;
@@ -64,24 +59,35 @@ namespace MP.Mon.Pages
[Inject]
protected NavigationManager NavManager { get; set; } = null!;
private async Task setupConf()
protected int slowRefreshMs
{
CurrConfig = await MMDataService.ConfigGetAll();
get => 1000 * slowRefreshSec;
}
#endregion Protected Properties
#region Protected Methods
/// <summary>
/// Recupera il valore e se trovato aggiorna
/// </summary>
/// <param name="chiave">Valore da cercare</param>
/// <param name="varObj">String in cui salvare il valore se trovato</param>
/// <returns></returns>
protected bool getConfVal(string chiave, ref string varObj)
{
bool answ = false;
if (CurrConfig != null && CurrConfig.Count > 0)
{
// sistemo i parametri opzionali...
getConfValInt("keepAliveMin", ref keepAliveMin);
getConfValInt("MON_maxCol", ref maxCol);
int intDoAnim = 0;
getConfValInt("doAnimate", ref intDoAnim);
doAnimate = intDoAnim == 1;
getConfValInt("pageRefreshSec", ref slowRefreshSec);
getConfValInt("MSE_cacheDuration", ref fastRefreshSec);
getConfVal("sART", ref showArt);
Log.Info($"Effettuato setup parametri | keepAlive: {keepAliveMin} | MaxCol: {maxCol} | doAnimate: {doAnimate} | slowRefreshSec: {slowRefreshSec} | fastRefreshSec: {fastRefreshSec}");
ConfigModel? risultato = CurrConfig.FirstOrDefault(x => x.Chiave == chiave);
if (risultato != null)
{
varObj = risultato.Valore;
answ = !string.IsNullOrEmpty(risultato.Valore);
}
}
return answ;
}
/// <summary>
@@ -106,72 +112,164 @@ namespace MP.Mon.Pages
}
/// <summary>
/// Recupera il valore e se trovato aggiorna
/// Recupera da conf eventuale setup tag dell'IOB indicato
/// </summary>
/// <param name="chiave">Valore da cercare</param>
/// <param name="varObj">String in cui salvare il valore se trovato</param>
/// <param name="codIob"></param>
/// <returns></returns>
protected bool getConfVal(string chiave, ref string varObj)
protected List<TagData>? getIobTag(string codIob)
{
bool answ = false;
if (CurrConfig != null && CurrConfig.Count > 0)
List<TagData>? answ = null;
if (MMDataService.currTagConf != null)
{
// sistemo i parametri opzionali...
ConfigModel? risultato = CurrConfig.FirstOrDefault(x => x.Chiave == chiave);
if (risultato != null)
// cerco x chiave IOB...
if (MMDataService.currTagConf.ContainsKey(codIob))
{
varObj = risultato.Valore;
answ = !string.IsNullOrEmpty(risultato.Valore);
answ = MMDataService.currTagConf[codIob];
}
}
return answ;
}
private async Task ReloadData()
/// <summary>
/// Recupera da redis (in una chiamata soltanto) tutti i valori richiesti e compone un
/// dizionario x ottimizzare visualizzazione
/// </summary>
/// <param name="codIob"></param>
/// <returns></returns>
protected Dictionary<string, string> getTagVal(string codIob)
{
ListMSE = await MMDataService.MseGetAll();
Dictionary<string, string> answ = new Dictionary<string, string>();
// recupero conf tags...
var currTags = getIobTag(codIob);
if (currTags != null && currTags.Count > 0)
{
// FIXME TODO !!!! FARE !!!! - da verificare
answ = currTags.ToDictionary(x => x.TagLocation, x => MMDataService.getTagConf(x.TagLocation));
}
return answ;
}
public void Dispose()
protected override async Task OnInitializedAsync()
{
fastTimer.Stop();
fastTimer.Dispose();
await setupConf();
//await ReloadData();
MMDataService.dataPipe.EA_NewMessage += DataPipe_EA_NewMessage;
MMDataService.blinkPipe.EA_NewMessage += BlinkPipe_EA_NewMessage;
StartTimer();
}
#endregion Protected Methods
#region Private Fields
//private static System.Timers.Timer fastTimer = new System.Timers.Timer(4000);
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
private static System.Timers.Timer slowTimer = new System.Timers.Timer(300000);
private List<ConfigModel>? CurrConfig = null;
private bool doBlink = false;
private List<MappaStatoExpl>? listMSE = null;
#endregion Private Fields
#region Private Methods
private void BlinkPipe_EA_NewMessage(object? sender, EventArgs e)
{
PubSubEventArgs currArgs = (PubSubEventArgs)e;
// conversione on-the-fly List<string> --> allarmi
if (!string.IsNullOrEmpty(currArgs.newMessage))
{
try
{
var dataRaw = JsonConvert.DeserializeObject<string>(currArgs.newMessage);
if (dataRaw != null)
{
bool.TryParse($"{dataRaw}", out doBlink);
}
}
catch
{ }
InvokeAsync(() =>
{
StateHasChanged();
});
}
}
/// <summary>
/// Ricevuto nuovi dati da mostrare!
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <exception cref="NotImplementedException"></exception>
private void DataPipe_EA_NewMessage(object? sender, EventArgs e)
{
//fastTimer.Stop();
PubSubEventArgs currArgs = (PubSubEventArgs)e;
// conversione on-the-fly List<string> --> allarmi
if (!string.IsNullOrEmpty(currArgs.newMessage))
{
try
{
var dataList = JsonConvert.DeserializeObject<List<MappaStatoExpl>>(currArgs.newMessage);
if (dataList != null)
{
#if DEBUG
// hack: legge 4 volte i dati x stressare sistema
var singleData = dataList;
listMSE = new List<MappaStatoExpl>();
for (int i = 0; i < 4; i++)
{
listMSE.AddRange(singleData);
}
#else
listMSE = dataList;
#endif
}
}
catch
{ }
}
InvokeAsync(() =>
{
// attesa random 0-50ms...
Random rnd = new Random();
Task.Delay(rnd.Next(5, 50));
StateHasChanged();
});
//fastTimer.Start();
}
private void disposeTimers()
{
slowTimer.Elapsed -= ElapsedSlowTimer;
slowTimer.Stop();
slowTimer.Dispose();
}
private static System.Timers.Timer fastTimer = new System.Timers.Timer(4000);
private static System.Timers.Timer slowTimer = new System.Timers.Timer(300000);
public void StartTimer()
private async Task setupConf()
{
// timer veloce
fastTimer = new System.Timers.Timer(fastRefreshMs);
fastTimer.Elapsed += ElapsedFastTimer;
fastTimer.Enabled = true;
fastTimer.Start();
// timer lento
slowTimer = new System.Timers.Timer(slowRefreshMs);
slowTimer.Elapsed += ElapsedSlowTimer;
slowTimer.Enabled = true;
slowTimer.Start();
}
public void ElapsedFastTimer(Object source, System.Timers.ElapsedEventArgs e)
{
var pUpd = Task.Run(async () =>
CurrConfig = await MMDataService.ConfigGetAll();
if (CurrConfig != null && CurrConfig.Count > 0)
{
await ReloadData();
//await Task.Delay(1);
await InvokeAsync(StateHasChanged);
});
pUpd.Wait();
// sistemo i parametri opzionali...
getConfValInt("keepAliveMin", ref keepAliveMin);
getConfValInt("MON_maxCol", ref maxCol);
int intDoAnim = 0;
getConfValInt("doAnimate", ref intDoAnim);
doAnimate = intDoAnim == 1;
getConfValInt("pageRefreshSec", ref slowRefreshSec);
getConfVal("sART", ref showArt);
Log.Info($"setupConf | Effettuato setup parametri | keepAlive: {keepAliveMin} | MaxCol: {maxCol} | doAnimate: {doAnimate} | slowRefreshSec: {slowRefreshSec} | fastRefreshMs: {fastRefreshMs}");
}
}
public async void ElapsedSlowTimer(Object source, System.Timers.ElapsedEventArgs e)
{
ListMSE = null;
NavManager.NavigateTo(NavManager.Uri);
}
#endregion Private Methods
}
}
+1 -1
View File
@@ -5,4 +5,4 @@
Layout = "_Layout";
}
<component type="typeof(App)" render-mode="ServerPrerendered" />
<component type="typeof(App)" render-mode="Server" />
+15 -8
View File
@@ -28,17 +28,24 @@
<a class="dismiss">🗙</a>
</div>
@* Riconnessione server app: https://www.syncfusion.com/faq/how-do-i-reconnect-blazor-server-side-automatically *@
@*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.defaultReconnectionHandler._reconnectCallback = function (d) {
document.location.reload();
}
Blazor.start().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()
}
}
});
});
</script>
<script src="_framework/blazor.server.js"></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>
<script src="lib/chartBoot.js"></script>
</body>
</html>
-1
View File
@@ -21,7 +21,6 @@ string redisSrvAddr = connStringRedis.Substring(0, connStringRedis.IndexOf(":"))
// avvio oggetto shared x redis...
var redisMultiplexer = ConnectionMultiplexer.Connect(connStringRedis);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
@@ -7,6 +7,6 @@ by editing this MSBuild file. In order to learn more about this please visit htt
<PropertyGroup>
<TimeStampOfAssociatedLegacyPublishXmlFile />
<EncryptedPassword>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAA+11nhJeDSkeTlSej+COD3AAAAAACAAAAAAADZgAAwAAAABAAAACFCXZ0UR7Czo59aaRCHU5QAAAAAASAAACgAAAAEAAAACYlKt9E6s77uEikpKwyhdQYAAAAUwae989LovFbsfjRp69HCVpyUQZbqLyYFAAAAMW8mLSAxWmKaOvB4nkDgUpS27/b</EncryptedPassword>
<History>True|2022-04-14T07:37:09.1341280Z;True|2022-02-26T18:24:32.0833123+01:00;False|2022-02-26T18:24:15.3994092+01:00;False|2022-02-26T18:23:44.8358586+01:00;True|2021-05-26T19:49:30.0427896+02:00;False|2021-05-26T19:49:14.9065510+02:00;True|2021-05-25T17:48:33.3901785+02:00;True|2021-05-25T17:46:09.2063020+02:00;True|2021-05-25T17:42:47.8167539+02:00;True|2021-05-25T17:22:03.1877438+02:00;True|2021-05-25T17:21:05.1565775+02:00;True|2021-05-25T16:26:34.1426996+02:00;True|2021-05-25T16:14:28.2842402+02:00;True|2021-05-25T15:02:11.7131495+02:00;</History>
<History>True|2022-07-12T14:34:20.2940329Z;True|2022-04-14T09:37:09.1341280+02:00;True|2022-02-26T18:24:32.0833123+01:00;False|2022-02-26T18:24:15.3994092+01:00;False|2022-02-26T18:23:44.8358586+01:00;True|2021-05-26T19:49:30.0427896+02:00;False|2021-05-26T19:49:14.9065510+02:00;True|2021-05-25T17:48:33.3901785+02:00;True|2021-05-25T17:46:09.2063020+02:00;True|2021-05-25T17:42:47.8167539+02:00;True|2021-05-25T17:22:03.1877438+02:00;True|2021-05-25T17:21:05.1565775+02:00;True|2021-05-25T16:26:34.1426996+02:00;True|2021-05-25T16:14:28.2842402+02:00;True|2021-05-25T15:02:11.7131495+02:00;</History>
</PropertyGroup>
</Project>
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>Modulo MON MAPO</i>
<h4>Versione: 6.15.2204.1416</h4>
<h4>Versione: 6.15.2207.1219</h4>
<br /> Note di rilascio:
<ul>
<li>
+1 -1
View File
@@ -1 +1 @@
6.15.2204.1416
6.15.2207.1219
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>6.15.2204.1416</version>
<version>6.15.2207.1219</version>
<url>https://nexus.steamware.net/repository/SWS/MP-MON/stable/LAST/MP.Mon.zip</url>
<changelog>https://nexus.steamware.net/repository/SWS/MP-MON/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>
-14
View File
@@ -4,19 +4,6 @@
<div class="page">
<main>
@*<div class="top-row px-4 justify-content-between">
<div class="px-2">
<img class="logoImg img-fluid" src="images/LogoMapo.png" width="80" />
<span class="mainHead p-3"><b><span style="color: #DEDEDE;">MP MON</span>itor</b></span>
</div>
<div class="px-2">
<span id="text-white text-right">
@($"{DateTime.Now:dddd dd MMMM yyyy, HH:mm}")
</span>
<img class="logoImg img-fluid" src="images/logoCliente.png" width="32" />
EgalWare
</div>
</div>*@
<div class="top-row px-4 justify-content-between">
<CmpHeader></CmpHeader>
</div>
@@ -27,6 +14,5 @@
<div class="fixed-bottom bottom-row px-2">
<CmpFooter></CmpFooter>
</div>
</main>
</div>
-39
View File
@@ -1,39 +0,0 @@
<div class="top-row ps-3 navbar navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="">MP.Mon</a>
<button title="Navigation menu" class="navbar-toggler" @onclick="ToggleNavMenu">
<span class="navbar-toggler-icon"></span>
</button>
</div>
</div>
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
<nav class="flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="oi oi-home" aria-hidden="true"></span> Home
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="counter">
<span class="oi oi-plus" aria-hidden="true"></span> Counter
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="fetchdata">
<span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
</NavLink>
</div>
</nav>
</div>
@code {
private bool collapseNavMenu = true;
private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;
private void ToggleNavMenu()
{
collapseNavMenu = !collapseNavMenu;
}
}
-62
View File
@@ -1,62 +0,0 @@
.navbar-toggler {
background-color: rgba(255, 255, 255, 0.1);
}
.top-row {
height: 3.5rem;
background-color: rgba(0,0,0,0.4);
}
.navbar-brand {
font-size: 1.1rem;
}
.oi {
width: 2rem;
font-size: 1.1rem;
vertical-align: text-top;
top: -2px;
}
.nav-item {
font-size: 0.9rem;
padding-bottom: 0.5rem;
}
.nav-item:first-of-type {
padding-top: 1rem;
}
.nav-item:last-of-type {
padding-bottom: 1rem;
}
.nav-item ::deep a {
color: #d7d7d7;
border-radius: 4px;
height: 3rem;
display: flex;
align-items: center;
line-height: 3rem;
}
.nav-item ::deep a.active {
background-color: rgba(255,255,255,0.25);
color: white;
}
.nav-item ::deep a:hover {
background-color: rgba(255,255,255,0.1);
color: white;
}
@media (min-width: 641px) {
.navbar-toggler {
display: none;
}
.collapse {
/* Never collapse the sidebar for wide screens */
display: block;
}
}
-16
View File
@@ -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; }
}
+17
View File
@@ -0,0 +1,17 @@
{
"DetailedErrors": true,
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"CodApp": "MP.MON",
"ConnectionStrings": {
"MP.Mon": "Server=localhost\\SQLEXPRESS;Database=MoonPro; User ID=steamware;Password=viadante16; integrated security=False; MultipleActiveResultSets=True; App=Blazor.ServerApp;",
"MP.Stats": "Server=localhost\\SQLEXPRESS;Database=MoonPro_STATS; User ID=steamware;Password=viadante16; integrated security=False; MultipleActiveResultSets=True; App=Blazor.ServerApp;",
"Redis": "localhost:6379,DefaultDatabase=13,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false"
}
}
+1 -1
View File
@@ -10,6 +10,6 @@
"ConnectionStrings": {
"MP.Mon": "Server=SQL2016DEV;Database=MoonPro; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=Blazor.ServerApp;",
"MP.Stats": "Server=SQL2016DEV;Database=MoonPro_STATS; User ID=sa;Password=keyhammer16; integrated security=False; MultipleActiveResultSets=True; App=Blazor.ServerApp;",
"Redis": "localhost:6379,DefaultDatabase=13,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false"
"Redis": "localhost:6379,DefaultDatabase=1,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false"
}
}
+1 -16
View File
@@ -7,28 +7,13 @@
"destination": "wwwroot/lib/bootstrap/"
},
{
"library": "bootstrap-icons@1.8.1",
"library": "bootstrap-icons@1.8.3",
"destination": "wwwroot/lib/bootstrap-icons/"
},
{
"provider": "cdnjs",
"library": "font-awesome@6.1.1",
"destination": "wwwroot/lib/font-awesome/"
},
{
"provider": "cdnjs",
"library": "Chart.js@3.7.1",
"destination": "wwwroot/lib/Chart.js/"
},
{
"provider": "cdnjs",
"library": "chartjs-adapter-luxon@1.1.0",
"destination": "wwwroot/lib/chartjs-adapter-luxon/"
},
{
"provider": "cdnjs",
"library": "luxon@2.3.1",
"destination": "wwwroot/lib/luxon/"
}
]
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
@@ -1,7 +0,0 @@
/*!
* Chart.js v3.7.1
* https://www.chartjs.org
* (c) 2022 Chart.js Contributors
* Released under the MIT License
*/
export { H as HALF_PI, aX as INFINITY, P as PI, aW as PITAU, aZ as QUARTER_PI, aY as RAD_PER_DEG, T as TAU, a_ as TWO_THIRDS_PI, Q as _addGrace, V as _alignPixel, a0 as _alignStartEnd, p as _angleBetween, a$ as _angleDiff, _ as _arrayUnique, a6 as _attachContext, aq as _bezierCurveTo, an as _bezierInterpolation, av as _boundSegment, al as _boundSegments, a3 as _capitalize, ak as _computeSegments, a7 as _createResolver, aH as _decimalPlaces, aP as _deprecated, a8 as _descriptors, af as _elementsEqual, M as _factorize, aJ as _filterBetween, F as _getParentNode, U as _int16Range, ah as _isBetween, ag as _isClickEvent, K as _isDomSupported, z as _isPointInArea, w as _limitValue, aI as _longestText, aK as _lookup, x as _lookupByKey, S as _measureText, aN as _merger, aO as _mergerIf, aw as _normalizeAngle, ao as _pointInLine, ai as _readValueToProps, A as _rlookupByKey, aD as _setMinAndMaxByKey, am as _steppedInterpolation, ap as _steppedLineTo, az as _textX, $ as _toLeftRightCenter, aj as _updateBezierControlPoints, as as addRoundedRectPath, aG as almostEquals, aF as almostWhole, O as callback, ad as clearCanvas, W as clipArea, aM as clone, c as color, h as createContext, ab as debounce, j as defined, aC as distanceBetweenPoints, ar as drawPoint, D as each, e as easingEffects, N as finiteOrDefault, aU as fontString, o as formatNumber, B as getAngleFromPoint, aL as getHoverColor, E as getMaximumSize, y as getRelativePosition, ax as getRtlAdapter, aT as getStyle, b as isArray, g as isFinite, a5 as isFunction, k as isNullOrUndef, q as isNumber, i as isObject, l as listenArrayEvents, L as log10, a2 as merge, a9 as mergeIf, aE as niceNum, aB as noop, ay as overrideTextDirection, G as readUsedSize, X as renderText, r as requestAnimFrame, a as resolve, f as resolveObjectKey, aA as restoreTextDirection, ac as retinaScale, ae as setsEqual, s as sign, aR as splineCurve, aS as splineCurveMonotone, J as supportsEventListenerOptions, I as throttled, R as toDegrees, n as toDimension, Z as toFont, aQ as toFontString, aV as toLineHeight, C as toPadding, m as toPercentage, t as toRadians, at as toTRBL, au as toTRBLCorners, aa as uid, Y as unclipArea, u as unlistenArrayEvents, v as valueOrDefault } from './chunks/helpers.segment.js';
-1
View File
@@ -1 +0,0 @@
export{H as HALF_PI,aX as INFINITY,P as PI,aW as PITAU,aZ as QUARTER_PI,aY as RAD_PER_DEG,T as TAU,a_ as TWO_THIRDS_PI,Q as _addGrace,V as _alignPixel,a0 as _alignStartEnd,p as _angleBetween,a$ as _angleDiff,_ as _arrayUnique,a6 as _attachContext,aq as _bezierCurveTo,an as _bezierInterpolation,av as _boundSegment,al as _boundSegments,a3 as _capitalize,ak as _computeSegments,a7 as _createResolver,aH as _decimalPlaces,aP as _deprecated,a8 as _descriptors,af as _elementsEqual,M as _factorize,aJ as _filterBetween,F as _getParentNode,U as _int16Range,ah as _isBetween,ag as _isClickEvent,K as _isDomSupported,z as _isPointInArea,w as _limitValue,aI as _longestText,aK as _lookup,x as _lookupByKey,S as _measureText,aN as _merger,aO as _mergerIf,aw as _normalizeAngle,ao as _pointInLine,ai as _readValueToProps,A as _rlookupByKey,aD as _setMinAndMaxByKey,am as _steppedInterpolation,ap as _steppedLineTo,az as _textX,$ as _toLeftRightCenter,aj as _updateBezierControlPoints,as as addRoundedRectPath,aG as almostEquals,aF as almostWhole,O as callback,ad as clearCanvas,W as clipArea,aM as clone,c as color,h as createContext,ab as debounce,j as defined,aC as distanceBetweenPoints,ar as drawPoint,D as each,e as easingEffects,N as finiteOrDefault,aU as fontString,o as formatNumber,B as getAngleFromPoint,aL as getHoverColor,E as getMaximumSize,y as getRelativePosition,ax as getRtlAdapter,aT as getStyle,b as isArray,g as isFinite,a5 as isFunction,k as isNullOrUndef,q as isNumber,i as isObject,l as listenArrayEvents,L as log10,a2 as merge,a9 as mergeIf,aE as niceNum,aB as noop,ay as overrideTextDirection,G as readUsedSize,X as renderText,r as requestAnimFrame,a as resolve,f as resolveObjectKey,aA as restoreTextDirection,ac as retinaScale,ae as setsEqual,s as sign,aR as splineCurve,aS as splineCurveMonotone,J as supportsEventListenerOptions,I as throttled,R as toDegrees,n as toDimension,Z as toFont,aQ as toFontString,aV as toLineHeight,C as toPadding,m as toPercentage,t as toRadians,at as toTRBL,au as toTRBLCorners,aa as uid,Y as unclipArea,u as unlistenArrayEvents,v as valueOrDefault}from"./chunks/helpers.segment.js";
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 861 KiB

File diff suppressed because one or more lines are too long
@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bank" viewBox="0 0 16 16">
<path d="M8 .95 14.61 4h.89a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.5.5H15v7a.5.5 0 0 1 .485.379l.5 2A.5.5 0 0 1 15.5 17H.5a.5.5 0 0 1-.485-.621l.5-2A.5.5 0 0 1 1 14V7H.5a.5.5 0 0 1-.5-.5v-2A.5.5 0 0 1 .5 4h.89L8 .95zM3.776 4h8.447L8 2.05 3.776 4zM2 7v7h1V7H2zm2 0v7h2.5V7H4zm3.5 0v7h1V7h-1zm2 0v7H12V7H9.5zM13 7v7h1V7h-1zm2-1V5H1v1h14zm-.39 9H1.39l-.25 1h13.72l-.25-1z"/>
</svg>

Before

Width:  |  Height:  |  Size: 494 B

@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-house-heart-fill" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8.707 1.5a1 1 0 0 0-1.414 0L.646 8.146a.5.5 0 0 0 .708.707L8 2.207l6.646 6.646a.5.5 0 0 0 .708-.707L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.707 1.5Z"/>
<path fill-rule="evenodd" d="m8 3.293 6 6V13.5a1.5 1.5 0 0 1-1.5 1.5h-9A1.5 1.5 0 0 1 2 13.5V9.293l6-6Zm0 5.189c1.664-1.673 5.825 1.254 0 5.018-5.825-3.764-1.664-6.691 0-5.018Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 524 B

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-house-heart" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8.707 1.5a1 1 0 0 0-1.414 0L.646 8.146a.5.5 0 0 0 .708.707L2 8.207V13.5A1.5 1.5 0 0 0 3.5 15h9a1.5 1.5 0 0 0 1.5-1.5V8.207l.646.646a.5.5 0 0 0 .708-.707L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.707 1.5ZM13 7.207l-5-5-5 5V13.5a.5.5 0 0 0 .5.5h9a.5.5 0 0 0 .5-.5V7.207Zm-5-.225C9.664 5.309 13.825 8.236 8 12 2.175 8.236 6.336 5.309 8 6.982Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 526 B

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-pentagon-fill" viewBox="0 0 16 16">
<path d="m8 0 8 6.5-3 9.5H3L0 6.5 8 0z"/>
</svg>

Before

Width:  |  Height:  |  Size: 182 B

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-pentagon-half" viewBox="0 0 16 16">
<path d="m8 1.288 6.842 5.56L12.267 15H8V1.288zM16 6.5 8 0 0 6.5 3 16h10l3-9.5z"/>
</svg>

Before

Width:  |  Height:  |  Size: 223 B

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-pentagon" viewBox="0 0 16 16">
<path d="m8 1.288 6.842 5.56L12.267 15H3.733L1.158 6.847 8 1.288zM16 6.5 8 0 0 6.5 3 16h10l3-9.5z"/>
</svg>

Before

Width:  |  Height:  |  Size: 236 B

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-tools" viewBox="0 0 16 16">
<path d="M1 0 0 1l2.2 3.081a1 1 0 0 0 .815.419h.07a1 1 0 0 1 .708.293l2.675 2.675-2.617 2.654A3.003 3.003 0 0 0 0 13a3 3 0 1 0 5.878-.851l2.654-2.617.968.968-.305.914a1 1 0 0 0 .242 1.023l3.356 3.356a1 1 0 0 0 1.414 0l1.586-1.586a1 1 0 0 0 0-1.414l-3.356-3.356a1 1 0 0 0-1.023-.242L10.5 9.5l-.96-.96 2.68-2.643A3.005 3.005 0 0 0 16 3c0-.269-.035-.53-.102-.777l-2.14 2.141L12 4l-.364-1.757L13.777.102a3 3 0 0 0-3.675 3.68L7.462 6.46 4.793 3.793a1 1 0 0 1-.293-.707v-.071a1 1 0 0 0-.419-.814L1 0zm9.646 10.646a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708l-3-3a.5.5 0 0 1 0-.708zM3 11l.471.242.529.026.287.445.445.287.026.529L5 13l-.242.471-.026.529-.445.287-.287.445-.529.026L3 15l-.471-.242L2 14.732l-.287-.445L1.268 14l-.026-.529L1 13l.242-.471.026-.529.445-.287.287-.445.529-.026L3 11z"/>
</svg>

Before

Width:  |  Height:  |  Size: 919 B

@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x-lg" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M13.854 2.146a.5.5 0 0 1 0 .708l-11 11a.5.5 0 0 1-.708-.708l11-11a.5.5 0 0 1 .708 0Z"/>
<path fill-rule="evenodd" d="M2.146 2.146a.5.5 0 0 0 0 .708l11 11a.5.5 0 0 0 .708-.708l-11-11a.5.5 0 0 0-.708 0Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 366 B

-16
View File
@@ -1,16 +0,0 @@
///Setup del chart desiderato con id univoco
window.setup = (id, config) => {
var ctx = document.getElementById(id).getContext('2d');
//let currentDate = new Date();
//console.log(currentDate + " - Calling setup...");
//console.log(id);
if (window['chart-' + id] instanceof Chart) {
//window.myChart.destroy();
window['chart-' + id].destroy();
//console.log("Chart " + id + " destroyed!");
}
window['chart-' + id] = new Chart(ctx, config);
//console.log("Chart " + id + " created!");
//console.log(window['chart-' + id]);
}
@@ -1,91 +0,0 @@
/*!
* chartjs-adapter-luxon v1.1.0
* https://www.chartjs.org
* (c) 2021 chartjs-adapter-luxon Contributors
* Released under the MIT license
*/
import { _adapters } from 'chart.js';
import { DateTime } from 'luxon';
const FORMATS = {
datetime: DateTime.DATETIME_MED_WITH_SECONDS,
millisecond: 'h:mm:ss.SSS a',
second: DateTime.TIME_WITH_SECONDS,
minute: DateTime.TIME_SIMPLE,
hour: {hour: 'numeric'},
day: {day: 'numeric', month: 'short'},
week: 'DD',
month: {month: 'short', year: 'numeric'},
quarter: "'Q'q - yyyy",
year: {year: 'numeric'}
};
_adapters._date.override({
_id: 'luxon', // DEBUG
/**
* @private
*/
_create: function(time) {
return DateTime.fromMillis(time, this.options);
},
formats: function() {
return FORMATS;
},
parse: function(value, format) {
const options = this.options;
if (value === null || typeof value === 'undefined') {
return null;
}
const type = typeof value;
if (type === 'number') {
value = this._create(value);
} else if (type === 'string') {
if (typeof format === 'string') {
value = DateTime.fromFormat(value, format, options);
} else {
value = DateTime.fromISO(value, options);
}
} else if (value instanceof Date) {
value = DateTime.fromJSDate(value, options);
} else if (type === 'object' && !(value instanceof DateTime)) {
value = DateTime.fromObject(value);
}
return value.isValid ? value.valueOf() : null;
},
format: function(time, format) {
const datetime = this._create(time);
return typeof format === 'string'
? datetime.toFormat(format, this.options)
: datetime.toLocaleString(format);
},
add: function(time, amount, unit) {
const args = {};
args[unit] = amount;
return this._create(time).plus(args).valueOf();
},
diff: function(max, min, unit) {
return this._create(max).diff(this._create(min)).as(unit).valueOf();
},
startOf: function(time, unit, weekday) {
if (unit === 'isoWeek') {
weekday = Math.trunc(Math.min(Math.max(0, weekday), 6));
const dateTime = this._create(time);
return dateTime.minus({days: (dateTime.weekday - weekday + 7) % 7}).startOf('day').valueOf();
}
return unit ? this._create(time).startOf(unit).valueOf() : time;
},
endOf: function(time, unit) {
return this._create(time).endOf(unit).valueOf();
}
});
@@ -1 +0,0 @@
import{_adapters}from"chart.js";import{DateTime}from"luxon";const FORMATS={datetime:DateTime.DATETIME_MED_WITH_SECONDS,millisecond:"h:mm:ss.SSS a",second:DateTime.TIME_WITH_SECONDS,minute:DateTime.TIME_SIMPLE,hour:{hour:"numeric"},day:{day:"numeric",month:"short"},week:"DD",month:{month:"short",year:"numeric"},quarter:"'Q'q - yyyy",year:{year:"numeric"}};_adapters._date.override({_id:"luxon",_create:function(t){return DateTime.fromMillis(t,this.options)},formats:function(){return FORMATS},parse:function(t,e){var r=this.options;if(null==t)return null;var a=typeof t;return"number"==a?t=this._create(t):"string"==a?t="string"==typeof e?DateTime.fromFormat(t,e,r):DateTime.fromISO(t,r):t instanceof Date?t=DateTime.fromJSDate(t,r):"object"!=a||t instanceof DateTime||(t=DateTime.fromObject(t)),t.isValid?t.valueOf():null},format:function(t,e){const r=this._create(t);return"string"==typeof e?r.toFormat(e,this.options):r.toLocaleString(e)},add:function(t,e,r){const a={};return a[r]=e,this._create(t).plus(a).valueOf()},diff:function(t,e,r){return this._create(t).diff(this._create(e)).as(r).valueOf()},startOf:function(t,e,r){if("isoWeek"!==e)return e?this._create(t).startOf(e).valueOf():t;{r=Math.trunc(Math.min(Math.max(0,r),6));const a=this._create(t);return a.minus({days:(a.weekday-r+7)%7}).startOf("day").valueOf()}},endOf:function(t,e){return this._create(t).endOf(e).valueOf()}});
@@ -1,96 +0,0 @@
/*!
* chartjs-adapter-luxon v1.1.0
* https://www.chartjs.org
* (c) 2021 chartjs-adapter-luxon Contributors
* Released under the MIT license
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('chart.js'), require('luxon')) :
typeof define === 'function' && define.amd ? define(['chart.js', 'luxon'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Chart, global.luxon));
}(this, (function (chart_js, luxon) { 'use strict';
const FORMATS = {
datetime: luxon.DateTime.DATETIME_MED_WITH_SECONDS,
millisecond: 'h:mm:ss.SSS a',
second: luxon.DateTime.TIME_WITH_SECONDS,
minute: luxon.DateTime.TIME_SIMPLE,
hour: {hour: 'numeric'},
day: {day: 'numeric', month: 'short'},
week: 'DD',
month: {month: 'short', year: 'numeric'},
quarter: "'Q'q - yyyy",
year: {year: 'numeric'}
};
chart_js._adapters._date.override({
_id: 'luxon', // DEBUG
/**
* @private
*/
_create: function(time) {
return luxon.DateTime.fromMillis(time, this.options);
},
formats: function() {
return FORMATS;
},
parse: function(value, format) {
const options = this.options;
if (value === null || typeof value === 'undefined') {
return null;
}
const type = typeof value;
if (type === 'number') {
value = this._create(value);
} else if (type === 'string') {
if (typeof format === 'string') {
value = luxon.DateTime.fromFormat(value, format, options);
} else {
value = luxon.DateTime.fromISO(value, options);
}
} else if (value instanceof Date) {
value = luxon.DateTime.fromJSDate(value, options);
} else if (type === 'object' && !(value instanceof luxon.DateTime)) {
value = luxon.DateTime.fromObject(value);
}
return value.isValid ? value.valueOf() : null;
},
format: function(time, format) {
const datetime = this._create(time);
return typeof format === 'string'
? datetime.toFormat(format, this.options)
: datetime.toLocaleString(format);
},
add: function(time, amount, unit) {
const args = {};
args[unit] = amount;
return this._create(time).plus(args).valueOf();
},
diff: function(max, min, unit) {
return this._create(max).diff(this._create(min)).as(unit).valueOf();
},
startOf: function(time, unit, weekday) {
if (unit === 'isoWeek') {
weekday = Math.trunc(Math.min(Math.max(0, weekday), 6));
const dateTime = this._create(time);
return dateTime.minus({days: (dateTime.weekday - weekday + 7) % 7}).startOf('day').valueOf();
}
return unit ? this._create(time).startOf(unit).valueOf() : time;
},
endOf: function(time, unit) {
return this._create(time).endOf(unit).valueOf();
}
});
})));
@@ -1,7 +0,0 @@
/*!
* chartjs-adapter-luxon v1.1.0
* https://www.chartjs.org
* (c) 2021 chartjs-adapter-luxon Contributors
* Released under the MIT license
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(require("chart.js"),require("luxon")):"function"==typeof define&&define.amd?define(["chart.js","luxon"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Chart,e.luxon)}(this,(function(e,t){"use strict";const n={datetime:t.DateTime.DATETIME_MED_WITH_SECONDS,millisecond:"h:mm:ss.SSS a",second:t.DateTime.TIME_WITH_SECONDS,minute:t.DateTime.TIME_SIMPLE,hour:{hour:"numeric"},day:{day:"numeric",month:"short"},week:"DD",month:{month:"short",year:"numeric"},quarter:"'Q'q - yyyy",year:{year:"numeric"}};e._adapters._date.override({_id:"luxon",_create:function(e){return t.DateTime.fromMillis(e,this.options)},formats:function(){return n},parse:function(e,n){const r=this.options;if(null==e)return null;const i=typeof e;return"number"===i?e=this._create(e):"string"===i?e="string"==typeof n?t.DateTime.fromFormat(e,n,r):t.DateTime.fromISO(e,r):e instanceof Date?e=t.DateTime.fromJSDate(e,r):"object"!==i||e instanceof t.DateTime||(e=t.DateTime.fromObject(e)),e.isValid?e.valueOf():null},format:function(e,t){const n=this._create(e);return"string"==typeof t?n.toFormat(t,this.options):n.toLocaleString(t)},add:function(e,t,n){const r={};return r[n]=t,this._create(e).plus(r).valueOf()},diff:function(e,t,n){return this._create(e).diff(this._create(t)).as(n).valueOf()},startOf:function(e,t,n){if("isoWeek"===t){n=Math.trunc(Math.min(Math.max(0,n),6));const t=this._create(e);return t.minus({days:(t.weekday-n+7)%7}).startOf("day").valueOf()}return t?this._create(e).startOf(t).valueOf():e},endOf:function(e,t){return this._create(e).endOf(t).valueOf()}})}));
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+11
View File
@@ -36,6 +36,17 @@
{
<span>@totalCount records</span>
}
@if (totalCount > 0)
{
if (!fileExist)
{
<button class="btn btn-block btn-sm btn-primary" @onclick="() => requestSave()"><span class="oi oi-wrench"></span> Prepare Data</button>
}
else
{
<a target="_blank" href="Download?fileName=@fileName" class="btn btn-block btn-sm btn-success"><span class="oi oi-cloud-download"></span> Download Data</a>
}
}
</div>
<div class="p-1 flex-fill text-right small">
@if (totalCount > 0)
+6 -6
View File
@@ -4,7 +4,7 @@
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>MP.Stats</RootNamespace>
<UserSecretsId>826e877c-ba70-4253-84cb-d0b1cafd4440</UserSecretsId>
<Version>6.15.2204.1416</Version>
<Version>6.15.2207.0718</Version>
</PropertyGroup>
<ItemGroup>
@@ -185,12 +185,12 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="ElmahCore" Version="2.1.1" />
<PackageReference Include="ElmahCore.Common" Version="2.1.1" />
<PackageReference Include="ElmahCore.Sql" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="6.0.4" />
<PackageReference Include="ElmahCore" Version="2.1.2" />
<PackageReference Include="ElmahCore.Common" Version="2.1.2" />
<PackageReference Include="ElmahCore.Sql" Version="2.1.2" />
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="6.0.6" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="NLog.Web.AspNetCore" Version="4.14.0" />
<PackageReference Include="NLog.Web.AspNetCore" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
+1
View File
@@ -110,6 +110,7 @@ namespace MP.Stats.Pages
;
private async Task HandleRedraw()
{
await Task.Delay(1);
// calcolo hist frequenza con EFCore: https://entityframeworkcore.com/knowledge-base/60871048/group-by-and-to-dictionary-in-ef-core-3-1
randData = RandomizeData();
//var histDict = randData.GroupBy(r => r).Select(g => new
+23 -4
View File
@@ -33,11 +33,30 @@
<a class="dismiss">🗙</a>
</div>
@* Riconnessione server app: https://www.syncfusion.com/faq/how-do-i-reconnect-blazor-server-side-automatically *@
@*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.defaultReconnectionHandler._reconnectCallback = function (d) {
document.location.reload();
}
//Blazor.start().then(() => {
// Blazor.defaultReconnectionHandler._reconnectionDisplay = {
// show: () => { },
// update: (d) => { },
// rejected: (d) => document.location.reload()
// };
//});
Blazor.start().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()
}
}
});
});
</script>
<script src="_framework/blazor.server.js"></script>
@@ -7,6 +7,6 @@ by editing this MSBuild file. In order to learn more about this please visit htt
<PropertyGroup>
<TimeStampOfAssociatedLegacyPublishXmlFile />
<EncryptedPassword>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAA+11nhJeDSkeTlSej+COD3AAAAAACAAAAAAADZgAAwAAAABAAAACFCXZ0UR7Czo59aaRCHU5QAAAAAASAAACgAAAAEAAAACYlKt9E6s77uEikpKwyhdQYAAAAUwae989LovFbsfjRp69HCVpyUQZbqLyYFAAAAMW8mLSAxWmKaOvB4nkDgUpS27/b</EncryptedPassword>
<History>True|2022-02-26T17:24:32.0833123Z;False|2022-02-26T18:24:15.3994092+01:00;False|2022-02-26T18:23:44.8358586+01:00;True|2021-05-26T19:49:30.0427896+02:00;False|2021-05-26T19:49:14.9065510+02:00;True|2021-05-25T17:48:33.3901785+02:00;True|2021-05-25T17:46:09.2063020+02:00;True|2021-05-25T17:42:47.8167539+02:00;True|2021-05-25T17:22:03.1877438+02:00;True|2021-05-25T17:21:05.1565775+02:00;True|2021-05-25T16:26:34.1426996+02:00;True|2021-05-25T16:14:28.2842402+02:00;True|2021-05-25T15:02:11.7131495+02:00;</History>
<History>True|2022-07-05T08:07:03.1380003Z;True|2022-02-26T18:24:32.0833123+01:00;False|2022-02-26T18:24:15.3994092+01:00;False|2022-02-26T18:23:44.8358586+01:00;True|2021-05-26T19:49:30.0427896+02:00;False|2021-05-26T19:49:14.9065510+02:00;True|2021-05-25T17:48:33.3901785+02:00;True|2021-05-25T17:46:09.2063020+02:00;True|2021-05-25T17:42:47.8167539+02:00;True|2021-05-25T17:22:03.1877438+02:00;True|2021-05-25T17:21:05.1565775+02:00;True|2021-05-25T16:26:34.1426996+02:00;True|2021-05-25T16:14:28.2842402+02:00;True|2021-05-25T15:02:11.7131495+02:00;</History>
</PropertyGroup>
</Project>

Some files were not shown because too many files have changed in this diff Show More