172 Commits

Author SHA1 Message Date
Samuele Locatelli 018733e918 Merge branch 'develop' into WasmTest 2026-05-06 11:17:05 +02:00
Samuele Locatelli cbcb6e3dba Modifica spostamento ore con ricerca 2026-05-06 11:16:48 +02:00
Samuele E. Locatelli (W11-AI) 18579f792a Merge branch 'develop' of https://gitlab.steamware.net/egalware-web/gest/gpw_next into develop 2026-03-31 18:25:03 +02:00
Samuele E. Locatelli (W11-AI) f9e40a90de Implementazione interfaccia servizi CoreSmart server e x WASM, bozza metodi x WASM http calls 2026-03-31 18:24:59 +02:00
Samuele Locatelli 47afa9c546 Update x impiego DtCart shared 2026-03-30 10:06:45 +02:00
Samuele Locatelli 5554cf5b27 Migrazione servizi su UIMessageService del Core x porting componenti 2026-03-30 09:52:33 +02:00
Samuele Locatelli f0866f4197 Correzione sln x Smart8 (escludo smart che era net10) 2026-03-28 10:07:57 +01:00
Samuele Locatelli d00a8347d4 Refresh dipendenze (da rivedere global file...) 2026-03-28 10:01:46 +01:00
Samuele Locatelli 27eaf83f07 Completato cleanup MainLayout x server page 2026-03-28 09:49:10 +01:00
Samuele Locatelli 0364f264ba Cleanup MainLayout x spostmento funzionalità 2026-03-28 09:39:26 +01:00
Samuele Locatelli e6f3e1715b Inizio cleanup e sposstamento proj 8 e 10 x WASM migration 2026-03-27 19:07:51 +01:00
Samuele Locatelli e6ebbfcc81 Modifiche x scorporo parte shared nuova 2026-03-27 10:32:19 +01:00
Samuele Locatelli 9b6ea3c983 Continuo spostamenti 2026-03-27 10:32:10 +01:00
Samuele Locatelli 08e037ac45 Spostamento progetti 2026-03-27 10:31:53 +01:00
Samuele Locatelli a2d4ab9434 Ancora test vari ma sbagliato display prerender/WASM, da sempliciare a mano 2026-03-26 18:46:00 +01:00
Samuele Locatelli 2004452f30 Aggiunto progetto preliminare dotnet10 x GPW Smart (testing wasm/hybrid/server mixed), aggiunto proj shared nuovo 2026-03-26 15:57:53 +01:00
Samuele Locatelli edfb857755 Ancora update componente CLient x test porting su WASM applicazione GPW.Smart8 2026-03-26 10:26:54 +01:00
Samuele Locatelli df1f541247 Continuo riscrittura e gestione alternativa eventi x recupero utente e funzioni in modalità mista (Server/WASM) 2026-03-26 08:43:35 +01:00
Samuele Locatelli ca255b10d4 Inizio porting progetto a vero WASM x PWA installabile 2026-03-25 19:10:55 +01:00
Samuele Locatelli eee5b42e8d Merge tag 'FixFlushRedis_03' into develop
Fix in core.smart.dataservices
2025-09-12 15:46:49 +02:00
Samuele Locatelli d8aefaef96 Merge branch 'release/FixFlushRedis_03' 2025-09-12 15:46:39 +02:00
Samuele Locatelli 7640156f85 Fix flush in altro ambito 2025-09-12 15:46:21 +02:00
Samuele Locatelli 69407c87fb Merge tag 'FixFlushRedis_02' into develop
Fix flush cond display a 2 sec conferma timbrature
2025-09-12 15:38:02 +02:00
Samuele Locatelli 5724eefa8e Merge branch 'release/FixFlushRedis_02' 2025-09-12 15:37:42 +02:00
Samuele Locatelli cd8040686a Update display conferma timbrature 2025-09-12 15:37:23 +02:00
Samuele Locatelli 07f840beb7 Update tempo conferma timbratura (da conf) 2025-09-12 15:17:52 +02:00
Samuele Locatelli 1b9ddd61b3 Merge tag 'FixRedisFlush_01' into develop
Fix flush redis con nuovo pattern ottimizzato da MAPO
2025-09-12 12:11:40 +02:00
Samuele Locatelli 9cead83478 Merge branch 'release/FixRedisFlush_01' 2025-09-12 12:11:23 +02:00
Samuele Locatelli d0407381d2 Update modalità flush cache redis x master-replica 2025-09-12 12:10:58 +02:00
Samuele Locatelli 865c892e26 Merge tag 'AddReleaseLic_01' into develop
Fix gestione rimozione licenza utente
2025-09-01 11:13:32 +02:00
Samuele Locatelli d27d68a6c8 Merge branch 'release/AddReleaseLic_01' 2025-09-01 11:13:04 +02:00
Samuele Locatelli 9d02f7208d Fix condizioni rilettura completa licenze 2025-09-01 10:55:31 +02:00
Samuele Locatelli a8652e9df6 Fix gestione cessazione licenza (completato metodo mancante) 2025-09-01 10:54:04 +02:00
Samuele Locatelli c734bdce8d Merge tag 'SpostaOre_FasiOrd_01' into develop
Fix display e ordinamento fasi in sposta ore (da fase ancestor e con
titoletto)
2025-07-22 12:35:08 +02:00
Samuele Locatelli 921d0b950b Merge branch 'release/SpostaOre_FasiOrd_01' 2025-07-22 12:34:46 +02:00
Samuele Locatelli 3eb429c46f Fix reorder fasi in sposta ore 2025-07-22 12:34:17 +02:00
Samuele Locatelli 51211b42b2 Merge tag 'FixToggleEntrata_01' into develop
Fix in/out timbratura + fix check periodo richieste permesso
2025-07-15 19:01:49 +02:00
Samuele Locatelli 8d0e73a0bc Merge branch 'release/FixToggleEntrata_01' 2025-07-15 18:59:37 +02:00
Samuele Locatelli ea06b2732f Fix controllo data-ira eventi inizio/fine permesso 2025-07-15 18:59:07 +02:00
Samuele Locatelli d92ee756cc Fix selettore IN/OUT timbrature 2025-07-15 18:14:08 +02:00
Samuele Locatelli 2bffb77d2b Merge tag 'FixAdmCal_02' into develop
Update cal x WRKLOG
2025-07-03 07:18:27 +02:00
Samuele Locatelli f4c7236efc Merge branch 'release/FixAdmCal_02' 2025-07-03 07:17:50 +02:00
Samuele Locatelli ddd9ba9f05 GPW.WRKLOG: riporto calendario ADM su WRKLOG! 2025-07-03 07:17:32 +02:00
Samuele Locatelli fbfc20f282 Fix metodo sync x WRKLOG 2025-07-02 19:09:58 +02:00
Samuele Locatelli 425b8b84cc Merge tag 'FixAdmCal_01' into develop
Fix display calendario x ferie  che scomparivano
2025-07-02 19:06:42 +02:00
Samuele Locatelli 183f177a70 Merge branch 'release/FixAdmCal_01' 2025-07-02 19:06:27 +02:00
Samuele Locatelli 8ee0f6bcbc Fix display calendario ADM 2025-07-02 19:06:01 +02:00
Samuele Locatelli 1bd8351de4 Update gestione approvazione timbrature 2025-07-02 18:47:43 +02:00
Samuele Locatelli 153597f44e Bozza gestione ticket da LiMan/GPW 2025-06-25 18:45:07 +02:00
Samuele Locatelli d85a98fe37 Update parziale pagina Dipendenti 2025-06-24 19:18:47 +02:00
Samuele Locatelli 94f4697d64 Merge tag 'PaginaDipMan_02' into develop
Ripubblicazione
2025-06-24 16:26:58 +02:00
Samuele Locatelli 46deed6787 Merge branch 'release/PaginaDipMan_02' 2025-06-24 16:25:19 +02:00
Samuele Locatelli 2516d18f02 Update parziale dip edit 2025-06-24 16:24:41 +02:00
Samuele Locatelli 80587c76cd Aggiunto controllo LOCK/UNLOCK licenze utente 2025-06-24 09:16:10 +02:00
Samuele Locatelli be6bf2286b Update gestione tag mensili da ricalcola 2025-06-23 19:24:25 +02:00
Samuele Locatelli 794ae6df67 Update pagina gestione dipendenti (NON ancora completa) 2025-06-23 19:03:53 +02:00
Samuele Locatelli fda9430a7d Merge tag 'PaginaDipMan_01' into develop
iAggiunta pagina dipendenti (parziale)
2025-06-23 17:47:49 +02:00
Samuele Locatelli 0b16942154 Merge branch 'release/PaginaDipMan_01' 2025-06-23 17:47:07 +02:00
Samuele Locatelli 2f5c4d822c Update display QR corretto tipo link 2025-06-23 17:46:38 +02:00
Samuele Locatelli 2ecad55883 Aggiunta prima vers display QRCode GEN x ADM 2025-06-23 17:04:56 +02:00
Samuele Locatelli 1a75678882 Merge branch 'develop' of https://gitlab.steamware.net/steamware/gpw_next into develop 2025-06-23 16:31:09 +02:00
Samuele Locatelli 72289ed173 Inizio gestione QrCode display 2025-06-23 16:30:46 +02:00
Rawan.Abouzahra a759ff89e0 aggiunta checkbox inattivi 2025-06-23 16:11:54 +02:00
Samuele Locatelli 07fbdb3075 Note modifiche + fix display resp 2025-06-23 12:43:12 +02:00
Rawan.Abouzahra 4304ffbb52 bozza modfica codice pag dipendenti 2025-06-23 12:29:30 +02:00
Samuele Locatelli 54860393cb Aggiunta elemento lettura dati 2025-06-23 11:14:45 +02:00
Rawan.Abouzahra 1f9f999240 inizio codice pag dipendenti 2025-06-23 10:58:09 +02:00
Samuele Locatelli 6a43370a88 Bozza pag dipendenti 2025-06-23 09:17:46 +02:00
Samuele Locatelli f848addb54 Merge tag 'AddElencoRepAndFixFasiMan' into develop
Sistemato loop infinito FasiMan + sistemazione gestione pagina
ElencoReport
2025-06-21 12:04:43 +02:00
Samuele Locatelli 691bf16289 Merge branch 'release/AddElencoRepAndFixFasiMan' 2025-06-21 12:04:26 +02:00
Samuele Locatelli 7c5442ef76 Fix errore modulo fasi man che nascondeva una copia di se stesso annidiata --> infiniteLoop!!! 2025-06-21 12:03:59 +02:00
Samuele Locatelli 92add869a8 Trovato errore in sposta fasi: INIZIO fix per ricorsione in caricamento 2025-06-21 11:53:20 +02:00
Samuele Locatelli 1648ad0349 Altri update pagine 2025-06-21 11:53:07 +02:00
Samuele Locatelli 5f5aa727e4 Modifica criteri selezione oggetti in sposta ore: condizione solo attivi su ogni filtro! 2025-06-21 11:52:42 +02:00
Samuele Locatelli 76b3503429 Merge tag 'SpostaOreMan_02' into develop
Fix schema colori pagina spostamento ore
2025-06-20 17:30:40 +02:00
Samuele Locatelli 498c6ee383 Merge branch 'release/SpostaOreMan_02' 2025-06-20 17:30:27 +02:00
Samuele Locatelli 3f1e39c64e Fix colori ADM sposta ore 2025-06-20 17:30:06 +02:00
Samuele Locatelli 367cfbe468 Merge tag 'SpostaOreMan_01' into develop
Completata pagina spostamento ore
2025-06-20 15:07:33 +02:00
Samuele Locatelli 4c65cb91fb Merge branch 'release/SpostaOreMan_01' 2025-06-20 15:07:19 +02:00
Samuele Locatelli 4a44b3315b Completata review della gestione pagina spostamento ore 2025-06-20 15:06:35 +02:00
Samuele Locatelli 1831db5cbb Update comportamento x spostamento ore 2025-06-20 13:08:16 +02:00
Samuele Locatelli 847e502a7f Aggiunto stored x effettivo spostamento ore 2025-06-20 12:48:29 +02:00
Rawan.Abouzahra 8052250d86 spostamentoOre modifica comportamento visibilità controlli 2025-06-20 11:45:23 +02:00
Rawan.Abouzahra f653485cd2 spostamentoOre ultima modifica 2025-06-20 11:41:38 +02:00
Rawan.Abouzahra 6113a07042 spostamentoOre bozza 2025-06-19 17:29:49 +02:00
Samuele Locatelli bf7d1073fb refresh versione 2025-06-19 12:18:18 +02:00
Samuele Locatelli b88a6483e2 Iniziato filtri a cascata 2025-06-19 12:14:40 +02:00
Rawan.Abouzahra 1168167837 codice spostaOre 3 2025-06-19 11:54:59 +02:00
Rawan.Abouzahra 36d7674304 codice spostaOre 2025-06-19 11:51:02 +02:00
Rawan.Abouzahra c0e092b2fe bozza spostaOre 2025-06-19 09:38:37 +02:00
Rawan.Abouzahra 3896778ba8 Merge branches 'develop' and 'develop' of https://gitlab.steamware.net/egalware-web/gest/gpw_next into develop 2025-06-18 10:36:38 +02:00
Rawan.Abouzahra 5a53cec01b update 2025-06-18 10:32:02 +02:00
Samuele Locatelli 78b8eac671 Bozza metodi e dati x pagina spostamento ore fasi 2025-06-18 10:24:58 +02:00
Samuele Locatelli a318d45cde Merge remote-tracking branch 'origin/develop' into release/AddTimbMensExpl_01 2025-06-18 10:12:04 +02:00
Samuele Locatelli 6a57c5e7bc Inizio inserimento nuove stored 2025-06-18 10:11:09 +02:00
Rawan.Abouzahra 65931d29f9 codice timbrature mensili finito 2025-06-13 14:41:58 +02:00
Rawan.Abouzahra 291cbac5bc codice Timbrature Mensili 2025-06-13 13:20:00 +02:00
Rawan.Abouzahra 07b953dcd5 codice GpwDataService completato 2025-06-12 16:58:31 +02:00
Samuele Locatelli bfc033108f Bozza modifiche EFCore x nuova pagina 2025-06-12 15:09:03 +02:00
Samuele Locatelli 3a149e679f Merge tag 'AddMonthTagPage_01' into develop
Rilascio pagina tag month basata su lavoro di Rawan
2025-06-12 12:44:45 +02:00
Samuele Locatelli 7fc7aea82e Merge branch 'release/AddMonthTagPage_01' 2025-06-12 12:43:46 +02:00
Rawan.Abouzahra 5e94e828ec Merge branch 'temp' into develop 2025-06-12 12:27:36 +02:00
Rawan.Abouzahra dfee393e27 pagina dettaglio tag completata 2025-06-12 12:26:08 +02:00
Samuele Locatelli bd7bdf3d72 Update componente dettaglio TAGS 2025-06-12 10:55:34 +02:00
Rawan.Abouzahra f8fca473f3 update modulo 2025-06-12 10:30:17 +02:00
Samuele Locatelli 1fbc8b314a Fix display area monthTag 2025-06-12 09:21:24 +02:00
Rawan.Abouzahra 641eed422c composizione modulo listTag(non compila) 2025-06-11 17:05:41 +02:00
Samuele Locatelli 17f27d0c8e Aggiunta stored x toggle stato chiamata 2025-06-11 15:57:35 +02:00
Samuele Locatelli f4142aafdd aggiunta dbset mancante 2025-06-11 15:04:56 +02:00
Samuele Locatelli a4c29f26b1 Aggiunta metodi recupero tag dettaglio 2025-06-11 14:57:07 +02:00
Samuele Locatelli 291338a61e Update pagina TagMensili 2025-06-11 12:54:08 +02:00
Rawan.Abouzahra 77f0550e83 correzione recupero dati 2025-06-11 12:38:04 +02:00
Rawan.Abouzahra 1a00fe1a13 Merge branch 'develop' of https://gitlab.steamware.net/egalware-web/gest/gpw_next into develop 2025-06-11 12:24:43 +02:00
Rawan.Abouzahra 23275cc614 inizio modifica pagina 2025-06-11 12:22:53 +02:00
Samuele Locatelli e9de43db2b Bozza metodi data x pag tag mensili 2025-06-11 10:04:06 +02:00
Samuele Locatelli deee79e8f7 Merge branch 'main' into develop 2025-06-10 11:09:05 +02:00
Samuele Locatelli 833e9e2a93 Merge branch 'develop' 2025-06-10 11:08:41 +02:00
Samuele Locatelli cd81220658 Update conf yaml x CI/CD della parte ADM 2025-06-10 11:06:24 +02:00
Samuele Locatelli e7671572da Merge branch 'develop' of https://gitlab.steamware.net/steamware/gpw_next into develop 2025-06-10 10:51:39 +02:00
Samuele Locatelli 3d272c4fdb Completo refresh progetto 2025-06-10 10:46:16 +02:00
Samuele Locatelli 5bdd3bd601 Update calendario 2025-06-10 10:46:04 +02:00
Rawan.Abouzahra 2e593c9fdc Refresh file da PC Rawan 2025-06-10 10:42:44 +02:00
Samuele Locatelli 49268c614f Merge tag 'TryFixCalWrkLog_06' into develop
Aggiunta controlli arrotondamento richieste timbrature + fix completato
calendario ADM
2025-06-10 08:43:50 +02:00
Samuele Locatelli d9b55223a7 Merge branch 'release/TryFixCalWrkLog_06' 2025-06-10 08:43:34 +02:00
Samuele Locatelli ef4586df24 Fix condizione modificabilità timbrature richieste oltre i 5 min 2025-06-10 08:43:02 +02:00
Samuele Locatelli f8ee0e08e8 Omogeneizzato comportamento sel calendario annuale x Radzen 2025-06-10 08:29:19 +02:00
Samuele Locatelli 68da69ed64 Merge tag 'TryFixCalWrkLog_05' into develop
ADM: fix calendaio Radzen x sel mese che da loop
2025-06-10 07:00:10 +02:00
Samuele Locatelli 82fea86b57 Merge branch 'release/TryFixCalWrkLog_05' 2025-06-10 06:59:48 +02:00
Samuele Locatelli 429c4c0086 Fix calendario ADM x radzen (eliminato sel mese che da loop) 2025-06-10 06:59:25 +02:00
Samuele Locatelli 00073c0199 Code reord (codemaid) 2025-06-09 18:54:42 +02:00
Samuele Locatelli a067f706f1 Cleanup aree commentate 2025-06-09 18:54:19 +02:00
Samuele Locatelli 625aab6f25 Merge tag 'TryFixCalWrkLog_04' into develop
Update install x pubblicazione anche in area WRKLOG8
2025-06-09 17:05:26 +02:00
Samuele Locatelli 9a6686e210 Merge branch 'release/TryFixCalWrkLog_04' 2025-06-09 17:05:07 +02:00
Samuele Locatelli c60bb11e4a uypdate yaml 2025-06-09 17:04:47 +02:00
Samuele Locatelli 9ada45cd61 Aggiunta conf x pulish WRKLOG8 + update YAML CI/CD x aggiungere deploy sito WRKLOG8 2025-06-09 17:04:41 +02:00
Samuele Locatelli 8b5ff27ef6 Merge tag 'TryFixCalWrkLog_03' into develop
Prima implementazione calendario mobile x app desktop
2025-06-09 16:03:09 +02:00
Samuele Locatelli edfe294cd4 Merge branch 'release/TryFixCalWrkLog_03' 2025-06-09 16:02:41 +02:00
Samuele Locatelli 321fe7a349 Completata prima review calendario interno x fer/fest/mal 2025-06-09 16:01:43 +02:00
Samuele Locatelli da08bdfaa0 Fix configurazione IIS01:
- redis impostato in ambiente devel
2025-06-09 11:22:41 +02:00
Samuele Locatelli 9f6dd2bf7d Inizio modifica calendario SMART inserito in WRKLOG:
- aggiunta gestione eventi
- fix dataora inizio
2025-06-09 10:35:21 +02:00
Samuele Locatelli 533db060b9 Bozza modifiche: inserito (parzialmente) calendario EGW x mese (manca week e gestione mensile puntuale migliore...) 2025-06-03 19:45:54 +02:00
Samuele Locatelli b7172a7d85 Merge tag 'TryFixCalWrkLog_02' into develop
Update x hide calendario con problemi...
2025-06-03 17:29:10 +02:00
Samuele Locatelli 0cb8a06741 Merge branch 'release/TryFixCalWrkLog_02' 2025-06-03 17:29:00 +02:00
Samuele Locatelli bbd575c032 Correzione x installers CORE SMART su nuget 2025-06-03 17:10:18 +02:00
Samuele Locatelli 5002d498cb Fix nuget x SMART 2025-06-03 17:04:16 +02:00
Samuele Locatelli 2a706243a7 Merge tag 'TryFixCalWrkLog_01' into develop
Update con disattivazione modulo calendario personale WRKLOG
2025-06-03 17:02:22 +02:00
Samuele Locatelli fa89c11f67 Merge branch 'release/TryFixCalWrkLog_01' 2025-06-03 17:01:59 +02:00
Samuele Locatelli 9097b203a0 GPW WRKLOG: errore in calendario, temporaneamente fix disattivando calendario x utenti 2025-06-03 17:01:14 +02:00
Samuele Locatelli f7f7e8962c Merge tag 'FixRedisSentinel_01' into develop
Fix puntamento server sentinel redis a cluster (NO localhost)
2025-05-13 15:06:06 +02:00
Samuele Locatelli 20ea9acda0 Merge branch 'release/FixRedisSentinel_01' 2025-05-13 15:05:46 +02:00
Samuele Locatelli b086972605 Update conf redis x sentinel (riduzione) 2025-05-13 14:54:32 +02:00
Samuele Locatelli a4de1bd223 Merge tag 'EmailPwdUpdate_01' into develop
Update pwd invio email (creata app passwd)
2025-04-30 09:23:06 +02:00
Samuele Locatelli 3a6c8836ce Merge branch 'release/EmailPwdUpdate_01' 2025-04-30 09:22:53 +02:00
Samuele Locatelli 6bbbeb389d Update pwd x app core con invio email gmail tramite services@steamware.net 2025-04-30 09:21:26 +02:00
Samuele Locatelli 4682b22a14 Merge tag 'Smar8_03' into develop
Update gestione modale e altri check x SMART 8
2025-03-25 08:23:06 +01:00
Samuele Locatelli 5c810d7b78 Merge branch 'release/Smar8_03' 2025-03-25 08:22:54 +01:00
Samuele Locatelli b830d7a54e GPPW SMART
- update modal wait
- update deploy
- check attivazioni + frequente
2025-03-25 08:22:34 +01:00
Samuele Locatelli 9cdd57feab update conf deploy (da verificare post fix 6/8) 2025-03-24 09:07:28 +01:00
Samuele Locatelli 070ddf25ba Correzione net framework deploy api: 6 --> 8 2025-03-24 08:36:18 +01:00
Samuele Locatelli 807d74acf8 Update conf vari a net8 2025-03-24 08:30:04 +01:00
Samuele Locatelli b47981c46f Correzione conf email x GPW 2025-03-24 08:25:06 +01:00
Samuele Locatelli 56af3748f6 ancora pub profiles 2025-03-24 08:19:49 +01:00
Samuele Locatelli 6ac492164c Aggiunta profili pubblicazione missing 2025-03-24 08:19:42 +01:00
Samuele Locatelli 93d8ec8ceb Merge tag 'Smar8_02' into develop
FIx core in vers 6.0
2025-03-22 11:42:11 +01:00
Samuele Locatelli 8ff5749075 Merge branch 'release/Smar8_02' 2025-03-22 11:41:57 +01:00
Samuele Locatelli ac634a27f1 API:
correzione livello minimo parte CORE (8 -->6)
2025-03-22 11:41:21 +01:00
Samuele Locatelli ded174dfda Merge tag 'Smar8_01' into develop
update versione 8 in prod
2025-03-22 11:39:10 +01:00
Samuele Locatelli 3ea72f9371 Merge branch 'release/Smar8_01' 2025-03-22 11:34:38 +01:00
Samuele Locatelli b5694319cd Merge branch 'net8.0' into develop 2025-03-22 11:33:41 +01:00
Samuele Locatelli 52a52b3993 Merge tag 'FixUserPwd01' into develop
Fix stringhe connessione con utente dedicato
2024-08-19 10:48:38 +02:00
Samuele Locatelli 6f243eb188 Merge branch 'release/FixUserPwd01' 2024-08-19 10:47:36 +02:00
Samuele Locatelli 28a7c403d9 Merge branch 'net8.0' into develop 2024-08-19 10:44:44 +02:00
285 changed files with 72110 additions and 1570 deletions
+81 -4
View File
@@ -69,6 +69,7 @@ stages:
- release
# ---------- BUILD ----------
CORE.Api:build:
stage: build
tags:
@@ -82,7 +83,6 @@ CORE.Api:build:
script:
- dotnet build $env:APP_NAME/$env:APP_NAME.csproj
# ---------- BUILD ----------
CORE.WLOG:build:
stage: build
tags:
@@ -109,6 +109,19 @@ CORE.Smart:build:
script:
- dotnet build $env:APP_NAME/$env:APP_NAME.csproj
CORE.ADM:build:
stage: build
tags:
- win
variables:
APP_NAME: GPW.CORE.ADM
SOL_NAME: GPW.CORE.ADM
before_script:
- *nuget-fix
- dotnet restore "$env:SOL_NAME.sln"
script:
- dotnet build $env:APP_NAME/$env:APP_NAME.csproj
# ---------- STAGING ----------
CORE.Api:staging:
stage: staging
@@ -164,6 +177,27 @@ CORE.Smart:staging:
- dotnet build $env:APP_NAME/$env:APP_NAME.csproj
- dotnet publish -p:PublishProfile=IIS01.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=$IIS_PWD -p:AllowUntrustedCertificate=true -p:verbosity=quiet $env:APP_NAME/$env:APP_NAME.csproj
CORE.ADM:staging:
stage: staging
tags:
- win
environment:
name: staging
url: https://iis01.egalware.com/GPW/CORE.ADM8
variables:
APP_NAME: GPW.CORE.ADM
SOL_NAME: GPW.CORE.ADM
only:
- develop
needs: ["CORE.ADM:build"]
before_script:
- *nuget-fix
- dotnet restore "$env:SOL_NAME.sln"
script:
- dotnet build $env:APP_NAME/$env:APP_NAME.csproj
- dotnet publish -p:PublishProfile=IIS01.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=$IIS_PWD -p:AllowUntrustedCertificate=true -p:verbosity=quiet $env:APP_NAME/$env:APP_NAME.csproj
# ---------- DEPLOY ----------
CORE.Api:deploy:
stage: deploy
@@ -203,6 +237,7 @@ CORE.WLOG:deploy:
- dotnet build $env:APP_NAME/$env:APP_NAME.csproj
# IIS PROD
- dotnet publish -p:PublishProfile=IIS-PROD.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=$IIS_PWD -p:AllowUntrustedCertificate=true -p:verbosity=quiet $env:APP_NAME/$env:APP_NAME.csproj
- dotnet publish -p:PublishProfile=IIS-PROD8.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=$IIS_PWD -p:AllowUntrustedCertificate=true -p:verbosity=quiet $env:APP_NAME/$env:APP_NAME.csproj
CORE.Smart:deploy:
stage: deploy
@@ -224,6 +259,26 @@ CORE.Smart:deploy:
# IIS INT
- dotnet publish -p:PublishProfile=IIS-INT.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=$IIS_PWD -p:AllowUntrustedCertificate=true -p:verbosity=quiet $env:APP_NAME/$env:APP_NAME.csproj
CORE.ADM:deploy:
stage: deploy
tags:
- win
variables:
APP_NAME: GPW.CORE.ADM
SOL_NAME: GPW.CORE.ADM
only:
- main
needs: ["CORE.ADM:build"]
before_script:
- *nuget-fix
- dotnet restore "$env:SOL_NAME.sln"
script:
- dotnet build $env:APP_NAME/$env:APP_NAME.csproj
# IIS PROD
- dotnet publish -p:PublishProfile=IIS-PROD.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=$IIS_PWD -p:AllowUntrustedCertificate=true -p:verbosity=quiet $env:APP_NAME/$env:APP_NAME.csproj
# ---------- RELEASE ----------
CORE.Api:release:
stage: release
tags:
@@ -251,7 +306,6 @@ CORE.Api:release:
# script:
# - dotnet publish -c Release -o ./publish GPW.CORE.Api/GPW.CORE.Api.csproj
# ---------- RELEASE ----------
CORE.WLOG:release:
stage: release
tags:
@@ -276,7 +330,6 @@ CORE.WLOG:release:
# script:
# - dotnet publish -c Release -o ./publish GPW.CORE.WRKLOG/GPW.CORE.WRKLOG.csproj
CORE.Smart:release:
stage: release
tags:
@@ -299,4 +352,28 @@ CORE.Smart:release:
- *hashBuild
- *nexusUpload
# script:
# - dotnet publish -c Release -o ./publish GPW.CORE.WRKLOG/GPW.CORE.WRKLOG.csproj
# - dotnet publish -c Release -o ./publish GPW.CORE.WRKLOG/GPW.CORE.WRKLOG.csproj
# CORE.ADM:release:
# stage: release
# tags:
# - win
# variables:
# APP_NAME: GPW.CORE.ADM
# SOL_NAME: GPW.CORE.ADM
# only:
# - main
# except:
# - branches
# needs: ["CORE.ADM:build"]
# artifacts:
# paths:
# - publish/
# script:
# - dotnet build $env:APP_NAME/$env:APP_NAME.csproj
# - dotnet publish -p:PublishProfile=IISProfile.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release $env:APP_NAME/$env:APP_NAME.csproj -o:publish -p:verbosity=quiet
# # qui il deploy su nexus...
# - *hashBuild
# - *nexusUpload
# # script:
# # - dotnet publish -c Release -o ./publish GPW.CORE.WRKLOG/GPW.CORE.WRKLOG.csproj
+1 -1
View File
@@ -10,7 +10,7 @@
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/GPW.CORE.WRKLOG/bin/Debug/net6.0/GPW.CORE.WRKLOG.dll",
"program": "${workspaceFolder}/GPW.CORE.WRKLOG/bin/Debug/net8.0/GPW.CORE.WRKLOG.dll",
"args": [],
"cwd": "${workspaceFolder}/GPW.CORE.WRKLOG",
"stopAtEntry": false,
+6
View File
@@ -11,6 +11,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GPW.CORE.ADM", "GPW.CORE.ADM\GPW.CORE.ADM.csproj", "{4D06AE30-AD81-42FC-B66D-B072A794C599}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GPW.CORE", "GPW.CORE\GPW.CORE.csproj", "{C83EC748-3D5A-27B4-E4E8-B12A09283A8A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -25,6 +27,10 @@ Global
{4D06AE30-AD81-42FC-B66D-B072A794C599}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4D06AE30-AD81-42FC-B66D-B072A794C599}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4D06AE30-AD81-42FC-B66D-B072A794C599}.Release|Any CPU.Build.0 = Release|Any CPU
{C83EC748-3D5A-27B4-E4E8-B12A09283A8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C83EC748-3D5A-27B4-E4E8-B12A09283A8A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C83EC748-3D5A-27B4-E4E8-B12A09283A8A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C83EC748-3D5A-27B4-E4E8-B12A09283A8A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
+2
View File
@@ -57,6 +57,8 @@
<script src="lib/luxon/luxon.js"></script>
<script src="lib/chartjs-adapter-luxon/chartjs-adapter-luxon.js"></script>
<script src="lib/chartBoot.js"></script>
<script type="text/javascript" src="lib/qrcode.js"></script>
<script type="text/javascript" src="lib/qrHelper.js"></script>
</body>
@@ -17,42 +17,72 @@
</div>
</div>
<div class="card-body p-1 small">
@if (ListRecords == null || isLoading)
{
<EgwCoreLib.Razor.LoadingData></EgwCoreLib.Razor.LoadingData>
}
else if (totalCount == 0)
{
<div class="alert alert-info">Nessun record trovato</div>
}
else
{
<table class="table table-striped table-sm text-start">
<thead>
<tr class="">
<th>
<table class="table table-striped table-sm text-start">
<thead>
<tr class="">
<th>
@if (legacyMode)
{
<button class="mx-1 btn btn-info btn-sm" @onclick="SelectAll"><i class="fa-solid fa-circle"></i></button>
<button class="btn btn-secondary opacity-50 btn-sm" @onclick="() => ForceReload(true)"><i class="fa-solid fa-circle"></i></button>
@if(ListUidSel.Count>0)
}
else
{
@if (allSel)
{
<button class="mx-1 btn btn-success btn-sm" @onclick="() => DoApproveSel()"><i class="fa-solid fa-thumbs-up"></i> ALL</button>
<i class="fa-solid fa-toggle-on text-primary fs-5" @onclick="ToggleSelection"></i>
}
</th>
<th>Dipendente <Sorter ParamName="Dipendente" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th>DataOra <Sorter ParamName="DataOra" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th class="text-center">IN</th>
<th class="text-center"></th>
<th class="text-center">OUT</th>
<th class="text-end"></th>
else
{
<i class="fa-solid fa-toggle-off text-secondary fs-5" @onclick="ToggleSelection"></i>
}
}
@if ((legacyMode && ListUidSel.Count > 0) || (!legacyMode && HasRowSelected))
{
<button class="mx-1 btn btn-success btn-sm" @onclick="() => DoApproveSel()"><i class="fa-solid fa-thumbs-up"></i> Approva Sel</button>
}
</th>
<th>Dipendente <Sorter ParamName="Dipendente" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th>DataOra <Sorter ParamName="DataOra" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th class="text-center">IN</th>
<th class="text-center"></th>
<th class="text-center">OUT</th>
<th class="text-end"></th>
</tr>
</thead>
<tbody>
@if (ListRecords == null || isLoading)
{
<tr class="align-middle">
<td colspan="8">
<EgwCoreLib.Razor.LoadingData></EgwCoreLib.Razor.LoadingData>
</td>
</tr>
</thead>
<tbody>
}
else if (totalCount == 0)
{
<tr class="align-middle">
<td colspan="8">
<div class="alert alert-info mb-0">Nessun record trovato</div>
</td>
</tr>
}
else
{
@foreach (var item in ListRecords)
{
<tr class="align-middle">
<td>
<button class="mx-1 btn @CssCheckSel(item.UID) btn-sm" @onclick="() => ToggleUid(item.UID)"><i class="fa-solid @IconCheckSel(item.UID)"></i></button>
<button class="btn btn-success btn-sm" @onclick="() => DoApprove(item)"><i class="fa-solid fa-thumbs-up"></i></button>
@if (legacyMode)
{
<button class="mx-1 btn @CssCheckSel(item.UID) btn-sm" @onclick="() => ToggleUid(item.UID)"><i class="fa-solid @IconCheckSel(item.UID)"></i></button>
}
else
{
<input class="form-check-input" type="checkbox" @bind="item.Selected"></input>
}
<button class="btn btn-success btn-sm ms-1" @onclick="() => DoApprove(item)"><i class="fa-solid fa-thumbs-up"></i></button>
</td>
<td>
@item.DipNav.Abbrev
@@ -80,9 +110,9 @@
</td>
</tr>
}
</tbody>
</table>
}
}
</tbody>
</table>
</div>
<div class="card-footer">
@@ -1,6 +1,7 @@
using EgwCoreLib.Razor;
using GPW.CORE.Data;
using GPW.CORE.Data.DbModels;
using GPW.CORE.Data.DTO;
using GPW.CORE.Data.Services;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
@@ -44,15 +45,13 @@ namespace GPW.CORE.ADM.Components.Compo
protected async Task DoApprove(TimbratureModel selItem)
{
isLoading = true;
#if false
#endif
// se non si tratta di una timbratura "last second"...
if (selItem.DataOra.Hour != 23 && selItem.DataOra.Minute != 59 && selItem.DataOra.Second != 59)
{
// arrotondo ingresso/uscita ai 5 minuti secondo sia entrata o uscita...
var dtTimb = Utils.DateRounded(selItem.DataOra, 5, !(selItem.Entrata ?? false));
selItem.DataOra = dtTimb;
}
}
// indico approvato
selItem.Approv = true;
// salvo!
@@ -65,6 +64,13 @@ namespace GPW.CORE.ADM.Components.Compo
await InvokeAsync(StateHasChanged);
}
private bool legacyMode = false;
protected List<TimbratureDTO> ListSelected
{
get => ListRecords != null ? ListRecords.Where(x => x.Selected).ToList() : new List<TimbratureDTO>();
}
protected async Task DoApproveSel()
{
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Sicuro di voler approvare i {ListUidSel.Count} record selezionati?"))
@@ -73,10 +79,35 @@ namespace GPW.CORE.ADM.Components.Compo
isLoading = true;
await InvokeAsync(StateHasChanged);
int numProc = 0;
foreach (var item in ListRecords)
if (legacyMode)
{
// se selezionato...
if (ListUidSel.Contains(item.UID))
foreach (var item in ListRecords)
{
// se selezionato...
if (ListUidSel.Contains(item.UID))
{
// se non si tratta di una timbratura "last second"...
if (item.DataOra.Hour != 23 && item.DataOra.Minute != 59 && item.DataOra.Second != 59)
{
// arrotondo ingresso/uscita ai 5 minuti secondo sia entrata o uscita...
var dtTimb = Utils.DateRounded(item.DataOra, 5, !(item.Entrata ?? false));
item.DataOra = dtTimb;
}
// indico approvato
item.Approv = true;
// salvo!
bool fatto = await GDataServ.TimbratureUpdate(item);
if (fatto)
{
numProc++;
}
}
}
}
else
{
foreach (var item in ListSelected)
{
// se non si tratta di una timbratura "last second"...
if (item.DataOra.Hour != 23 && item.DataOra.Minute != 59 && item.DataOra.Second != 59)
@@ -88,16 +119,18 @@ namespace GPW.CORE.ADM.Components.Compo
// indico approvato
item.Approv = true;
// salvo!
bool fatto = await GDataServ.TimbratureUpdate(item);
bool fatto = await GDataServ.TimbratureUpdate(item, false);
if (fatto)
{
numProc++;
}
}
// svuoto cache
allSel = false;
}
await Task.Delay(1);
if (numProc > 0)
{
await GDataServ.FlushRedisCache();
await ReloadData();
}
await Task.Delay(1);
@@ -185,6 +218,23 @@ namespace GPW.CORE.ADM.Components.Compo
await ReloadData();
}
/// <summary>
/// Effettua toggle selezione globale delle righe mostrateGpwDataService gDataServprivate async Task ReloadData
/// </summary>
protected void ToggleSelection()
{
allSel = !allSel;
foreach (var item in ListRecords)
{
item.Selected = allSel;
}
}
protected bool HasRowSelected
{
get => ListRecords != null && ListRecords.Count(x => x.Selected) > 0;
//get => ListRecords != null && ListRecords.Where(x => x.Selected).Count() > 0;
}
protected async void ToggleUid(string uid)
{
if (ListUidSel.Contains(uid))
@@ -204,6 +254,7 @@ namespace GPW.CORE.ADM.Components.Compo
#region Private Fields
private static Logger Log = LogManager.GetCurrentClassLogger();
private bool allSel = false;
private string gridKey = "ApprovTimbMan";
private bool sortAsc = true;
private string sortField = "";
@@ -219,10 +270,10 @@ namespace GPW.CORE.ADM.Components.Compo
private bool isLoading { get; set; } = false;
private List<DipendentiModel> ListDipendenti { get; set; } = new List<DipendentiModel>();
private List<TimbratureModel>? ListRecords { get; set; } = null;
private List<TimbratureDTO>? ListRecords { get; set; } = null;
private List<string> ListUidSel { get; set; } = new List<string>();
private int numRecord { get; set; } = 10;
private List<TimbratureModel>? SearchRecords { get; set; } = null;
private List<TimbratureDTO>? SearchRecords { get; set; } = null;
private int totalCount { get; set; } = 0;
#endregion Private Properties
@@ -243,12 +294,18 @@ namespace GPW.CORE.ADM.Components.Compo
ListRecords = null;
try
{
SearchRecords = await GDataServ.TimbratureRichieste();
var rawData = await GDataServ.TimbratureRichieste();
SearchRecords = rawData
.Where(x => (IdxDipSel == 0 || x.IdxDipendente == IdxDipSel))
.Select(x => new TimbratureDTO(x))
.ToList();
#if false
// verifico filtro per IdxDip
if (IdxDipSel > 0)
{
SearchRecords = SearchRecords.Where(x => x.IdxDipendente == IdxDipSel).ToList();
}
#endif
}
catch (Exception ex)
{
@@ -303,7 +360,7 @@ namespace GPW.CORE.ADM.Components.Compo
}
else
{
ListRecords = new List<TimbratureModel>();
ListRecords = new List<TimbratureDTO>();
}
}
@@ -178,7 +178,7 @@ namespace GPW.CORE.ADM.Components.Compo
{
SearchRecords = null;
await Task.Delay(1);
SearchRecords = await GDataServ.CalFestFeriePeriodo(DtStart, DtEnd);
SearchRecords = GDataServ.CalFestFeriePeriodo(DtStart, DtEnd);
// conteggio!
totalCount = SearchRecords.Count;
// paginazione
@@ -16,17 +16,7 @@
<b>Calendario Aziendale</b>
</div>
<div class="col-4 text-end">
<div class="d-flex justify-content-around">
@if (currView == "year" || currView == "planner")
{
<div class="small">
<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center" Gap="0.5rem" class="rz-px-2">
<RadzenLabel Text="Mese:" />
<RadzenDropDown @bind-Value="@startMonth" Change="StartMonthChange" TextProperty="Text" ValueProperty="Value" Data="@(Enum.GetValues(typeof(Month)).Cast<Month>().Where(x => ((int)x % 3 == 0)).Select(t => new { Text = $"{t}", Value = t }))" class="rz-display-inline-flex small" />
</RadzenStack>
</div>
}
</div>
<b>@numEvFilt/@numEvAll</b> (selez/anno)
</div>
</div>
</div>
@@ -35,7 +25,7 @@
<RadzenScheduler @ref=@scheduler style="height: 100%;" Culture=@(new System.Globalization.CultureInfo("it-IT"))
TItem="EventDTO" Data="@EvDtoFilt" SelectedIndex="@selectedIndex" Date="@SelDate"
StartProperty="DtStart" EndProperty="DtEnd" TextProperty="CodTipo"
SlotRender=@OnSlotRender SlotSelect=@OnSlotSelect
SlotRender=@OnSlotRender SlotSelect=@OnSlotSelect TodayText="Oggi"
AppointmentSelect=@OnAppointmentSelect AppointmentRender=@OnAppointmentRender
LoadData=OnLoadData>
<Template Context="EvDTO">
@@ -53,9 +43,8 @@
<RadzenDayView />
<RadzenWeekView />
<RadzenMonthView MaxAppointmentsInSlot="4" />
<RadzenYearPlannerView StartMonth="@startMonth" MaxAppointmentsInSlot="3" />
@* <RadzenYearTimelineView StartMonth="@startMonth" /> *@
<RadzenYearView StartMonth="@startMonth" />
<RadzenYearPlannerView StartMonth="Month.January" MaxAppointmentsInSlot="3" />
<RadzenYearView StartMonth="Month.January" />
</ChildContent>
</RadzenScheduler>
</div>
@@ -1,13 +1,14 @@
using GPW.CORE.Data.DTO;
using Microsoft.AspNetCore.Components;
using Microsoft.Identity.Client;
using Radzen.Blazor.Rendering;
using Radzen.Blazor;
using static EgwCoreLib.Razor.Toggler;
using NLog;
using Radzen;
using Radzen.Blazor;
using Radzen.Blazor.Rendering;
using System;
using static System.Runtime.InteropServices.JavaScript.JSType;
using GPW.CORE.Data.DTO;
using System.Diagnostics;
using static EgwCoreLib.Razor.Toggler;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace GPW.CORE.ADM.Components.Compo
{
@@ -24,9 +25,6 @@ namespace GPW.CORE.ADM.Components.Compo
[Parameter]
public DateTime firstDate { get; set; } = new DateTime(DateTime.Today.Year, 1, 1);
[Parameter]
public bool ShowNeedConf { get; set; } = false;
[Parameter]
public DateTime maxDate { get; set; } = new DateTime(DateTime.Today.Year + 1, 1, 1);
@@ -43,6 +41,9 @@ namespace GPW.CORE.ADM.Components.Compo
[Parameter]
public EventCallback<int> MonthReq { get; set; }
[Parameter]
public bool ShowNeedConf { get; set; } = false;
#endregion Public Properties
#region Protected Fields
@@ -82,6 +83,8 @@ namespace GPW.CORE.ADM.Components.Compo
[Inject]
protected DialogService DialogService { get; set; } = null!;
protected Month StartMonth { get; set; } = Month.January;
#endregion Protected Properties
#region Protected Methods
@@ -101,17 +104,63 @@ namespace GPW.CORE.ADM.Components.Compo
await Task.Delay(1);
}
protected string btnSel(string bName)
{
bool answ = false;
switch (bName)
{
case "CHIU":
answ = showChiu;
break;
case "FER":
answ = showFer;
break;
case "FEST":
answ = showFest;
break;
case "MAL":
answ = showMal;
break;
case "PER":
answ = showPer;
break;
default:
break;
}
return answ ? "btn-primary" : "btn-secondary";
}
#if false
protected override async Task OnInitializedAsync()
{
await Task.Delay(1);
// il mese viene preimpostato sul trimestre corrente...
startMonth = (Month)((DateTime.Today.Month / 6) * 6);
// il mese viene preimpostato sul semestre corrente...
StartMonth = (Month)((DateTime.Today.Month / 6) * 6);
}
#endif
protected override void OnParametersSet()
protected override async Task OnParametersSetAsync()
{
FilterData();
scheduler.Reload();
numEvAll = 0;
numEvFilt = 0;
if (EvDtoList != null && EvDtoList.Count > 0)
{
numEvAll = EvDtoList.Count();
FilterData();
try
{
await scheduler.Reload();
}
catch (Exception exc)
{
Log.Error($"eccezione durante OnParametersSet{Environment.NewLine}{exc}");
}
}
}
protected async Task StartMonthChange()
@@ -119,10 +168,41 @@ namespace GPW.CORE.ADM.Components.Compo
await scheduler.Reload();
}
protected void ToggChiu()
{
showChiu = !showChiu;
FilterData();
}
protected void ToggFer()
{
showFer = !showFer;
FilterData();
}
protected void ToggFest()
{
showFest = !showFest;
FilterData();
}
protected void ToggMal()
{
showMal = !showMal;
FilterData();
}
protected void ToggPer()
{
showPer = !showPer;
FilterData();
}
#endregion Protected Methods
#region Private Fields
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
private int selectedIndex = 2;
#endregion Private Fields
@@ -132,15 +212,24 @@ namespace GPW.CORE.ADM.Components.Compo
private int cMonth { get; set; } = 3;
private string currView { get; set; } = "";
private List<EventDTO> EvDtoFilt { get; set; } = new List<EventDTO>();
private int numEvAll { get; set; } = 0;
private int numEvFilt { get; set; } = 0;
private string schedHeight { get; set; } = "height: 50rem;";
private DateTime SelDate { get; set; } = DateTime.Today;
private Month startMonth { get; set; } = Month.January;
private bool showChiu { get; set; } = true;
private bool showFer { get; set; } = true;
private bool showFest { get; set; } = true;
private bool showMal { get; set; } = true;
private bool showPer { get; set; } = true;
#endregion Private Properties
#region Private Methods
private void FilterData()
{
// in primis copio tutto
@@ -180,77 +269,24 @@ namespace GPW.CORE.ADM.Components.Compo
.Where(x => !x.CodTipo.Equals("PERM", StringComparison.InvariantCultureIgnoreCase) && !x.CodTipo.Equals("104", StringComparison.InvariantCultureIgnoreCase))
.ToList();
}
}
private bool showChiu { get; set; } = true;
private bool showFer { get; set; } = true;
private bool showFest { get; set; } = true;
private bool showMal { get; set; } = true;
private bool showPer { get; set; } = true;
protected string btnSel(string bName)
{
bool answ = false;
switch (bName)
{
case "CHIU":
answ = showChiu;
break;
case "FER":
answ = showFer;
break;
case "FEST":
answ = showFest;
break;
case "MAL":
answ = showMal;
break;
case "PER":
answ = showPer;
break;
default:
break;
}
return answ ? "btn-primary" : "btn-secondary";
}
protected void ToggMal()
{
showMal = !showMal;
FilterData();
}
protected void ToggPer()
{
showPer = !showPer;
FilterData();
}
protected void ToggFer()
{
showFer = !showFer;
FilterData();
}
protected void ToggFest()
{
showFest = !showFest;
FilterData();
}
protected void ToggChiu()
{
showChiu = !showChiu;
FilterData();
numEvFilt = EvDtoFilt.Count();
}
/// <summary>
/// Sistemazione colore sfonto di ogni evento mostrato
/// </summary>
/// <param name="args"></param>
private void OnAppointmentRender(SchedulerAppointmentRenderEventArgs<EventDTO> args)
{
// Never call StateHasChanged in AppointmentRender - would lead to infinite loop
args.Attributes["style"] = $"background: {args.Data.Color}; color: {args.Data.ForeColor};";
}
/// <summary>
/// Selezione evento per display
/// </summary>
/// <param name="selEv"></param>
/// <returns></returns>
private async Task OnAppointmentSelect(SchedulerAppointmentSelectEventArgs<EventDTO> selEv)
{
var copy = selEv.Data.Clone();
@@ -258,16 +294,26 @@ namespace GPW.CORE.ADM.Components.Compo
var data = await DialogService.OpenAsync<TaskDetail>("", new Dictionary<string, object> { { "ThisTask", copy } });
}
/// <summary>
/// Gestione richeista caricamento dati dal controllo x avere nuovo set da mostrare
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
private async Task OnLoadData(SchedulerLoadDataEventArgs args)
{
await Task.Delay(1);
currView = scheduler.SelectedView.Text.ToLowerInvariant();
// controllo se sia cambiata data... di almeno 1 anno in questo caso...
if (SelDate != scheduler.Date || Math.Abs(scheduler.Date.Subtract(args.Start).TotalDays) > 365)
DateTime dtMid = args.Start.AddDays(args.End.Subtract(args.Start).TotalDays / 2);
// controllo se sia cambiata data anno precedente...
if (dtMid.Year != SelDate.Year)
{
SelDate = args.Start.AddMonths(1);
// riporto data al controller parent...
SelDate = dtMid;
await DtReq.InvokeAsync(SelDate);
}
// di almeno 1 anno in questo caso...
else if (SelDate != scheduler.Date || Math.Abs(scheduler.Date.Subtract(args.Start).TotalDays) > 365)
{
SelDate = args.Start.AddDays(4);
await DtReq.InvokeAsync(SelDate);
}
@@ -178,7 +178,7 @@ namespace GPW.CORE.ADM.Components.Compo
ListRecords = null;
try
{
SearchRecords = await GDataServ.AnagClientiAll();
SearchRecords = await GDataServ.AnagClientiAllAsync();
// verifico condizioni filtro
if (ToggleData.isActive)
{
@@ -48,8 +48,11 @@ namespace GPW.CORE.ADM.Components.Compo
aTimer.Stop();
aTimer.Dispose();
}
int tOutPeriod = 300000;
//int tOutPeriod = 1000;
#if DEBUG
int tOutPeriod = 1000;
#else
int tOutPeriod = 10000;
#endif
aTimer = new System.Timers.Timer(tOutPeriod);
aTimer.Elapsed += ElapsedTimer;
aTimer.Enabled = true;
@@ -65,7 +65,4 @@
</table>
}
</div>
<div class="card-footer">
<EgwCoreLib.Razor.DataPager PageSize="@numRecord" currPage="@currPage" numRecordChanged="SetNumRec" numPageChanged="SetPage" totalCount="@totalCount" showLoading="@isLoading"></EgwCoreLib.Razor.DataPager>
</div>
</div>
@@ -0,0 +1,321 @@
@if (CurrMode == EditMode.FullEdit)
{
<div class="row g-2">
<div class="col-md-3">
<div class="form-floating">
<input type="text" class="form-control" @bind="@CurrRecord.Cognome">
<label class="small">Cognome</label>
</div>
</div>
<div class="col-md-3">
<div class="form-floating">
<input type="text" class="form-control" @bind="@CurrRecord.Nome">
<label class="small">Nome</label>
</div>
</div>
<div class="col-md-1">
<div class="form-floating">
<input type="text" class="form-control" @bind="@CurrRecord.Matricola">
<label class="small">Matricola</label>
</div>
</div>
<div class="col-md-2">
<div class="form-floating">
<select @bind="@CurrRecord.CodOrario" class="form-select form-select-sm" title="Profilo Orario">
<option value="">--- Selezionare ---</option>
@foreach (var item in ListOrari)
{
<option value="@item.codOrario">@item.descOrario</option>
}
</select>
<label class="small">Profilo Orario</label>
</div>
</div>
<div class="col-md-3 align-content-center">
<button class="btn btn-success btn-lg my-1 w-100" @onclick="() => DoSave()"><i class="fas fa-floppy-disk"></i> Save</button>
</div>
</div>
<div class="row g-2 my-1">
<div class="col-md-3">
<div class="form-floating">
<input type="text" class="form-control" @bind="@CurrRecord.Dominio">
<label class="small">Dominio</label>
</div>
</div>
<div class="col-md-3">
<div class="form-floating">
<input type="text" class="form-control" @bind="@CurrRecord.Utente">
<label class="small">Utente</label>
</div>
</div>
<div class="col-md-3">
<div class="form-floating">
<input type="text" class="form-control" @bind="@CurrRecord.Email">
<label class="small">Email</label>
</div>
</div>
<div class="col-md-3 align-content-center">
<button class="btn btn-warning btn-lg my-1 w-100" @onclick="() => DoCancel()"><i class="fas fa-ban"></i> Cancel</button>
</div>
</div>
<div class="row g-2 my-1">
<div class="col-md-3">
<div class="form-floating">
<input type="text" class="form-control" @bind="@CurrRecord.Cf">
<label class="small">Codice Fiscale</label>
</div>
</div>
<div class="col-md-3">
<div class="form-floating">
<input type="date" class="form-control" @bind="@CurrRecord.DataNascita">
<label class="small">Data Nascita</label>
</div>
</div>
<div class="col-md-3">
<div class="form-floating">
<input type="text" class="form-control" @bind="@CurrRecord.LuogoNascita">
<label class="small">Luogo Nascita</label>
</div>
</div>
<div class="col-md-1">
<div class="form-floating">
<input type="text" class="form-control" @bind="@CurrRecord.ProvNascita">
<label class="small">Prov</label>
</div>
</div>
<div class="col-md-1">
<div class="form-floating">
<input type="text" class="form-control" @bind="@CurrRecord.NazNascita">
<label class="small">Naz</label>
</div>
</div>
<div class="col-md-1">
<div class="form-floating">
<input type="text" class="form-control" @bind="@CurrRecord.CodHw">
<label class="small">CodHw</label>
</div>
</div>
</div>
<div class="row g-2 my-1">
<div class="col-md-2">
<div class="form-floating">
<input type="text" class="form-control" @bind="@CurrRecord.Gruppo">
<label class="small">Gruppo</label>
</div>
</div>
<div class="col-md-1">
<div class="form-floating">
<div class="form-control">
<div class="form-check form-switch">
<input type="checkbox" class="form-check-input" @bind="@CurrRecord.Attivo">
</div>
</div>
<label class="small">Att.</label>
</div>
</div>
<div class="col-md-3">
<div class="form-floating">
<select @bind="@CurrRecord.idxResp" class="form-select form-select-sm" title="Responsabile">
<option value="0">--- Selezionare ---</option>
@foreach (var item in ListDipendenti)
{
<option value="@item.IdxDipendente">@item.Cognome @item.Nome</option>
}
</select>
<label class="small">Responsabile</label>
</div>
</div>
<div class="col-md-3">
<div class="form-floating">
<input type="date" class="form-control" @bind="@CurrRecord.DataAssunzione">
<label class="small">Assunzione</label>
</div>
</div>
<div class="col-md-3">
<div class="form-floating">
<input type="date" class="form-control" @bind="@CurrRecord.DataCessazione">
<label class="small">Cessazione</label>
</div>
</div>
</div>
}
else if (CurrMode == EditMode.ResetRequest)
{
<div class="row g-2">
<div class="col-8">
<div class="row">
<div class="col-4 pe-0">
<div class="form-floating">
<input type="text" class="form-control" @bind="@ReqReset.Richiedente">
<label class="small"><i class="fa-solid fa-user"></i> Richiedente</label>
</div>
</div>
<div class="col-4 px-0">
<div class="form-floating">
<input type="email" class="form-control" @bind="@ReqReset.Email">
<label class="small"><i class="fa-regular fa-envelope"></i> Email</label>
</div>
</div>
<div class="col-4 ps-0">
<div class="form-floating">
<input type="text" class="form-control" @bind="@ReqReset.Telefono">
<label class="small"><i class="fa-solid fa-phone"></i> Telefono</label>
</div>
</div>
</div>
<ul class="list-group">
<li class="list-group-item d-flex justify-content-between" aria-current="true">
<div class="px-1">Anagr:</div>
<div class="px-1">@($"{CurrRecord.DataNascita:yyyy-MM-dd}") @CurrRecord.LuogoNascita (@CurrRecord.ProvNascita | @CurrRecord.NazNascita)</div>
</li>
<li class="list-group-item d-flex justify-content-between" aria-current="true">
<div class="px-1">@CurrRecord.Cf</div>
<div class="px-1">@CurrRecord.Email</div>
</li>
<li class="list-group-item d-flex justify-content-between" aria-current="true">
<div class="px-1">
@if (CurrRecord.DataCessazione <= DateTime.Today)
{
<span>Periodo:</span>
}
else
{
<span>Assunzione:</span>
}
</div>
<div class="px-1">
<span>@($"{CurrRecord.DataAssunzione:yyyy-MM-dd}")</span>
@if (CurrRecord.DataCessazione <= DateTime.Today)
{
<span>
&rarr; @($"{CurrRecord.DataCessazione:yyyy-MM-dd}")
</span>
}
</div>
</li>
<li class="list-group-item d-flex justify-content-between" aria-current="true">
<div class="px-1">Lock Licenza</div>
<div class="px-1">
<span class="text-danger">
<i class="fa-solid fa-lock"></i> <b>@($"{UnlockDateLic:dddd dd MMMM yyyy}")</b>
</span>
</div>
</li>
</ul>
</div>
<div class="col-4">
<div class="row">
@*
<div class="col-12">
<div class="form-floating">
<input type="text" class="form-control" @bind="@ReqReset.Richiedente">
<label class="small"><i class="fa-solid fa-user"></i> Richiedente</label>
</div>
</div>
<div class="col-6 pe-0">
<div class="form-floating">
<input type="email" class="form-control" @bind="@ReqReset.Email">
<label class="small"><i class="fa-regular fa-envelope"></i> Email</label>
</div>
</div>
<div class="col-6 ps-0">
<div class="form-floating">
<input type="text" class="form-control" @bind="@ReqReset.Telefono">
<label class="small"><i class="fa-solid fa-phone"></i> Telefono</label>
</div>
</div>
*@
<div class="col-12">
<div class="form-floating">
<textarea class="form-control" @bind="@ReqReset.Causale" style="min-height: 8rem;"></textarea>
<label class="small"><i class="fa-regular fa-message"></i> Causale</label>
</div>
</div>
<div class="col-12 text-center mt-2">
<button class="btn btn-primary btn-lg my-1 w-100" @onclick="() => DoActivate()" title="Invio richiesta sblocco licenza">Invio Richiesta <i class="far fa-paper-plane"></i></button>
</div>
</div>
</div>
</div>
}
else if (CurrMode == EditMode.KeyRegen)
{
<div class="row g-2">
<div class="col-8">
<ul class="list-group">
<li class="list-group-item d-flex justify-content-between" aria-current="true">
<div class="px-1">Anagr:</div>
<div class="px-1">@($"{CurrRecord.DataNascita:yyyy-MM-dd}") @CurrRecord.LuogoNascita (@CurrRecord.ProvNascita | @CurrRecord.NazNascita)</div>
</li>
@* <li class="list-group-item d-flex justify-content-between" aria-current="true">
<div class="px-1"><b>@CurrRecord.Cognome</b> @CurrRecord.Nome</div>
<div class="px-1">@CurrRecord.Matricola</div>
</li> *@
<li class="list-group-item d-flex justify-content-between" aria-current="true">
<div class="px-1">@CurrRecord.Cf</div>
<div class="px-1">@CurrRecord.Email</div>
</li>
<li class="list-group-item d-flex justify-content-between" aria-current="true">
<div class="px-1">
@if (CurrRecord.DataCessazione <= DateTime.Today)
{
<span>Periodo:</span>
}
else
{
<span>Assunzione:</span>
}
</div>
<div class="px-1">
<span>@($"{CurrRecord.DataAssunzione:yyyy-MM-dd}")</span>
@if (CurrRecord.DataCessazione <= DateTime.Today)
{
<span>
&rarr; @($"{CurrRecord.DataCessazione:yyyy-MM-dd}")
</span>
}
</div>
</li>
</ul>
</div>
<div class="col-4">
@if (CurrRecord.Attivo ?? false)
{
if (CheckActivationUnlocked)
{
<button class="btn btn-danger btn-lg my-1 w-100" @onclick="() => DoRelease()" title="Cessazione utente + Rilascio Licenza">Cessazione Utente <i class="fas fa-link-slash"></i></button>
@if (!CheckActivation && (CurrRecord.Attivo ?? false))
{
<button class="btn btn-primary btn-lg my-1 w-100" @onclick="() => DoReissue()" title="Assegna Licenza ad utente già Attivo">Assegna Licenza <i class="fas fa-rotate"></i></button>
}
}
<button class="btn btn-primary btn-lg my-1 w-100" @onclick="() => DoResync()" title="Rigenera Token Auth SMART + associa Licenza">Rigen + Sync Auth <i class="fas fa-rotate"></i></button>
}
else
{
@if (LicenzeOk && LicenzeDisponibili)
{
<button class="btn btn-success btn-lg my-1 w-100" @onclick="() => DoActivate()" title="Attiva utente + Assegna Licenza">Attiva Utente <i class="fas fa-link"></i></button>
}
}
<div class="text-center">
@if (LockExpired)
{
<span class="text-success">
<i class="fa-solid fa-unlock"></i> <b>@($"{UnlockDateLic:dddd dd MMMM yyyy}")</b>
</span>
}
else
{
<span class="text-danger">
<i class="fa-solid fa-lock"></i> <b>@($"{UnlockDateLic:dddd dd MMMM yyyy}")</b>
</span>
}
</div>
</div>
</div>
}
else
{
<div class="alert a fs-6">Modo controllo non definito</div>
}
@@ -0,0 +1,238 @@
using GPW.CORE.Data.DbModels;
using GPW.CORE.Data.DTO;
using GPW.CORE.Data.Services;
using Microsoft.AspNetCore.Components;
using Microsoft.EntityFrameworkCore.SqlServer.Query.Internal;
using System.Runtime.CompilerServices;
namespace GPW.CORE.ADM.Components.Compo
{
public partial class DipendentiEdit
{
#region Public Enums
/// <summary>
/// Modalità Edit
/// </summary>
public enum EditMode
{
None = 0,
KeyRegen,
ResetRequest,
FullEdit
}
#endregion Public Enums
#region Public Properties
[Parameter]
public EditMode CurrMode { get; set; } = EditMode.None;
[Parameter]
public DipendentiModel? CurrRecord { get; set; } = null;
[Parameter]
public EventCallback<DipendentiModel> EC_Activate { get; set; }
[Parameter]
public EventCallback<DipendentiModel> EC_Reissue { get; set; }
[Parameter]
public EventCallback<DipendentiModel> EC_Release { get; set; }
[Parameter]
public EventCallback<DipendentiModel> EC_Resync { get; set; }
[Parameter]
public EventCallback<DipendentiModel> EC_update { get; set; }
[Parameter]
public List<DipendentiModel> ListDipendenti { get; set; } = null!;
[Parameter]
public List<AnagOrariModel> ListOrari { get; set; } = null!;
#endregion Public Properties
#region Protected Fields
protected bool CheckActivation = false;
protected bool CheckActivationUnlocked = false;
protected string CodImpiego = "";
protected int IdxSubLic = 0;
protected bool LicenzeDisponibili = false;
protected bool LicenzeOk = false;
protected bool LockExpired = false;
protected int NumDipAct = 0;
protected DateTime UnlockDateLic = DateTime.Today.AddMonths(3);
#endregion Protected Fields
#region Protected Properties
[Inject]
protected MessageService AppMServ { get; set; } = null!;
[Inject]
protected LicenseService LicServ { get; set; } = null!;
#endregion Protected Properties
#region Protected Methods
/// <summary>
/// Attiva + Assegna Licenza
/// </summary>
/// <returns></returns>
protected async Task DoActivate()
{
await EC_Activate.InvokeAsync(CurrRecord);
}
protected async Task DoCancel()
{
await EC_update.InvokeAsync(CurrRecord);
}
/// <summary>
/// Assegna Licenza
/// </summary>
/// <returns></returns>
protected async Task DoReissue()
{
await EC_Reissue.InvokeAsync(CurrRecord);
}
/// <summary>
/// Rilascia Licenza
/// </summary>
/// <returns></returns>
protected async Task DoRelease()
{
await EC_Release.InvokeAsync(CurrRecord);
}
/// <summary>
/// Richiesta Rilascio Licenza
/// </summary>
/// <returns></returns>
protected async Task DoReqUnlock()
{
// invio richiesta sblocco licenza prima della scadenza naturale lock
//await EC_Release.InvokeAsync(CurrRecord);
await Task.Delay(1);
}
/// <summary>
/// Genera una nuova chiave utente + riassegna Licenza
/// </summary>
/// <returns></returns>
protected async Task DoResync()
{
await EC_Resync.InvokeAsync(CurrRecord);
}
protected async Task DoSave()
{
bool fatto = false;
if (CurrRecord != null)
{
DateTime adesso = DateTime.Now;
// chiama resync dati licenza (cod impiego / codAuth)
fatto = LicServ.SendTicketReq(ReqReset.Richiedente.Trim(), ReqReset.Email.Trim(), ReqReset.Telefono.Trim(), ReqReset.Causale.Trim(), CodImpiego, IdxSubLic);
// chiudo
LicServ.ResetTicketCache();
// reset richiesta
ReqReset = new DatiReqResetDTO();
#if false
// evento reset
raiseReset();
#endif
await EC_update.InvokeAsync(CurrRecord);
}
}
protected override void OnParametersSet()
{
DoActivCheck();
}
#endregion Protected Methods
#region Private Fields
private DatiReqResetDTO ReqReset = new DatiReqResetDTO();
#endregion Private Fields
#region Private Methods
/// <summary>
/// Effettua verifiche attivazioni e dati vari
/// </summary>
/// <exception cref="NotImplementedException"></exception>
private void DoActivCheck()
{
if (ListDipendenti != null && ListDipendenti.Count > 0)
{
NumDipAct = ListDipendenti.Where(x => x.Attivo ?? false).Count();
if (CurrRecord != null)
{
// calcolo CodImpiego
CodImpiego = LicServ.HashDip(CurrRecord);
UnlockDateLic = LockExpiry();
LockExpired = UnlockDateLic <= DateTime.Today.AddDays(1);
var onlineActInfo = LicServ.GetOnlineActivationInfo(CodImpiego);
if (onlineActInfo != null)
{
// verifico unlock licenza online...
#if false
CheckActivationUnlocked = LicServ.CheckActivationUnlocked(CodImpiego);
#endif
CheckActivation = onlineActInfo.CodImpiego == CodImpiego;
CheckActivationUnlocked = onlineActInfo.VetoUnlock <= DateTime.Today || string.IsNullOrEmpty(onlineActInfo.CodImpiego);
IdxSubLic = onlineActInfo.IdxSubLic;
}
// verifico licenze
LicenzeOk = NumDipAct <= LicServ.ActivList.Count();
// verifico licenze disponibili
LicenzeDisponibili = LicServ.AppLicense.NumLicenze > NumDipAct;
}
}
}
/// <summary>
/// Restitusice la data di unlock del dipendente
/// </summary>
private DateTime LockExpiry()
{
DateTime cessato = CurrRecord.DataCessazione ?? DateTime.Today.AddDays(-1);
bool isAttivo = CurrRecord.Attivo ?? false;
DateTime answ = isAttivo ? DateTime.Today.AddDays(90) : cessato;
// verifico SE sia disponibile licenza...
var activationsList = LicServ.ActivList;
var currAct = activationsList.Where(x => x.CodImpiego == CodImpiego).FirstOrDefault();
// se trovo record
if (currAct != null)
{
answ = currAct.VetoUnlock;
}
return answ;
}
#endregion Private Methods
}
}
@@ -0,0 +1,226 @@
@if (RecordEdit != null)
{
<div class="modal fade show" tabindex="-1" style="display:block; background-color: rgba(10,10,10,.6);" aria-modal="true" role="dialog" data-keyboard="true">
<div class="modal-dialog @modalSize">
<div class="modal-content">
<div class="modal-header d-flex justify-content-between">
<div class="px-1 fs-4 modal-title">
<b>@RecordEdit.Cognome</b> @RecordEdit.Nome
@if (CtrlMode == DipendentiEdit.EditMode.FullEdit)
{
<span>| Modifica Record @RecordEdit.IdxDipendente</span>
}
else if (CtrlMode == DipendentiEdit.EditMode.ResetRequest)
{
<span>| Sblocco Licenza</span>
}
</div>
<div class="px-1">
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" @onclick=ForceReload></button>
</div>
</div>
<div class="modal-body p-1 small">
<DipendentiEdit CurrMode="CtrlMode" CurrRecord="RecordEdit" EC_update="ForceReload" EC_Activate="DoActivate" EC_Release="ReleaseLicense" ListDipendenti="@ListDipendentiAttiviOrd" ListOrari="@ListOrari"></DipendentiEdit>
</div>
</div>
</div>
</div>
}
<div class="card shadow">
<div class="card-header">
<div class="d-flex justify-content-between">
<div class="px-0 d-flex">
<div class="px-2">
<h4>Dipendenti</h4>
</div>
<div class="px-2">
<div class="px-1 py-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" @bind=@ShowInatt @bind:after=ForceReload>
<label class="form-check-label">Mostra Inattivi</label>
</div>
</div>
</div>
<div class="px-2">
<button class="btn btn-success" @onclick=CreateNew tooltip="Add New"><i class="fa-solid fa-plus"></i> Add New</button>
</div>
</div>
<div class="px-0 d-flex">
<div class="d-flex">
<div class="px-1 align-content-center">
<div class="input-group input-group-sm">
<span class="input-group-text">
Mostra QRCode
<span class="form-check form-switch align-content-center ms-2" title="Mostra QRCode">
<input class="form-check-input" type="checkbox" @bind=@ShowQrCode>
</span>
</span>
</div>
</div>
@if (ShowQrCode)
{
<div class="ps-1 pe-0 align-content-center">
<div class="input-group input-group-sm">
<span class="input-group-text">
@TextQrLinkInt
<span class="form-check form-switch align-content-center ms-2" title="@TextQrLinkInt">
<input class="form-check-input" type="checkbox" @bind=@ShowLinkInt>
</span>
</span>
</div>
</div>
<div class="ps-0 pe-1 align-content-center">
<div class="input-group input-group-sm">
<span class="input-group-text">
@TextQrLinkCore
<span class="form-check form-switch align-content-center ms-2" title="@TextQrLinkCore">
<input class="form-check-input" type="checkbox" @bind=@ShowLinkCore>
</span>
</span>
</div>
</div>
}
</div>
</div>
</div>
<div class="d-flex bg-dark bg-gradient text-light p-1">
<div class="px-2 mx-1 border border-2 border-info rounded rounded-3 align-content-center g-1"><i class="fa-solid fa-database"></i> Licenze Locali: disponibili <b>@NumLicDispLocal</b> / utenti attivi <b>@NumLicActLocal</b></div>
<div class="px-2 mx-1 border border-2 border-success rounded rounded-3 align-content-center g-1"><i class="fa-solid fa-cloud"></i> Licenze Online: disponibili <b>@NumLicDispOnline</b> / utenti attivi <b>@NumLicActOnline</b></div>
<button class="mx-1 btn btn-success" @onclick="DoRefresh"><i class="fa-solid fa-cloud-arrow-down g-1"></i> Refresh Status Online</button>
@if (NeedAllocation)
{
<button class="mx-1 btn btn-primary" @onclick="DoFixMissing"><i class="fa-solid fa-cloud-arrow-up g-1"></i> Allocazione Licenze</button>
}
else
{
<button class="mx-1 btn btn-secondary disabled" disabled><i class="fa-solid fa-cloud-arrow-up g-1"></i> Allocazione Licenze</button>
}
<button class="mx-1 btn btn-outline-secondary"><i class="fa-solid fa-ticket g-1"></i> Ticket Aperti <b>@NumTicket</b></button>
<button class="mx-1 btn btn-warning g-1"><i class="fa-solid fa-key"></i> Rigenera AuthKey</button>
</div>
</div>
<div class="card-body p-1 small">
@if (ListRecords == null || isLoading)
{
<EgwCoreLib.Razor.LoadingData></EgwCoreLib.Razor.LoadingData>
}
else if (totalCount == 0)
{
<div class="alert alert-info">Nessun record trovato</div>
}
else
{
<div class="row">
@if (ShowQrCode)
{
@foreach (var item in ListRecords)
{
<div class="col-12 col-md-6 col-lg-4 col-xl-3 mb-2">
<div class="card shadow">
<div class="card-header p-0">
<UserQrCode LinkInt="ShowLinkInt" RecordDip="item" LinkCore="ShowLinkCore"></UserQrCode>
</div>
<div class="card-body py-1">
<div class="fs-1 fw-bold">@item.Cognome</div>
<div class="fs-4">@item.Nome</div>
</div>
<div class="card-footer d-flex justify-content-between">
<div class="px-1"><img src="images/logoegw.png" class="imf-fluid" width="32" /> <span class="fs-6">Egalware</span></div>
<div class="px-1 fs-6 align-content-center"><i>SMART a-link</i></div>
</div>
</div>
</div>
}
}
else
{
<div class="col-12">
<table class="table table-striped table-sm text-start">
<thead>
<tr>
<th>
<button class="btn btn-primary btn-sm" @onclick="() => ForceReload()"><i class="fa-solid fa-rotate"></i></button>
</th>
<th>Cognome <Sorter ParamName="Cognome" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th>Nome <Sorter ParamName="Nome" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th>Matricola <Sorter ParamName="Matricola" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th>Profilo <Sorter ParamName="Profilo" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th>Dominio <Sorter ParamName="Dominio" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th>Utente <Sorter ParamName="Utente" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th>Email <Sorter ParamName="Email" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th>CF <Sorter ParamName="CF" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th>CodeHw <Sorter ParamName="CodeHw" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th>Dati anagrafici <Sorter ParamName="DatiAnag" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th>Gruppo <Sorter ParamName="Gruppo" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th>Stato licenza <Sorter ParamName="StatoLic" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th class="text-end">Responsabile <Sorter ParamName="Responsabile" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
</tr>
</thead>
<tbody>
@foreach (var item in ListRecords)
{
<tr class="@CheckSel(item)">
<td class="text-nowrap">
<button class="btn btn-info btn-sm" @onclick="() => DoSelect(item)" title="Dettaglio Record"><i class="fa-solid fa-search"></i></button>
@if (RecordEdit == null)
{
if (CheckFreeEdit(item.IdxDipendente))
{
<button class="btn btn-primary btn-sm mx-1" @onclick="() => DoEdit(item)" title="Modifica record">
<i class="fa-solid fa-edit"></i>
</button>
}
else
{
<button class="btn btn-warning btn-sm mx-1" @onclick="() => RequestReset(item)" title="Richiesta sblocco Licenza">
<i class="fa-solid fa-question-circle"></i>
</button>
}
}
else
{
<button class="btn btn-secondary btn-sm mx-1" disabled><i class="fa-solid fa-edit"></i></button>
}
</td>
<td class="text-start">@item.Cognome</td>
<td class="text-start">@item.Nome</td>
<td class="text-start">@item.Matricola</td>
<td class="text-start">@item.CodOrario</td>
<td class="text-start">@item.Dominio</td>
<td class="text-start">@item.Utente</td>
<td class="text-start">@item.Email</td>
<td class="text-start">@item.Cf</td>
<td class="text-start">@item.CodHw</td>
<td class="text-start">@($"{item.LuogoNascita}") - @($"{item.ProvNascita}") - @($"{item.NazNascita}") - @($"{item.DataNascita:dd/MM/yyyy}")</td>
<td class="text-start">@item.Gruppo</td>
<td class="text-start">@($"{item.DataAssunzione:dd/MM/yyyy}") - @($"{item.DataCessazione:dd/MM/yyyy}")</td>
<td class="text-end">
<select @bind="@item.idxResp" class="form-select form-select-sm disabled" disabled style="min-width: 12rem;">
<option value="0">--- Selezionare ---</option>
@foreach (var dip in ListDipendentiOrd)
{
<option value="@dip.IdxDipendente">@($"{dip.Cognome} {dip.Nome}")</option>
}
</select>
</td>
</tr>
}
</tbody>
</table>
</div>
}
</div>
}
</div>
<div class="card-footer">
<EgwCoreLib.Razor.DataPager PageSize="@numRecord" currPage="@currPage" numRecordChanged="SetNumRec" numPageChanged="SetPage" totalCount="@totalCount" showLoading="@isLoading"></EgwCoreLib.Razor.DataPager>
</div>
</div>
@@ -0,0 +1,568 @@
using EgwCoreLib.Razor;
using GPW.CORE.Data.DbModels;
using GPW.CORE.Data.Services;
using Microsoft.AspNetCore.Components;
using NLog;
using System.Buffers;
using System.Threading.Tasks;
namespace GPW.CORE.ADM.Components.Compo
{
public partial class DipendentiMan : IDisposable
{
#region Public Methods
public void Dispose()
{
AppMServ.EA_SearchUpdated -= AppMServ_EA_SearchUpdated;
}
#endregion Public Methods
#region Protected Fields
protected int NumLicActLocal = 0;
protected int NumLicActOnline = 0;
protected int NumLicDispLocal = 0;
protected int NumLicDispOnline = 0;
protected int NumTicket = 0;
#endregion Protected Fields
#region Protected Properties
[Inject]
protected MessageService AppMServ { get; set; } = null!;
[Inject]
protected GpwDataService GDataServ { get; set; } = null!;
[Inject]
protected LicenseService LicServ { get; set; } = null!;
protected List<DipendentiModel> ListDipendentiAttiviOrd
{
get => ListDipendenti != null ? ListDipendenti.Where(x => x.Attivo ?? false).OrderBy(x => x.Cognome).ThenBy(x => x.Nome).ToList() : new List<DipendentiModel>();
}
protected List<DipendentiModel> ListDipendentiOrd
{
get => ListDipendenti != null ? ListDipendenti.OrderBy(x => x.Cognome).ThenBy(x => x.Nome).ToList() : new List<DipendentiModel>();
}
protected string modalSize
{
get => CtrlMode == DipendentiEdit.EditMode.FullEdit ? "modal-xl" : "modal-lg";
}
protected bool NeedAllocation
{
get => NumLicActOnline == NumLicActLocal && NumLicActOnline != NumLicActLocal;
}
protected string TextQrLinkCore
{
get => ShowLinkCore ? "GPW Core" : "GPW Legacy";
}
protected string TextQrLinkInt
{
get => ShowLinkInt ? "Link Interno" : "Link Esterno";
}
#endregion Protected Properties
#region Protected Methods
protected string CheckSel(DipendentiModel curItem)
{
string answ = curItem.Attivo ?? false ? "" : "text-secondary striked";
if (RecordEdit != null)
{
answ = curItem.Cf == RecordEdit.Cf ? "table-info" : "";
}
return answ;
}
protected async Task CreateNew()
{
}
protected void DoEdit(DipendentiModel? selItem)
{
CtrlMode = DipendentiEdit.EditMode.FullEdit;
RecordEdit = selItem;
}
protected void RequestReset(DipendentiModel? selItem)
{
CtrlMode = DipendentiEdit.EditMode.ResetRequest;
RecordEdit = selItem;
}
protected async Task DoFixMissing()
{
// procedo SOLO SE il numero online/offline è differente in primis...
if (NeedAllocation)
{
// ciclo tutti gli utenti attivi
// verifico SE sia disponibile licenza...
var activationsList = LicServ.ActivList;
Dictionary<string, string> CodList = new Dictionary<string, string>();
// ciclo x ogni dip attivo...
foreach (var item in ListDipendentiAttiviOrd)
{
// calcolo codImpiego
string currCodImp = LicServ.HashDip(item);
// cerco se abbia attivazione
var currActiv = activationsList.Where(x => x.CodImpiego == currCodImp).FirstOrDefault();
if (currActiv == null || currActiv.CodImpiego != currCodImp)
{
CodList.Add(currCodImp, item.AuthKey);
}
}
// provo attivazione in blocco
await LicServ.TryActivationMult(CodList);
// cmq faccio refresh
await FullRefresh();
// ricalcolo licenze
await RefreshLicData(true);
}
await ReloadData();
}
protected async Task DoRefresh()
{
isLoading = true;
await LicServ.resetActivList();
await FullRefresh();
await ReloadData();
// ricalcolo licenze
await RefreshLicData(false);
isLoading = false;
}
protected void DoSelect(DipendentiModel currRec)
{
CtrlMode = DipendentiEdit.EditMode.KeyRegen;
RecordEdit = currRec;
}
protected async Task ForceReload()
{
currPage = 1;
CtrlMode = DipendentiEdit.EditMode.None;
RecordEdit = null;
await ReloadData();
// ricalcolo licenze
await RefreshLicData(false);
}
protected override async Task OnInitializedAsync()
{
await ReloadConfData();
await ReloadData();
await RefreshLicData(true);
AppMServ.EA_SearchUpdated += AppMServ_EA_SearchUpdated;
}
protected async Task SetNumRec(int newNum)
{
numRecord = newNum;
currPage = 1;
await AppMServ.NumRowGridSet(gridKey, newNum);
await InvokeAsync(ReloadData);
}
protected async Task SetPage(int newNum)
{
currPage = newNum;
await InvokeAsync(ReloadData);
}
protected async Task SortRequested(Sorter.SortCallBack e)
{
sortField = e.ParamName;
sortAsc = e.IsAscending;
await ReloadData();
}
#endregion Protected Methods
#region Private Fields
private static Logger Log = LogManager.GetCurrentClassLogger();
private int currPage = 1;
private DipendentiEdit.EditMode CtrlMode = DipendentiEdit.EditMode.None;
private string gridKey = "DipendentiMan";
private bool isLoading = false;
private int numRecord = 10;
private DipendentiModel? RecordEdit = null;
private string searchVal = "";
private bool ShowInatt = false;
private bool ShowLinkCore = true;
private bool ShowLinkInt = true;
private bool ShowQrCode = false;
private bool sortAsc = true;
private string sortField = "";
#endregion Private Fields
#region Private Properties
private List<DipendentiModel>? ListDipendenti { get; set; } = null;
private List<AnagOrariModel> ListOrari { get; set; } = null!;
private List<DipendentiModel>? ListRecords { get; set; } = null;
private List<DipendentiModel>? SearchRecords { get; set; } = null;
private int totalCount { get; set; } = 0;
#endregion Private Properties
#region Private Methods
private void AppMServ_EA_SearchUpdated()
{
ReloadData().ConfigureAwait(false);
}
/// <summary>
/// Verifica licenza (se sia libera x modifica o prima associazione)
/// </summary>
/// <param name="IdxDip"></param>
/// <returns></returns>
public bool CheckFreeEdit(int IdxDip)
{
bool answ = false;
if (IdxDip > 0)
{
// cerco!
var currUser = ListDipendentiAttiviOrd.Where(x => x.IdxDipendente == IdxDip).FirstOrDefault();
if (currUser != null)
{
// verifico SE sia disponibile licenza...
var activationsList = LicServ.ActivList;
var currHash = LicServ.HashDip(currUser);
var currAct = activationsList.Where(x => x.CodImpiego == currHash).FirstOrDefault();
// se NON c'è licenza è ok (editabile)
answ = (currAct == null);
// ora verifico: se NON ha licenza OK, altrimenti deve essere scaduta...
if (!answ)
{
answ = currAct.VetoUnlock <= DateTime.Today;
}
}
}
return answ;
}
/// <summary>
/// Rilascia licenza e rilegge conf
/// </summary>
/// <param name="CurrRecord"></param>
/// <returns></returns>
private async Task ReleaseLicense(DipendentiModel CurrRecord)
{
// verifica SE ci sono licenze disponibili
if (NumLicDispOnline > NumLicActOnline)
{
// chiamo rimozione licenza
var CodImpiego = LicServ.HashDip(CurrRecord);
bool fatto = await LicServ.TryRemoveActivation(CodImpiego, CurrRecord.AuthKey);
if (fatto)
{
// disattiva utente
GDataServ.DipUpdateActive(CurrRecord.IdxDipendente, false);
}
LicServ.ResetLicenseData();
}
// disattivo record mostrato...
RecordEdit = null;
// ricarico
await ReloadData();
// ricalcolo licenze
await RefreshLicData(true);
}
private async Task DoActivate(DipendentiModel CurrRecord)
{
// verifica SE ci sono licenze disponibili
if (NumLicDispOnline > NumLicActOnline)
{
// attiva utente
GDataServ.DipUpdateActive(CurrRecord.IdxDipendente, true);
string CodImpiego = LicServ.HashDip(CurrRecord);
// effettua riassegnazione
bool fatto = LicServ.TryActivation(CodImpiego, CurrRecord.AuthKey);
}
await ReloadData();
// ricalcolo licenze
await RefreshLicData(true);
}
private async Task FullRefresh()
{
LicServ.ResetLicenseData();
// eseguo call di recupero da online
bool refreshApp = await LicServ.RefreshApplic();
bool refreshAct = await LicServ.RefreshLicense();
bool refreshPay = LicServ.RefreshPayload();
// chiama update di TUTTE le authKey verso il server online
int numLoc = 0;
foreach (var item in ListDipendentiAttiviOrd)
{
var CodImpiego = LicServ.HashDip(item);
bool fatto = await LicServ.TryRefreshActivation(CodImpiego, item.AuthKey);
if (fatto)
numLoc++;
}
Log.Trace($"NumLoc: {numLoc}");
}
private async Task RefreshLicData(bool forceReload)
{
if (!LicServ.HasAppData || forceReload)
{
await FullRefresh();
}
NumLicDispLocal = LicServ.NumLicDb;
NumLicActLocal = LicServ.ActivList.Count();
NumLicDispOnline = LicServ.AppLicense.NumLicenze;
NumLicActOnline = LicServ.AppLicense.NumLicenzeAttive;
}
private async Task ReloadConfData()
{
ListOrari = await GDataServ.AnagOrarioAll();
}
private async Task ReloadData()
{
isLoading = true;
ListRecords = null;
ListDipendenti = await GDataServ.DipendentiGetAll();
if (ShowInatt)
{
SearchRecords = ListDipendenti;
}
else
{
SearchRecords = ListDipendenti.Where(x => (x.Attivo ?? false)).ToList();
}
// eseguo filtro ricerca
try
{
if (!string.IsNullOrEmpty(searchVal))
{
SearchRecords = SearchRecords
.Where(x => x.Cognome.Contains(searchVal) || x.Nome.Contains(searchVal) || x.Cf.Contains(searchVal) || x.Email.Contains(searchVal))
.ToList();
}
}
catch (Exception ex)
{
Log.Error($"Eccezione in recupero dati{Environment.NewLine}{ex}");
}
totalCount = SearchRecords.Count;
SortTable();
isLoading = false;
}
/// <summary>
/// Sorting e paging tabella
/// </summary>
private void SortTable()
{
if (SearchRecords != null)
{
// se ho ordinamento riordino...
if (!string.IsNullOrEmpty(sortField))
{
switch (sortField)
{
case "Cognome":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.Cognome).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.Cognome).ToList();
}
break;
case "Nome":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.Nome).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.Nome).ToList();
}
break;
case "Matricola":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.Matricola).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.Matricola).ToList();
}
break;
case "Profilo":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.CodOrario).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.CodOrario).ToList();
}
break;
case "Dominio":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.Dominio).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.Dominio).ToList();
}
break;
case "Utente":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.Utente).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.Utente).ToList();
}
break;
case "Email":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.Email).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.Email).ToList();
}
break;
case "CF":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.Cf).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.Cf).ToList();
}
break;
case "CodeHw":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.CodHw).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.CodHw).ToList();
}
break;
case "DatiAnag":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.LuogoNascita).ThenBy(x => x.ProvNascita).ThenBy(x => x.NazNascita).ThenBy(x => x.DataNascita).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.LuogoNascita).ThenBy(x => x.ProvNascita).ThenBy(x => x.NazNascita).ThenBy(x => x.DataNascita).ToList();
}
break;
case "Gruppo":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.Gruppo).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.Gruppo).ToList();
}
break;
case "StatoLic":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.DataAssunzione).ThenBy(x => x.DataCessazione).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.DataAssunzione).ThenBy(x => x.DataCessazione).ToList();
}
break;
case "Responsabile":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.idxResp).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.idxResp).ToList();
}
break;
default:
break;
}
}
// filtro x display
ListRecords = SearchRecords
.Skip(numRecord * (currPage - 1))
.Take(numRecord)
.ToList();
}
else
{
ListRecords = new List<DipendentiModel>();
}
}
#endregion Private Methods
}
}
+2 -2
View File
@@ -32,7 +32,7 @@
<span class="input-group-text" title="Cliente">C</span>
<select @bind="@IdxCli" class="form-select form-select-sm" title="Cliente" @bind:after=SaveCli>
<option value="0">--- Selezionare ---</option>
@foreach (var item in ListClienti)
@foreach (var item in ListClientiFilt)
{
<option value="@item.IdxCliente">@($"{item.RagSociale}")</option>
}
@@ -45,7 +45,7 @@
<span class="input-group-text" title="Progetto">P</span>
<select @bind="@IdxPrj" class="form-select form-select-sm" title="Progetto" @bind:after=SaveProj>
<option value="0">--- Selezionare ---</option>
@foreach (var item in ListProgetti)
@foreach (var item in ListProgettiFilt)
{
<option value="@item.IdxProgetto">@($"{item.NomeProj} | {item.DescrProj}")</option>
}
+51 -20
View File
@@ -86,6 +86,37 @@ namespace GPW.CORE.ADM.Components.Compo
[Inject]
protected IJSRuntime JSRuntime { get; set; } = null!;
protected List<AnagClientiModel> ListClientiFilt
{
get
{
List<AnagClientiModel> answ = new List<AnagClientiModel>();
if (ShowOnlyActive)
{
answ = ListClienti.Where(x => x.Attivo).ToList();
}
else
{
answ = ListClienti;
}
return answ;
}
}
protected List<AnagProgettiModel> ListProgettiFilt
{
get
{
List<AnagProgettiModel> answ = new List<AnagProgettiModel>();
if (IdxCli > 0)
{
ListProgetti = GDataServ.AnagProjByCli(IdxCli);
answ = ListProgetti.Where(x => (x.Attivo ?? false) || !ShowOnlyActive).ToList();
}
return answ;
}
}
#endregion Protected Properties
#region Protected Methods
@@ -202,10 +233,10 @@ namespace GPW.CORE.ADM.Components.Compo
/// init valori da config
/// </summary>
/// <returns></returns>
protected async Task InitConf()
protected void InitConf()
{
// leggo conf standard controllo RegAtt
var sWarningRatioPerc = await GDataServ.ConfigGetKey("WarningRatioPerc");
var sWarningRatioPerc = GDataServ.ConfigGetKey("WarningRatioPerc");
if (sWarningRatioPerc != null)
{
double.TryParse(sWarningRatioPerc.valore, out warnRatio);
@@ -214,9 +245,9 @@ namespace GPW.CORE.ADM.Components.Compo
protected override async Task OnInitializedAsync()
{
await InitConf();
InitConf();
await ReloadSel();
await ReloadData();
ReloadAnagBase();
}
protected override async Task OnParametersSetAsync()
@@ -243,11 +274,14 @@ namespace GPW.CORE.ADM.Components.Compo
#region Private Fields
private string gridKey = "FasiMan";
private int idxCli = 0;
private int idxPrj = 0;
private AnagFasiModel? RecordEdit = null;
private AnagFasiExplModel? RecordSel = null;
private double warnRatio = 50;
#endregion Private Fields
@@ -255,11 +289,17 @@ namespace GPW.CORE.ADM.Components.Compo
#region Private Properties
private bool isLoading { get; set; } = false;
private List<AnagClientiModel> ListClienti { get; set; } = new List<AnagClientiModel>();
private List<AnagProgettiModel> ListProgetti { get; set; } = new List<AnagProgettiModel>();
private List<AnagFasiExplModel>? listRecords { get; set; } = new List<AnagFasiExplModel>();
private List<TagFasiDTO> ListTagFasi { get; set; } = new List<TagFasiDTO>();
private string NewCodTagFase { get; set; } = "ND";
private int totalCount { get; set; } = 0;
#endregion Private Properties
@@ -321,27 +361,18 @@ namespace GPW.CORE.ADM.Components.Compo
return answ;
}
private void ReloadAnagBase()
{
ListTagFasi = GDataServ.AnagTagFasiAll();
ListClienti = GDataServ.AnagClientiAll();
}
private async Task ReloadData()
{
ListTagFasi = await GDataServ.AnagTagFasiAll();
if (CanSelProj)
{
listRecords = new List<AnagFasiExplModel>();
ListProgetti = new List<AnagProgettiModel>();
ListClienti = await GDataServ.AnagClientiAll();
if (ShowOnlyActive)
{
ListClienti = ListClienti.Where(x => x.Attivo).ToList();
}
// seleziono proj da client
if (IdxCli > 0)
{
ListProgetti = await GDataServ.AnagProjByCli(IdxCli);
if (ShowOnlyActive)
{
ListProgetti = ListProgetti.Where(x => x.Attivo ?? false).ToList();
}
}
// se abilitato x rilettura locale --> leggo fasi!
if (CanSelProj && IdxCli > 0 && IdxPrj > 0)
{
@@ -0,0 +1,58 @@
<div class="card shadow">
<div class="card-header">
Dettaglio Mensile
</div>
<div class="card-body p-1 small">
@if (ListRecords == null || isLoading)
{
<EgwCoreLib.Razor.LoadingData></EgwCoreLib.Razor.LoadingData>
}
else if (totalCount == 0)
{
<div class="alert alert-info">Nessun record trovato</div>
}
else
{
<table class="table table-striped table-sm text-start">
<thead>
<tr>
<th> </th>
<th>Data <Sorter ParamName="Data" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th class="text-end">Tag <Sorter ParamName="Tag" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
</tr>
</thead>
<tbody>
@foreach (var item in ListRecords)
{
<tr>
<td>
@if (item.isActive)
{
<button class="btn btn-primary btn-sm px-1 py-0" @onclick="() => DoToggle(item)"><i class="fa-solid fa-thumbs-up"></i></button>
}
else
{
<button class="btn btn-secondary btn-sm px-1 py-0" @onclick="() => DoToggle(item)"><i class="fa-solid fa-thumbs-down"></i></button>
}
</td>
<td>
@($"{item.DtRif:yyyy.MM.dd, dddd}")
</td>
<td class="text-end">@item.CodTag</td>
</tr>
}
</tbody>
<tfoot>
<tr>
<td colspan="3">
<EgwCoreLib.Razor.DataPager PageSize="@numRecord" currPage="@currPage" totalCount="@totalCount" showLoading="@isLoading" numRecordChanged="SetNumRec" numPageChanged="SetPage"></EgwCoreLib.Razor.DataPager>
</td>
</tr>
</tfoot>
</table>
}
</div>
</div>
@@ -0,0 +1,213 @@
using EgwCoreLib.Razor;
using EgwCoreLib.Utils;
using GPW.CORE.Data.DbModels;
using GPW.CORE.Data.DTO;
using GPW.CORE.Data.Services;
using Microsoft.AspNetCore.Components;
using NLog;
namespace GPW.CORE.ADM.Components.Compo
{
public partial class MonthTagDetail
{
#region Public Properties
[Parameter]
public MonthTagModel RecSel { get; set; } = null!;
#endregion Public Properties
#region Protected Properties
[Inject]
protected MessageService AppMServ { get; set; } = null!;
[Inject]
protected AppAuthService AuthServ { get; set; } = null!;
[Inject]
protected GpwDataService GDataServ { get; set; } = null!;
protected int IdxDipSel { get; set; } = 0;
#endregion Protected Properties
#region Protected Methods
protected string CheckSel(TagFasiDTO curItem)
{
string answ = "";
if (SelItem != null)
{
answ = curItem.CodTagFase == SelItem.CodTagFase ? "table-info" : "";
}
// verifico stato attivo
answ += !curItem.Enabled ? " striked" : "";
return answ;
}
protected void DoSelect(MonthTagModel currRec)
{
SelRecord = currRec;
}
protected async Task DoToggle(ListTagDDModel selRec)
{
if (selRec != null)
{
GDataServ.ListTagDDToggle(selRec.IdxTagDD);
}
await ReloadData();
}
protected override void OnInitialized()
{
CurrPeriodo.Fine = DateTime.Today.AddDays(1);
}
protected override async Task OnParametersSetAsync()
{
CurrPeriodo.Fine = new DateTime(RecSel.Anno, RecSel.Mese, 1).AddMonths(1);
CurrPeriodo.Inizio = new DateTime(RecSel.Anno, RecSel.Mese, 1);
IdxDipSel = RecSel.IdxDipendente;
await ReloadData();
}
protected async void Recalc()
{
await Task.Delay(200);
}
protected async Task SetNumRec(int newNum)
{
numRecord = newNum;
currPage = 1;
await AppMServ.NumRowGridSet(gridKey, newNum);
await InvokeAsync(ReloadData);
}
protected async Task SetPage(int newNum)
{
currPage = newNum;
await InvokeAsync(ReloadData);
}
protected async Task SortRequested(Sorter.SortCallBack e)
{
sortField = e.ParamName;
sortAsc = e.IsAscending;
await ReloadData();
}
protected string Traduci(string lemma)
{
return AuthServ.Traduci(lemma, AppMServ.UserLang);
}
#endregion Protected Methods
#region Private Fields
private static Logger Log = LogManager.GetCurrentClassLogger();
private string gridKey = "TagsMan";
private TagFasiDTO? SelItem = null;
private bool sortAsc = true;
private string sortField = "";
#endregion Private Fields
#region Private Properties
private int currPage { get; set; } = 1;
private DtUtils.Periodo CurrPeriodo { get; set; } = new DtUtils.Periodo(DtUtils.PeriodSet.ThisMonth);
private bool isLoading { get; set; } = false;
private List<ListTagDDModel>? ListRecords { get; set; } = null;
private int numRecord { get; set; } = 50;
private List<ListTagDDModel>? SearchRecords { get; set; } = null;
private MonthTagModel? SelRecord { get; set; } = null;
private bool ShowInatt { get; set; } = false;
private int totalCount { get; set; } = 0;
#endregion Private Properties
#region Private Methods
private async Task ReloadData()
{
isLoading = true;
ListRecords = null;
try
{
SearchRecords = await GDataServ.ListTagDD(IdxDipSel, CurrPeriodo.Inizio, CurrPeriodo.Fine);
}
catch (Exception ex)
{
Log.Error($"Eccezione in recupero dati{Environment.NewLine}{ex}");
}
totalCount = SearchRecords.Count;
SortTable();
isLoading = false;
}
private async Task SavePeriodo(DtUtils.Periodo newPeiodo)
{
CurrPeriodo = newPeiodo;
await ReloadData();
}
private void SortTable()
{
if (SearchRecords != null)
{
// se ho ordinamento riordino...
if (!string.IsNullOrEmpty(sortField))
{
switch (sortField)
{
#if true
case "Data":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.DtRif).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.DtRif).ToList();
}
break;
case "IdxTagDD":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.IdxTagDD).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.IdxTagDD).ToList();
}
break;
#endif
default:
break;
}
}
// filtro x display
ListRecords = SearchRecords
.Skip(numRecord * (currPage - 1))
.Take(numRecord)
.ToList();
}
else
{
ListRecords = new List<ListTagDDModel>();
}
}
#endregion Private Methods
}
}
@@ -34,7 +34,91 @@
</div>
</div>
<div class="card-body p-1 small">
<p>elenco da stored</p>
@if (ListRecords == null || isLoading)
{
<EgwCoreLib.Razor.LoadingData></EgwCoreLib.Razor.LoadingData>
}
else if (totalCount == 0)
{
<div class="alert alert-info">Nessun record trovato</div>
}
else
{
<div class="row">
<div class="@mainDivCss">
<table class="table table-striped table-sm text-start">
<thead>
<tr>
<th>
<button class="btn btn-primary btn-sm" @onclick="() => ForceReload()"><i class="fa-solid fa-rotate"></i></button>
</th>
<th>Anno <Sorter ParamName="Anno" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th>Mese <Sorter ParamName="Mese" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th>Cognome Nome <Sorter ParamName="CognomeNome" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th class="text-end">CodTag <Sorter ParamName="CodTag" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th class="text-end"># Tag <Sorter ParamName="NumTag" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th class="text-end"># Dis <Sorter ParamName="NumDis" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
@*
<th>Colonna 4 <Sorter ParamName="" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th>Colonna 5 <Sorter ParamName="" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th> *@
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in ListRecords)
{
<tr class="@CssCheckSel(item)">
<td>
@if (SelItem == null)
{
<button class="btn btn-primary btn-sm" @onclick="() => DoSelect(item)"><i class="fa-solid fa-search"></i></button>
}
else
{
<button class="btn btn-secondary btn-sm" disabled><i class="fa-solid fa-edit"></i></button>
}
</td>
<td>@item.Anno</td>
<td>@item.Mese</td>
<td>@item.CognomeNome</td>
<td class="text-end">@item.CodTag</td>
<td class="text-end">@item.NumTag</td>
<td class="text-end">@item.NumDis</td>
@*
<td>
@if (item.Enabled && item.NumFasi == 0)
{
<button class="btn btn-danger btn-sm" @onclick="() => DoDelete(item)"><i class="fa-solid fa-trash"></i></button>
}
else
{
<button class="btn btn-secondary btn-sm" disabled><i class="fa-solid fa-trash"></i></button>
}
</td> *@
</tr>
}
</tbody>
<tfoot>
<tr>
<td colspan="7">
<EgwCoreLib.Razor.DataPager PageSize="@numRecord" currPage="@currPage" totalCount="@totalCount" showLoading="@isLoading" numRecordChanged="SetNumRec" numPageChanged="SetPage"></EgwCoreLib.Razor.DataPager>
</td>
</tr>
</tfoot>
</table>
</div>
@if (SelRecord != null)
{
<div class="@detDivCss">
<MonthTagDetail RecSel="@SelRecord"></MonthTagDetail>
</div>
}
</div>
}
</div>
</div>
@@ -1,7 +1,10 @@
using EgwCoreLib.Razor;
using EgwCoreLib.Utils;
using GPW.CORE.Data.DbModels;
using GPW.CORE.Data.DTO;
using GPW.CORE.Data.Services;
using Microsoft.AspNetCore.Components;
using NLog;
namespace GPW.CORE.ADM.Components.Compo
{
@@ -24,6 +27,38 @@ namespace GPW.CORE.ADM.Components.Compo
#region Protected Methods
protected string CheckSel(TagFasiDTO curItem)
{
string answ = "";
if (SelItem != null)
{
answ = curItem.CodTagFase == SelItem.CodTagFase ? "table-info" : "";
}
// verifico stato attivo
answ += !curItem.Enabled ? " striked" : "";
return answ;
}
protected void DoSelect(MonthTagModel currRec)
{
SelRecord = currRec;
}
private string mainDivCss
{
get => SelRecord == null ? "col-12" : "col-12 col-lg-9";
}
private string detDivCss
{
get => SelRecord == null ? "col-0" : "col-12 col-lg-3";
}
protected string CssCheckSel(MonthTagModel currRec)
{
bool isSel = SelRecord != null && SelRecord.IdxDipendente == currRec.IdxDipendente && SelRecord.Anno == currRec.Anno && SelRecord.Mese == currRec.Mese;
return isSel ? "table-info" : "";
}
protected async Task ForceReload()
{
currPage = 1;
@@ -31,14 +66,25 @@ namespace GPW.CORE.ADM.Components.Compo
await ReloadData();
}
protected override async Task OnInitializedAsync()
protected override void OnInitialized()
{
CurrPeriodo.Fine = DateTime.Today.AddDays(1);
}
protected async void Recalc()
protected async Task Recalc()
{
await Task.Delay(200);
// eseguo ricalcolo
isLoading = true;
GDataServ.MonthTagRecalc(IdxDipSel, CurrPeriodo.Inizio, CurrPeriodo.Fine, "BP", 270);
// rileggo
await ReloadData();
}
protected async Task SortRequested(Sorter.SortCallBack e)
{
sortField = e.ParamName;
sortAsc = e.IsAscending;
await ReloadData();
}
protected string Traduci(string lemma)
@@ -46,8 +92,33 @@ namespace GPW.CORE.ADM.Components.Compo
return AuthServ.Traduci(lemma, AppMServ.UserLang);
}
protected async Task SetNumRec(int newNum)
{
numRecord = newNum;
currPage = 1;
await AppMServ.NumRowGridSet(gridKey, newNum);
await InvokeAsync(ReloadData);
}
protected async Task SetPage(int newNum)
{
currPage = newNum;
await InvokeAsync(ReloadData);
}
#endregion Protected Methods
#region Private Fields
private static Logger Log = LogManager.GetCurrentClassLogger();
private string gridKey = "TagsMan";
private TagFasiDTO? SelItem = null;
private bool sortAsc = true;
private string sortField = "";
#endregion Private Fields
#region Private Properties
private int currPage { get; set; } = 1;
@@ -57,9 +128,8 @@ namespace GPW.CORE.ADM.Components.Compo
private List<DipendentiModel> ListDipendenti { get; set; } = new List<DipendentiModel>();
private List<MonthTagModel>? ListRecords { get; set; } = null;
private int numRecord { get; set; } = 10;
private List<MonthTagModel>? SearchRecords { get; set; } = null;
private MonthTagModel? SelRecord { get; set; } = null;
private bool ShowInatt { get; set; } = false;
@@ -83,10 +153,9 @@ namespace GPW.CORE.ADM.Components.Compo
{
ListDipendenti = rawList.Where(x => (x.Attivo ?? false)).ToList();
}
#if false
try
{
SearchRecords = await GDataServ.TeRaExplGetFilt(IdxDipSel, CurrPeriodo.Inizio, CurrPeriodo.Fine, ShowInatt, ShowWE, MaxErrMin, MaxErrPlus);
SearchRecords = await GDataServ.MonthTagList(IdxDipSel, CurrPeriodo.Inizio, CurrPeriodo.Fine);
// verifico filtro per IdxDip
if (IdxDipSel > 0)
{
@@ -100,10 +169,6 @@ namespace GPW.CORE.ADM.Components.Compo
totalCount = SearchRecords.Count;
SortTable();
isLoading = false;
// tolgo eventuale send data...
isSendingData = false;
#endif
await Task.Delay(1);
}
private async Task SavePeriodo(DtUtils.Periodo newPeiodo)
@@ -112,6 +177,100 @@ namespace GPW.CORE.ADM.Components.Compo
await ReloadData();
}
private void SortTable()
{
if (SearchRecords != null)
{
// se ho ordinamento riordino...
if (!string.IsNullOrEmpty(sortField))
{
switch (sortField)
{
#if true
case "Anno":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.Anno).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.Anno).ToList();
}
break;
case "Mese":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.Mese).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.Mese).ToList();
}
break;
case "CognomeNome":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.CognomeNome).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.CognomeNome).ToList();
}
break;
case "CodTag":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.CodTag).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.CodTag).ToList();
}
break;
case "NumTag":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.NumTag).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.NumTag).ToList();
}
break;
case "NumDis":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.NumDis).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.NumDis).ToList();
}
break;
#endif
default:
break;
}
}
// filtro x display
ListRecords = SearchRecords
.Skip(numRecord * (currPage - 1))
.Take(numRecord)
.ToList();
}
else
{
ListRecords = new List<MonthTagModel>();
}
}
#endregion Private Methods
}
}
@@ -146,18 +146,17 @@
@if (ShowFasi && RecordSel != null)
{
<tr class="align-middle @CheckSel(RecordSel)">
<td>
<td class="text-nowrap">
<button class="btn btn-secondary btn-sm" disabled><i class="fa-solid fa-search"></i></button>
<button class="btn btn-secondary btn-sm" disabled><i class="fa-solid fa-edit"></i></button>
<button class="btn btn-secondary btn-sm" disabled><i class="fa-solid fa-angles-right"></i></button>
</td>
<td>
<td class="text-nowrap">
<div class="fw-bold">
@RecordSel.Gruppo
</div>
</td>
<td>
<td class="text-nowrap">
<div class="fw-bold">
@RecordSel.RagSociale
</div>
@@ -189,13 +188,12 @@
@foreach (var item in ListRecords)
{
<tr class="align-middle @CheckSel(item)">
<td>
<td class="text-nowrap">
@if (RecordEdit == null)
{
<button class="btn btn-info btn-sm" @onclick="() => DoSelect(item)"><i class="fa-solid fa-search"></i></button>
<button class="btn btn-primary btn-sm" @onclick="() => DoEdit(item)"><i class="fa-solid fa-edit"></i></button>
<button class="btn btn-warning btn-sm" @onclick="() => DoShowFasi(item)"><i class="fa-solid fa-angles-right"></i></button>
@* <a class="btn btn-warning btn-sm" href="fasi" target="_blank"><i class="fa-solid fa-angles-right"></i></a> *@
}
else
{
@@ -204,12 +202,12 @@
<button class="btn btn-secondary btn-sm" disabled><i class="fa-solid fa-angles-right"></i></button>
}
</td>
<td>
<td class="text-nowrap">
<div class="fw-bold">
@item.Gruppo
</div>
</td>
<td>
<td class="text-nowrap">
<div class="fw-bold">
@item.RagSociale
</div>
@@ -148,7 +148,7 @@ namespace GPW.CORE.ADM.Components.Compo
protected async Task initConf()
{
// leggo conf standard controllo RegAtt
var sWarningRatioPerc = await GDataServ.ConfigGetKey("WarningRatioPerc");
var sWarningRatioPerc = await GDataServ.ConfigGetKeyAsync("WarningRatioPerc");
if (sWarningRatioPerc != null)
{
double.TryParse(sWarningRatioPerc.valore, out warnRatio);
@@ -374,7 +374,7 @@ namespace GPW.CORE.ADM.Components.Compo
isLoading = true;
ListRecords = null;
ListGruppi = await GDataServ.AnagGruppiAll();
ListClienti = await GDataServ.AnagClientiAll();
ListClienti = await GDataServ.AnagClientiAllAsync();
try
{
SearchRecords = await GDataServ.AnagProjCalcFilt(Gruppo, IdxCliente, ShowPrjArc, ShowPrjZH, ShowPrjStr);
@@ -201,7 +201,7 @@ namespace GPW.CORE.ADM.Components.Compo
{
SearchRecords = null;
await Task.Delay(1);
SearchRecords = await GDataServ.RegMalattieGetByPeriod(DtStart, DtEnd);
SearchRecords = GDataServ.RegMalattieGetByPeriod(DtStart, DtEnd);
// conteggio!
totalCount = SearchRecords.Count;
// paginazione
@@ -294,12 +294,12 @@ namespace GPW.CORE.ADM.Components.Compo
private async Task initConf()
{
// leggo conf standard giorni permessi/ferie
var sNumDayFerieRichAntic = await GDataServ.ConfigGetKey("NumDayFerieRichAntic");
var sNumDayFerieRichAntic = await GDataServ.ConfigGetKeyAsync("NumDayFerieRichAntic");
if (sNumDayFerieRichAntic != null)
{
int.TryParse(sNumDayFerieRichAntic.valore, out NumDayFerieRichAntic);
}
var sNumDayPermMax = await GDataServ.ConfigGetKey("NumDayPermMax");
var sNumDayPermMax = await GDataServ.ConfigGetKeyAsync("NumDayPermMax");
if (sNumDayPermMax != null)
{
int.TryParse(sNumDayPermMax.valore, out NumDayPermMax);
@@ -364,7 +364,7 @@ namespace GPW.CORE.ADM.Components.Compo
await initConf();
await Task.Delay(1);
// carico richieste di TUTTI
SearchRecords = await GDataServ.RegRichiesteGetByDip(0, dtInizio, dtFine);
SearchRecords = GDataServ.RegRichiesteGetByDip(0, dtInizio, dtFine);
// filtro x tipo richieste...
if (ShowNeedConf)
{
@@ -0,0 +1,34 @@
<div class="card shadow mb-5 border border-secondary">
<div class="card-header">
<h3>Elaborazioni disponibili</h3>
</div>
<div class="card-body">
@if (ListRecords == null || isLoading)
{
<EgwCoreLib.Razor.LoadingData></EgwCoreLib.Razor.LoadingData>
}
else if (totalCount == 0)
{
<div class="alert alert-info">Nessun record trovato</div>
}
else
{
<div class="row">
@foreach (var item in ListRecords)
{
<a target="_blank" href="@(fullUrl(item.ReportUrl))" class="col-12 col-md-6 col-lg-4 col-xl-3 p-2">
<div class="border border-2 border-dark rounded rounded-4 shadow shadow-lg @item.CssClass">
<div class="areaTesto px-2">
<h3>@item.Nome</h3>
<p class="small">@item.Descrizione</p>
</div>
</div>
</a>
}
</div>
}
</div>
</div>
@@ -0,0 +1,70 @@
using GPW.CORE.Data.DbModels;
using GPW.CORE.Data.DTO;
using GPW.CORE.Data.Services;
using Microsoft.AspNetCore.Components;
namespace GPW.CORE.ADM.Components.Compo
{
public partial class ReportProgettiMan
{
#region Protected Properties
[Inject]
protected MessageService AppMServ { get; set; } = null!;
[Inject]
protected AppAuthService AuthServ { get; set; } = null!;
[Inject]
protected IConfiguration config { get; set; } = null!;
[Inject]
protected GpwDataService GDataServ { get; set; } = null!;
#endregion Protected Properties
#region Protected Methods
protected string fullUrl(string repUrl)
{
return $"{reportBaseUrl}{repUrl}";
}
protected override async Task OnInitializedAsync()
{
reportBaseUrl = config.GetValue<string>("ServerConf:ReportBaseUrl") ?? "http://W2019-SQL-STEAM/ReportServer?";
await ReloadData();
}
protected string Traduci(string lemma)
{
return AuthServ.Traduci(lemma, AppMServ.UserLang);
}
#endregion Protected Methods
#region Private Fields
private bool isLoading = false;
private string reportBaseUrl = "";
private int totalCount = 0;
#endregion Private Fields
#region Private Properties
private List<ElencoReportModel>? ListRecords { get; set; } = null;
#endregion Private Properties
#region Private Methods
private async Task ReloadData()
{
ListRecords = await GDataServ.ElencoReportFilt("A1");
totalCount = ListRecords.Count;
}
#endregion Private Methods
}
}
@@ -121,7 +121,7 @@ namespace GPW.CORE.ADM.Components.Compo
// svuoto temp folder dopo 1 min
await clearDir(1);
// carico conf specifica...
var rCodTimbra = await GDataServ.ConfigGetKey("ExpOreCodTimbra");
var rCodTimbra = await GDataServ.ConfigGetKeyAsync("ExpOreCodTimbra");
if (rCodTimbra != null)
{
TimbExp = rCodTimbra.valore;
@@ -322,7 +322,7 @@ namespace GPW.CORE.ADM.Components.Compo
{
foreach (var item in list2fix)
{
// escludo date da oggi in poi...
// escludo date da dtRif in poi...
if (item.DataLav < DateTime.Today)
{
GiustificativiModel rec2del = new GiustificativiModel()
@@ -0,0 +1,291 @@
<div class="card shadow mb-5 border border-secondary">
<div class="card-header px-0">
<div class="d-flex justify-content-between px-2">
<div class="px-0 d-flex justify-content-between">
<div class="px-2">
<h3>Attivit&agrave;</h3>
</div>
@* <div class="px-2">
<button class="btn btn-success" @onclick=Recalc tooltip="Add New"><i class="fa-solid fa-plus"></i> @Traduci("Ricalcola")</button>
</div> *@
</div>
<div class="px-0">
<div class="px-0">
<div class="d-flex">
<div class="px-1 align-content-center">
<div class="input-group input-group-sm">
<span class="input-group-text">
Dipendente
</span>
<select @bind="@IdxDipSel" class="form-select form-select-sm" @bind:after=ForceReload>
<option value="0">--- Selezionare ---</option>
@foreach (var item in ListDipendentiFilt)
{
<option value="@item.IdxDipendente">@($"{item.Cognome} {item.Nome}")</option>
}
</select>
<span class="input-group-text px-0">
<span class="form-check form-switch align-content-center ms-2" title="Mostra inattivi">
<input class="form-check-input" type="checkbox" @bind=@ShowDipInatt>
</span>
</span>
</div>
</div>
<div class="px-0">
<PeriodoSel CurrPeriodo="@CurrPeriodo" E_PeriodoSel="@SavePeriodo"></PeriodoSel>
</div>
</div>
</div>
</div>
</div>
<div class="d-flex justify-content-end bg-secondary bg-gradient bg-opacity-75 py-1 px-0">
<div class="px-1 d-flex">
<div class="input-group input-group-sm">
<span class="input-group-text">
Cliente
</span>
<select @bind="@IdxCliSelFrom" class="form-select form-select-sm" @bind:after=ForceReload>
<option value="0">--- Tutti ---</option>
@foreach (var item in ListClientiFiltFrom)
{
<option value="@item.IdxCliente">@($"{item.RagSociale}")</option>
}
</select>
<span class="input-group-text px-0">
<span class="form-check form-switch align-content-center ms-2" title="Mostra inattivi">
<input class="form-check-input" type="checkbox" @bind=@ShowCliInattFrom>
</span>
</span>
</div>
</div>
<div class="px-1 d-flex">
<div class="input-group input-group-sm">
<span class="input-group-text">
Progetto
</span>
@if (IdxCliSelFrom == 0)
{
<select @bind="@IdxProjSelFrom" disabled class="form-select form-select-sm text-trim opacity-75" style="maxFrom-width:20rem;">
<option value="0">--- Tutti ---</option>
</select>
}
else
{
<select @bind="@IdxProjSelFrom" class="form-select form-select-sm text-trim" style="max-width:20rem;" @bind:after=ForceReload>
<option value="0">--- Tutti ---</option>
@foreach (var item in ListProgettiFiltFrom)
{
<option value="@item.IdxProgetto" title="@($"{item.DescrProj}")">@($"{item.NomeProj}")</option>
}
</select>
<span class="input-group-text px-0">
<span class="form-check form-switch align-content-center ms-2" title="Mostra inattivi">
<input class="form-check-input" type="checkbox" @bind=@ShowProjInattFrom>
</span>
</span>
}
</div>
</div>
<div class="px-2 d-flex">
<div class="input-group input-group-sm">
<span class="input-group-text">Fase</span>
@if (IdxProjSelFrom == 0)
{
<select @bind="@IdxFaseSelFrom" disabled class="form-select form-select-sm text-trim opacity-75" style="max-width:20rem;">
<option value="0">--- Tutti ---</option>
</select>
}
else
{
<select @bind="@IdxFaseSelFrom" class="form-select form-select-sm text-trim" style="max-width:20rem;" @bind:after=ForceReload>
<option value="0">--- Tutti ---</option>
@foreach (var item in ListFasiFiltFrom)
{
if (item.BudgetTime > 0)
{
<option value="@item.IdxFase" title="@($"{item.DescrizioneFase}")">@($"{item.NomeFase}")</option>
}
else
{
<option disabled class="bg-secondary bg-opacity-25 fw-bold" value="@item.IdxFase" title="@($"{item.DescrizioneFase}")">@($"{item.NomeFase}")</option>
}
}
</select>
<span class="input-group-text px-0">
<span class="form-check form-switch align-content-center ms-2" title="Mostra inattivi">
<input class="form-check-input" type="checkbox" @bind=@ShowFaseInattFrom>
</span>
</span>
}
</div>
</div>
</div>
</div>
<div class="card-body p-1 small">
@if (ListRecords == null || isLoading)
{
<EgwCoreLib.Razor.LoadingData></EgwCoreLib.Razor.LoadingData>
}
else if (totalCount == 0)
{
<div class="alert alert-info">Nessun record trovato</div>
}
else
{
<div class="row">
<div class="@mainDivCss">
<table class="table table-striped table-sm text-start small">
<thead>
<tr>
<th class="text-center" title="Toggle Seleziona Tutti">
@if (allSel)
{
<i class="fa-solid fa-toggle-on text-primary fs-5" @onclick="ToggleSelection"></i>
}
else
{
<i class="fa-solid fa-toggle-off text-secondary fs-5" @onclick="ToggleSelection"></i>
}
</th>
<th class="text-start">Cognome Nome <Sorter ParamName="CognomeNome" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th class="text-start">Ore <Sorter ParamName="OreTot" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th class="text-start">Periodo <Sorter ParamName="Periodo" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th class="text-start">Gruppo <Sorter ParamName="Gruppo" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th class="text-start">Progetto <Sorter ParamName="Progetto" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th class="text-start">Descrizione <Sorter ParamName="Descrizione" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
</tr>
</thead>
<tbody>
@foreach (var item in ListRecords)
{
<tr class="@CssCheckSel(item)">
<td class="text-center">
<input class="form-check-input" type="checkbox" @bind="item.Selected"></input>
</td>
<td class="text-start">@item.CognomeNome</td>
<td class="text-start">@($"{item.OreTot:N2}")</td>
<td class="text-center">
<div class="bg-secondary bg-gradient rounded-2 text-light text-nowrap px-3 py-1">
@($"{item.Inizio:dd/MM/yy HH:mm}") - @($"{item.Fine:HH:mm}")
</div>
</td>
<td class="text-start">@($"{item.Gruppo}") - @($"{item.RagSociale}")</td>
<td class="text-start">@($"{item.NomeProj}") - @($"{item.NomeFase}")</td>
<td class="text-start text-truncate" style="max-width: 20rem;" title="@item.Descrizione">@item.Descrizione</td>
</tr>
}
</tbody>
<tfoot>
<tr>
<td colspan="7">
<EgwCoreLib.Razor.DataPager PageSize="@numRecord" currPage="@currPage" totalCount="@totalCount" showLoading="@isLoading" numRecordChanged="SetNumRec" numPageChanged="SetPage"></EgwCoreLib.Razor.DataPager>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
}
</div>
<div class="card-footer bg-primary bg-gradient bg-opacity-75 px-0 py-0">
<div class="d-flex justify-content-between py-1">
<div class="px-1 d-flex">
<div class="px-1 align-content-center">
@if (IdxFaseSelTo > 0 && HasRowSelected)
{
<button class="btn btn-success shadow" @onclick="SpostaSel">Sposta Ore <i class="fa-solid fa-angles-right"></i></button>
}
else
{
<button class="btn btn-secondary disabled">Sposta Ore <i class="fa-solid fa-angles-right"></i></button>
}
</div>
</div>
<div class="px-1 d-flex justify-content-end">
<div class="px-1 d-flex align-content-center">
</div>
<div class="px-1 d-flex">
<div class="input-group input-group-sm">
<span class="input-group-text">
Cliente
</span>
<select @bind="@IdxCliSelTo" class="form-select form-select-sm">
<option value="0">--- Tutti ---</option>
@foreach (var item in ListClientiFiltTo)
{
<option value="@item.IdxCliente">@($"{item.RagSociale}")</option>
}
</select>
<span class="input-group-text px-0">
<span class="form-check form-switch align-content-center ms-2" title="Mostra inattivi">
<input class="form-check-input" type="checkbox" @bind=@ShowCliInattTo>
</span>
</span>
</div>
</div>
<div class="px-1 d-flex">
<div class="input-group input-group-sm">
<span class="input-group-text">Progetto</span>
@if (IdxCliSelTo == 0)
{
<select @bind="@IdxProjSelTo" disabled class="form-select form-select-sm text-trim opacity-75" style="max-width:20rem;">
<option value="0">--- Tutti ---</option>
</select>
}
else
{
<select @bind="@IdxProjSelTo" class="form-select form-select-sm text-trim" style="max-width:20rem;">
<option value="0">--- Tutti ---</option>
@foreach (var item in ListProgettiFiltTo)
{
<option value="@item.IdxProgetto" title="@($"{item.DescrProj}")">@($"{item.NomeProj}")</option>
}
</select>
<span class="input-group-text px-0">
<span class="form-check form-switch align-content-center ms-2" title="Mostra inattivi">
<input class="form-check-input" type="checkbox" @bind=@ShowProjInattTo>
</span>
</span>
}
</div>
</div>
<div class="px-1 d-flex">
<div class="input-group input-group-sm">
<span class="input-group-text">Fase</span>
@if (IdxProjSelTo == 0)
{
<select @bind="@IdxFaseSelTo" disabled class="form-select form-select-sm text-trim opacity-75" style="max-width:20rem;">
<option value="0">--- Tutti ---</option>
</select>
}
else
{
<select @bind="@IdxFaseSelTo" class="form-select form-select-sm text-trim" style="max-width:20rem;">
<option value="0">--- Tutti ---</option>
@foreach (var item in ListFasiFiltTo)
{
if (item.BudgetTime > 0)
{
<option value="@item.IdxFase" title="@($"{item.DescrizioneFase}")">@($"{item.NomeFase}")</option>
}
else
{
<option disabled class="bg-secondary bg-opacity-25 fw-bold" value="@item.IdxFase" title="@($"{item.DescrizioneFase}")">@($"{item.NomeFase}")</option>
}
}
</select>
<span class="input-group-text px-0">
<span class="form-check form-switch align-content-center ms-2" title="Mostra inattivi">
<input class="form-check-input" type="checkbox" @bind=@ShowFaseInattTo>
</span>
</span>
}
</div>
</div>
</div>
</div>
</div>
</div>
@@ -0,0 +1,546 @@
using EgwCoreLib.Razor;
using EgwCoreLib.Utils;
using GPW.CORE.Data.DbModels;
using GPW.CORE.Data.DTO;
using GPW.CORE.Data.Services;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using NLog;
namespace GPW.CORE.ADM.Components.Compo
{
public partial class SpostaOreMan : IDisposable
{
#region Public Methods
public void Dispose()
{
AppMServ.EA_SearchUpdated -= AppMServ_EA_SearchUpdated;
}
#endregion Public Methods
#region Protected Properties
[Inject]
protected MessageService AppMServ { get; set; } = null!;
[Inject]
protected AppAuthService AuthServ { get; set; } = null!;
[Inject]
protected GpwDataService GDataServ { get; set; } = null!;
protected bool HasRowSelected
{
get => ListRecords != null && ListRecords.Where(x => x.Selected).Count() > 0;
}
protected int IdxCliSelFrom
{
get => idxCliFrom;
set
{
if (idxCliFrom != value)
{
idxCliFrom = value;
idxProjFrom = 0;
idxFaseFrom = 0;
}
}
}
protected int IdxCliSelTo
{
get => idxCliTo;
set
{
if (idxCliTo != value)
{
idxCliTo = value;
idxProjTo = 0;
idxFaseTo = 0;
}
}
}
protected int IdxDipSel
{
get => idxDipendente;
set => idxDipendente = value;
}
protected int IdxFaseSelFrom
{
get => idxFaseFrom;
set => idxFaseFrom = value;
}
protected int IdxFaseSelTo
{
get => idxFaseTo;
set => idxFaseTo = value;
}
protected int IdxProjSelFrom
{
get => idxProjFrom;
set
{
if (idxProjFrom != value)
{
idxProjFrom = value;
idxFaseFrom = 0;
}
}
}
protected int IdxProjSelTo
{
get => idxProjTo;
set
{
if (idxProjTo != value)
{
idxProjTo = value;
idxFaseTo = 0;
}
}
}
[Inject]
protected IJSRuntime JSRuntime { get; set; } = null!;
protected List<AnagClientiModel> ListClientiFiltFrom
{
get
{
List<AnagClientiModel> answ = new List<AnagClientiModel>();
if (ShowCliInattFrom)
{
answ = ListClienti;
}
else
{
answ = ListClienti.Where(x => x.Attivo).ToList();
}
return answ;
}
}
protected List<AnagClientiModel> ListClientiFiltTo
{
get
{
List<AnagClientiModel> answ = new List<AnagClientiModel>();
if (ShowCliInattTo)
{
answ = ListClienti;
}
else
{
answ = ListClienti.Where(x => x.Attivo).ToList();
}
return answ;
}
}
protected List<DipendentiModel> ListDipendentiFilt
{
get
{
List<DipendentiModel> answ = new List<DipendentiModel>();
if (ShowDipInatt)
{
answ = ListDipendenti;
}
else
{
answ = ListDipendenti.Where(x => (x.Attivo ?? false)).ToList();
}
return answ;
}
}
protected List<AnagFasiModel> ListFasiFiltFrom
{
get
{
List<AnagFasiModel> answ = new List<AnagFasiModel>();
if (idxProjFrom > 0)
{
answ = ListFasi
.Where(x => x.IdxProgetto == IdxProjSelFrom && (x.Attivo || ShowFaseInattFrom))
.OrderBy(x => x.CodFase)
.ToList();
}
return answ;
}
}
protected List<AnagFasiModel> ListFasiFiltTo
{
get
{
List<AnagFasiModel> answ = new List<AnagFasiModel>();
if (idxProjTo > 0)
{
answ = ListFasi
.Where(x => x.IdxProgetto == IdxProjSelTo && (x.Attivo || ShowFaseInattTo))
.OrderBy(x => x.CodFase)
.ToList();
}
return answ;
}
}
protected List<AnagProgettiModel> ListProgettiFiltFrom
{
get
{
List<AnagProgettiModel> answ = new List<AnagProgettiModel>();
if (idxCliFrom > 0)
{
answ = ListProgetti.Where(x => x.IdxCliente == IdxCliSelFrom && ((x.Attivo ?? false) || ShowProjInattFrom)).ToList();
}
return answ;
}
}
protected List<AnagProgettiModel> ListProgettiFiltTo
{
get
{
List<AnagProgettiModel> answ = new List<AnagProgettiModel>();
if (idxCliTo > 0)
{
answ = ListProgetti.Where(x => x.IdxCliente == IdxCliSelTo && ((x.Attivo ?? false) || ShowProjInattTo)).ToList();
}
return answ;
}
}
#endregion Protected Properties
#region Protected Methods
protected string CssCheckSel(RegAttDayExpDTO currRec)
{
bool isSel = SelRecord != null && SelRecord.IdxDipendente == currRec.IdxDipendente;
return isSel ? "table-info" : "";
}
protected async Task ForceReload()
{
currPage = 1;
SelRecord = null;
await ReloadData();
}
protected async Task ForceReloadList()
{
await ReloadBaseData();
}
protected override async Task OnInitializedAsync()
{
AppMServ.EA_SearchUpdated += AppMServ_EA_SearchUpdated;
await ReloadBaseData();
}
protected async void Recalc()
{
await Task.Delay(200);
}
protected async Task SetNumRec(int newNum)
{
numRecord = newNum;
currPage = 1;
await AppMServ.NumRowGridSet(gridKey, newNum);
await InvokeAsync(ReloadData);
}
protected async Task SetPage(int newNum)
{
currPage = newNum;
allSel = false;
await InvokeAsync(ReloadData);
}
protected async Task SortRequested(Sorter.SortCallBack e)
{
sortField = e.ParamName;
sortAsc = e.IsAscending;
await ReloadData();
}
/// <summary>
/// Effettua spostamento degli item selezionati verso la fase di destinazione
/// </summary>
protected async Task SpostaSel()
{
var cliente = ListClienti.FirstOrDefault(x => x.IdxCliente == IdxCliSelTo);
var progetto = ListProgetti.FirstOrDefault(x => x.IdxProgetto == IdxProjSelTo);
var fase = ListFasi.FirstOrDefault(x => x.IdxFase == IdxFaseSelTo);
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Sicuro di voler spostare i record selezionati?{Environment.NewLine}{Environment.NewLine}Cliente: {cliente.RagSociale}{Environment.NewLine}Progetto: {progetto.NomeProj} | {progetto.DescrProj}{Environment.NewLine}Fase: {fase.DescrizioneFase}"))
return;
// solo se ho una fase dest selezionata
if (IdxFaseSelTo > 0)
{
Dictionary<int, int> list2move = new Dictionary<int, int>();
foreach (var item in ListRecords)
{
if (item.Selected)
{
// inserisco in dizionario la riga da spostare
list2move.Add(item.IdxRA, IdxFaseSelTo);
}
}
// sposto righe!
await GDataServ.RegAttUpdateFase(list2move);
await ReloadData();
}
}
/// <summary>
/// Effettua toggle selezione globale delle righe mostrateGpwDataService gDataServprivate async Task ReloadData
/// </summary>
protected void ToggleSelection()
{
allSel = !allSel;
foreach (var item in ListRecords)
{
item.Selected = allSel;
}
}
protected string Traduci(string lemma)
{
return AuthServ.Traduci(lemma, AppMServ.UserLang);
}
#endregion Protected Methods
#region Private Fields
private static Logger Log = LogManager.GetCurrentClassLogger();
private bool allSel = false;
private int currPage = 1;
private string gridKey = "TimbMan";
private int idxCliFrom = 0;
private int idxCliTo = 0;
private int idxDipendente = 0;
private int idxFaseFrom = 0;
private int idxFaseTo = 0;
private int idxProjFrom = 0;
private int idxProjTo = 0;
private bool isAncest = false;
private bool isLoading = false;
private int numRecord = 10;
private bool ShowCliInattFrom = false;
private bool ShowCliInattTo = false;
private bool ShowDipInatt = false;
private bool ShowFaseInattFrom = false;
private bool ShowFaseInattTo = false;
private bool ShowProjInattFrom = false;
private bool ShowProjInattTo = false;
private bool sortAsc = true;
private string sortField = "";
private int totalCount = 0;
#endregion Private Fields
#region Private Properties
private DtUtils.Periodo CurrPeriodo { get; set; } = new DtUtils.Periodo(DtUtils.PeriodSet.ThisMonth);
private List<AnagClientiModel> ListClienti { get; set; } = new List<AnagClientiModel>();
private List<DipendentiModel> ListDipendenti { get; set; } = new List<DipendentiModel>();
private List<AnagFasiModel> ListFasi { get; set; } = new List<AnagFasiModel>();
private List<AnagProgettiModel> ListProgetti { get; set; } = new List<AnagProgettiModel>();
private List<RegAttDayExpDTO>? ListRecords { get; set; } = null;
private string mainDivCss
{
get => SelRecord == null ? "col-12" : "col-12 col-lg-9";
}
private List<RegAttDayExpDTO>? SearchRecords { get; set; } = null;
private RegAttDayExpDTO? SelRecord { get; set; } = null;
#endregion Private Properties
#region Private Methods
private async void AppMServ_EA_SearchUpdated()
{
await ReloadData();
}
/// <summary>
/// Caricamento dati "statici" dei selettori
/// </summary>
/// <returns></returns>
private async Task ReloadBaseData()
{
ListDipendenti = await GDataServ.DipendentiGetAll();
ListClienti = await GDataServ.AnagClientiAllAsync();
ListProgetti = await GDataServ.AnagProjAll();
ListFasi = await GDataServ.AnagFasiAll();
}
private async Task ReloadData()
{
isLoading = true;
await InvokeAsync(StateHasChanged);
// tolgo selezione toggle
allSel = false;
// carico i dati della tabella
List<RegAttivitaDayExplModel> rawData = await GDataServ.RegAttDayExplList(idxDipendente, CurrPeriodo.Inizio, CurrPeriodo.Fine, idxCliFrom, idxProjFrom, idxFaseFrom, isAncest);
// se ho ricerca filtro (descrizione)
if (!string.IsNullOrWhiteSpace(AppMServ.SearchVal))
{
rawData = rawData
.Where(x => x.Descrizione.Contains(AppMServ.SearchVal, StringComparison.InvariantCultureIgnoreCase))
.ToList();
}
// converto da model a DTO...
SearchRecords = rawData
.Select(x => new RegAttDayExpDTO(x))
.ToList();
totalCount = SearchRecords.Count;
// paginazione e sorting
SortTable();
isLoading = false;
await InvokeAsync(StateHasChanged);
}
private async Task SavePeriodo(DtUtils.Periodo newPeiodo)
{
CurrPeriodo = newPeiodo;
await ReloadData();
}
private void SortTable()
{
if (SearchRecords != null)
{
if (!string.IsNullOrEmpty(sortField))
{
switch (sortField)
{
case "CognomeNome":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.CognomeNome).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.CognomeNome).ToList();
}
break;
case "OreTot":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.OreTot).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.OreTot).ToList();
}
break;
case "Periodo":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.Inizio).ThenBy(x => x.Fine).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.Inizio).ThenBy(x => x.Fine).ToList();
}
break;
case "Gruppo":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.Gruppo).ThenBy(x => x.RagSociale).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.Gruppo).ThenBy(x => x.RagSociale).ToList();
}
break;
case "Progetto":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.NomeProj).ThenBy(x => x.NomeFase).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.NomeProj).ThenBy(x => x.NomeFase).ToList();
}
break;
case "Descrizione":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.Descrizione).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.Descrizione).ToList();
}
break;
default:
break;
}
}
ListRecords = SearchRecords
.Skip(numRecord * (currPage - 1))
.Take(numRecord)
.ToList();
}
}
#endregion Private Methods
}
}
+1 -1
View File
@@ -33,7 +33,7 @@
}
else if (totalCount == 0)
{
<div class="alert alert-info">Nessun record trovato</div>
<div class="alert alert-warning text-bg-danger align-content-center text-center fs-4">Nessun record trovato</div>
}
else
{
@@ -38,6 +38,7 @@ namespace GPW.CORE.ADM.Components.Compo
protected string CheckSel(TagFasiDTO curItem)
{
string answ = "";
if (SelItem != null)
{
answ = curItem.CodTagFase == SelItem.CodTagFase ? "table-info" : "";
@@ -154,7 +155,7 @@ namespace GPW.CORE.ADM.Components.Compo
ListRecords = null;
try
{
SearchRecords = await GDataServ.AnagTagFasiAll();
SearchRecords = await GDataServ.AnagTagFasiAllAsync();
// verifico filtro per ricerca
if (!string.IsNullOrEmpty(CurrSearch))
{
@@ -166,7 +167,7 @@ namespace GPW.CORE.ADM.Components.Compo
Log.Error($"Eccezione in recupero dati{Environment.NewLine}{ex}");
}
totalCount = SearchRecords.Count;
SortTable();
SortTable();
isLoading = false;
}
@@ -21,7 +21,7 @@
}
</div>
</li>
@if (model.DtEnd.Subtract(model.DtStart).TotalDays < 1)
@if (model.DtEnd.Subtract(model.DtStart).TotalDays < 1 && model.CodTipo != "FER")
{
<li class="list-group-item">
<div class="d-flex justify-content-between">
@@ -51,7 +51,7 @@
</div>
</li>
}
@if(!model.Conf)
@if (!model.Conf)
{
<li class="list-group-item text-center bg-danger text-warning">
<b>NON CONFERMATO</b>
@@ -0,0 +1,100 @@
<div class="card shadow">
<div class="card-header">
<div class="d-flex justify-content-between">
<div class="px-0 d-flex">
<div class="px-0">
<h3>@Traduci("timbMensili")</h3>
</div>
<div class="px-2">
<button class="btn btn-success" @onclick=Recalc tooltip="Add New"><i class="fa-solid fa-plus"></i> @Traduci("Ricalcola")</button>
</div>
</div>
<div class="px-0">
<div class="d-flex align-middle">
<div class="px-1 py-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" @bind=@ShowInatt @bind:after=ForceReload>
<label class="form-check-label">Mostra Inattivi</label>
</div>
</div>
<div class="px-1 py-1">
<select @bind="@IdxDipSel" class="form-select form-select-sm" @bind:after=ForceReload>
<option value="0">--- Selezionare ---</option>
@foreach (var item in ListDipendenti)
{
<option value="@item.IdxDipendente">@($"{item.Cognome} {item.Nome}")</option>
}
</select>
</div>
<div class="px-0">
<PeriodoSel CurrPeriodo="@CurrPeriodo" E_PeriodoSel="@SavePeriodo"></PeriodoSel>
</div>
</div>
</div>
</div>
</div>
<div class="card-body p-1 small">
@if (ListRecords == null || isLoading)
{
<EgwCoreLib.Razor.LoadingData></EgwCoreLib.Razor.LoadingData>
}
else if (totalCount == 0)
{
<div class="alert alert-info">Nessun record trovato</div>
}
else
{
<div class="row">
<div class="@mainDivCss">
<table class="table table-striped table-sm text-start">
<thead>
<tr>
<th class="text-end">Anno <Sorter ParamName="Anno" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th class="text-end">Mese <Sorter ParamName="Mese" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th class="text-end">Dipendente <Sorter ParamName="IdxDipendente" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th class="text-end">Ordinarie <Sorter ParamName="totOreOrd" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th class="text-end">Lavorate <Sorter ParamName="totLav" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th class="text-end">Non Lavorate <Sorter ParamName="totOreNonLav" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th class="text-end">Permessi <Sorter ParamName="totOrePerm" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th class="text-end">Ferie <Sorter ParamName="totOreFer" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th class="text-end">Festive <Sorter ParamName="totOreFest" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
<th class="text-end">Straordinarie <Sorter ParamName="totOreStra" IsAsc="@sortAsc" CurrParam="@sortField" sortReq="SortRequested"></Sorter></th>
</tr>
</thead>
<tbody>
@foreach (var item in ListRecords)
{
<tr class="@CssCheckSel(item)">
<td class="text-end">@item.Anno</td>
<td class="text-end">@item.Mese</td>
<td class="text-end">@item.IdxDipendente</td>
<td class="text-end">@item.totOreOrd</td>
<td class="text-end">@item.totLav.ToString("N2")</td>
<td class="text-end">@item.totOreNonLav.ToString("N2")</td>
<td class="text-end">@item.totOrePerm.ToString("N2")</td>
<td class="text-end">@item.totOreFer</td>
<td class="text-end">@item.totOreFest</td>
<td class="text-end">@item.totOreStra.ToString("N2")</td>
</tr>
}
</tbody>
</table>
</div>
</div>
}
</div>
<div class="card-footer">
<EgwCoreLib.Razor.DataPager PageSize="@numRecord" currPage="@currPage" totalCount="@totalCount" showLoading="@isLoading" numRecordChanged="SetNumRec" numPageChanged="SetPage"></EgwCoreLib.Razor.DataPager>
</div>
</div>
@@ -0,0 +1,280 @@
using EgwCoreLib.Razor;
using EgwCoreLib.Utils;
using GPW.CORE.Data.DbModels;
using GPW.CORE.Data.Services;
using Microsoft.AspNetCore.Components;
using NLog;
namespace GPW.CORE.ADM.Components.Compo
{
public partial class TimbMensMan
{
[Inject]
protected AppAuthService AuthServ { get; set; } = null!;
[Inject]
protected MessageService AppMServ { get; set; } = null!;
[Inject]
protected GpwDataService GDataServ { get; set; } = null!;
protected int IdxDipSel { get; set; } = 0;
protected string Traduci(string lemma)
{
return AuthServ.Traduci(lemma, AppMServ.UserLang);
}
protected async void Recalc()
{
await Task.Delay(200);
}
protected async Task ForceReload()
{
currPage = 1;
SelRecord = null;
await ReloadData();
}
protected async Task SortRequested(Sorter.SortCallBack e)
{
sortField = e.ParamName;
sortAsc = e.IsAscending;
await ReloadData();
}
protected string CssCheckSel(TimbMeseExplModel currRec)
{
bool isSel = SelRecord != null && SelRecord.IdxDipendente == currRec.IdxDipendente && SelRecord.Anno == currRec.Anno && SelRecord.Mese == currRec.Mese;
return isSel ? "table-info" : "";
}
protected async Task SetNumRec(int newNum)
{
numRecord = newNum;
currPage = 1;
await AppMServ.NumRowGridSet(gridKey, newNum);
await InvokeAsync(ReloadData);
}
protected async Task SetPage(int newNum)
{
currPage = newNum;
await InvokeAsync(ReloadData);
}
private bool sortAsc = true;
private string sortField = "";
private bool ShowInatt { get; set; } = false;
private int currPage { get; set; } = 1;
private TimbMeseExplModel? SelRecord { get; set; } = null;
private bool isLoading { get; set; } = false;
private List<TimbMeseExplModel>? ListRecords { get; set; } = null;
private int numRecord { get; set; } = 10;
private int totalCount { get; set; } = 0;
private DtUtils.Periodo CurrPeriodo { get; set; } = new DtUtils.Periodo(DtUtils.PeriodSet.ThisMonth);
private List<DipendentiModel> ListDipendenti { get; set; } = new List<DipendentiModel>();
private List<TimbMeseExplModel>? SearchRecords { get; set; } = null;
private string gridKey = "TimbMan";
private static Logger Log = LogManager.GetCurrentClassLogger();
private string mainDivCss
{
get => SelRecord == null ? "col-12" : "col-12 col-lg-9";
}
private string detDivCss
{
get => SelRecord == null ? "col-0" : "col-12 col-lg-3";
}
private async Task ReloadData()
{
isLoading = true;
ListRecords = null;
var rawList = await GDataServ.DipendentiGetAll();
#if true
if (ShowInatt)
{
ListDipendenti = rawList;
}
else
{
ListDipendenti = rawList.Where(x => (x.Attivo ?? false)).ToList();
}
try
{
SearchRecords = await GDataServ.TimbMeseExplList(IdxDipSel, CurrPeriodo.Inizio, CurrPeriodo.Fine);
// verifico filtro per IdxDip
if (IdxDipSel > 0)
{
SearchRecords = SearchRecords.Where(x => x.IdxDipendente == IdxDipSel).ToList();
}
}
catch (Exception ex)
{
Log.Error($"Eccezione in recupero dati{Environment.NewLine}{ex}");
}
totalCount = SearchRecords.Count;
SortTable();
#endif
isLoading = false;
}
private void SortTable()
{
if (SearchRecords != null)
{
// se ho ordinamento riordino...
if (!string.IsNullOrEmpty(sortField))
{
switch (sortField)
{
case "Anno":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.Anno).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.Anno).ToList();
}
break;
case "Mese":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.Mese).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.Mese).ToList();
}
break;
case "IdxDipendente":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.IdxDipendente).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.IdxDipendente).ToList();
}
break;
case "totOreOrd":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.totOreOrd).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.totOreOrd).ToList();
}
break;
case "totLav":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.totLav).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.totLav).ToList();
}
break;
case "totOreNonLav":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.totOreNonLav).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.totOreNonLav).ToList();
}
break;
case "totOrePerm":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.totOrePerm).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.totOrePerm).ToList();
}
break;
case "totOreFer":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.totOreFer).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.totOreFer).ToList();
}
break;
case "totOreFest":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.totOreFest).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.totOreFest).ToList();
}
break;
case "totOreStra":
if (sortAsc)
{
SearchRecords = SearchRecords.OrderBy(x => x.totOreStra).ToList();
}
else
{
SearchRecords = SearchRecords.OrderByDescending(x => x.totOreStra).ToList();
}
break;
default:
break;
}
}
// filtro x display
ListRecords = SearchRecords
.Skip(numRecord * (currPage - 1))
.Take(numRecord)
.ToList();
}
else
{
ListRecords = new List<TimbMeseExplModel>();
}
}
private async Task SavePeriodo(DtUtils.Periodo newPeiodo)
{
CurrPeriodo = newPeiodo;
await ReloadData();
}
}
}
@@ -0,0 +1,5 @@
<div class="card-body text-center">
<div class="img-fluid" id="qrCodeImg_@idxDipendente"></div>
</div>
@@ -0,0 +1,107 @@
using GPW.CORE.Data.DbModels;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
namespace GPW.CORE.ADM.Components.Compo
{
public partial class UserQrCode
{
#region Public Properties
[Parameter]
public bool LinkInt { get; set; } = true;
[Parameter]
public bool LinkCore { get; set; } = true;
[Parameter]
public DipendentiModel? RecordDip { get; set; } = null;
#endregion Public Properties
#region Protected Fields
protected string rawCode = "";
#endregion Protected Fields
#region Protected Methods
protected int idxDipendente
{
get => RecordDip != null ? RecordDip.IdxDipendente : 0;
}
protected string getUrlCode(string baseUrl, string authKey)
{
return $"{baseUrl}jumper?idxDipendente={RecordDip.IdxDipendente}&authKey={authKey}";
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (RecordDip != null)
{
string baseUrl = LinkInt ? UrlLinkInt : UrlLinkExt;
// aggiungo parte core/legacy
baseUrl += LinkCore ? UrlLinkCore : UrlLinkLega;
//calcolo authKey valida x url --> escaped!
string authKeyFix = System.Web.HttpUtility.UrlEncode(RecordDip.AuthKey);
string newCode = getUrlCode(baseUrl, authKeyFix);
if (rawCode != newCode)
{
rawCode = newCode;
await JSRuntime.InvokeVoidAsync("clearContent", $"qrCodeImg_{RecordDip.IdxDipendente}");
await JSRuntime.InvokeVoidAsync("displayQr", $"qrCodeImg_{RecordDip.IdxDipendente}", rawCode);
}
}
}
protected override void OnInitialized()
{
initConf();
}
#endregion Protected Methods
#region Private Fields
private string UrlLinkExt = "";
private string UrlLinkInt = "";
private string UrlLinkCore = "";
private string UrlLinkLega = "";
#endregion Private Fields
#region Private Properties
private int _idxDip { get; set; } = 0;
[Inject]
private IConfiguration Configuration { get; set; } = null!;
[Inject]
private IJSRuntime JSRuntime { get; set; } = null!;
#endregion Private Properties
#region Private Methods
/// <summary>
/// init valori da config
/// </summary>
/// <returns></returns>
private void initConf()
{
UrlLinkInt = Configuration.GetValue<string>("OptPar:UrlLinkInt") ?? "";
UrlLinkExt = Configuration.GetValue<string>("OptPar:UrlLinkExt") ?? "";
UrlLinkCore = Configuration.GetValue<string>("OptPar:UrlLinkCore") ?? "";
UrlLinkLega = Configuration.GetValue<string>("OptPar:UrlLinkLega") ?? "";
}
#endregion Private Methods
}
}
@@ -83,9 +83,9 @@ namespace GPW.CORE.ADM.Components.Layout
#region Private Properties
private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;
protected string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;
private string? TextCss => onlyIcon ? "d-none" : "";
protected string? TextCss => onlyIcon ? "d-none" : "";
#endregion Private Properties
@@ -1,7 +1,14 @@
@page "/Dipendenti"
@inject MessageService AppMServ
@inject AppAuthService AuthServ
<WIP></WIP>
<DipendentiMan></DipendentiMan>
@code {
protected override void OnInitialized()
{
AppMServ.ShowSearch = true;
AppMServ.PageName = AuthServ.Traduci("ManDipendenti", AppMServ.UserLang);
AppMServ.PageIcon = AuthServ.Traduci("ManDipendentiExpl");
}
}
@@ -16,13 +16,17 @@ namespace GPW.CORE.ADM.Components.Pages
[Inject]
protected MessageService AppMServ { get; set; } = null!;
[Inject]
protected AppAuthService AuthService { get; set; } = null!;
[Inject]
protected GpwDataService GDataServ { get; set; } = null!;
[Inject]
protected NavigationManager NavManager { get; set; } = null!;
protected LicenseService LicServ { get; set; } = null!;
[Inject]
protected AppAuthService AuthService { get; set; } = null!;
protected NavigationManager NavManager { get; set; } = null!;
#endregion Protected Properties
@@ -35,6 +39,8 @@ namespace GPW.CORE.ADM.Components.Pages
await Task.Delay(10);
await AuthService.FlushRedisCache();
await Task.Delay(10);
LicServ.ResetLicenseData();
await Task.Delay(10);
AppMServ.clonedRA = null;
AppMServ.recordRA = null;
@@ -13,7 +13,7 @@ namespace GPW.CORE.ADM.Components.Pages
protected int anno = DateTime.Today.Year;
protected DateTime dtMax = DateTime.Today.AddYears(1);
protected DateTime dtMax = DateTime.Today.AddMonths(1);
protected DateTime dtMin = DateTime.Today;
@@ -67,7 +67,7 @@ namespace GPW.CORE.ADM.Components.Pages
await Task.Delay(5);
}
isLoading = false;
await ReloadData();
ReloadData();
}
protected async Task AddFerie()
@@ -93,13 +93,13 @@ namespace GPW.CORE.ADM.Components.Pages
await Task.Delay(5);
}
isLoading = false;
await ReloadData();
ReloadData();
}
protected override async Task OnInitializedAsync()
{
// recupero mesi da gestire
var monthConf = await DataService.ConfigGetKey("NumMesiCalAzienda");
var monthConf = await DataService.ConfigGetKeyAsync("NumMesiCalAzienda");
if (monthConf != null)
{
int intVal = 0;
@@ -107,10 +107,10 @@ namespace GPW.CORE.ADM.Components.Pages
numMesi = intVal > 0 ? intVal : numMesi;
}
// fix iniziale date... setup periodo (da rivedere in funzione eventi cambio mese dei controlli?!?)
DateTime oggi = DateTime.Today;
dtMin = new DateTime(oggi.Year - 1, 1, 1);
dtMax = dtMin.AddYears(3);
await ReloadData();
dtRif = DateTime.Today;
dtMin = new DateTime(dtRif.Year, 1, 1);
dtMax = dtMin.AddYears(1);
ReloadData();
}
#endregion Protected Methods
@@ -118,6 +118,7 @@ namespace GPW.CORE.ADM.Components.Pages
#region Private Fields
private string DescrFerie = "CHIUSURA UFFICIO";
private DateTime dtRif = DateTime.Today;
private bool isLoading = false;
private bool ShowAddFer = false;
private bool ShowAddFes = false;
@@ -126,11 +127,8 @@ namespace GPW.CORE.ADM.Components.Pages
#region Private Properties
private List<CalFesteFerieModel> ListFermateAzienda { get; set; } = new List<CalFesteFerieModel>();
private List<RegMalattieModel> ListMalattie { get; set; } = new List<RegMalattieModel>();
private List<RegRichiesteModel> ListRichiesteDip { get; set; } = new List<RegRichiesteModel>();
private DateTime DtInizio { get; set; } = DateTime.Today;
private DateTime DtFine { get; set; } = DateTime.Today;
private DateTime DtInizio { get; set; } = DateTime.Today;
/// <summary>
/// Elenco eventi formato originale (EventDTO)
@@ -153,44 +151,38 @@ namespace GPW.CORE.ADM.Components.Pages
#region Private Methods
private async Task ForceReloadCal()
private void ForceReloadCal()
{
await ReloadData();
ReloadData();
}
private async Task ReloadData()
private void ReloadData()
{
isLoading = true;
// recupero direttamente da oggetto DB
SchedEvList = await DataService.EventListPeriodo(idxDipendente, dtMin, dtMax);
SchedEvList = DataService.EventListPeriodo(idxDipendente, dtMin, dtMax);
isLoading = false;
}
private async Task SetDate(DateTime newDate)
private void SetDate(DateTime newDate)
{
// se la data fosse esterna all'intervallo considerato...)
if (newDate < dtMin || newDate > dtMax)
{
// verifico se "allargare" alla minima o alla massima
if (newDate < dtMin)
{
dtMin = new DateTime(newDate.Year - 1, 1, 1);
}
else
{
dtMax = new DateTime(newDate.Year + 1, 1, 1);
}
await ReloadData();
dtRif = newDate;
dtMin = new DateTime(newDate.Year, 1, 1);
dtMax = new DateTime(newDate.Year + 1, 1, 1);
ReloadData();
}
}
private async Task SetMonth(int newNum)
private void SetMonth(int newNum)
{
if (numMesi != newNum)
{
numMesi = newNum;
}
await ReloadData();
ReloadData();
}
private void TglAddFer()
+2 -2
View File
@@ -4,7 +4,7 @@
<PageTitle>Home</PageTitle>
<div class="row">
<div class="row px-0 mx-0">
<div class="col-12 col-lg-10 col-xl-8 offset-lg-1 offset-xl-2">
<div class="mt-2 p-4 bg-secondary bg-gradient bg-opacity-25 border border-light rounded shadow">
<div class="row">
@@ -31,7 +31,7 @@
</div>
</div>
<div class="m1-4 py-4">
<div class="mt-5">
@if (ListMenu == null || ListMenu.Count == 0)
{
<LoadingData></LoadingData>
+18 -29
View File
@@ -12,7 +12,7 @@ namespace GPW.CORE.ADM.Components.Pages
protected int anno = DateTime.Today.Year;
protected DateTime dtMax = DateTime.Today.AddYears(1);
protected DateTime dtMax = DateTime.Today.AddMonths(1);
protected DateTime dtMin = DateTime.Today;
@@ -40,7 +40,7 @@ namespace GPW.CORE.ADM.Components.Pages
protected override async Task OnInitializedAsync()
{
// recupero mesi da gestire
var monthConf = await DataService.ConfigGetKey("NumMesiCalAzienda");
var monthConf = await DataService.ConfigGetKeyAsync("NumMesiCalAzienda");
if (monthConf != null)
{
int intVal = 0;
@@ -48,28 +48,23 @@ namespace GPW.CORE.ADM.Components.Pages
numMesi = intVal > 0 ? intVal : numMesi;
}
// fix iniziale date... setup periodo (da rivedere in funzione eventi cambio mese dei controlli?!?)
DateTime oggi = DateTime.Today;
dtMin = new DateTime(oggi.Year - 1, 1, 1);
dtMax = dtMin.AddYears(3);
await ReloadData();
dtRif = DateTime.Today;
dtMin = new DateTime(dtRif.Year, 1, 1);
dtMax = dtMin.AddYears(1);
ReloadData();
}
#endregion Protected Methods
#region Private Fields
private DateTime dtRif = DateTime.Today;
private bool isLoading = false;
#endregion Private Fields
#region Private Properties
private List<CalFesteFerieModel> ListFermateAzienda { get; set; } = new List<CalFesteFerieModel>();
private List<RegMalattieModel> ListMalattie { get; set; } = new List<RegMalattieModel>();
private List<RegRichiesteModel> ListRichiesteDip { get; set; } = new List<RegRichiesteModel>();
/// <summary>
/// Elenco eventi formato originale (EventDTO)
/// </summary>
@@ -79,44 +74,38 @@ namespace GPW.CORE.ADM.Components.Pages
#region Private Methods
private async Task ForceReloadCal()
private void ForceReloadCal()
{
await ReloadData();
ReloadData();
}
private async Task ReloadData()
private void ReloadData()
{
isLoading = true;
// recupero direttamente da oggetto DB
SchedEvList = await DataService.EventListPeriodo(idxDipendente, dtMin, dtMax);
SchedEvList = DataService.EventListPeriodo(idxDipendente, dtMin, dtMax);
isLoading = false;
}
private async Task SetDate(DateTime newDate)
private void SetDate(DateTime newDate)
{
// se la data fosse esterna all'intervallo considerato...)
if (newDate < dtMin || newDate > dtMax)
{
// verifico se "allargare" alla minima o alla massima
if (newDate < dtMin)
{
dtMin = new DateTime(newDate.Year - 1, 1, 1);
}
else
{
dtMax = new DateTime(newDate.Year + 1, 1, 1);
}
await ReloadData();
dtRif = newDate;
dtMin = new DateTime(newDate.Year, 1, 1);
dtMax = new DateTime(newDate.Year + 1, 1, 1);
ReloadData();
}
}
private async Task SetMonth(int newNum)
private void SetMonth(int newNum)
{
if (numMesi != newNum)
{
numMesi = newNum;
}
await ReloadData();
ReloadData();
}
#endregion Private Methods
@@ -1,7 +1,15 @@
@page "/ReportProgetti"
@inject MessageService AppMServ
@inject AppAuthService AuthServ
<WIP></WIP>
<ReportProgettiMan></ReportProgettiMan>
@code {
protected override void OnInitialized()
{
// imposto pagina e info testata
AppMServ.ShowSearch = true;
AppMServ.PageName = AuthServ.Traduci("ReportPrj", AppMServ.UserLang);
AppMServ.PageIcon = AuthServ.Traduci("ReportPrjExpl");
}
}
@@ -22,7 +22,14 @@
}
</div>
<div class="col-8 ps-0">
<CalendarioAziendale EvDtoList="@SchedEvList" MonthDispl="@numMesi" firstDate="@dtMin" minDate="@dtMin" maxDate="@dtMax" MonthReq="SetMonth" DtReq="SetDate" ShowNeedConf="@OnlyNeedConf"></CalendarioAziendale>
@if (isLoading)
{
<LoadingData></LoadingData>
}
else
{
<CalendarioAziendale EvDtoList="@SchedEvList" MonthDispl="@numMesi" firstDate="@dtMin" minDate="@dtMin" maxDate="@dtMax" MonthReq="SetMonth" DtReq="SetDate" ShowNeedConf="@OnlyNeedConf"></CalendarioAziendale>
}
</div>
</div>
</div>
@@ -12,7 +12,7 @@ namespace GPW.CORE.ADM.Components.Pages
protected int anno = DateTime.Today.Year;
protected DateTime dtMax = DateTime.Today.AddYears(1);
protected DateTime dtMax = DateTime.Today.AddMonths(1);
protected DateTime dtMin = DateTime.Today;
@@ -41,20 +41,21 @@ namespace GPW.CORE.ADM.Components.Pages
{
initToggler();
// recupero mesi da gestire
var monthConf = await DataService.ConfigGetKey("NumMesiCalAzienda");
var monthConf = await DataService.ConfigGetKeyAsync("NumMesiCalAzienda");
if (monthConf != null)
{
int intVal = 0;
int.TryParse(monthConf.valore, out intVal);
numMesi = intVal > 0 ? intVal : numMesi;
}
// fix iniziale date... setup periodo (da rivedere in funzione eventi cambio mese dei controlli?!?)
DateTime oggi = DateTime.Today;
dtMin = new DateTime(oggi.Year - 1, 1, 1);
dtMax = dtMin.AddYears(3);
await ReloadData();
dtRif = DateTime.Today;
dtMin = new DateTime(dtRif.Year, 1, 1);
dtMax = dtMin.AddYears(1);
ReloadData();
}
private DateTime dtRif = DateTime.Today;
#endregion Protected Methods
#region Private Fields
@@ -65,12 +66,6 @@ namespace GPW.CORE.ADM.Components.Pages
#region Private Properties
private List<CalFesteFerieModel> ListFermateAzienda { get; set; } = new List<CalFesteFerieModel>();
private List<RegMalattieModel> ListMalattie { get; set; } = new List<RegMalattieModel>();
private List<RegRichiesteModel> ListRichiesteDip { get; set; } = new List<RegRichiesteModel>();
private bool OnlyNeedConf { get; set; } = false;
/// <summary>
@@ -91,9 +86,9 @@ namespace GPW.CORE.ADM.Components.Pages
await Task.Delay(1);
}
private async Task ForceReloadCal()
private void ForceReloadCal()
{
await ReloadData();
ReloadData();
}
private void initToggler()
@@ -106,39 +101,34 @@ namespace GPW.CORE.ADM.Components.Pages
};
}
private async Task ReloadData()
private void ReloadData()
{
isLoading = true;
// recupero direttamente da oggetto DB
SchedEvList = await DataService.EventListPeriodo(idxDipendente, dtMin, dtMax);
SchedEvList = DataService.EventListPeriodo(idxDipendente, dtMin, dtMax);
isLoading = false;
}
private async Task SetDate(DateTime newDate)
private void SetDate(DateTime newDate)
{
// se la data fosse esterna all'intervallo considerato...)
if (newDate < dtMin || newDate > dtMax)
{
// verifico se "allargare" alla minima o alla massima
if (newDate < dtMin)
{
dtMin = new DateTime(newDate.Year - 1, 1, 1);
}
else
{
dtMax = new DateTime(newDate.Year + 1, 1, 1);
}
await ReloadData();
dtRif = newDate;
// ricalcolo periodo
dtMin = new DateTime(dtRif.Year, 1, 1);
dtMax = new DateTime(dtRif.Year + 1, 1, 1);
ReloadData();
}
}
private async Task SetMonth(int newNum)
private void SetMonth(int newNum)
{
if (numMesi != newNum)
{
numMesi = newNum;
}
await ReloadData();
ReloadData();
}
#endregion Private Methods
+13 -3
View File
@@ -1,7 +1,17 @@
@page "/SpostaOre"
@page "/SpostaOre"
@inject MessageService AppMServ
@inject AppAuthService AuthServ
<WIP></WIP>
@code {
<SpostaOreMan></SpostaOreMan>
@code {
protected override void OnInitialized()
{
// imposto pagina e info testata
AppMServ.ShowSearch = true;
AppMServ.PageName = AuthServ.Traduci("SpostaOre", AppMServ.UserLang);
AppMServ.PageIcon = AuthServ.Traduci("SpostaOreExpl");
}
}
@@ -1,7 +1,16 @@
@page "/TimbratureMensili"
@inject MessageService AppMServ
@inject AppAuthService AuthServ
<WIP></WIP>
<TimbMensMan></TimbMensMan>
@code {
protected override void OnInitialized()
{
// imposto pagina e info testata
AppMServ.ShowSearch = false;
AppMServ.PageName = AuthServ.Traduci("timbMensili", AppMServ.UserLang);
AppMServ.PageIcon = AuthServ.Traduci("timbMensiliExpl");
}
}
+6 -7
View File
@@ -4,7 +4,7 @@
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<Version>4.1.2502.0418</Version>
<Version>4.1.2605.0611</Version>
</PropertyGroup>
<ItemGroup>
@@ -33,14 +33,13 @@
<ItemGroup>
<PackageReference Include="Azure.Identity" Version="1.11.4" />
<PackageReference Include="Blazored.FluentValidation" Version="2.2.0" />
<PackageReference Include="EgwCoreLib.Razor" Version="1.5.2501.1716" />
<PackageReference Include="EgwCoreLib.Utils" Version="1.5.2501.1716" />
<PackageReference Include="EgwCoreLib.Razor" Version="1.5.2511.312" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Negotiate" Version="8.0.8" />
<PackageReference Include="Microsoft.Web.LibraryManager.Build" Version="2.1.175" />
<PackageReference Include="NLog" Version="5.4.0" />
<PackageReference Include="NLog.Web.AspNetCore" Version="5.4.0" />
<PackageReference Include="Radzen.Blazor" Version="5.9.7" />
<PackageReference Include="System.Text.Json" Version="9.0.0" />
<PackageReference Include="NLog" Version="6.1.1" />
<PackageReference Include="NLog.Web.AspNetCore" Version="6.1.2" />
<PackageReference Include="Radzen.Blazor" Version="7.0.8" />
<PackageReference Include="System.Text.Json" Version="8.0.5" />
</ItemGroup>
<ItemGroup>
@@ -7,7 +7,7 @@ by editing this MSBuild file. In order to learn more about this please visit htt
<PropertyGroup>
<TimeStampOfAssociatedLegacyPublishXmlFile />
<EncryptedPassword>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAw3dMMgC4FUywyOTV2xvCRgAAAAACAAAAAAADZgAAwAAAABAAAADrbAogtj/xpZqylbgs9Hb3AAAAAASAAACgAAAAEAAAAFm1lcdH7oj+NFy4QgZ7q18YAAAAROPsyRR12dhPTKfMEQ5yNCAZJ5K7C4pvFAAAAEFBVTwItjyYP2BlOTsuK1g9myQ8</EncryptedPassword>
<History>True|2025-02-04T17:54:56.3466849Z||;True|2024-10-04T10:17:22.7335334+02:00||;True|2024-09-13T19:29:52.0716814+02:00||;True|2024-09-13T18:38:16.4907845+02:00||;True|2024-09-13T09:22:22.8253732+02:00||;True|2024-09-12T16:07:39.0226825+02:00||;True|2024-09-12T10:58:30.2473031+02:00||;True|2024-09-12T10:03:37.9121520+02:00||;True|2024-09-11T19:18:09.6865317+02:00||;True|2024-09-11T17:21:29.6285775+02:00||;True|2024-09-11T17:06:36.9651346+02:00||;True|2024-09-10T17:58:48.6965236+02:00||;True|2024-09-10T15:56:39.2931971+02:00||;True|2024-09-10T12:27:20.6683309+02:00||;True|2024-09-07T10:37:21.9427027+02:00||;True|2024-09-06T19:01:32.2132061+02:00||;True|2024-09-06T18:20:28.3994458+02:00||;True|2024-09-05T10:43:51.3246848+02:00||;True|2024-09-05T10:26:17.6114175+02:00||;True|2024-09-05T09:25:03.5122942+02:00||;True|2024-09-04T18:21:49.9717603+02:00||;True|2023-04-11T10:12:15.0154900+02:00||;False|2023-04-11T10:11:47.1977827+02:00||;True|2023-04-11T09:18:55.4555319+02:00||;True|2023-04-11T09:16:05.8827677+02:00||;True|2022-06-06T12:56:03.5790550+02:00||;False|2022-06-06T12:54:19.4739620+02:00||;False|2022-06-06T12:53:46.4246554+02:00||;</History>
<History>True|2025-06-10T05:22:28.6193301Z||;False|2025-06-10T07:20:26.1957391+02:00||;True|2025-02-04T18:54:56.3466849+01:00||;True|2024-10-04T10:17:22.7335334+02:00||;True|2024-09-13T19:29:52.0716814+02:00||;True|2024-09-13T18:38:16.4907845+02:00||;True|2024-09-13T09:22:22.8253732+02:00||;True|2024-09-12T16:07:39.0226825+02:00||;True|2024-09-12T10:58:30.2473031+02:00||;True|2024-09-12T10:03:37.9121520+02:00||;True|2024-09-11T19:18:09.6865317+02:00||;True|2024-09-11T17:21:29.6285775+02:00||;True|2024-09-11T17:06:36.9651346+02:00||;True|2024-09-10T17:58:48.6965236+02:00||;True|2024-09-10T15:56:39.2931971+02:00||;True|2024-09-10T12:27:20.6683309+02:00||;True|2024-09-07T10:37:21.9427027+02:00||;True|2024-09-06T19:01:32.2132061+02:00||;True|2024-09-06T18:20:28.3994458+02:00||;True|2024-09-05T10:43:51.3246848+02:00||;True|2024-09-05T10:26:17.6114175+02:00||;True|2024-09-05T09:25:03.5122942+02:00||;True|2024-09-04T18:21:49.9717603+02:00||;True|2023-04-11T10:12:15.0154900+02:00||;False|2023-04-11T10:11:47.1977827+02:00||;True|2023-04-11T09:18:55.4555319+02:00||;True|2023-04-11T09:16:05.8827677+02:00||;True|2022-06-06T12:56:03.5790550+02:00||;False|2022-06-06T12:54:19.4739620+02:00||;False|2022-06-06T12:53:46.4246554+02:00||;</History>
<LastFailureDetails />
</PropertyGroup>
</Project>
+34 -28
View File
@@ -1,4 +1,37 @@
{
"profiles": {
"http": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true,
"applicationUrl": "http://localhost:5145",
"nativeDebugging": true,
"sqlDebugging": true
},
"https": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true,
"applicationUrl": "https://localhost:7000;http://localhost:5145",
"nativeDebugging": true,
"sqlDebugging": true
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"nativeDebugging": true,
"sqlDebugging": true
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": true,
@@ -7,32 +40,5 @@
"applicationUrl": "http://localhost:18461",
"sslPort": 44382
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5145",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7000;http://localhost:5145",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
}
+2 -1
View File
@@ -4,5 +4,6 @@
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
},
"DetailedErrors": true
}
+11 -3
View File
@@ -5,6 +5,7 @@
"Microsoft.AspNetCore": "Warning"
}
},
"DetailedErrors": true,
"NLog": {
"variables": {
"baseFileDir": "${basedir}/logs/",
@@ -51,7 +52,7 @@
"ConnectionStrings": {
"GPW.DB": "Server=W2019-SQL-STEAM;Database=GPW; User ID=UserGPW; Password=Us3rGpw!75x93$77; integrated security=False; MultipleActiveResultSets=True; App=GPW.CORE.WRKLOG; TrustServerCertificate=True;",
"GPW.DB.Auth": "Server=W2019-SQL-STEAM;Database=SteamWare_Anagrafica;User ID=sa;Password=keyhammer16;integrated security=False;MultipleActiveResultSets=True;App=GPW.ADM; TrustServerCertificate=True;",
"Redis": "localhost:26379,serviceName=prod,DefaultDatabase=15,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false,password=BtN9Py1wtLfLRvmzWnOPJ7RytDM+CLiVsJ/16zduNTlV8IOPGNrtzJSXPUnImA5PqmUMhKaUqo9NdHIG"
"Redis": "redis.ufficio:26379,serviceName=prod,DefaultDatabase=15,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false,password=BtN9Py1wtLfLRvmzWnOPJ7RytDM+CLiVsJ/16zduNTlV8IOPGNrtzJSXPUnImA5PqmUMhKaUqo9NdHIG"
},
"ExternalProviders": {
"MailKit": {
@@ -59,7 +60,7 @@
"Address": "smtp.gmail.com",
"Port": "587",
"Account": "services@steamware.net",
"Password": "vpsad24068!",
"Password": "ruejpcwgycvbmmsr",
"SenderEmail": "services@steamware.net",
"SenderName": "Steamware Email BOT"
}
@@ -73,10 +74,17 @@
"ServerConf": {
"AdmList": "1,6",
"BaseUrl": "/GPW/CORE.ADM",
"BasePathExport": "c:\\\\temp\\GPW_ADM_Export"
"BasePathExport": "c:\\\\temp\\GPW_ADM_Export",
"ReportBaseUrl": "http://w2019-sql-steam/ReportServer/Pages/ReportViewer.aspx?/Steamware/"
},
"AdmApp": {
"LinkMal": "https://office.egalware.com/GPW/CORE.ADM/malattia",
"LinkRich": "https://office.egalware.com/GPW/CORE.ADM/richiesteDip"
},
"OptPar": {
"UrlLinkInt": "https://office.egalware.com/GPW/",
"UrlLinkExt": "https://seriate.egalware.com/GPW/",
"UrlLinkCore": "CORE.SMART/",
"UrlLinkLega": "SMART/"
}
}
+105 -3
View File
@@ -220,9 +220,6 @@ a,
.shortcuts {
text-align: center;
}
.shortcuts .shortcut-icon {
font-size: 2rem;
}
.shortcuts .shortcut {
min-width: 10rem;
min-height: 5rem;
@@ -329,4 +326,109 @@ a,
font-size: 0.9em;
line-height: 1.2;
}
}
/* gestione btn report */
.reportPivot {
background: #EFEFEF;
background-image: url(../images/PivotData.png);
background-repeat: no-repeat;
background-position: top;
background-position: left;
min-height: 250px;
height: 100%;
width: 100%;
display: block;
position: relative;
}
.reportOre {
background: #EFEFEF;
background-image: url(../images/ReportGerarchico.png);
background-repeat: no-repeat;
background-position: top;
background-position: left;
min-height: 250px;
height: 100%;
width: 100%;
display: block;
position: relative;
}
.reportFolders {
background: #EFEFEF;
background-image: url(../images/ReportFolders.png);
background-repeat: no-repeat;
background-position: top;
background-position: left;
min-height: 250px;
height: 100%;
width: 100%;
display: block;
position: relative;
}
.reportBadge {
background: #EFEFEF;
background-image: url(../images/Barcode.png);
background-repeat: no-repeat;
background-position: top;
background-position: left;
min-height: 250px;
height: 100%;
width: 100%;
display: block;
position: relative;
}
/* Text position */
.areaTesto {
white-space: normal;
overflow: visible;
position: absolute;
left: 0;
right: 0;
bottom: 50%;
bottom: 0;
margin: 0;
padding: 0 20px;
min-height: 25%;
line-height: 1.5;
color: White;
background: #333;
background: rgba(50, 50, 50, 0.9);
-webkit-background-clip: padding;
background-clip: padding-box;
border-bottom-left-radius: inherit;
border-bottom-right-radius: inherit;
}
/* versioni small */
.areaTestoSmall {
white-space: normal;
overflow: visible;
position: absolute;
left: 0;
right: 0;
bottom: 50%;
bottom: 0;
margin: 0;
padding: 0 3px;
min-height: 50%;
line-height: 1.5;
font-size: 7pt;
color: White;
background: #999;
background: rgba(160, 160, 160, 0.9);
-webkit-background-clip: padding;
background-clip: padding-box;
border-bottom-left-radius: inherit;
border-bottom-right-radius: inherit;
}
.reportFoldersSmall {
background: #EFEFEF;
background-image: url(../images/ReportGerarchico.png);
background-repeat: no-repeat;
background-position: left top;
background-size: 60px 60px;
min-height: 36px;
height: 100%;
width: 100%;
max-width: 100%;
display: block;
position: relative;
}
+113 -4
View File
@@ -202,10 +202,6 @@ a, .btn-link {
text-align: center;
}
.shortcuts .shortcut-icon {
font-size: 2*@blSCut;
}
.shortcuts .shortcut {
min-width: @blSCut * 10;
min-height: @blSCut * 5;
@@ -328,3 +324,116 @@ a, .btn-link {
line-height: 1.2;
}
}
/* gestione btn report */
.reportPivot {
background: #EFEFEF;
background-image: url(../images/PivotData.png);
background-repeat: no-repeat;
background-position: top;
background-position: left;
min-height: 250px;
height: 100%;
width: 100%;
display: block;
position: relative;
}
.reportOre {
background: #EFEFEF;
background-image: url(../images/ReportGerarchico.png);
background-repeat: no-repeat;
background-position: top;
background-position: left;
min-height: 250px;
height: 100%;
width: 100%;
display: block;
position: relative;
}
.reportFolders {
background: #EFEFEF;
background-image: url(../images/ReportFolders.png);
background-repeat: no-repeat;
background-position: top;
background-position: left;
min-height: 250px;
height: 100%;
width: 100%;
display: block;
position: relative;
}
.reportBadge {
background: #EFEFEF;
background-image: url(../images/Barcode.png);
background-repeat: no-repeat;
background-position: top;
background-position: left;
min-height: 250px;
height: 100%;
width: 100%;
display: block;
position: relative;
}
/* Text position */
.areaTesto {
white-space: normal;
overflow: visible;
position: absolute;
left: 0;
right: 0;
bottom: 50%;
bottom: 0;
margin: 0;
padding: 0 20px;
min-height: 25%;
line-height: 1.5;
color: White;
background: #333;
background: rgba(50,50,50,.9);
-webkit-background-clip: padding;
background-clip: padding-box;
border-bottom-left-radius: inherit;
border-bottom-right-radius: inherit;
}
/* versioni small */
.areaTestoSmall {
white-space: normal;
overflow: visible;
position: absolute;
left: 0;
right: 0;
bottom: 50%;
bottom: 0;
margin: 0;
padding: 0 3px;
min-height: 50%;
line-height: 1.5;
font-size: 7pt;
color: White;
background: #999;
background: rgba(160,160,160,.9);
-webkit-background-clip: padding;
background-clip: padding-box;
border-bottom-left-radius: inherit;
border-bottom-right-radius: inherit;
}
.reportFoldersSmall {
background: #EFEFEF;
background-image: url(../images/ReportGerarchico.png);
background-repeat: no-repeat;
background-position: left top;
background-size: 60px 60px;
min-height: 36px;
height: 100%;
width: 100%;
max-width: 100%;
display: block;
position: relative;
}
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

+25
View File
@@ -0,0 +1,25 @@
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: 240,
height: 240,
correctLevel: QRCode.CorrectLevel.L
//correctLevel: QRCode.CorrectLevel.M
//correctLevel: QRCode.CorrectLevel.Q
//correctLevel: QRCode.CorrectLevel.H
});
}
}
catch
{ }
}
+702
View File
@@ -0,0 +1,702 @@
/**
* @fileoverview
* - Using the 'QRCode for Javascript library'
* - Fixed dataset of 'QRCode for Javascript library' for support full-spec.
* - this library has no dependencies.
*
* @author davidshimjs
* @see <a href="http://www.d-project.com/" target="_blank">http://www.d-project.com/</a>
* @see <a href="http://jeromeetienne.github.com/jquery-qrcode/" target="_blank">http://jeromeetienne.github.com/jquery-qrcode/</a>
*/
var QRCode;
(function () {
//---------------------------------------------------------------------
// QRCode for JavaScript
//
// Copyright (c) 2009 Kazuhiko Arase
//
// URL: http://www.d-project.com/
//
// Licensed under the MIT license:
// http://www.opensource.org/licenses/mit-license.php
//
// The word "QR Code" is registered trademark of
// DENSO WAVE INCORPORATED
// http://www.denso-wave.com/qrcode/faqpatent-e.html
//
//---------------------------------------------------------------------
function QR8bitByte(data) {
this.mode = QRMode.MODE_8BIT_BYTE;
this.data = data;
this.parsedData = [];
// Added to support UTF-8 Characters
for (var i = 0, l = this.data.length; i < l; i++) {
var byteArray = [];
var code = this.data.charCodeAt(i);
if (code > 0x10000) {
byteArray[0] = 0xF0 | ((code & 0x1C0000) >>> 18);
byteArray[1] = 0x80 | ((code & 0x3F000) >>> 12);
byteArray[2] = 0x80 | ((code & 0xFC0) >>> 6);
byteArray[3] = 0x80 | (code & 0x3F);
} else if (code > 0x800) {
byteArray[0] = 0xE0 | ((code & 0xF000) >>> 12);
byteArray[1] = 0x80 | ((code & 0xFC0) >>> 6);
byteArray[2] = 0x80 | (code & 0x3F);
} else if (code > 0x80) {
byteArray[0] = 0xC0 | ((code & 0x7C0) >>> 6);
byteArray[1] = 0x80 | (code & 0x3F);
} else {
byteArray[0] = code;
}
this.parsedData.push(byteArray);
}
this.parsedData = Array.prototype.concat.apply([], this.parsedData);
if (this.parsedData.length != this.data.length) {
this.parsedData.unshift(191);
this.parsedData.unshift(187);
this.parsedData.unshift(239);
}
}
QR8bitByte.prototype = {
getLength: function (buffer) {
return this.parsedData.length;
},
write: function (buffer) {
for (var i = 0, l = this.parsedData.length; i < l; i++) {
buffer.put(this.parsedData[i], 8);
}
}
};
function QRCodeModel(typeNumber, errorCorrectLevel) {
this.typeNumber = typeNumber;
this.errorCorrectLevel = errorCorrectLevel;
this.modules = null;
this.moduleCount = 0;
this.dataCache = null;
this.dataList = [];
}
QRCodeModel.prototype = {
addData: function (data) { var newData = new QR8bitByte(data); this.dataList.push(newData); this.dataCache = null; }, isDark: function (row, col) {
if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) { throw new Error(row + "," + col); }
return this.modules[row][col];
}, getModuleCount: function () { return this.moduleCount; }, make: function () { this.makeImpl(false, this.getBestMaskPattern()); }, makeImpl: function (test, maskPattern) {
this.moduleCount = this.typeNumber * 4 + 17; this.modules = new Array(this.moduleCount); for (var row = 0; row < this.moduleCount; row++) { this.modules[row] = new Array(this.moduleCount); for (var col = 0; col < this.moduleCount; col++) { this.modules[row][col] = null; } }
this.setupPositionProbePattern(0, 0); this.setupPositionProbePattern(this.moduleCount - 7, 0); this.setupPositionProbePattern(0, this.moduleCount - 7); this.setupPositionAdjustPattern(); this.setupTimingPattern(); this.setupTypeInfo(test, maskPattern); if (this.typeNumber >= 7) { this.setupTypeNumber(test); }
if (this.dataCache == null) { this.dataCache = QRCodeModel.createData(this.typeNumber, this.errorCorrectLevel, this.dataList); }
this.mapData(this.dataCache, maskPattern);
}, setupPositionProbePattern: function (row, col) { for (var r = -1; r <= 7; r++) { if (row + r <= -1 || this.moduleCount <= row + r) continue; for (var c = -1; c <= 7; c++) { if (col + c <= -1 || this.moduleCount <= col + c) continue; if ((0 <= r && r <= 6 && (c == 0 || c == 6)) || (0 <= c && c <= 6 && (r == 0 || r == 6)) || (2 <= r && r <= 4 && 2 <= c && c <= 4)) { this.modules[row + r][col + c] = true; } else { this.modules[row + r][col + c] = false; } } } }, getBestMaskPattern: function () {
var minLostPoint = 0; var pattern = 0; for (var i = 0; i < 8; i++) { this.makeImpl(true, i); var lostPoint = QRUtil.getLostPoint(this); if (i == 0 || minLostPoint > lostPoint) { minLostPoint = lostPoint; pattern = i; } }
return pattern;
}, createMovieClip: function (target_mc, instance_name, depth) {
var qr_mc = target_mc.createEmptyMovieClip(instance_name, depth); var cs = 1; this.make(); for (var row = 0; row < this.modules.length; row++) { var y = row * cs; for (var col = 0; col < this.modules[row].length; col++) { var x = col * cs; var dark = this.modules[row][col]; if (dark) { qr_mc.beginFill(0, 100); qr_mc.moveTo(x, y); qr_mc.lineTo(x + cs, y); qr_mc.lineTo(x + cs, y + cs); qr_mc.lineTo(x, y + cs); qr_mc.endFill(); } } }
return qr_mc;
}, setupTimingPattern: function () {
for (var r = 8; r < this.moduleCount - 8; r++) {
if (this.modules[r][6] != null) { continue; }
this.modules[r][6] = (r % 2 == 0);
}
for (var c = 8; c < this.moduleCount - 8; c++) {
if (this.modules[6][c] != null) { continue; }
this.modules[6][c] = (c % 2 == 0);
}
}, setupPositionAdjustPattern: function () {
var pos = QRUtil.getPatternPosition(this.typeNumber); for (var i = 0; i < pos.length; i++) {
for (var j = 0; j < pos.length; j++) {
var row = pos[i]; var col = pos[j]; if (this.modules[row][col] != null) { continue; }
for (var r = -2; r <= 2; r++) { for (var c = -2; c <= 2; c++) { if (r == -2 || r == 2 || c == -2 || c == 2 || (r == 0 && c == 0)) { this.modules[row + r][col + c] = true; } else { this.modules[row + r][col + c] = false; } } }
}
}
}, setupTypeNumber: function (test) {
var bits = QRUtil.getBCHTypeNumber(this.typeNumber); for (var i = 0; i < 18; i++) { var mod = (!test && ((bits >> i) & 1) == 1); this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod; }
for (var i = 0; i < 18; i++) { var mod = (!test && ((bits >> i) & 1) == 1); this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod; }
}, setupTypeInfo: function (test, maskPattern) {
var data = (this.errorCorrectLevel << 3) | maskPattern; var bits = QRUtil.getBCHTypeInfo(data); for (var i = 0; i < 15; i++) { var mod = (!test && ((bits >> i) & 1) == 1); if (i < 6) { this.modules[i][8] = mod; } else if (i < 8) { this.modules[i + 1][8] = mod; } else { this.modules[this.moduleCount - 15 + i][8] = mod; } }
for (var i = 0; i < 15; i++) { var mod = (!test && ((bits >> i) & 1) == 1); if (i < 8) { this.modules[8][this.moduleCount - i - 1] = mod; } else if (i < 9) { this.modules[8][15 - i - 1 + 1] = mod; } else { this.modules[8][15 - i - 1] = mod; } }
this.modules[this.moduleCount - 8][8] = (!test);
}, mapData: function (data, maskPattern) {
var inc = -1; var row = this.moduleCount - 1; var bitIndex = 7; var byteIndex = 0; for (var col = this.moduleCount - 1; col > 0; col -= 2) {
if (col == 6) col--; while (true) {
for (var c = 0; c < 2; c++) {
if (this.modules[row][col - c] == null) {
var dark = false; if (byteIndex < data.length) { dark = (((data[byteIndex] >>> bitIndex) & 1) == 1); }
var mask = QRUtil.getMask(maskPattern, row, col - c); if (mask) { dark = !dark; }
this.modules[row][col - c] = dark; bitIndex--; if (bitIndex == -1) { byteIndex++; bitIndex = 7; }
}
}
row += inc; if (row < 0 || this.moduleCount <= row) { row -= inc; inc = -inc; break; }
}
}
}
}; QRCodeModel.PAD0 = 0xEC; QRCodeModel.PAD1 = 0x11; QRCodeModel.createData = function (typeNumber, errorCorrectLevel, dataList) {
var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel); var buffer = new QRBitBuffer(); for (var i = 0; i < dataList.length; i++) { var data = dataList[i]; buffer.put(data.mode, 4); buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber)); data.write(buffer); }
var totalDataCount = 0; for (var i = 0; i < rsBlocks.length; i++) { totalDataCount += rsBlocks[i].dataCount; }
if (buffer.getLengthInBits() > totalDataCount * 8) {
throw new Error("code length overflow. ("
+ buffer.getLengthInBits()
+ ">"
+ totalDataCount * 8
+ ")");
}
if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) { buffer.put(0, 4); }
while (buffer.getLengthInBits() % 8 != 0) { buffer.putBit(false); }
while (true) {
if (buffer.getLengthInBits() >= totalDataCount * 8) { break; }
buffer.put(QRCodeModel.PAD0, 8); if (buffer.getLengthInBits() >= totalDataCount * 8) { break; }
buffer.put(QRCodeModel.PAD1, 8);
}
return QRCodeModel.createBytes(buffer, rsBlocks);
}; QRCodeModel.createBytes = function (buffer, rsBlocks) {
var offset = 0; var maxDcCount = 0; var maxEcCount = 0; var dcdata = new Array(rsBlocks.length); var ecdata = new Array(rsBlocks.length); for (var r = 0; r < rsBlocks.length; r++) {
var dcCount = rsBlocks[r].dataCount; var ecCount = rsBlocks[r].totalCount - dcCount; maxDcCount = Math.max(maxDcCount, dcCount); maxEcCount = Math.max(maxEcCount, ecCount); dcdata[r] = new Array(dcCount); for (var i = 0; i < dcdata[r].length; i++) { dcdata[r][i] = 0xff & buffer.buffer[i + offset]; }
offset += dcCount; var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount); var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1); var modPoly = rawPoly.mod(rsPoly); ecdata[r] = new Array(rsPoly.getLength() - 1); for (var i = 0; i < ecdata[r].length; i++) { var modIndex = i + modPoly.getLength() - ecdata[r].length; ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0; }
}
var totalCodeCount = 0; for (var i = 0; i < rsBlocks.length; i++) { totalCodeCount += rsBlocks[i].totalCount; }
var data = new Array(totalCodeCount); var index = 0; for (var i = 0; i < maxDcCount; i++) { for (var r = 0; r < rsBlocks.length; r++) { if (i < dcdata[r].length) { data[index++] = dcdata[r][i]; } } }
for (var i = 0; i < maxEcCount; i++) { for (var r = 0; r < rsBlocks.length; r++) { if (i < ecdata[r].length) { data[index++] = ecdata[r][i]; } } }
return data;
}; var QRMode = { MODE_NUMBER: 1 << 0, MODE_ALPHA_NUM: 1 << 1, MODE_8BIT_BYTE: 1 << 2, MODE_KANJI: 1 << 3 }; var QRErrorCorrectLevel = { L: 1, M: 0, Q: 3, H: 2 }; var QRMaskPattern = { PATTERN000: 0, PATTERN001: 1, PATTERN010: 2, PATTERN011: 3, PATTERN100: 4, PATTERN101: 5, PATTERN110: 6, PATTERN111: 7 }; var QRUtil = {
PATTERN_POSITION_TABLE: [[], [6, 18], [6, 22], [6, 26], [6, 30], [6, 34], [6, 22, 38], [6, 24, 42], [6, 26, 46], [6, 28, 50], [6, 30, 54], [6, 32, 58], [6, 34, 62], [6, 26, 46, 66], [6, 26, 48, 70], [6, 26, 50, 74], [6, 30, 54, 78], [6, 30, 56, 82], [6, 30, 58, 86], [6, 34, 62, 90], [6, 28, 50, 72, 94], [6, 26, 50, 74, 98], [6, 30, 54, 78, 102], [6, 28, 54, 80, 106], [6, 32, 58, 84, 110], [6, 30, 58, 86, 114], [6, 34, 62, 90, 118], [6, 26, 50, 74, 98, 122], [6, 30, 54, 78, 102, 126], [6, 26, 52, 78, 104, 130], [6, 30, 56, 82, 108, 134], [6, 34, 60, 86, 112, 138], [6, 30, 58, 86, 114, 142], [6, 34, 62, 90, 118, 146], [6, 30, 54, 78, 102, 126, 150], [6, 24, 50, 76, 102, 128, 154], [6, 28, 54, 80, 106, 132, 158], [6, 32, 58, 84, 110, 136, 162], [6, 26, 54, 82, 110, 138, 166], [6, 30, 58, 86, 114, 142, 170]], G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0), G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0), G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1), getBCHTypeInfo: function (data) {
var d = data << 10; while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) { d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15))); }
return ((data << 10) | d) ^ QRUtil.G15_MASK;
}, getBCHTypeNumber: function (data) {
var d = data << 12; while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) { d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18))); }
return (data << 12) | d;
}, getBCHDigit: function (data) {
var digit = 0; while (data != 0) { digit++; data >>>= 1; }
return digit;
}, getPatternPosition: function (typeNumber) { return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1]; }, getMask: function (maskPattern, i, j) { switch (maskPattern) { case QRMaskPattern.PATTERN000: return (i + j) % 2 == 0; case QRMaskPattern.PATTERN001: return i % 2 == 0; case QRMaskPattern.PATTERN010: return j % 3 == 0; case QRMaskPattern.PATTERN011: return (i + j) % 3 == 0; case QRMaskPattern.PATTERN100: return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0; case QRMaskPattern.PATTERN101: return (i * j) % 2 + (i * j) % 3 == 0; case QRMaskPattern.PATTERN110: return ((i * j) % 2 + (i * j) % 3) % 2 == 0; case QRMaskPattern.PATTERN111: return ((i * j) % 3 + (i + j) % 2) % 2 == 0; default: throw new Error("bad maskPattern:" + maskPattern); } }, getErrorCorrectPolynomial: function (errorCorrectLength) {
var a = new QRPolynomial([1], 0); for (var i = 0; i < errorCorrectLength; i++) { a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0)); }
return a;
}, getLengthInBits: function (mode, type) { if (1 <= type && type < 10) { switch (mode) { case QRMode.MODE_NUMBER: return 10; case QRMode.MODE_ALPHA_NUM: return 9; case QRMode.MODE_8BIT_BYTE: return 8; case QRMode.MODE_KANJI: return 8; default: throw new Error("mode:" + mode); } } else if (type < 27) { switch (mode) { case QRMode.MODE_NUMBER: return 12; case QRMode.MODE_ALPHA_NUM: return 11; case QRMode.MODE_8BIT_BYTE: return 16; case QRMode.MODE_KANJI: return 10; default: throw new Error("mode:" + mode); } } else if (type < 41) { switch (mode) { case QRMode.MODE_NUMBER: return 14; case QRMode.MODE_ALPHA_NUM: return 13; case QRMode.MODE_8BIT_BYTE: return 16; case QRMode.MODE_KANJI: return 12; default: throw new Error("mode:" + mode); } } else { throw new Error("type:" + type); } }, getLostPoint: function (qrCode) {
var moduleCount = qrCode.getModuleCount(); var lostPoint = 0; for (var row = 0; row < moduleCount; row++) {
for (var col = 0; col < moduleCount; col++) {
var sameCount = 0; var dark = qrCode.isDark(row, col); for (var r = -1; r <= 1; r++) {
if (row + r < 0 || moduleCount <= row + r) { continue; }
for (var c = -1; c <= 1; c++) {
if (col + c < 0 || moduleCount <= col + c) { continue; }
if (r == 0 && c == 0) { continue; }
if (dark == qrCode.isDark(row + r, col + c)) { sameCount++; }
}
}
if (sameCount > 5) { lostPoint += (3 + sameCount - 5); }
}
}
for (var row = 0; row < moduleCount - 1; row++) { for (var col = 0; col < moduleCount - 1; col++) { var count = 0; if (qrCode.isDark(row, col)) count++; if (qrCode.isDark(row + 1, col)) count++; if (qrCode.isDark(row, col + 1)) count++; if (qrCode.isDark(row + 1, col + 1)) count++; if (count == 0 || count == 4) { lostPoint += 3; } } }
for (var row = 0; row < moduleCount; row++) { for (var col = 0; col < moduleCount - 6; col++) { if (qrCode.isDark(row, col) && !qrCode.isDark(row, col + 1) && qrCode.isDark(row, col + 2) && qrCode.isDark(row, col + 3) && qrCode.isDark(row, col + 4) && !qrCode.isDark(row, col + 5) && qrCode.isDark(row, col + 6)) { lostPoint += 40; } } }
for (var col = 0; col < moduleCount; col++) { for (var row = 0; row < moduleCount - 6; row++) { if (qrCode.isDark(row, col) && !qrCode.isDark(row + 1, col) && qrCode.isDark(row + 2, col) && qrCode.isDark(row + 3, col) && qrCode.isDark(row + 4, col) && !qrCode.isDark(row + 5, col) && qrCode.isDark(row + 6, col)) { lostPoint += 40; } } }
var darkCount = 0; for (var col = 0; col < moduleCount; col++) { for (var row = 0; row < moduleCount; row++) { if (qrCode.isDark(row, col)) { darkCount++; } } }
var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5; lostPoint += ratio * 10; return lostPoint;
}
}; var QRMath = {
glog: function (n) {
if (n < 1) { throw new Error("glog(" + n + ")"); }
return QRMath.LOG_TABLE[n];
}, gexp: function (n) {
while (n < 0) { n += 255; }
while (n >= 256) { n -= 255; }
return QRMath.EXP_TABLE[n];
}, EXP_TABLE: new Array(256), LOG_TABLE: new Array(256)
}; for (var i = 0; i < 8; i++) { QRMath.EXP_TABLE[i] = 1 << i; }
for (var i = 8; i < 256; i++) { QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^ QRMath.EXP_TABLE[i - 5] ^ QRMath.EXP_TABLE[i - 6] ^ QRMath.EXP_TABLE[i - 8]; }
for (var i = 0; i < 255; i++) { QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i; }
function QRPolynomial(num, shift) {
if (num.length == undefined) { throw new Error(num.length + "/" + shift); }
var offset = 0; while (offset < num.length && num[offset] == 0) { offset++; }
this.num = new Array(num.length - offset + shift); for (var i = 0; i < num.length - offset; i++) { this.num[i] = num[i + offset]; }
}
QRPolynomial.prototype = {
get: function (index) { return this.num[index]; }, getLength: function () { return this.num.length; }, multiply: function (e) {
var num = new Array(this.getLength() + e.getLength() - 1); for (var i = 0; i < this.getLength(); i++) { for (var j = 0; j < e.getLength(); j++) { num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j))); } }
return new QRPolynomial(num, 0);
}, mod: function (e) {
if (this.getLength() - e.getLength() < 0) { return this; }
var ratio = QRMath.glog(this.get(0)) - QRMath.glog(e.get(0)); var num = new Array(this.getLength()); for (var i = 0; i < this.getLength(); i++) { num[i] = this.get(i); }
for (var i = 0; i < e.getLength(); i++) { num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio); }
return new QRPolynomial(num, 0).mod(e);
}
}; function QRRSBlock(totalCount, dataCount) { this.totalCount = totalCount; this.dataCount = dataCount; }
QRRSBlock.RS_BLOCK_TABLE = [[1, 26, 19], [1, 26, 16], [1, 26, 13], [1, 26, 9], [1, 44, 34], [1, 44, 28], [1, 44, 22], [1, 44, 16], [1, 70, 55], [1, 70, 44], [2, 35, 17], [2, 35, 13], [1, 100, 80], [2, 50, 32], [2, 50, 24], [4, 25, 9], [1, 134, 108], [2, 67, 43], [2, 33, 15, 2, 34, 16], [2, 33, 11, 2, 34, 12], [2, 86, 68], [4, 43, 27], [4, 43, 19], [4, 43, 15], [2, 98, 78], [4, 49, 31], [2, 32, 14, 4, 33, 15], [4, 39, 13, 1, 40, 14], [2, 121, 97], [2, 60, 38, 2, 61, 39], [4, 40, 18, 2, 41, 19], [4, 40, 14, 2, 41, 15], [2, 146, 116], [3, 58, 36, 2, 59, 37], [4, 36, 16, 4, 37, 17], [4, 36, 12, 4, 37, 13], [2, 86, 68, 2, 87, 69], [4, 69, 43, 1, 70, 44], [6, 43, 19, 2, 44, 20], [6, 43, 15, 2, 44, 16], [4, 101, 81], [1, 80, 50, 4, 81, 51], [4, 50, 22, 4, 51, 23], [3, 36, 12, 8, 37, 13], [2, 116, 92, 2, 117, 93], [6, 58, 36, 2, 59, 37], [4, 46, 20, 6, 47, 21], [7, 42, 14, 4, 43, 15], [4, 133, 107], [8, 59, 37, 1, 60, 38], [8, 44, 20, 4, 45, 21], [12, 33, 11, 4, 34, 12], [3, 145, 115, 1, 146, 116], [4, 64, 40, 5, 65, 41], [11, 36, 16, 5, 37, 17], [11, 36, 12, 5, 37, 13], [5, 109, 87, 1, 110, 88], [5, 65, 41, 5, 66, 42], [5, 54, 24, 7, 55, 25], [11, 36, 12], [5, 122, 98, 1, 123, 99], [7, 73, 45, 3, 74, 46], [15, 43, 19, 2, 44, 20], [3, 45, 15, 13, 46, 16], [1, 135, 107, 5, 136, 108], [10, 74, 46, 1, 75, 47], [1, 50, 22, 15, 51, 23], [2, 42, 14, 17, 43, 15], [5, 150, 120, 1, 151, 121], [9, 69, 43, 4, 70, 44], [17, 50, 22, 1, 51, 23], [2, 42, 14, 19, 43, 15], [3, 141, 113, 4, 142, 114], [3, 70, 44, 11, 71, 45], [17, 47, 21, 4, 48, 22], [9, 39, 13, 16, 40, 14], [3, 135, 107, 5, 136, 108], [3, 67, 41, 13, 68, 42], [15, 54, 24, 5, 55, 25], [15, 43, 15, 10, 44, 16], [4, 144, 116, 4, 145, 117], [17, 68, 42], [17, 50, 22, 6, 51, 23], [19, 46, 16, 6, 47, 17], [2, 139, 111, 7, 140, 112], [17, 74, 46], [7, 54, 24, 16, 55, 25], [34, 37, 13], [4, 151, 121, 5, 152, 122], [4, 75, 47, 14, 76, 48], [11, 54, 24, 14, 55, 25], [16, 45, 15, 14, 46, 16], [6, 147, 117, 4, 148, 118], [6, 73, 45, 14, 74, 46], [11, 54, 24, 16, 55, 25], [30, 46, 16, 2, 47, 17], [8, 132, 106, 4, 133, 107], [8, 75, 47, 13, 76, 48], [7, 54, 24, 22, 55, 25], [22, 45, 15, 13, 46, 16], [10, 142, 114, 2, 143, 115], [19, 74, 46, 4, 75, 47], [28, 50, 22, 6, 51, 23], [33, 46, 16, 4, 47, 17], [8, 152, 122, 4, 153, 123], [22, 73, 45, 3, 74, 46], [8, 53, 23, 26, 54, 24], [12, 45, 15, 28, 46, 16], [3, 147, 117, 10, 148, 118], [3, 73, 45, 23, 74, 46], [4, 54, 24, 31, 55, 25], [11, 45, 15, 31, 46, 16], [7, 146, 116, 7, 147, 117], [21, 73, 45, 7, 74, 46], [1, 53, 23, 37, 54, 24], [19, 45, 15, 26, 46, 16], [5, 145, 115, 10, 146, 116], [19, 75, 47, 10, 76, 48], [15, 54, 24, 25, 55, 25], [23, 45, 15, 25, 46, 16], [13, 145, 115, 3, 146, 116], [2, 74, 46, 29, 75, 47], [42, 54, 24, 1, 55, 25], [23, 45, 15, 28, 46, 16], [17, 145, 115], [10, 74, 46, 23, 75, 47], [10, 54, 24, 35, 55, 25], [19, 45, 15, 35, 46, 16], [17, 145, 115, 1, 146, 116], [14, 74, 46, 21, 75, 47], [29, 54, 24, 19, 55, 25], [11, 45, 15, 46, 46, 16], [13, 145, 115, 6, 146, 116], [14, 74, 46, 23, 75, 47], [44, 54, 24, 7, 55, 25], [59, 46, 16, 1, 47, 17], [12, 151, 121, 7, 152, 122], [12, 75, 47, 26, 76, 48], [39, 54, 24, 14, 55, 25], [22, 45, 15, 41, 46, 16], [6, 151, 121, 14, 152, 122], [6, 75, 47, 34, 76, 48], [46, 54, 24, 10, 55, 25], [2, 45, 15, 64, 46, 16], [17, 152, 122, 4, 153, 123], [29, 74, 46, 14, 75, 47], [49, 54, 24, 10, 55, 25], [24, 45, 15, 46, 46, 16], [4, 152, 122, 18, 153, 123], [13, 74, 46, 32, 75, 47], [48, 54, 24, 14, 55, 25], [42, 45, 15, 32, 46, 16], [20, 147, 117, 4, 148, 118], [40, 75, 47, 7, 76, 48], [43, 54, 24, 22, 55, 25], [10, 45, 15, 67, 46, 16], [19, 148, 118, 6, 149, 119], [18, 75, 47, 31, 76, 48], [34, 54, 24, 34, 55, 25], [20, 45, 15, 61, 46, 16]]; QRRSBlock.getRSBlocks = function (typeNumber, errorCorrectLevel) {
var rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel); if (rsBlock == undefined) { throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel); }
var length = rsBlock.length / 3; var list = []; for (var i = 0; i < length; i++) { var count = rsBlock[i * 3 + 0]; var totalCount = rsBlock[i * 3 + 1]; var dataCount = rsBlock[i * 3 + 2]; for (var j = 0; j < count; j++) { list.push(new QRRSBlock(totalCount, dataCount)); } }
return list;
}; QRRSBlock.getRsBlockTable = function (typeNumber, errorCorrectLevel) { switch (errorCorrectLevel) { case QRErrorCorrectLevel.L: return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0]; case QRErrorCorrectLevel.M: return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1]; case QRErrorCorrectLevel.Q: return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2]; case QRErrorCorrectLevel.H: return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3]; default: return undefined; } }; function QRBitBuffer() { this.buffer = []; this.length = 0; }
QRBitBuffer.prototype = {
get: function (index) { var bufIndex = Math.floor(index / 8); return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) == 1; }, put: function (num, length) { for (var i = 0; i < length; i++) { this.putBit(((num >>> (length - i - 1)) & 1) == 1); } }, getLengthInBits: function () { return this.length; }, putBit: function (bit) {
var bufIndex = Math.floor(this.length / 8); if (this.buffer.length <= bufIndex) { this.buffer.push(0); }
if (bit) { this.buffer[bufIndex] |= (0x80 >>> (this.length % 8)); }
this.length++;
}
}; var QRCodeLimitLength = [[17, 14, 11, 7], [32, 26, 20, 14], [53, 42, 32, 24], [78, 62, 46, 34], [106, 84, 60, 44], [134, 106, 74, 58], [154, 122, 86, 64], [192, 152, 108, 84], [230, 180, 130, 98], [271, 213, 151, 119], [321, 251, 177, 137], [367, 287, 203, 155], [425, 331, 241, 177], [458, 362, 258, 194], [520, 412, 292, 220], [586, 450, 322, 250], [644, 504, 364, 280], [718, 560, 394, 310], [792, 624, 442, 338], [858, 666, 482, 382], [929, 711, 509, 403], [1003, 779, 565, 439], [1091, 857, 611, 461], [1171, 911, 661, 511], [1273, 997, 715, 535], [1367, 1059, 751, 593], [1465, 1125, 805, 625], [1528, 1190, 868, 658], [1628, 1264, 908, 698], [1732, 1370, 982, 742], [1840, 1452, 1030, 790], [1952, 1538, 1112, 842], [2068, 1628, 1168, 898], [2188, 1722, 1228, 958], [2303, 1809, 1283, 983], [2431, 1911, 1351, 1051], [2563, 1989, 1423, 1093], [2699, 2099, 1499, 1139], [2809, 2213, 1579, 1219], [2953, 2331, 1663, 1273]];
function _isSupportCanvas() {
return typeof CanvasRenderingContext2D != "undefined";
}
// android 2.x doesn't support Data-URI spec
function _getAndroid() {
var android = false;
var sAgent = navigator.userAgent;
if (/android/i.test(sAgent)) { // android
android = true;
var aMat = sAgent.toString().match(/android ([0-9]\.[0-9])/i);
if (aMat && aMat[1]) {
android = parseFloat(aMat[1]);
}
}
return android;
}
var svgDrawer = (function () {
var Drawing = function (el, htOption) {
this._el = el;
this._htOption = htOption;
};
Drawing.prototype.draw = function (oQRCode) {
var _htOption = this._htOption;
var _el = this._el;
var nCount = oQRCode.getModuleCount();
var nWidth = Math.floor(_htOption.width / nCount);
var nHeight = Math.floor(_htOption.height / nCount);
this.clear();
function makeSVG(tag, attrs) {
var el = document.createElementNS('http://www.w3.org/2000/svg', tag);
for (var k in attrs)
if (attrs.hasOwnProperty(k)) el.setAttribute(k, attrs[k]);
return el;
}
var svg = makeSVG("svg", { 'viewBox': '0 0 ' + String(nCount) + " " + String(nCount), 'width': '100%', 'height': '100%', 'fill': _htOption.colorLight });
svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink");
_el.appendChild(svg);
svg.appendChild(makeSVG("rect", { "fill": _htOption.colorLight, "width": "100%", "height": "100%" }));
svg.appendChild(makeSVG("rect", { "fill": _htOption.colorDark, "width": "1", "height": "1", "id": "template" }));
for (var row = 0; row < nCount; row++) {
for (var col = 0; col < nCount; col++) {
if (oQRCode.isDark(row, col)) {
var child = makeSVG("use", { "x": String(col), "y": String(row) });
child.setAttributeNS("http://www.w3.org/1999/xlink", "href", "#template")
svg.appendChild(child);
}
}
}
};
Drawing.prototype.clear = function () {
while (this._el.hasChildNodes())
this._el.removeChild(this._el.lastChild);
};
return Drawing;
})();
var useSVG = document.documentElement.tagName.toLowerCase() === "svg";
// Drawing in DOM by using Table tag
var Drawing = useSVG ? svgDrawer : !_isSupportCanvas() ? (function () {
var Drawing = function (el, htOption) {
this._el = el;
this._htOption = htOption;
};
/**
* Draw the QRCode
*
* @param {QRCode} oQRCode
*/
Drawing.prototype.draw = function (oQRCode) {
var _htOption = this._htOption;
var _el = this._el;
var nCount = oQRCode.getModuleCount();
var nWidth = Math.floor(_htOption.width / nCount);
var nHeight = Math.floor(_htOption.height / nCount);
var aHTML = ['<table style="border:0;border-collapse:collapse;">'];
for (var row = 0; row < nCount; row++) {
aHTML.push('<tr>');
for (var col = 0; col < nCount; col++) {
aHTML.push('<td style="border:0;border-collapse:collapse;padding:0;margin:0;width:' + nWidth + 'px;height:' + nHeight + 'px;background-color:' + (oQRCode.isDark(row, col) ? _htOption.colorDark : _htOption.colorLight) + ';"></td>');
}
aHTML.push('</tr>');
}
aHTML.push('</table>');
_el.innerHTML = aHTML.join('');
// Fix the margin values as real size.
var elTable = _el.childNodes[0];
var nLeftMarginTable = (_htOption.width - elTable.offsetWidth) / 2;
var nTopMarginTable = (_htOption.height - elTable.offsetHeight) / 2;
if (nLeftMarginTable > 0 && nTopMarginTable > 0) {
elTable.style.margin = nTopMarginTable + "px " + nLeftMarginTable + "px";
}
};
/**
* Clear the QRCode
*/
Drawing.prototype.clear = function () {
this._el.innerHTML = '';
};
return Drawing;
})() : (function () { // Drawing in Canvas
function _onMakeImage() {
this._elImage.src = this._elCanvas.toDataURL("image/png");
//this._elImage.style.display = "block";
//this._elCanvas.style.display = "none";
this._elImage.className = "img-fluid";
}
// Android 2.1 bug workaround
// http://code.google.com/p/android/issues/detail?id=5141
if (this._android && this._android <= 2.1) {
var factor = 1 / window.devicePixelRatio;
var drawImage = CanvasRenderingContext2D.prototype.drawImage;
CanvasRenderingContext2D.prototype.drawImage = function (image, sx, sy, sw, sh, dx, dy, dw, dh) {
if (("nodeName" in image) && /img/i.test(image.nodeName)) {
for (var i = arguments.length - 1; i >= 1; i--) {
arguments[i] = arguments[i] * factor;
}
} else if (typeof dw == "undefined") {
arguments[1] *= factor;
arguments[2] *= factor;
arguments[3] *= factor;
arguments[4] *= factor;
}
drawImage.apply(this, arguments);
};
}
/**
* Check whether the user's browser supports Data URI or not
*
* @private
* @param {Function} fSuccess Occurs if it supports Data URI
* @param {Function} fFail Occurs if it doesn't support Data URI
*/
function _safeSetDataURI(fSuccess, fFail) {
var self = this;
self._fFail = fFail;
self._fSuccess = fSuccess;
// Check it just once
if (self._bSupportDataURI === null) {
var el = document.createElement("img");
var fOnError = function () {
self._bSupportDataURI = false;
if (self._fFail) {
self._fFail.call(self);
}
};
var fOnSuccess = function () {
self._bSupportDataURI = true;
if (self._fSuccess) {
self._fSuccess.call(self);
}
};
el.onabort = fOnError;
el.onerror = fOnError;
el.onload = fOnSuccess;
el.src = "data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; // the Image contains 1px data.
return;
} else if (self._bSupportDataURI === true && self._fSuccess) {
self._fSuccess.call(self);
} else if (self._bSupportDataURI === false && self._fFail) {
self._fFail.call(self);
}
};
/**
* Drawing QRCode by using canvas
*
* @constructor
* @param {HTMLElement} el
* @param {Object} htOption QRCode Options
*/
var Drawing = function (el, htOption) {
this._bIsPainted = false;
this._android = _getAndroid();
this._htOption = htOption;
this._elCanvas = document.createElement("canvas");
this._elCanvas.width = htOption.width;
this._elCanvas.height = htOption.height;
el.appendChild(this._elCanvas);
this._el = el;
this._oContext = this._elCanvas.getContext("2d");
this._bIsPainted = false;
this._elImage = document.createElement("img");
this._elImage.alt = "Scan me!";
this._elImage.style.display = "none";
this._elImage.className = "img-fluid";
this._el.appendChild(this._elImage);
this._bSupportDataURI = null;
};
/**
* Draw the QRCode
*
* @param {QRCode} oQRCode
*/
Drawing.prototype.draw = function (oQRCode) {
var _elImage = this._elImage;
var _oContext = this._oContext;
var _htOption = this._htOption;
var nCount = oQRCode.getModuleCount();
var nWidth = _htOption.width / nCount;
var nHeight = _htOption.height / nCount;
var nRoundedWidth = Math.round(nWidth);
var nRoundedHeight = Math.round(nHeight);
_elImage.style.display = "none";
_elImage.className = "img-fluid";
this.clear();
for (var row = 0; row < nCount; row++) {
for (var col = 0; col < nCount; col++) {
var bIsDark = oQRCode.isDark(row, col);
var nLeft = col * nWidth;
var nTop = row * nHeight;
_oContext.strokeStyle = bIsDark ? _htOption.colorDark : _htOption.colorLight;
_oContext.lineWidth = 1;
_oContext.fillStyle = bIsDark ? _htOption.colorDark : _htOption.colorLight;
_oContext.fillRect(nLeft, nTop, nWidth, nHeight);
// 안티 앨리어싱 방지 처리
_oContext.strokeRect(
Math.floor(nLeft) + 0.5,
Math.floor(nTop) + 0.5,
nRoundedWidth,
nRoundedHeight
);
_oContext.strokeRect(
Math.ceil(nLeft) - 0.5,
Math.ceil(nTop) - 0.5,
nRoundedWidth,
nRoundedHeight
);
}
}
this._bIsPainted = true;
};
/**
* Make the image from Canvas if the browser supports Data URI.
*/
Drawing.prototype.makeImage = function () {
if (this._bIsPainted) {
_safeSetDataURI.call(this, _onMakeImage);
}
};
/**
* Return whether the QRCode is painted or not
*
* @return {Boolean}
*/
Drawing.prototype.isPainted = function () {
return this._bIsPainted;
};
/**
* Clear the QRCode
*/
Drawing.prototype.clear = function () {
this._oContext.clearRect(0, 0, this._elCanvas.width, this._elCanvas.height);
this._bIsPainted = false;
};
/**
* @private
* @param {Number} nNumber
*/
Drawing.prototype.round = function (nNumber) {
if (!nNumber) {
return nNumber;
}
return Math.floor(nNumber * 1000) / 1000;
};
return Drawing;
})();
/**
* Get the type by string length
*
* @private
* @param {String} sText
* @param {Number} nCorrectLevel
* @return {Number} type
*/
function _getTypeNumber(sText, nCorrectLevel) {
var nType = 1;
var length = _getUTF8Length(sText);
for (var i = 0, len = QRCodeLimitLength.length; i <= len; i++) {
var nLimit = 0;
switch (nCorrectLevel) {
case QRErrorCorrectLevel.L:
nLimit = QRCodeLimitLength[i][0];
break;
case QRErrorCorrectLevel.M:
nLimit = QRCodeLimitLength[i][1];
break;
case QRErrorCorrectLevel.Q:
nLimit = QRCodeLimitLength[i][2];
break;
case QRErrorCorrectLevel.H:
nLimit = QRCodeLimitLength[i][3];
break;
}
if (length <= nLimit) {
break;
} else {
nType++;
}
}
if (nType > QRCodeLimitLength.length) {
throw new Error("Too long data");
}
return nType;
}
function _getUTF8Length(sText) {
var replacedText = encodeURI(sText).toString().replace(/\%[0-9a-fA-F]{2}/g, 'a');
return replacedText.length + (replacedText.length != sText ? 3 : 0);
}
/**
* @class QRCode
* @constructor
* @example
* new QRCode(document.getElementById("test"), "http://jindo.dev.naver.com/collie");
*
* @example
* var oQRCode = new QRCode("test", {
* text : "http://naver.com",
* width : 128,
* height : 128
* });
*
* oQRCode.clear(); // Clear the QRCode.
* oQRCode.makeCode("http://map.naver.com"); // Re-create the QRCode.
*
* @param {HTMLElement|String} el target element or 'id' attribute of element.
* @param {Object|String} vOption
* @param {String} vOption.text QRCode link data
* @param {Number} [vOption.width=256]
* @param {Number} [vOption.height=256]
* @param {String} [vOption.colorDark="#000000"]
* @param {String} [vOption.colorLight="#ffffff"]
* @param {QRCode.CorrectLevel} [vOption.correctLevel=QRCode.CorrectLevel.H] [L|M|Q|H]
*/
QRCode = function (el, vOption) {
this._htOption = {
width: 256,
height: 256,
typeNumber: 4,
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: QRErrorCorrectLevel.H
};
if (typeof vOption === 'string') {
vOption = {
text: vOption
};
}
// Overwrites options
if (vOption) {
for (var i in vOption) {
this._htOption[i] = vOption[i];
}
}
if (typeof el == "string") {
el = document.getElementById(el);
}
if (this._htOption.useSVG) {
Drawing = svgDrawer;
}
this._android = _getAndroid();
this._el = el;
this._oQRCode = null;
this._oDrawing = new Drawing(this._el, this._htOption);
if (this._htOption.text) {
this.makeCode(this._htOption.text);
}
};
/**
* Make the QRCode
*
* @param {String} sText link data
*/
QRCode.prototype.makeCode = function (sText) {
this._oQRCode = new QRCodeModel(_getTypeNumber(sText, this._htOption.correctLevel), this._htOption.correctLevel);
this._oQRCode.addData(sText);
this._oQRCode.make();
this._el.title = sText;
this._oDrawing.draw(this._oQRCode);
this.makeImage();
};
/**
* Make the Image from Canvas element
* - It occurs automatically
* - Android below 3 doesn't support Data-URI spec.
*
* @private
*/
QRCode.prototype.makeImage = function () {
if (typeof this._oDrawing.makeImage == "function" && (!this._android || this._android >= 3)) {
this._oDrawing.makeImage();
}
};
/**
* Clear the QRCode
*/
QRCode.prototype.clear = function () {
this._oDrawing.clear();
};
/**
* @name QRCode.CorrectLevel
*/
QRCode.CorrectLevel = QRErrorCorrectLevel;
})();
File diff suppressed because one or more lines are too long
+9 -1
View File
@@ -1,5 +1,13 @@
{
"version": 1,
"isRoot": true,
"tools": {}
"tools": {
"dotnet-ef": {
"version": "9.0.7",
"commands": [
"dotnet-ef"
],
"rollForward": false
}
}
}
+36 -4
View File
@@ -580,13 +580,44 @@ namespace GPW.CORE.Api.Data
#region Private Methods
/// <summary>
/// Esegue flush memoria redis dato pattern
/// Esegue flush memoria redis dato pat2Flush
/// </summary>
/// <param name="pattern"></param>
/// <param name="pat2Flush"></param>
/// <returns></returns>
private async Task<bool> ExecFlushRedisPattern(RedisValue pattern)
private async Task<bool> ExecFlushRedisPattern(RedisValue pat2Flush)
{
bool answ = false;
var masterEndpoint = redisConn.GetEndPoints()
.Where(ep => redisConn.GetServer(ep).IsConnected && !redisConn.GetServer(ep).IsReplica)
.FirstOrDefault();
// sepattern è "*" elimino intero DB...
if (masterEndpoint != null && (pat2Flush.Equals(new RedisValue("*")) || pat2Flush == RedisValue.Null))
{
redisConn.GetServer(masterEndpoint).FlushDatabase(database: redisDb.Database);
}
else
{
var server = redisConn.GetServer(masterEndpoint);
var keys = server.Keys(database: redisDb.Database, pattern: pat2Flush, pageSize: 1000);
var deleteTasks = new List<Task>();
foreach (var key in keys)
{
deleteTasks.Add(redisDb.KeyDeleteAsync(key));
if (deleteTasks.Count >= 1000)
{
await Task.WhenAll(deleteTasks);
deleteTasks.Clear();
}
}
if (deleteTasks.Count > 0)
{
await Task.WhenAll(deleteTasks);
}
}
answ = true;
#if false
var listEndpoints = redisConn.GetEndPoints();
foreach (var endPoint in listEndpoints)
{
@@ -601,7 +632,8 @@ namespace GPW.CORE.Api.Data
}
answ = true;
}
}
}
#endif
return answ;
}
+3 -3
View File
@@ -17,9 +17,9 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog.Web.AspNetCore" Version="5.4.0" />
<PackageReference Include="StackExchange.Redis" Version="2.8.24" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.7.3" />
<PackageReference Include="NLog.Web.AspNetCore" Version="6.1.2" />
<PackageReference Include="StackExchange.Redis" Version="2.8.37" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\GPW.CORE.Data\GPW.CORE.Data.csproj" />
@@ -23,6 +23,6 @@ by editing this MSBuild file. In order to learn more about this please visit htt
<EnableMsDeployAppOffline>True</EnableMsDeployAppOffline>
<UserName>jenkins</UserName>
<_SavePWD>True</_SavePWD>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
</Project>
@@ -23,6 +23,6 @@ by editing this MSBuild file. In order to learn more about this please visit htt
<EnableMsDeployAppOffline>True</EnableMsDeployAppOffline>
<UserName>jenkins</UserName>
<_SavePWD>True</_SavePWD>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
</Project>
@@ -23,6 +23,6 @@ by editing this MSBuild file. In order to learn more about this please visit htt
<EnableMsDeployAppOffline>True</EnableMsDeployAppOffline>
<UserName>jenkins</UserName>
<_SavePWD>True</_SavePWD>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
</Project>
@@ -23,6 +23,6 @@ by editing this MSBuild file. In order to learn more about this please visit htt
<EnableMsDeployAppOffline>True</EnableMsDeployAppOffline>
<UserName>jenkins</UserName>
<_SavePWD>True</_SavePWD>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
</Project>
+2 -2
View File
@@ -51,7 +51,7 @@
"AllowedHosts": "*",
"ConnectionStrings": {
"GPW.DB": "Server=W2019-SQL-STEAM; Database=GPW; User ID=UserGPW; Password=Us3rGpw!75x93$77; integrated security=False; MultipleActiveResultSets=True;App=LiMan.API; TrustServerCertificate=True;",
"Redis": "localhost:26379,serviceName=prod,DefaultDatabase=15,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,password=BtN9Py1wtLfLRvmzWnOPJ7RytDM+CLiVsJ/16zduNTlV8IOPGNrtzJSXPUnImA5PqmUMhKaUqo9NdHIG"
"Redis": "redis.ufficio:26379,serviceName=prod,DefaultDatabase=15,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,password=BtN9Py1wtLfLRvmzWnOPJ7RytDM+CLiVsJ/16zduNTlV8IOPGNrtzJSXPUnImA5PqmUMhKaUqo9NdHIG"
},
"ExternalProviders": {
"MailKit": {
@@ -59,7 +59,7 @@
"Address": "smtp.gmail.com",
"Port": "587",
"Account": "services@steamware.net",
"Password": "vpsad24068",
"Password": "ruejpcwgycvbmmsr",
"SenderEmail": "services@steamware.net",
"SenderName": "Steamware Email BOT"
}
+299 -12
View File
@@ -6,6 +6,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using NLog;
using System.Data;
namespace GPW.CORE.Data.Controllers
{
@@ -43,7 +44,7 @@ namespace GPW.CORE.Data.Controllers
}
catch (Exception exc)
{
Log.Error($"Errore in AnagClientiAll:{Environment.NewLine}{exc}");
Log.Error($"Errore in AnagClientiAllAsync:{Environment.NewLine}{exc}");
}
}
return dbResult;
@@ -1054,7 +1055,7 @@ namespace GPW.CORE.Data.Controllers
}
catch (Exception exc)
{
Log.Error($"Errore in AnagProjByCli:{Environment.NewLine}{exc}");
Log.Error($"Errore in AnagProjByCliAsync:{Environment.NewLine}{exc}");
}
}
return dbResult;
@@ -1337,7 +1338,7 @@ namespace GPW.CORE.Data.Controllers
}
catch (Exception exc)
{
Log.Error($"Errore in AnagTagFasiAll:{Environment.NewLine}{exc}");
Log.Error($"Errore in AnagTagFasiAllAsync:{Environment.NewLine}{exc}");
}
}
return dbResult;
@@ -2030,11 +2031,61 @@ namespace GPW.CORE.Data.Controllers
return answ;
}
/// <summary>
/// Ricalcola Tag Mensili dato dipendente, periodo, tag
/// </summary>
/// <param name="idxDipendente">IdxDipendente</param>
/// <param name="attivo">Stato attivo richiesto</param>
/// <returns></returns>
public bool DipUpdateActive(int idxDipendente, bool attivo)
{
// init dati necessari
bool fatto = false;
// cerco su DB recuperando set di dati....
using (GPWContext dbCtx = new GPWContext(_configuration))
{
try
{
var pAttivo = new SqlParameter("@attivo", attivo);
var pIdxDip = new SqlParameter("@Original_idxDipendente", idxDipendente);
var dbResult = dbCtx
.Database
.ExecuteSqlRaw("EXEC dbo.stp_AD_updateActive @attivo, @Original_idxDipendente", pAttivo, pIdxDip);
fatto = dbResult > 0;
}
catch (Exception exc)
{
Log.Error($"Errore in DipUpdateActive:{Environment.NewLine}{exc}");
}
}
return fatto;
}
public void Dispose()
{
Log.Info("Dispose di GPWController");
}
/// <summary>
/// Recupera Elenco Report x mostrare link
/// </summary>
/// <param name="Area">Se vuoto = tutti</param>
/// <returns></returns>
public List<ElencoReportModel> ElencoReportFilt(string Area)
{
List<ElencoReportModel> dbResult = new List<ElencoReportModel>();
using (GPWContext dbCtx = new GPWContext(_configuration))
{
DateTime oggi = DateTime.Today;
dbResult = dbCtx
.DbSetElencoReport
.Where(x => string.IsNullOrEmpty(Area) || x.Area == Area)
.ToList();
}
return dbResult;
}
/// <summary>
/// Esegue recupero dati in formato ExportCommessa
/// </summary>
@@ -2047,7 +2098,7 @@ namespace GPW.CORE.Data.Controllers
List<ExpCommessaModel> dbResult = new List<ExpCommessaModel>();
using (GPWContext dbCtx = new GPWContext(_configuration))
{
SqlParameter pIdxDip = new SqlParameter("@idxDipendente", idxDipendente);
SqlParameter pIdxDip = new SqlParameter("@idxRA", idxDipendente);
SqlParameter pInizio = new SqlParameter("@dataFrom", dtInizio);
SqlParameter pFine = new SqlParameter("@dataTo", dtFine);
@@ -2055,7 +2106,7 @@ namespace GPW.CORE.Data.Controllers
{
dbResult = dbCtx
.DbSetExpCommessa
.FromSqlRaw("EXEC stp_RA_pivot_getByIdxDipData @idxDipendente, @dataFrom, @dataTo", pIdxDip, pInizio, pFine)
.FromSqlRaw("EXEC stp_RA_pivot_getByIdxDipData @idxRA, @dataFrom, @dataTo", pIdxDip, pInizio, pFine)
.ToList();
}
catch (Exception exc)
@@ -2457,6 +2508,137 @@ namespace GPW.CORE.Data.Controllers
return done;
}
/// <summary>
/// Recupero dati dettaglio tag da stored dedicata
/// </summary>
/// <param name="idxDipendente"></param>
/// <param name="dataFrom"></param>
/// <param name="dataTo"></param>
/// <returns></returns>
public List<ListTagDDModel> ListTagDD(int idxDipendente, DateTime dataFrom, DateTime dataTo)
{
// init dati necessari
List<ListTagDDModel> dbResult = new List<ListTagDDModel>();
// cerco su DB recuperando set di dati....
using (GPWContext dbCtx = new GPWContext(_configuration))
{
try
{
var pidxDipendente = new SqlParameter("@idxRA", idxDipendente);
var pdataFrom = new SqlParameter("@dataFrom", dataFrom);
var pdataTo = new SqlParameter("@dataTo", dataTo);
dbResult = dbCtx
.DbSetListTagDD
.FromSqlRaw("EXEC dbo.stp_LTDD_ByUserDate @idxRA, @dataFrom, @dataTo", pidxDipendente, pdataFrom, pdataTo)
.ToList();
}
catch (Exception exc)
{
Log.Error($"Errore in ListTagDD:{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Toggle attiazione record da stored dedicata
/// </summary>
/// <param name="idxTagDD"></param>
/// <returns></returns>
public bool ListTagDDToggle(int idxTagDD)
{
bool answ = false;
// cerco su DB recuperando set di dati....
using (GPWContext dbCtx = new GPWContext(_configuration))
{
try
{
var pIdxTagDD = new SqlParameter("@IdxTagDD", idxTagDD);
var dbResult = dbCtx
.Database
.ExecuteSqlRaw("EXEC dbo.stp_LTDD_toggleActive @IdxTagDD", pIdxTagDD);
answ = dbResult > 0;
}
catch (Exception exc)
{
Log.Error($"Errore in ListTagDDToggle:{Environment.NewLine}{exc}");
}
}
return answ;
}
/// <summary>
/// Recupero dati month tag da stored dedicata
/// </summary>
/// <param name="idxDipendente"></param>
/// <param name="dataFrom"></param>
/// <param name="dataTo"></param>
/// <returns></returns>
public List<MonthTagModel> MonthTagList(int idxDipendente, DateTime dataFrom, DateTime dataTo)
{
// init dati necessari
List<MonthTagModel> dbResult = new List<MonthTagModel>();
// cerco su DB recuperando set di dati....
using (GPWContext dbCtx = new GPWContext(_configuration))
{
try
{
var pidxDipendente = new SqlParameter("@idxDipendente", idxDipendente);
var pdataFrom = new SqlParameter("@dataFrom", dataFrom);
var pdataTo = new SqlParameter("@dataTo", dataTo);
dbResult = dbCtx
.DbSetMonthTag
.FromSqlRaw("EXEC dbo.stp_LTM_ByUserDate @idxDipendente, @dataFrom, @dataTo", pidxDipendente, pdataFrom, pdataTo)
.ToList();
}
catch (Exception exc)
{
Log.Error($"Errore in MonthTagList:{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Ricalcola Tag Mensili dato dipendente, periodo, tag
/// </summary>
/// <param name="idxDipendente">IdxDipendente</param>
/// <param name="dataFrom">Inizio periodo ricalcolo</param>
/// <param name="dataTo">Fine periodo ricalcolo</param>
/// <param name="codTag">Cod TAG da ricalcolare</param>
/// <param name="minParam">Valore minimo parametri</param>
/// <returns></returns>
public bool MonthTagRecalc(int idxDipendente, DateTime dataFrom, DateTime dataTo, string codTag, int minParam)
{
// init dati necessari
bool fatto = false;
// cerco su DB recuperando set di dati....
using (GPWContext dbCtx = new GPWContext(_configuration))
{
try
{
var pCodTag = new SqlParameter("@CodTag", codTag);
var pIdxDipendente = new SqlParameter("@idxDipendente", idxDipendente);
var pDataFrom = new SqlParameter("@DtStart", dataFrom);
var pDataTo = new SqlParameter("@DtEnd", dataTo);
var pMinParam = new SqlParameter("@minParam", minParam);
var dbResult = dbCtx
.Database
.ExecuteSqlRaw("EXEC dbo.stp_LTDD_checkCreateByDipDate @CodTag, @idxDipendente, @DtStart, @DtEnd, @minParam", pCodTag, pIdxDipendente, pDataFrom, pDataTo, pMinParam);
fatto = dbResult > 0;
}
catch (Exception exc)
{
Log.Error($"Errore in MonthTagRecalc:{Environment.NewLine}{exc}");
}
}
return fatto;
}
/// <summary>
/// Elenco pareto progetti ordinati da filtro
/// </summary>
@@ -2503,6 +2685,47 @@ namespace GPW.CORE.Data.Controllers
return dbResult;
}
/// <summary>
/// Recupero dati delle attività filtrate x spostamento ore tra progetti
/// </summary>
/// <param name="idxDipendente"></param>
/// <param name="dataFrom"></param>
/// <param name="dataTo"></param>
/// <param name="idxCliente"></param>
/// <param name="idxProgetto"></param>
/// <param name="idxFase"></param>
/// <param name="isAncest"></param>
/// <returns></returns>
public List<RegAttivitaDayExplModel> RegAttDayExplList(int idxDipendente, DateTime dataFrom, DateTime dataTo, int idxCliente, int idxProgetto, int idxFase, bool isAncest)
{
// init dati necessari
List<RegAttivitaDayExplModel> dbResult = new List<RegAttivitaDayExplModel>();
// cerco su DB recuperando set di dati....
using (GPWContext dbCtx = new GPWContext(_configuration))
{
try
{
var pIdxDipendente = new SqlParameter("@idxRA", idxDipendente);
var pInizio = new SqlParameter("@dataFrom", dataFrom);
var pFine = new SqlParameter("@dataTo", dataTo);
var pIdxCliente = new SqlParameter("@idxCliente", idxCliente);
var pIdxProgetto = new SqlParameter("@idxProgetto", idxProgetto);
var pIdxFase = new SqlParameter("@idxFase", idxFase);
var pIsAncest = new SqlParameter("@soloAncest", isAncest);
dbResult = dbCtx
.DbSetDayRaExpl
.FromSqlRaw("EXEC dbo.stp_RAD_Expl_getByIdxDipPeriodo @idxRA, @dataFrom, @dataTo, @idxCliente, @idxProgetto, @idxFase, @soloAncest", pIdxDipendente, pInizio, pFine, pIdxCliente, pIdxProgetto, pIdxFase, pIsAncest)
.ToList();
}
catch (Exception exc)
{
Log.Error($"Errore in RegAttDayExplList:{Environment.NewLine}{exc}");
}
}
return dbResult;
}
public bool RegAttDelete(RegAttivitaModel currItem)
{
bool answ = false;
@@ -2598,13 +2821,13 @@ namespace GPW.CORE.Data.Controllers
{
try
{
var pIdxDip = new SqlParameter("@idxDipendente", IdxDip);
var pIdxDip = new SqlParameter("@idxRA", IdxDip);
var pDtStart = new SqlParameter("@inizio", DtStart);
var pDtEnd = new SqlParameter("@fine", DtEnd);
result = dbCtx
.Database
.ExecuteSqlRaw("EXEC stp_ricalcolaRegAttivitaExpl_byPeriodoUser @idxDipendente, @inizio, @fine", pIdxDip, pDtStart, pDtEnd);
.ExecuteSqlRaw("EXEC stp_ricalcolaRegAttivitaExpl_byPeriodoUser @idxRA, @inizio, @fine", pIdxDip, pDtStart, pDtEnd);
}
catch (Exception exc)
{
@@ -2668,6 +2891,37 @@ namespace GPW.CORE.Data.Controllers
return answ;
}
/// <summary>
/// Effettua spostamento di un record RA alla nuova fase indicata
/// </summary>
/// <param name="idxRA"></param>
/// <param name="idxFase"></param>
/// <returns></returns>
public bool RegAttUpdateFase(int idxRA, int idxFase)
{
// init dati necessari
bool answ = false;
// cerco su DB recuperando set di dati....
using (GPWContext dbCtx = new GPWContext(_configuration))
{
try
{
var pIdxRA = new SqlParameter("@Original_idxRA", idxRA);
var pIdxFase = new SqlParameter("@idxFase", idxFase);
var dbResult = dbCtx
.Database
.ExecuteSqlRaw("EXEC dbo.stp_RA_updateFase @idxFase, @Original_idxRA", pIdxFase, pIdxRA);
answ = dbResult > 0;
}
catch (Exception exc)
{
Log.Error($"Errore in RegAttUpdateFase:{Environment.NewLine}{exc}");
}
}
return answ;
}
/// <summary>
/// Recupera eventi dato criteri filtro
/// </summary>
@@ -3198,7 +3452,7 @@ namespace GPW.CORE.Data.Controllers
List<TeRaExplModel> dbResult = new List<TeRaExplModel>();
using (GPWContext dbCtx = new GPWContext(_configuration))
{
SqlParameter pIdxDip = new SqlParameter("@idxDipendente", IdxDip);
SqlParameter pIdxDip = new SqlParameter("@idxRA", IdxDip);
SqlParameter pDataFrom = new SqlParameter("@dataFrom", DtFrom);
SqlParameter pDataTo = new SqlParameter("@dataTo", DtTo);
SqlParameter pInatt = new SqlParameter("@showInattivi", ShowIn);
@@ -3208,7 +3462,7 @@ namespace GPW.CORE.Data.Controllers
dbResult = dbCtx
.DbSetTeRaExpl
.FromSqlRaw("EXEC stp_TE_RA_ByUserDate @idxDipendente, @dataFrom, @dataTo, @showInattivi, @showWE, @maxErrMin, @maxErrPlus", pIdxDip, pDataFrom, pDataTo, pInatt, pShowWE, pMaxErrMin, pMaxErrPlus)
.FromSqlRaw("EXEC stp_TE_RA_ByUserDate @idxRA, @dataFrom, @dataTo, @showInattivi, @showWE, @maxErrMin, @maxErrPlus", pIdxDip, pDataFrom, pDataTo, pInatt, pShowWE, pMaxErrMin, pMaxErrPlus)
.ToList();
}
return dbResult;
@@ -3283,13 +3537,13 @@ namespace GPW.CORE.Data.Controllers
{
try
{
var pIdxDip = new SqlParameter("@idxDipendente", IdxDip);
var pIdxDip = new SqlParameter("@idxRA", IdxDip);
var pDtStart = new SqlParameter("@inizio", DtStart);
var pDtEnd = new SqlParameter("@fine", DtEnd);
result = dbCtx
.Database
.ExecuteSqlRaw("EXEC stp_ricalcolaTimbExpl_byPeriodoUser @idxDipendente, @inizio, @fine", pIdxDip, pDtStart, pDtEnd);
.ExecuteSqlRaw("EXEC stp_ricalcolaTimbExpl_byPeriodoUser @idxRA, @inizio, @fine", pIdxDip, pDtStart, pDtEnd);
}
catch (Exception exc)
{
@@ -3299,6 +3553,39 @@ namespace GPW.CORE.Data.Controllers
return result != 0;
}
/// <summary>
/// Recupero dati di sunto delle timbrature mensili x dipendente da stored dedicata
/// </summary>
/// <param name="idxDipendente"></param>
/// <param name="dataFrom"></param>
/// <param name="dataTo"></param>
/// <returns></returns>
public List<TimbMeseExplModel> TimbMeseExplList(int idxDipendente, DateTime dataFrom, DateTime dataTo)
{
// init dati necessari
List<TimbMeseExplModel> dbResult = new List<TimbMeseExplModel>();
// cerco su DB recuperando set di dati....
using (GPWContext dbCtx = new GPWContext(_configuration))
{
try
{
var pidxDipendente = new SqlParameter("@idxRA", idxDipendente);
var pInizio = new SqlParameter("@inizio", dataFrom);
var pFine = new SqlParameter("@fine", dataTo);
dbResult = dbCtx
.DbSetTimbMeseExpl
.FromSqlRaw("EXEC dbo.stp_TimbMeseExpl @inizio, @fine, @idxRA", pInizio, pFine, pidxDipendente)
.ToList();
}
catch (Exception exc)
{
Log.Error($"Errore in TimbMeseExplList:{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Elenco timbrature successive alla data odierna x ogni dipendente (x recupero errori
/// timbrature future)
@@ -3453,7 +3740,6 @@ namespace GPW.CORE.Data.Controllers
.FirstOrDefault(x => x.IdxDipendente == currItem.IdxDipendente && x.DataOra == currItem.DataOra);
if (currRec != null)
{
// se non si tratta di una timbratura "last second"...
if (currItem.DataOra.Hour != 23 && currItem.DataOra.Minute != 59 && currItem.DataOra.Second != 59)
{
@@ -3493,6 +3779,7 @@ namespace GPW.CORE.Data.Controllers
}
return answ;
}
/// <summary>
/// Recupera l'elenco delle ultime attività inserite da un dipendente
/// </summary>
+16
View File
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GPW.CORE.Data.DTO
{
public class DatiReqResetDTO
{
public string Richiedente { get; set; } = "";
public string Email { get; set; } = "";
public string Telefono { get; set; } = "";
public string Causale { get; set; } = "";
}
}
+36
View File
@@ -0,0 +1,36 @@
using GPW.CORE.Data.DbModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GPW.CORE.Data.DTO
{
public class RegAttDayExpDTO : RegAttivitaDayExplModel
{
public RegAttDayExpDTO(RegAttivitaDayExplModel origRec)
{
this.CognomeNome=origRec.CognomeNome;
this.Descrizione=origRec.Descrizione;
this.Fine=origRec.Fine;
this.Inizio = origRec.Inizio;
this.RagSociale= origRec.RagSociale;
this.Gruppo=origRec.Gruppo;
this.NomeProj=origRec.NomeProj;
this.IdxProgetto=origRec.IdxProgetto;
this.IdxDipendente=origRec.IdxDipendente;
this.IdxRA=origRec.IdxRA;
this.IdxFase=origRec.IdxFase;
this.Importo=origRec.Importo;
this.MinTot=origRec.MinTot;
this.NomeFase=origRec.NomeFase;
this.OreTot=origRec.OreTot;
}
/// <summary>
/// Helper per selezione in tabella
/// </summary>
public bool Selected { get; set; } = false;
}
}
+29
View File
@@ -0,0 +1,29 @@
using GPW.CORE.Data.DbModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GPW.CORE.Data.DTO
{
public class TimbratureDTO : TimbratureModel
{
public TimbratureDTO(TimbratureModel origRec)
{
this.DataOra = origRec.DataOra;
this.IdxDipendente = origRec.IdxDipendente;
this.Entrata = origRec.Entrata;
this.Ipv4 = origRec.Ipv4;
this.CodTipoTimb = origRec.CodTipoTimb;
this.Approv = origRec.Approv;
this.DipNav = origRec.DipNav;
this.CodTipoTimbNav=origRec.CodTipoTimbNav;
}
/// <summary>
/// Helper per selezione in tabella
/// </summary>
public bool Selected { get; set; } = false;
}
}
+25
View File
@@ -31,6 +31,28 @@ namespace GPW.CORE.Data
#endregion Public Properties
#region Public Methods
/// <summary>
/// Calcolo Hash data stringa input
/// </summary>
/// <param name="rawData"></param>
/// <returns></returns>
public static string CalcHash(string rawData)
{
string hash = "";
// hashing!
using (var md5 = MD5.Create())
{
byte[] InputBytes = Encoding.UTF8.GetBytes(rawData);
var byteHash = md5.ComputeHash(InputBytes);
hash = BitConverter.ToString(byteHash).Replace("-", "").ToLowerInvariant();
}
return hash;
}
#endregion Public Methods
#region Private Fields
private DipendentiModel? rigaDip = null;
@@ -55,6 +77,8 @@ namespace GPW.CORE.Data
}
if (!string.IsNullOrEmpty(buffData))
{
hash = CalcHash(buffData);
#if false
// hashing!
using (var md5 = MD5.Create())
{
@@ -62,6 +86,7 @@ namespace GPW.CORE.Data
var byteHash = md5.ComputeHash(InputBytes);
hash = BitConverter.ToString(byteHash).Replace("-", "").ToLowerInvariant();
}
#endif
}
return hash;
}
+3 -1
View File
@@ -69,11 +69,13 @@ namespace GPW.CORE.Data.DbModels
[ForeignKey("CodOrario")]
public virtual AnagOrariModel? OrarioNav { get; set; }
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
if (!(obj is DipendentiModel item))
return false;
if (obj == null)
return false;
if (IdxDipendente != item.IdxDipendente)
return false;
if (AuthKey != item.AuthKey)
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace GPW.CORE.Data.DbModels
{
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
[Table("ElencoReport")]
public partial class ElencoReportModel
{
[Key]
public int IdxRep { get; set; } = 0;
public string Area { get; set; } = "";
[Column("nome")]
public string? Nome { get; set; } = "";
[Column("descrizione")]
public string? Descrizione { get; set; } = "";
[Column("cssClass")]
public string? CssClass { get; set; } = "";
public string ReportUrl { get; set; } = "";
}
}
+25
View File
@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
#nullable disable
namespace GPW.CORE.Data.DbModels
{
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
[Table("ListTagDD")]
public partial class ListTagDDModel
{
[Key]
public int IdxTagDD { get; set; } = 0;
public int IdxDipendente { get; set; } = 0;
public DateTime DtRif { get; set; } = DateTime.Today;
public string CodTag { get; set; } = "";
public bool isActive { get; set; } = true;
}
}
@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace GPW.CORE.Data.DbModels
{
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
public partial class RegAttivitaDayExplModel
{
[Key, Column("idxRA")]
public int IdxRA { get; set; } = 0;
[Column("idxDipendente")]
public int IdxDipendente { get; set; } = 0;
[Column("idxFase")]
public int IdxFase { get; set; } = 0;
[Column("idxProgetto")]
public int IdxProgetto { get; set; } = 0;
[Column("inizio")]
public DateTime Inizio { get; set; } = DateTime.Today;
[Column("fine")]
public DateTime Fine { get; set; } = DateTime.Today;
[Column("descrizione")]
public string Descrizione { get; set; } = "";
public string RagSociale { get; set; } = "";
[Column("nomeProj")]
public string NomeProj { get; set; } = "";
[Column("nomeFase")]
public string NomeFase { get; set; } = "";
[Column("cognomeNome")]
public string CognomeNome { get; set; } = "";
[Column("gruppo")]
public string Gruppo { get; set; } = "";
[Column("oreTot")]
public decimal OreTot { get; set; } = 0;
[Column("importo")]
public decimal Importo { get; set; } = 0;
[Column("minTot")]
public decimal MinTot { get; set; } = 0;
}
}
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
namespace GPW.CORE.Data.DbModels
{
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
// </Auto-Generated>
public partial class TimbMeseExplModel
{
public int Anno { get; set; } = 0;
public int Mese { get; set; } = 0;
public int IdxDipendente { get; set; } = 0;
//public string? CognomeNome { get; set; } = "";
public double totOreOrd { get; set; } = 0;
public double totOreFest { get; set; }= 0;
public double totOreDaLav { get; set; } = 0;
public double totOrePerm { get; set; }= 0;
public double totOreFer { get; set; } = 0;
public double totOreMal { get; set; }= 0;
public double totLav { get; set; } = 0;
public double totOreNonLav { get; set; } = 0;
public double totOreStra { get; set; } = 0;
public double totOreCassa { get; set; } = 0;
public double totOre104 { get; set; } = 0;
}
}
+1
View File
@@ -11,6 +11,7 @@ namespace GPW.CORE.Data
ND = 0,
Lavoro = 1
}
//public enum TestUser
//{
// LocatelliSamuele = 1,
+14 -11
View File
@@ -8,20 +8,23 @@
<PackageReference Include="Azure.Identity" Version="1.11.4" />
<PackageReference Include="Blazored.LocalStorage" Version="4.5.0" />
<PackageReference Include="Blazored.SessionStorage" Version="2.4.0" />
<PackageReference Include="EgwCoreLib.Utils" Version="1.5.2501.1716" />
<PackageReference Include="EgwCoreLib.Utils" Version="1.5.2511.312" />
<PackageReference Include="MailKit" Version="4.7.1.1" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.64.0" />
<PackageReference Include="NLog" Version="5.4.0" />
<PackageReference Include="RestSharp" Version="112.0.0" />
<PackageReference Include="StackExchange.Redis" Version="2.8.12" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.8" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.72.1" />
<PackageReference Include="NLog" Version="6.1.1" />
<PackageReference Include="RestSharp" Version="112.1.0" />
<PackageReference Include="StackExchange.Redis" Version="2.8.37" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="8.0.25" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.25" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.25" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.25" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.25">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="System.Security.Cryptography.Pkcs" Version="8.0.0" />
<PackageReference Include="System.Security.Cryptography.Pkcs" Version="8.0.1" />
<PackageReference Include="System.Text.Json" Version="8.0.5" />
</ItemGroup>
<ItemGroup>
+9 -3
View File
@@ -77,9 +77,10 @@ namespace GPW.CORE.Data
public virtual DbSet<ExpZucchettiModel> DbSetExpZucchetti { get; set; } = null!;
public virtual DbSet<ExpCommessaModel> DbSetExpCommessa { get; set; } = null!;
public virtual DbSet<MonthTagModel> DbSetMonthTag { get; set; } = null!;
public virtual DbSet<ListTagDDModel> DbSetListTagDD { get; set; } = null!;
public virtual DbSet<TimbMeseExplModel> DbSetTimbMeseExpl { get; set; } = null!;
public virtual DbSet<RegAttivitaDayExplModel> DbSetDayRaExpl { get; set; } = null!;
public virtual DbSet<ElencoReportModel> DbSetElencoReport { get; set; } = null!;
#endregion Public Properties
@@ -953,6 +954,11 @@ namespace GPW.CORE.Data
entity.HasKey(e => new { e.Anno, e.Mese, e.IdxDipendente });
});
modelBuilder.Entity<TimbMeseExplModel>(entity =>
{
entity.HasKey(e => new { e.Anno, e.Mese, e.IdxDipendente });
});
OnModelCreatingPartial(modelBuilder);
}
+12 -1
View File
@@ -48,6 +48,16 @@ namespace GPW.CORE.Data
CheckSumKey
}
/// <summary>
/// Tipologia di ticket
/// </summary>
public enum TipologiaTicket
{
ND = 0,
Licenze,
FileUpload
}
#endregion Public Enums
#region Public Classes
@@ -127,6 +137,7 @@ namespace GPW.CORE.Data
public string MasterKey { get; set; } = "";
public string ReqBody { get; set; } = "";
public TipologiaTicket Tipo { get; set; } = TipologiaTicket.ND;
#endregion Public Properties
}
@@ -217,4 +228,4 @@ namespace GPW.CORE.Data
#endregion Public Classes
}
}
}
+36 -4
View File
@@ -388,13 +388,44 @@ namespace GPW.CORE.Data.Services
#region Private Methods
/// <summary>
/// Esegue flush memoria redis dato pattern
/// Esegue flush memoria redis dato pat2Flush
/// </summary>
/// <param name="pattern"></param>
/// <param name="pat2Flush"></param>
/// <returns></returns>
private async Task<bool> ExecFlushRedisPattern(RedisValue pattern)
private async Task<bool> ExecFlushRedisPattern(RedisValue pat2Flush)
{
bool answ = false;
var masterEndpoint = redisConn.GetEndPoints()
.Where(ep => redisConn.GetServer(ep).IsConnected && !redisConn.GetServer(ep).IsReplica)
.FirstOrDefault();
// sepattern è "*" elimino intero DB...
if (masterEndpoint != null && (pat2Flush.Equals(new RedisValue("*")) || pat2Flush == RedisValue.Null))
{
redisConn.GetServer(masterEndpoint).FlushDatabase(database: redisDb.Database);
}
else
{
var server = redisConn.GetServer(masterEndpoint);
var keys = server.Keys(database: redisDb.Database, pattern: pat2Flush, pageSize: 1000);
var deleteTasks = new List<Task>();
foreach (var key in keys)
{
deleteTasks.Add(redisDb.KeyDeleteAsync(key));
if (deleteTasks.Count >= 1000)
{
await Task.WhenAll(deleteTasks);
deleteTasks.Clear();
}
}
if (deleteTasks.Count > 0)
{
await Task.WhenAll(deleteTasks);
}
}
answ = true;
#if false
var listEndpoints = redisConn.GetEndPoints();
foreach (var endPoint in listEndpoints)
{
@@ -409,7 +440,8 @@ namespace GPW.CORE.Data.Services
}
answ = true;
}
}
}
#endif
return answ;
}
File diff suppressed because it is too large Load Diff
+625 -21
View File
@@ -1,10 +1,13 @@
using GPW.CORE.Data.DbModels;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using NLog;
using RestSharp;
using StackExchange.Redis;
using System.Web;
using static GPW.CORE.Data.LiManObj;
using static System.Net.Mime.MediaTypeNames;
namespace GPW.CORE.Data.Services
{
@@ -44,6 +47,18 @@ namespace GPW.CORE.Data.Services
public string Applicazione { get; set; } = "";
public LiManObj.ApplicativoDTO AppLicense { get; set; } = new LiManObj.ApplicativoDTO();
public bool DoCheckLicOk
{
get
{
// verifico num dip attivi <= num licenze attive...
return true;
// verificare vecchia implementazione x check licenze (utenti attivi <= utenti licenza) + check payload (elenco hash utenti)
//return (licenzeGPW.checkLicenze && licenzeGPW.checkPayload);
}
}
public bool HasActivData
{
get
@@ -89,9 +104,27 @@ namespace GPW.CORE.Data.Services
}
public DateTime infoExpiry { get; set; } = DateTime.Today.AddDays(1);
public string Installazione { get; set; } = "";
public string MasterKey { get; set; } = "";
/// <summary>
/// Num licenze autorizzate dal DB
/// </summary>
public int NumLicDb
{
get
{
int answ = 0;
if (AKVList != null && AKVList.Count > 0)
{
answ = getAVKInt(Installazione);
}
return answ;
}
}
public bool ValidData
{
get
@@ -102,16 +135,6 @@ namespace GPW.CORE.Data.Services
}
}
public bool DoCheckLicOk
{
get
{
return true;
// verificare vecchia implementazione x check licenze (utenti attivi <= utenti licenza) + check payload (elenco hash utenti)
//return (licenzeGPW.checkLicenze && licenzeGPW.checkPayload);
}
}
#endregion Public Properties
#region Public Methods
@@ -150,6 +173,50 @@ namespace GPW.CORE.Data.Services
return await Task.FromResult(dbResult);
}
/// <summary>
/// Recupera DTO dati attivazione licenza dato codice impiego
/// </summary>
/// <param name="CodImpiego"></param>
/// <returns></returns>
public AttivazioneDTO? GetOnlineActivationInfo(string CodImpiego)
{
AttivazioneDTO? answ = null;
// cerco online
RestClient client = new RestClient(apiUrl);
//client.Authenticator = new HttpBasicAuthenticator("username", "password");
string MKeyEnc = HttpUtility.UrlEncode(MasterKey);
var request = new RestRequest($"/api/attivazioni/verifica?chiave={MKeyEnc}&CodImpiego={CodImpiego}");
var response = client.Get(request);
// controllo risposta
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
// verifico risposta
string rawData = $"{response.Content}";
if (!string.IsNullOrEmpty(rawData) && rawData.Length > 2)
{
try
{
// deserializzo
answ = JsonConvert.DeserializeObject<AttivazioneDTO>(rawData);
}
catch
{ }
}
}
return answ;
}
/// <summary>
/// Calcola HASH del codice impiego = payload utente
/// </summary>
/// <returns></returns>
public string HashDip(DipendentiModel recDip)
{
DataValidator cDV = new DataValidator(recDip);
string hash = cDV.HashDip;
return hash;
}
/// <summary>
/// Init della classe con variabili di base da Redis/DB
/// </summary>
@@ -179,7 +246,6 @@ namespace GPW.CORE.Data.Services
fatto = await setAppLicData(AppLicense, numDays);
}
}
await Task.Delay(1);
return fatto;
}
@@ -201,10 +267,45 @@ namespace GPW.CORE.Data.Services
fatto = await setActivList(onlineAct, numDays);
}
}
await Task.Delay(1);
return fatto;
}
/// <summary>
/// Effettua refresh Payload su server (Remoto) e recupera info licenza in locale (sovrascrivendo info locali Redis)
/// </summary>
/// <returns></returns>
public bool RefreshPayload()
{
bool answ = false;
// svuoto payload calcolato
ExecFlushRedisPattern((RedisValue)$"{rkeyPayload}:*");
// cerco online
RestClient client = new RestClient(apiUrl);
string MKeyEnc = HttpUtility.UrlEncode(MasterKey);
var request = new RestRequest($"/api/licenza/refreshPayload");
string newEnigma = DataValidator.CalcHash($"{DateTime.Now:yyyyMMddHHmmss}");
LicenseCoord newBody = new LicenseCoord()
{
MasterKey = MasterKey,
CodInst = Installazione,
CodApp = Applicazione,
Enigma = newEnigma
};
request.AddJsonBody(newBody);
var response = client.Post(request);
// controllo risposta
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
answ = true;
// salvo in redis contenuto serializzato
string rawData = $"{response.Content}";
// salvo in redis per 7 gg
setRSV(rKeyLic, rawData, TimeSpan.FromDays(7));
}
Log.Info($"Richiesta RefreshPayload eseguita");
return answ;
}
public async Task<bool> resetActivList()
{
await Task.Delay(1);
@@ -226,12 +327,89 @@ namespace GPW.CORE.Data.Services
return answ;
}
public void ResetLicenseData()
{
ExecFlushRedisPattern((RedisValue)$"{rKeyAttByLic}:*");
ExecFlushRedisPattern((RedisValue)$"{rKeyLic}:*");
ExecFlushRedisPattern((RedisValue)$"{rkeyPayload}:*");
ExecFlushRedisPattern((RedisValue)$"{rkeyTickets}:*");
}
public void ResetTicketCache()
{
ExecFlushRedisPattern((RedisValue)$"{rkeyTickets}:*");
// ricarico
var newList = getTickets();
}
/// <summary>
/// Tenta invio di un ticket x licenza indicata
/// </summary>
/// <param name="contName"></param>
/// <param name="contEmail"></param>
/// <param name="contPhone"></param>
/// <param name="reqBody"></param>
/// <param name="codImpiego"></param>
/// <param name="idxSubLic"></param>
/// <returns></returns>
public bool SendTicketReq(string contName, string contEmail, string contPhone, string reqBody, string codImpiego, int idxSubLic)
{
bool answ = false;
// cerco online
RestClient client = new RestClient(apiUrl);
string MKeyEnc = HttpUtility.UrlEncode(MasterKey);
var request = new RestRequest($"/api/ticket/sendReq");
SupportRequest richiesta = new SupportRequest()
{
ContactName = contName,
ContactEmail = contEmail,
ContactPhone = contPhone,
ReqBody = reqBody,
CodInst = Installazione,
CodApp = Applicazione,
MasterKey = MasterKey,
idxSubLic = idxSubLic,
CodImp = codImpiego,
Tipo = TipologiaTicket.Licenze
};
request.AddJsonBody(richiesta);
var response = client.Post(request);
// controllo risposta
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
// verifico risposta
string rawData = response.Content;
try
{
if (rawData.StartsWith("["))
{
// deserializzo
List<TicketDTO> tickets = JsonConvert.DeserializeObject<List<TicketDTO>>(rawData);
answ = tickets != null;
}
else
{
// deserializzo singolo
TicketDTO tickets = JsonConvert.DeserializeObject<TicketDTO>(rawData);
answ = tickets != null;
}
}
catch
{ }
}
Log.Info($"Richiesta SendTicketReq inviata | idxSub: {idxSubLic}");
return answ;
}
public async Task<bool> setActivList(List<LiManObj.AttivazioneDTO> newActList, int numDays)
{
bool fatto = false;
string rKey = $"{rKeyAttByLic}:{MasterKey}";
var rawData = JsonConvert.SerializeObject(newActList);
await setRSV(rKey, rawData, numDays * 24);
await setRSVAsync(rKey, rawData, numDays * 24);
fatto = true;
if (EA_InfoUpdated != null)
{
@@ -245,7 +423,7 @@ namespace GPW.CORE.Data.Services
bool fatto = false;
string cacheKey = $"{rKeyLic}:{MasterKey}";
var rawData = JsonConvert.SerializeObject(newAppDto);
await setRSV(cacheKey, rawData, numDays * 24);
await setRSVAsync(cacheKey, rawData, numDays * 24);
fatto = true;
if (EA_InfoUpdated != null)
{
@@ -254,6 +432,187 @@ namespace GPW.CORE.Data.Services
return fatto;
}
/// <summary>
/// Tenta attivazione licenza dato codice impiego
/// </summary>
/// <param name="CodImpiego"></param>
/// <returns></returns>
public bool TryActivation(string CodImpiego, string Chiave)
{
bool answ = false;
// cerco online
RestClient client = new RestClient(apiUrl);
//client.Authenticator = new HttpBasicAuthenticator("username", "password");
string MKeyEnc = HttpUtility.UrlEncode(MasterKey);
var request = new RestRequest($"/api/attivazioni");
Dictionary<string, string> parDict = new Dictionary<string, string>();
parDict.Add(CodImpiego, Chiave);
UserLicenseRequest newBody = new UserLicenseRequest()
{
MasterKey = MasterKey,
ParamDict = parDict
};
request.AddJsonBody(newBody);
var response = client.Post(request);
// controllo risposta
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
// verifico risposta
string rawData = $"{response.Content}";
try
{
// deserializzo
AttivazioneDTO datiAttivazione = JsonConvert.DeserializeObject<AttivazioneDTO>(rawData);
answ = datiAttivazione != null;
ResetLicenseData();
}
catch
{ }
}
Log.Info($"Richiesta tryActivation | CodImpiego: {CodImpiego}");
return answ;
}
/// <summary>
/// Tenta attivazione licenze dato dizionario codici impiego + chiavi
/// </summary>
/// <param name="ParamsList">Dizionario parametri attivazione di tipo (CodImpiego,Chiave)</param>
/// <returns></returns>
public async Task<bool> TryActivationMult(Dictionary<string, string> ParamsList)
{
bool answ = false;
// cerco online
RestClient client = new RestClient(apiUrl);
//client.Authenticator = new HttpBasicAuthenticator("username", "password");
string MKeyEnc = HttpUtility.UrlEncode(MasterKey);
var request = new RestRequest($"/api/attivazioni");
UserLicenseRequest newBody = new UserLicenseRequest()
{
MasterKey = MasterKey,
ParamDict = ParamsList
};
request.AddJsonBody(newBody);
var response = client.Post(request);
// controllo risposta
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
// verifico risposta
string rawData = $"{response.Content}";
try
{
if (rawData.Contains("["))
{
// deserializzo
List<AttivazioneDTO> datiAttivazione = JsonConvert.DeserializeObject<List<AttivazioneDTO>>(rawData);
answ = datiAttivazione != null;
}
else
{
// deserializzo singolo
AttivazioneDTO datiAttivazione = JsonConvert.DeserializeObject<AttivazioneDTO>(rawData);
answ = datiAttivazione != null;
ResetLicenseData();
await RefreshLicense();
}
}
catch
{ }
}
Log.Info($"Richiesta tryActivationMult | num params: {ParamsList.Count}");
return answ;
}
/// <summary>
/// Tenta refresh licenza dato codice impiego (aggiorna la authKey...)
/// </summary>
/// <param name="CodImpiego"></param>
/// <returns></returns>
public async Task<bool> TryRefreshActivation(string CodImpiego, string Chiave)
{
bool answ = false;
// cerco online
RestClient client = new RestClient(apiUrl);
//client.Authenticator = new HttpBasicAuthenticator("username", "password");
string MKeyEnc = HttpUtility.UrlEncode(MasterKey);
var request = new RestRequest($"/api/attivazioni/refreshKey");
Dictionary<string, string> parDict = new Dictionary<string, string>();
parDict.Add(CodImpiego, Chiave);
UserLicenseRequest newBody = new UserLicenseRequest()
{
MasterKey = MasterKey,
ParamDict = parDict
};
request.AddJsonBody(newBody);
var response = client.Post(request);
// controllo risposta
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
// verifico risposta
string rawData = $"{response.Content}";
try
{
if (rawData.Contains("["))
{
// deserializzo
List<AttivazioneDTO> datiAttivazione = JsonConvert.DeserializeObject<List<AttivazioneDTO>>(rawData);
answ = datiAttivazione != null;
}
else
{
// deserializzo singolo
AttivazioneDTO datiAttivazione = JsonConvert.DeserializeObject<AttivazioneDTO>(rawData);
answ = datiAttivazione != null;
ResetLicenseData();
await RefreshLicense();
}
}
catch
{ }
}
Log.Info($"Richiesta TryRefreshActivation | CodImpiego: {CodImpiego}");
return answ;
}
/// <summary>
/// Tenta rimozione licenza dato codice impiego
/// </summary>
/// <param name="CodImpiego"></param>
/// <returns></returns>
public async Task<bool> TryRemoveActivation(string CodImpiego, string Chiave)
{
bool answ = false;
// cerco online
RestClient client = new RestClient(apiUrl);
//client.Authenticator = new HttpBasicAuthenticator("username", "password");
string MKeyEnc = HttpUtility.UrlEncode(MasterKey);
var request = new RestRequest($"/api/attivazioni/removeKey");
Dictionary<string, string> parDict = new Dictionary<string, string>();
parDict.Add(CodImpiego, Chiave);
UserLicenseRequest newBody = new UserLicenseRequest()
{
MasterKey = MasterKey,
ParamDict = parDict
};
request.AddJsonBody(newBody);
var response = client.Post(request);
// controllo risposta
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
// verifico risposta
string rawData = $"{response.Content}";
try
{
bool.TryParse(rawData, out answ);
ResetLicenseData();
await RefreshLicense();
}
catch
{ }
}
Log.Info($"Richiesta TryRemoveActivation | CodImpiego: {CodImpiego} | answ: {answ}");
return answ;
}
#endregion Public Methods
#region Protected Fields
@@ -261,12 +620,22 @@ namespace GPW.CORE.Data.Services
/// <summary>
/// Chiave redis x attivazioni della licenza
/// </summary>
protected const string rKeyAttByLic = "LongCache:AttByLic";
protected const string rKeyAttByLic = "GPW.CORE:LongCache:AttByLic";
/// <summary>
/// Chiave redis x info licenza
/// </summary>
protected const string rKeyLic = "LongCache:LicData";
protected const string rKeyLic = "GPW.CORE:LongCache:LicData";
/// <summary>
/// Info payload
/// </summary>
protected const string rkeyPayload = "GPW.CORE:LongCache:Payload";
/// <summary>
/// Info tickets
/// </summary>
protected const string rkeyTickets = "GPW.CORE:LongCache:Tickets";
protected Random rnd = new Random();
@@ -274,6 +643,113 @@ namespace GPW.CORE.Data.Services
#region Protected Methods
/// <summary>
/// Verifica attivazione licenza dato codice impiego
/// </summary>
/// <param name="CodImpiego"></param>
/// <returns></returns>
protected async Task<bool> CheckActivation(string CodImpiego)
{
bool answ = false;
// cerco online
RestClient client = new RestClient(apiUrl);
//client.Authenticator = new HttpBasicAuthenticator("username", "password");
string MKeyEnc = HttpUtility.UrlEncode(MasterKey);
var request = new RestRequest($"/api/attivazioni/verifica?chiave={MKeyEnc}&CodImpiego={CodImpiego}");
var response = client.Get(request);
// controllo risposta
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
// verifico risposta
string rawData = $"{response.Content}";
try
{
// deserializzo
var datiAttivazione = JsonConvert.DeserializeObject<AttivazioneDTO>(rawData);
if (datiAttivazione != null)
{
answ = datiAttivazione != null && datiAttivazione.CodImpiego == CodImpiego;
}
}
catch
{ }
}
return await Task.FromResult(answ);
}
/// <summary>
/// Verifica attivazione licenza dato codice impiego
/// </summary>
/// <param name="CodImpiego"></param>
/// <returns></returns>
protected bool CheckActivationUnlocked(string CodImpiego)
{
bool answ = false;
// cerco online
RestClient client = new RestClient(apiUrl);
//client.Authenticator = new HttpBasicAuthenticator("username", "password");
string MKeyEnc = HttpUtility.UrlEncode(MasterKey);
var request = new RestRequest($"/api/attivazioni/verifica?chiave={MKeyEnc}&CodImpiego={CodImpiego}");
var response = client.Get(request);
// controllo risposta
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
// verifico risposta
string rawData = $"{response.Content}";
try
{
// deserializzo
var datiAttivazione = JsonConvert.DeserializeObject<AttivazioneDTO>(rawData);
if (datiAttivazione != null)
{
// verifico se il veto sia scaduto
answ = datiAttivazione.VetoUnlock <= DateTime.Today;
}
}
catch
{ }
}
return answ;
}
/// <summary>
/// Cerca di recuperare valore double da elenco AKV
/// </summary>
/// <param name="varReq">Chiave AKV richiesta</param>
/// <returns></returns>
protected double getAVKDouble(string varReq)
{
double answ = 0;
if (AKVList != null && AKVList.Count > 0)
{
var currRec = AKVList.Where(x => x.NomeVar == varReq).FirstOrDefault();
if (currRec != null)
{
answ = currRec.ValFloat ?? 0;
}
}
return answ;
}
/// <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 = 0;
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>
@@ -310,13 +786,41 @@ namespace GPW.CORE.Data.Services
}
/// <summary>
/// Salvataggio chiave in redis
/// Salvataggio chiave in Redis
/// </summary>
/// <param name="rKey"></param>
/// <param name="rVal"></param>
/// <param name="TTL"></param>
/// <returns></returns>
protected bool setRSV(string rKey, string rVal, TimeSpan TTL)
{
bool fatto = false;
fatto = redisDb.StringSet(rKey, rVal, TTL);
return fatto;
}
/// <summary>
/// Salvataggio chiave in Redis Async
/// </summary>
/// <param name="rKey"></param>
/// <param name="rVal"></param>
/// <param name="TTL"></param>
/// <returns></returns>
protected async Task<bool> setRSVAsync(string rKey, string rVal, TimeSpan TTL)
{
bool fatto = false;
fatto = await redisDb.StringSetAsync(rKey, rVal, TTL);
return fatto;
}
/// <summary>
/// Salvataggio chiave in Redis Async
/// </summary>
/// <param name="rKey"></param>
/// <param name="rVal"></param>
/// <param name="cacheMult"></param>
/// <returns></returns>
protected async Task<bool> setRSV(string rKey, string rVal, int cacheMult)
protected async Task<bool> setRSVAsync(string rKey, string rVal, int cacheMult)
{
bool fatto = false;
fatto = await redisDb.StringSetAsync(rKey, rVal, getCache(cacheMult));
@@ -324,15 +828,15 @@ namespace GPW.CORE.Data.Services
}
/// <summary>
/// Salvataggio chiave INT in redis
/// Salvataggio chiave INT in Redis Async
/// </summary>
/// <param name="rKey"></param>
/// <param name="rValInt"></param>
/// <param name="cacheMult"></param>
/// <returns></returns>
protected async Task<bool> setRSV(string rKey, int rValInt, int cacheMult)
protected async Task<bool> setRSVAsync(string rKey, int rValInt, int cacheMult)
{
return await setRSV(rKey, $"{rValInt}", cacheMult);
return await setRSVAsync(rKey, $"{rValInt}", cacheMult);
}
#endregion Protected Methods
@@ -363,6 +867,68 @@ namespace GPW.CORE.Data.Services
#region Private Methods
/// <summary>
/// Esegue flush memoria redis dato pat2Flush
/// </summary>
/// <param name="pat2Flush"></param>
/// <returns></returns>
private bool ExecFlushRedisPattern(RedisValue pat2Flush)
{
bool answ = false;
var masterEndpoint = redisConn.GetEndPoints()
.Where(ep => redisConn.GetServer(ep).IsConnected && !redisConn.GetServer(ep).IsReplica)
.FirstOrDefault();
// sepattern è "*" elimino intero DB...
if (masterEndpoint != null && (pat2Flush.Equals(new RedisValue("*")) || pat2Flush == RedisValue.Null))
{
redisConn.GetServer(masterEndpoint).FlushDatabase(database: redisDb.Database);
}
else
{
var server = redisConn.GetServer(masterEndpoint);
var keys = server.Keys(database: redisDb.Database, pattern: pat2Flush, pageSize: 1000);
var batch = new List<RedisKey>();
foreach (var key in keys)
{
batch.Add(key);
// Flush in batches of 1000
if (batch.Count >= 1000)
{
foreach (var item in batch)
redisDb.KeyDelete(item);
batch.Clear();
}
}
// Flush remaining keys
foreach (var item in batch)
redisDb.KeyDelete(item);
}
answ = true;
#if false
var listEndpoints = redisConn.GetEndPoints();
foreach (var endPoint in listEndpoints)
{
//var server = redisConnAdmin.GetServer(listEndpoints[0]);
var server = redisConn.GetServer(endPoint);
if (server != null)
{
var keyList = server.Keys(redisDb.Database, pattern);
foreach (var item in keyList)
{
redisDb.KeyDelete(item);
}
answ = true;
}
}
#endif
return answ;
}
/// <summary>
/// Durata cache da moltiplicatore (orario) + perturbazione percentuale (+/-10%)
/// </summary>
@@ -371,6 +937,44 @@ namespace GPW.CORE.Data.Services
return TimeSpan.FromHours((double)cacheMult * rnd.Next(900, 1100) / 1000);
}
/// <summary>
/// Recupera num ticket da sistema LiMan online
/// </summary>
/// <returns></returns>
private async Task<List<TicketDTO>> getTickets()
{
List<TicketDTO> answ = new List<TicketDTO>();
#if false
// cerco in cache locale...
string rawData = memLayer.ML.getRSV(rkeyTickets);
if (!string.IsNullOrEmpty(rawData))
{
answ = JsonConvert.DeserializeObject<List<TicketDTO>>(rawData);
}
// se vuoto rileggo
if (answ.Count == 0)
{
// cerco online
RestClient client = new RestClient(apiUrl);
//client.Authenticator = new HttpBasicAuthenticator("username", "password");
string MKeyEnc = HttpUtility.UrlEncode(MasterKey);
var request = new RestRequest($"/api/ticket/{installazione}?CodApp={applicazione}&Chiave={MKeyEnc}");
var response = client.Get(request);
// controllo risposta
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
// salvo in redis contenuto serializzato
rawData = response.Content;
// deserializzo
answ = JsonConvert.DeserializeObject<List<TicketDTO>>(rawData);
// salvo in redis per TTL std
memLayer.ML.setRSV(rkeyTickets, rawData, 20);
}
}
#endif
return answ;
}
/// <summary>
/// Elenco attivazioni attuali
/// </summary>
+1 -1
View File
@@ -7,7 +7,7 @@
}
},
"ConnectionStrings": {
"Redis": "localhost:26379,serviceName=prod,DefaultDatabase=15,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false,password=BtN9Py1wtLfLRvmzWnOPJ7RytDM+CLiVsJ/16zduNTlV8IOPGNrtzJSXPUnImA5PqmUMhKaUqo9NdHIG",
"Redis": "redis.ufficio:26379,serviceName=prod,DefaultDatabase=15,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false,password=BtN9Py1wtLfLRvmzWnOPJ7RytDM+CLiVsJ/16zduNTlV8IOPGNrtzJSXPUnImA5PqmUMhKaUqo9NdHIG",
"GPW.DB": "Server=W2019-SQL-STEAM;Database=GPW; User ID=UserGPW; Password=Us3rGpw!75x93$77; integrated security=False; MultipleActiveResultSets=True; App=GPW.CORE.WRKLOG; TrustServerCertificate=True;"
},
"MailDest": {
+4 -4
View File
@@ -60,11 +60,11 @@
"ExternalProviders": {
"MailKit": {
"SMTP": {
"Address": "smtp-mail.outlook.com",
"Address": "smtp.gmail.com",
"Port": "587",
"Account": "steamwarebot@outlook.it",
"Password": "siamoInViaNazionale93!",
"SenderEmail": "steamwarebot@outlook.it",
"Account": "services@steamware.net",
"Password": "ruejpcwgycvbmmsr",
"SenderEmail": "services@steamware.net",
"SenderName": "Steamware Email BOT"
}
}
+12 -2
View File
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.4.33205.214
# Visual Studio Version 18
VisualStudioVersion = 18.4.11605.240
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GPW.CORE.Data", "GPW.CORE.Data\GPW.CORE.Data.csproj", "{32DE3E46-CCED-4F7E-8EC1-A854DA4F51C1}"
EndProject
@@ -11,6 +11,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GPW.CORE.Smart8.Client", "G
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GPW.CORE", "GPW.CORE\GPW.CORE.csproj", "{98EF4DDB-F268-40C1-BACF-13BCFF41F19D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GPW.CORE.Smart8.Shared", "GPW.CORE.Smart8.Shared\GPW.CORE.Smart8.Shared.csproj", "{F3D5D10F-22CC-414F-B86F-37A926112D79}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -33,6 +35,14 @@ Global
{98EF4DDB-F268-40C1-BACF-13BCFF41F19D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{98EF4DDB-F268-40C1-BACF-13BCFF41F19D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{98EF4DDB-F268-40C1-BACF-13BCFF41F19D}.Release|Any CPU.Build.0 = Release|Any CPU
{F3D5D10F-22CC-414F-B86F-37A926112D79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F3D5D10F-22CC-414F-B86F-37A926112D79}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F3D5D10F-22CC-414F-B86F-37A926112D79}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F3D5D10F-22CC-414F-B86F-37A926112D79}.Release|Any CPU.Build.0 = Release|Any CPU
{0E8C2F3B-C5D0-84BB-3C55-3212282C5BF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0E8C2F3B-C5D0-84BB-3C55-3212282C5BF3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0E8C2F3B-C5D0-84BB-3C55-3212282C5BF3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0E8C2F3B-C5D0-84BB-3C55-3212282C5BF3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
+26
View File
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>
<!--<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>-->
<ItemGroup>
<!-- API Blazor necessarie per ComponentBase, InvokeAsync, StateHasChanged -->
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="8.0.25" />
<PackageReference Include="NLog" Version="6.1.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\GPW.CORE\GPW.CORE.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Smart\Pages\" />
<Folder Include="Smart\Timbra\" />
<Folder Include="Smart\Admin\" />
</ItemGroup>
</Project>
@@ -0,0 +1,139 @@
using GPW.CORE.Services;
using Microsoft.AspNetCore.Components;
namespace GPW.CORE.Shared.Smart.Common
{
public partial class CmpTop : IDisposable
{
#region Public Properties
[Parameter]
public ConfigDTO CurrConf { get; set; } = null!;
[Parameter]
public UserDTO? CurrUser { get; set; } = null;
[Parameter]
public EventCallback<bool> EC_ForceReset { get; set; }
[Parameter]
public EventCallback<bool> EC_ReturnHome { get; set; }
[Parameter]
public bool IpIsLocal { get; set; } = false;
[Parameter]
public string LocalNet { get; set; } = "###";
#endregion Public Properties
[Inject]
private UserStateService UState { get; set; } = null!;
#if false
[Inject]
private MessageService MService { get; set; } = null!;
#endif
#region Public Methods
public void Dispose()
{
if (_subscribed)
{
UState.OnChange -= UState_OnChange;
_subscribed = false;
}
GC.Collect();
}
#endregion Public Methods
protected override async Task OnParametersSetAsync()
{
await Task.Delay(10);
//await InvokeAsync(StateHasChanged);
//return base.OnParametersSetAsync();
// verifico isLocal...
if (!string.IsNullOrEmpty(LocalNet))
{
}
}
private string currIpv4 = "";
private bool _subscribed = false;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
//if (firstRender)
//{
// // iscriviti qui nell'istanza client
// UState.OnChange += UState_OnChange;
// _subscribed = true;
//}
if (!_subscribed)
{
_subscribed = true;
UState.OnChange += UState_OnChange;
}
if (CurrUser == null)
{
if (UState.CurrentUser != null)
{
CurrUser = UState.CurrentUser;
//await InvokeAsync(StateHasChanged);
}
}
//await base.OnAfterRenderAsync(firstRender);
}
private void UState_OnChange()
{
// siamo in un callback non-UI thread: usa InvokeAsync
_ = InvokeAsync(() =>
{
CurrUser = UState.CurrentUser;
StateHasChanged();
});
}
#region Protected Properties
protected string currDip
{
get => CurrUser != null ? CurrUser.DisplayName : "N.A. [0]";
}
protected string homeCss
{
get => IpIsLocal ? "text-light" : "text-danger";
}
protected string homeMessage
{
get => IpIsLocal ? "INT" : "EXT";
}
[Inject]
protected NavigationManager NavMan { get; set; } = null!;
protected string Nome { get; set; } = "";
#endregion Protected Properties
#region Protected Methods
protected async Task ForceReset()
{
await EC_ForceReset.InvokeAsync(true);
}
protected async Task ReturnHome()
{
await EC_ReturnHome.InvokeAsync(true);
}
#endregion Protected Methods
}
}
@@ -15,7 +15,7 @@
.username {
color: #ffffff;
padding-top: 10px;
/*padding-top: 10px;*/
font-size: 1.1rem;
}
@@ -0,0 +1,66 @@
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.JSInterop
@implements IDisposable
@inject IJSRuntime JS
<div style="padding:1rem; border:1px solid #ccc; border-radius:8px; max-width:350px;">
<h4>Execution Context Test</h4>
<p>
<strong>Context:</strong>
<span style="color:@(IsWasm ? "green" : "blue")">
@(IsWasm ? "WASM (Client)" : "Server")
</span>
</p>
<p>
<strong>Time:</strong> @CurrentTime.ToLongTimeString()
</p>
<button class="btn btn-primary btn-sm" @onclick="DoClick">Test Me</button>
<p>@lblOut</p>
</div>
@code {
bool IsWasm;
DateTime CurrentTime = DateTime.Now;
private CancellationTokenSource? _cts;
private string lblOut = "";
protected override void OnInitialized()
{
IsWasm = OperatingSystem.IsBrowser();
_cts = new CancellationTokenSource();
// avvia loop asincrono che funziona sia in server che in WASM
_ = TimeLoopAsync(_cts.Token);
}
private async Task TimeLoopAsync(CancellationToken token)
{
try
{
while (!token.IsCancellationRequested)
{
CurrentTime = DateTime.Now;
await InvokeAsync(StateHasChanged);
await Task.Delay(1000, token);
}
}
catch (TaskCanceledException) { }
}
private Task DoClick()
{
lblOut = $"Clicked | {DateTime.Now:HH:mm:ss}";
// log su console browser se siamo in WASM
if (IsWasm)
_ = JS.InvokeVoidAsync("console.log", $"ExecutionContextTest DoClick at {DateTime.Now}");
return Task.CompletedTask;
}
public void Dispose()
{
_cts?.Cancel();
_cts?.Dispose();
}
}
@@ -0,0 +1,60 @@
@using Microsoft.AspNetCore.Components.Routing
@using GPW.CORE.Services
@inject NavigationManager Nav
@inject RouteModeService RouteModeSvc
<a href="@Href" class="nav-link @CssClass" @onclick="OnClick" @onclick:preventDefault="true">
@ChildContent
</a>
@code {
[Parameter] public string Href { get; set; } = string.Empty;
[Parameter] public RenderFragment? ChildContent { get; set; }
[Parameter] public NavLinkMatch Match { get; set; } = NavLinkMatch.Prefix;
[Parameter] public bool ServerOnly { get; set; } = false;
[Parameter] public bool ClientOnly { get; set; } = false;
// Utility per active class
private string CssClass
{
get
{
var baseClass = ""; // puoi passare classi esterne concatenandole se vuoi
if (IsActive()) baseClass = string.IsNullOrEmpty(baseClass) ? "active" : $"{baseClass} active";
return baseClass;
}
}
protected override void OnInitialized()
{
var mode = ServerOnly ? RouteMode.ServerOnly : (ClientOnly ? RouteMode.ClientOnly : RouteMode.Hybrid);
RouteModeSvc.SetMode(Href, mode);
}
private bool IsActive()
{
var absoluteHref = Nav.ToAbsoluteUri(Href).AbsoluteUri;
var current = Nav.Uri;
if (Match == NavLinkMatch.All)
return string.Equals(current.TrimEnd('/'), absoluteHref.TrimEnd('/'), StringComparison.OrdinalIgnoreCase);
return current.StartsWith(absoluteHref, StringComparison.OrdinalIgnoreCase);
}
private void OnClick()
{
if (ServerOnly && OperatingSystem.IsBrowser())
{
Nav.NavigateTo(Href, forceLoad: true);
return;
}
if (ClientOnly && !OperatingSystem.IsBrowser())
{
Nav.NavigateTo(Href, forceLoad: true);
return;
}
// Navigazione client-side normale
Nav.NavigateTo(Href);
}
}

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