Compare commits
605 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2f7337348e | |||
| 7f88624935 | |||
| dacd3b9bcd | |||
| 596449f259 | |||
| e149445529 | |||
| 178d7a3ef0 | |||
| 53d505006a | |||
| 53e1abd2c0 | |||
| 321b7a3a6f | |||
| 2e54c8b164 | |||
| 8c978f68c2 | |||
| 781c570a3d | |||
| de2a8cb6a5 | |||
| 63e92f0c83 | |||
| 73a28e33b4 | |||
| f4d2265de2 | |||
| b40764c2bc | |||
| 0333154935 | |||
| fc19fb563e | |||
| fd6a0512ba | |||
| 7c4ae1f7dc | |||
| b9c2418532 | |||
| 50a6848f25 | |||
| 6e1b60cc71 | |||
| 23a3985251 | |||
| 274d58ab68 | |||
| 14637860e0 | |||
| fe0545084a | |||
| e37b5050e2 | |||
| fc3a6a70da | |||
| 9837f276d7 | |||
| 865aa0afab | |||
| ef2bd7c5d5 | |||
| 3c92333f0e | |||
| 190b7a10b7 | |||
| 7a89709a29 | |||
| 3777090416 | |||
| 16d13748c9 | |||
| 5a46df0f19 | |||
| d3ff540382 | |||
| 15fcbd57b9 | |||
| 07ac5aa9a5 | |||
| 488ca47e50 | |||
| b8af310248 | |||
| dbfc7fddc4 | |||
| e6196db490 | |||
| 00e4a0158e | |||
| 838e0f6957 | |||
| b955c6e38e | |||
| 51eb178934 | |||
| bd6ef3d0ae | |||
| 6e13ebe8a9 | |||
| 25656f5eec | |||
| bc260f5de5 | |||
| 26507ae5bf | |||
| f3fb081103 | |||
| 3930a9e8dc | |||
| 09d1f42934 | |||
| 394d924d1e | |||
| d2ad286f0f | |||
| 4e1e958db0 | |||
| de09175f28 | |||
| 2d009a76d8 | |||
| 533452776d | |||
| 209fe7aa6c | |||
| da214155c0 | |||
| d36b60dc17 | |||
| 8527b91e6c | |||
| d345e84279 | |||
| 8bf47bb03b | |||
| f1068e3f42 | |||
| c9c69f535a | |||
| baecdd9c32 | |||
| 56f0d36570 | |||
| aa7ef25da9 | |||
| 75340443a2 | |||
| 1eafdee5af | |||
| f9ea6f5721 | |||
| 3e363588e7 | |||
| 94d2d46919 | |||
| e6065535b4 | |||
| 26110c9885 | |||
| 38a9d7be73 | |||
| b69ca54dcc | |||
| bd1c955f72 | |||
| a4947a95cd | |||
| 4b7f560e5a | |||
| 69174bdb71 | |||
| f10fbffaf5 | |||
| 8c5fa25801 | |||
| e53daaf6a7 | |||
| 6e44e7cb56 | |||
| e2dccac335 | |||
| 27876c6530 | |||
| 4c10c121e3 | |||
| 0300ce6eac | |||
| 28ce9a3a1c | |||
| fc9cb8d67a | |||
| 7d9d3ccbef | |||
| 1dd4b4ae30 | |||
| a5646aeabb | |||
| 00ed8fbf17 | |||
| 1948fee63a | |||
| ba0c0af831 | |||
| d2504e4fb6 | |||
| 5c674bf62d | |||
| 7425be3e2a | |||
| 8cd48454a1 | |||
| f35edfb9db | |||
| 402442b8d2 | |||
| 10465fc7f3 | |||
| 9a87d67b3d | |||
| 473ce70f9a | |||
| 417fbe31c1 | |||
| 07e4ee2de1 | |||
| 34db49f776 | |||
| d7239dbf85 | |||
| 0ad217bc54 | |||
| 9f23e69505 | |||
| 58df987e47 | |||
| ae615bf8d6 | |||
| 6e956330ea | |||
| b75f501290 | |||
| 69c8b7c97a | |||
| 09a988ede9 | |||
| 63943fa46d | |||
| 762129bdd4 | |||
| 3cf826c048 | |||
| aa0b0f92e4 | |||
| 10fc218d8b | |||
| a700a8752c | |||
| 105cf4b756 | |||
| d46a0b731e | |||
| b0df9f97b4 | |||
| 46c8023ab4 | |||
| 93c1b3b189 | |||
| 9e66214f66 | |||
| a4df2bba0d | |||
| 705f2efd10 | |||
| 22f49241e4 | |||
| c043486f82 | |||
| 5c30b30a27 | |||
| 3dc74caa98 | |||
| 384db1cdd0 | |||
| 62b6c3a04d | |||
| fa716e9f2f | |||
| 476487b3c0 | |||
| 8899289d29 | |||
| d8a0f5c453 | |||
| 4434cff466 | |||
| 87c42e0910 | |||
| 34df9c59fb | |||
| 1daeb227ea | |||
| cac3f95895 | |||
| 6a169705e6 | |||
| 584177e5c6 | |||
| 44ca4a4fd6 | |||
| ead97b6863 | |||
| 5806f0619e | |||
| 204ecb47b7 | |||
| 388aa0cd65 | |||
| f10c0d19c7 | |||
| 9f105dd244 | |||
| 59e2622e58 | |||
| 614ebcf818 | |||
| b428ef59da | |||
| b4d2218f79 | |||
| ad6d4e9875 | |||
| 6530664616 | |||
| ba0dc30c42 | |||
| 8d9f106a9a | |||
| f408c0e9d6 | |||
| 81ad753268 | |||
| ed6bfd3b05 | |||
| 2b7346063a | |||
| fa33bc9753 | |||
| fff73423c2 | |||
| 0d159e76cc | |||
| 7e7393f42c | |||
| 1d8a64fb2a | |||
| c766ffeda3 | |||
| 86ded42bae | |||
| 9c6733546f | |||
| 201e092b21 | |||
| be122e6845 | |||
| 512494aa38 | |||
| 1eb2d54235 | |||
| de556ab2a8 | |||
| 564a87e177 | |||
| 140711eb39 | |||
| eb280b9556 | |||
| 5341eae5ca | |||
| 2cd3882808 | |||
| 10819e97f0 | |||
| 3ed1921d3d | |||
| 9ae0daa69e | |||
| f776112e5b | |||
| de9fc59637 | |||
| 5e75d12a79 | |||
| 2fab9ede6e | |||
| 7e1d1e464c | |||
| d548f0537c | |||
| b91b473dbe | |||
| 98a3f50771 | |||
| 551991bc95 | |||
| e561ccb2a7 | |||
| 9f3eb7dde0 | |||
| 2a31fb9dcf | |||
| bdaaefb076 | |||
| 74cde6035f | |||
| 2507a9e35e | |||
| d37766b3a3 | |||
| 3de47b92f2 | |||
| 81f9f4971e | |||
| 7e3fc3e8f5 | |||
| 1e0486e7b5 | |||
| be357ff225 | |||
| 8fff35405a | |||
| f7b482d36c | |||
| a719be6195 | |||
| efeca5935d | |||
| 6510fce274 | |||
| a0f30be0e3 | |||
| 91a956ae60 | |||
| 9d62995a70 | |||
| 8b85b4a2f8 | |||
| 619932b4c1 | |||
| b8429b1867 | |||
| 88a260e88f | |||
| 3dd5843ee5 | |||
| fd210e82d7 | |||
| 195ed3c157 | |||
| fb72e45e44 | |||
| 4c1d7d7056 | |||
| d6b8d47dc7 | |||
| 157fc77650 | |||
| acd88fd0a4 | |||
| c2523ff0bc | |||
| c5d897919d | |||
| 03ede3a967 | |||
| 19f34abbec | |||
| 8b20f36c1b | |||
| 262d237f12 | |||
| 3781031973 | |||
| ce2e409704 | |||
| 8fa92198f9 | |||
| 6a446c03e3 | |||
| 81c7008771 | |||
| b1a8db2882 | |||
| f64a7d3f3d | |||
| 1580c939dd | |||
| 899903aa5b | |||
| 8516049343 | |||
| 7a13e99d69 | |||
| f0d5c2a94a | |||
| ec37691dff | |||
| 7c2033d1de | |||
| 8f403c0dee | |||
| 88b7f4b9b9 | |||
| a45d6bcf6b | |||
| a115517dde | |||
| 26c21e48b3 | |||
| fc83cbf7ec | |||
| 94837e953e | |||
| 47a655c820 | |||
| 7fa1dbce3b | |||
| f16541a066 | |||
| f69c70b3b7 | |||
| 4a1fbe591e | |||
| 15a0bd295c | |||
| af3d49cf4e | |||
| 9b90a1b3ca | |||
| 3feea9e514 | |||
| ce5d50209e | |||
| 9e7c7dea40 | |||
| 3476cd79a4 | |||
| 6f7f676b01 | |||
| c3ea2126aa | |||
| 591aada1e0 | |||
| 98df74fa0d | |||
| 8dfdb68a6a | |||
| 8f08d6457c | |||
| 9b96f7134b | |||
| 520eb04d30 | |||
| cc308c05df | |||
| 6ee87f4bce | |||
| 131fb6ae15 | |||
| a78609b96d | |||
| fbd70decf5 | |||
| 84e4c086f4 | |||
| 5b695ea7c5 | |||
| f2befdd90d | |||
| eaf63a3c72 | |||
| 348cb21b0a | |||
| 137f8d601f | |||
| 9cc350da0c | |||
| 40e666fa1b | |||
| c129b9640c | |||
| af65a73e27 | |||
| c1d1c9746c | |||
| dd8e5272a3 | |||
| 65b22cbc65 | |||
| 5f859bb317 | |||
| 60fd732a8c | |||
| f345d804ab | |||
| f2e1d867e9 | |||
| 1789e9f40a | |||
| 537793cb8f | |||
| a750376dba | |||
| a9798bd366 | |||
| fc430a40af | |||
| 16e3a2d992 | |||
| 64701ff758 | |||
| ba89ff0726 | |||
| 708a907c05 | |||
| c18ebd0f89 | |||
| 8ff9385b67 | |||
| eb6652699a | |||
| 220aaf21c0 | |||
| 19beb952bb | |||
| 9a4bc648ee | |||
| 085540092a | |||
| 5e45bd2a69 | |||
| e48481bdc0 | |||
| 4428eed168 | |||
| 892603b956 | |||
| 4c9b662e4c | |||
| 7a6f08343c | |||
| 11ddd5ae79 | |||
| 1fb4795549 | |||
| 818396c6d8 | |||
| a3146a61cf | |||
| bda16699ab | |||
| 21b32386d7 | |||
| de448e95fc | |||
| 18d20707c0 | |||
| cc60712fd2 | |||
| aa236cfb5c | |||
| 44125ad79d | |||
| 5a751ff4af | |||
| fe2d31cfc5 | |||
| fa55eba725 | |||
| 18d48ecaae | |||
| 5c9098e072 | |||
| a01153771b | |||
| eae9f8f287 | |||
| 1a8753abea | |||
| fb413892a3 | |||
| 59560f927a | |||
| b1c02d1483 | |||
| d77d1603bc | |||
| 6b70c4be1d | |||
| f3fa19f96c | |||
| 13c09b4341 | |||
| 26cf47f6c7 | |||
| 8e79305eac | |||
| d88b0fac6f | |||
| 8d3a69afc1 | |||
| b00f5f26a6 | |||
| 492d6fa9f4 | |||
| df3f5e5625 | |||
| 2b48f19f92 | |||
| 223607f649 | |||
| 226459c819 | |||
| c50452f441 | |||
| 7cb2ad724c | |||
| 742bda00c1 | |||
| b8073b5a73 | |||
| 5be8e2735e | |||
| 6458f63c4a | |||
| 1c9d19daf9 | |||
| f332efba77 | |||
| 74b4c06f75 | |||
| 605c68d3d5 | |||
| 5166c4bc5e | |||
| 54d9dade4b | |||
| 83ab057286 | |||
| a197d61ddb | |||
| 074eaf343d | |||
| d85ede57c1 | |||
| 1162160350 | |||
| e72e975754 | |||
| 5cfc4bb865 | |||
| 5dcbe3ed46 | |||
| 3e2160d64d | |||
| e417edf727 | |||
| 3b862aa03f | |||
| 09581bd653 | |||
| 44acbb9360 | |||
| 3bffd2b78c | |||
| 52c73973e6 | |||
| 80e4590abe | |||
| b1d0bbf780 | |||
| 8051a1adb3 | |||
| b4562b6c83 | |||
| 80febcc6cb | |||
| 18b4c113d1 | |||
| 1a324a1cd9 | |||
| f4e02e6f6f | |||
| 11702db3e5 | |||
| b8d4bd1a65 | |||
| 26a97ed6ec | |||
| c33927fd93 | |||
| f73891da9e | |||
| 9a2f0a2fb8 | |||
| 59092a472b | |||
| 3d24578a3b | |||
| ff0b84042c | |||
| b43d849f3e | |||
| 9b382867f6 | |||
| e694553f89 | |||
| ce30ca1eba | |||
| b604046a2c | |||
| 7713465e00 | |||
| b549ef07a4 | |||
| 206f5e9bc4 | |||
| a6b8eeff5d | |||
| ee36394b3d | |||
| 3dd6ac1018 | |||
| 5a62abbdb0 | |||
| 6cb0544754 | |||
| a83ff37995 | |||
| 259679c178 | |||
| ce176cd47e | |||
| a781bbf6ff | |||
| 84d40f830c | |||
| 4902065f0a | |||
| ccc02a48b3 | |||
| f5c764eafb | |||
| a9ac7f284f | |||
| baa6a84ad5 | |||
| e2778a51ec | |||
| a0c831af95 | |||
| 37ae849c93 | |||
| 062b3fa556 | |||
| cea53a124c | |||
| 796679f91b | |||
| bf9241aacb | |||
| a18011e45d | |||
| a2154c0b84 | |||
| 5f06c38bf5 | |||
| 4307e6fe42 | |||
| ad8fbf4852 | |||
| 0e71534de7 | |||
| 3705bf6e5f | |||
| 6a4dff3386 | |||
| 41f65df85d | |||
| c460b5fb77 | |||
| 88ab08e4b8 | |||
| e39e62e4cc | |||
| 495885a2be | |||
| ac26e1fc37 | |||
| 9c089aad42 | |||
| 9843c061e6 | |||
| df91add2f3 | |||
| 96c430abd3 | |||
| 23caf99c91 | |||
| 3f94ad59de | |||
| 28296cb22a | |||
| f482e53a84 | |||
| 821b82d242 | |||
| 235a074147 | |||
| 9781967c4a | |||
| 6789a29661 | |||
| 1afd110487 | |||
| 22e2141cf3 | |||
| 896d2fbb12 | |||
| 2dc27d3917 | |||
| 231fb1209b | |||
| 5d31b10f75 | |||
| eb37fa4d0d | |||
| 35d7fea84b | |||
| 319680a974 | |||
| dfa0806326 | |||
| 5d635662c8 | |||
| 1b88196574 | |||
| 8fd0c430f9 | |||
| b8ea6f5c7a | |||
| f82e8a6506 | |||
| e4d3726203 | |||
| ffffb7ce63 | |||
| 9eed839919 | |||
| f523b19968 | |||
| 41de920ac3 | |||
| df00a96295 | |||
| d53ec5e37c | |||
| 90683eb2ca | |||
| ca49ba4065 | |||
| 5a24e4f6b4 | |||
| 100a0ee759 | |||
| f09f8ab566 | |||
| 825622144e | |||
| 8e6e3b55f4 | |||
| bda4ea12a2 | |||
| b408719b53 | |||
| a8147d257c | |||
| 347aa867c0 | |||
| 5c670365ec | |||
| 7c74090eb3 | |||
| 1a90e4b729 | |||
| f88e5e3d07 | |||
| 2a0c8d09d4 | |||
| f13e712470 | |||
| e7d100e7d3 | |||
| 0973c677a1 | |||
| 9b91c95369 | |||
| 15c2733e0e | |||
| 19a015e072 | |||
| e77c7b3c7f | |||
| 882ca626de | |||
| 4c87399a32 | |||
| b18820ce02 | |||
| d91455492e | |||
| 9357519813 | |||
| 23886b4109 | |||
| 44f9414f0d | |||
| 18865fa274 | |||
| a65b47623d | |||
| 0df42a5dce | |||
| 0ebd0133c9 | |||
| 34471c6073 | |||
| 405d73c3c7 | |||
| 932e9a75dd | |||
| a28c0fbac5 | |||
| 982aace898 | |||
| 9faefb3746 | |||
| 31c17016bd | |||
| 6882f43733 | |||
| 812023ae42 | |||
| 515ee06c00 | |||
| 60c1de1e38 | |||
| fcc13c4fba | |||
| 50b8753a1a | |||
| 9c8ec35bfd | |||
| e2508984a2 | |||
| 282c03abcc | |||
| 81466594c8 | |||
| cc8495f211 | |||
| 1ce55c272b | |||
| 972c781548 | |||
| a8a9b88d89 | |||
| 54b7dbb1c6 | |||
| 6ea98758ac | |||
| 079da2b384 | |||
| a5529352ad | |||
| 21a51fed05 | |||
| 2296ecf5b0 | |||
| aa2d400e8d | |||
| 8750d354b0 | |||
| ba9491220c | |||
| 6efa1c6dcb | |||
| 28e1dac334 | |||
| e5e47a3e88 | |||
| 1e2a09a469 | |||
| 2ef42fefd5 | |||
| c8cd8f090c | |||
| 33055e045d | |||
| 60793c02a5 | |||
| 17dfe8fc8a | |||
| 8055de2e9c | |||
| b8609a3917 | |||
| 6142f938bd | |||
| f24cd46b6b | |||
| ed5f69f576 | |||
| ce1d6f0cc8 | |||
| 2bd0f71785 | |||
| e6c03a18d2 | |||
| 78ea1c7ff9 | |||
| ff970b2519 | |||
| fe9af25bfb | |||
| 6e4e76262b | |||
| 86bfadb725 | |||
| 894882caf7 | |||
| 060dbd9ac9 | |||
| 5becae35af | |||
| 544ff232a9 | |||
| 980dbfd45c | |||
| 4f6d38e1ce | |||
| 9d4282c899 | |||
| 0eece9d283 | |||
| 95faf82065 | |||
| 02aabeb07e | |||
| f378470c0b | |||
| 7fcc248ddf | |||
| c32571dc47 | |||
| e00e0ec939 | |||
| 3ae367bb10 | |||
| 78db63442f | |||
| 2fe59376a1 | |||
| c27534ee93 | |||
| 8bd62b9ab0 | |||
| df8255447c | |||
| 59f13afcd2 | |||
| 0bc73851e1 | |||
| d643e9e0be | |||
| a583e8b9e8 | |||
| e20835878c | |||
| 07085d3260 | |||
| bec80c135e | |||
| 31d18243e9 | |||
| d7bfb7a5d1 | |||
| b6c6194da3 | |||
| a9a4b371d2 | |||
| 030fba6462 | |||
| a92c9c4694 |
+219
-46
@@ -1,6 +1,8 @@
|
||||
variables:
|
||||
VERS_MAIN: '2.9'
|
||||
VERS_MAIN: '3.0'
|
||||
NEW_REL: ''
|
||||
APP_NAME: 'GPW.App'
|
||||
SOL_NAME: 'GPW.APP'
|
||||
|
||||
# helper x fix pacchetti nuget da repo locale nexus.steamware.net
|
||||
.nuget-fix: &nuget-fix
|
||||
@@ -19,9 +21,45 @@ variables:
|
||||
if (! [String]::IsNullOrWhiteSpace($hasSource)) {
|
||||
dotnet nuget remove source nexus-proxy-v3
|
||||
}
|
||||
dotnet nuget add source https://nexus.steamware.net/repository/nuget-group-3/index.json -n "Steamware Nexus" -u nugetUser -p viaDante16 --store-password-in-clear-text
|
||||
dotnet nuget add source https://nexus.steamware.net/repository/nuget-group-3/index.json -n "Steamware Nexus" -u nugetUser -p $NEXUS_PASSWD --store-password-in-clear-text
|
||||
echo "Steamware Nexus Source added"
|
||||
|
||||
# helper creazione hash files x IIS
|
||||
.hashBuild: &hashBuild
|
||||
- |
|
||||
$Target = $env:APP_NAME + "\bin\publish\" + $env:APP_NAME + ".zip"
|
||||
$MD5 = Get-FileHash $Target -Algorithm MD5
|
||||
$SHA1 = Get-FileHash $Target -Algorithm SHA1
|
||||
New-Item $Target".md5"
|
||||
New-Item $Target".sha1"
|
||||
$MD5.Hash | Set-Content -Path $Target".md5"
|
||||
$SHA1.Hash | Set-Content -Path $Target".sha1"
|
||||
|
||||
echo "Created HASH files for $Target"
|
||||
|
||||
# helper x send su NEXUS x pack
|
||||
.nexusUpload: &nexusUpload
|
||||
- |
|
||||
Set-Alias mCurl C:\Windows\system32\curl.exe
|
||||
$fileVers = $env:APP_NAME + "\Resources\VersNum.txt"
|
||||
$VersNumb = Get-Content $fileVers
|
||||
echo "Curr Version: $VersNumb"
|
||||
if($CI_COMMIT_BRANCH -eq "master")
|
||||
{
|
||||
$version = "stable"
|
||||
}
|
||||
else
|
||||
{
|
||||
$version = "unstable"
|
||||
}
|
||||
$File2Send = Get-ChildItem($env:APP_NAME + "\bin\publish\*")
|
||||
ForEach ($File in $File2Send) {
|
||||
$FileName = Split-Path $File -leaf
|
||||
mCurl -v -u GitLab:$NEXUS_PASSWD --upload-file $File https://nexus.steamware.net/repository/SWS/$env:NEXUS_PATH/$version/LAST/$FileName
|
||||
mCurl -v -u GitLab:$NEXUS_PASSWD --upload-file $File https://nexus.steamware.net/repository/SWS/$env:NEXUS_PATH/$version/ARCHIVE/$VersNumb/$FileName
|
||||
}
|
||||
mCurl -v -u GitLab:$NEXUS_PASSWD --upload-file "$env:APP_NAME\Resources\manifest.xml" https://nexus.steamware.net/repository/SWS/$env:NEXUS_PATH/$version/LAST/manifest.xml
|
||||
mCurl -v -u GitLab:$NEXUS_PASSWD --upload-file "$env:APP_NAME\Resources\ChangeLog.html" https://nexus.steamware.net/repository/SWS/$env:NEXUS_PATH/$version/LAST/ChangeLog.html
|
||||
|
||||
stages:
|
||||
- build
|
||||
@@ -31,95 +69,199 @@ stages:
|
||||
|
||||
|
||||
CORE.Api:build:
|
||||
stage: build
|
||||
tags:
|
||||
- win
|
||||
before_script:
|
||||
- *nuget-fix
|
||||
- dotnet restore GPW.CORE.WRKLOG.sln
|
||||
script:
|
||||
- dotnet build GPW.CORE.Api/GPW.CORE.Api.csproj
|
||||
|
||||
stage: build
|
||||
tags:
|
||||
- win
|
||||
variables:
|
||||
APP_NAME: GPW.CORE.Api
|
||||
SOL_NAME: GPW.CORE.WRKLOG
|
||||
before_script:
|
||||
- *nuget-fix
|
||||
- dotnet restore "$env:SOL_NAME.sln"
|
||||
script:
|
||||
- dotnet build $env:APP_NAME/$env:APP_NAME.csproj
|
||||
|
||||
# ---------- BUILD ----------
|
||||
CORE.WLOG:build:
|
||||
stage: build
|
||||
tags:
|
||||
- win
|
||||
variables:
|
||||
APP_NAME: GPW.CORE.WRKLOG
|
||||
SOL_NAME: GPW.CORE.WRKLOG
|
||||
before_script:
|
||||
- *nuget-fix
|
||||
- dotnet restore GPW.CORE.WRKLOG.sln
|
||||
- dotnet restore "$env:SOL_NAME.sln"
|
||||
script:
|
||||
- dotnet build GPW.CORE.WRKLOG/GPW.CORE.WRKLOG.csproj
|
||||
- dotnet build $env:APP_NAME/$env:APP_NAME.csproj
|
||||
|
||||
CORE.Smart:build:
|
||||
stage: build
|
||||
tags:
|
||||
- win
|
||||
variables:
|
||||
APP_NAME: GPW.CORE.Smart
|
||||
SOL_NAME: GPW.CORE.Smart
|
||||
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
|
||||
tags:
|
||||
- win
|
||||
- win
|
||||
variables:
|
||||
APP_NAME: GPW.CORE.Api
|
||||
SOL_NAME: GPW.CORE.WRKLOG
|
||||
only:
|
||||
- develop
|
||||
needs: ["CORE.Api:build"]
|
||||
before_script:
|
||||
- *nuget-fix
|
||||
- *nuget-fix
|
||||
- dotnet restore "$env:SOL_NAME.sln"
|
||||
script:
|
||||
- dotnet publish -p:PublishProfile=IIS01.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=viadante16 -p:AllowUntrustedCertificate=true GPW.CORE.Api/GPW.CORE.Api.csproj
|
||||
- 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.WLOG:staging:
|
||||
stage: staging
|
||||
tags:
|
||||
- win
|
||||
variables:
|
||||
APP_NAME: GPW.CORE.WRKLOG
|
||||
SOL_NAME: GPW.CORE.WRKLOG
|
||||
only:
|
||||
- develop
|
||||
needs: ["CORE.WLOG:build"]
|
||||
before_script:
|
||||
- *nuget-fix
|
||||
- *nuget-fix
|
||||
- dotnet restore "$env:SOL_NAME.sln"
|
||||
script:
|
||||
- dotnet publish -p:PublishProfile=IIS01.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=viadante16 -p:AllowUntrustedCertificate=true GPW.CORE.WRKLOG/GPW.CORE.WRKLOG.csproj
|
||||
- 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.Smart:staging:
|
||||
stage: staging
|
||||
tags:
|
||||
- win
|
||||
environment:
|
||||
name: staging
|
||||
url: https://iis01.egalware.com/GPW/CORE.Smart
|
||||
variables:
|
||||
APP_NAME: GPW.CORE.Smart
|
||||
SOL_NAME: GPW.CORE.Smart
|
||||
only:
|
||||
- develop
|
||||
needs: ["CORE.Smart: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
|
||||
tags:
|
||||
- win
|
||||
only:
|
||||
- main
|
||||
needs: ["CORE.Api:build"]
|
||||
script:
|
||||
# IIS 02
|
||||
- dotnet publish -p:PublishProfile=IIS02.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=viadante16 -p:AllowUntrustedCertificate=true GPW.CORE.Api/GPW.CORE.Api.csproj
|
||||
# IIS DEV
|
||||
- dotnet publish -p:PublishProfile=IIS03.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=viadante16 -p:AllowUntrustedCertificate=true GPW.CORE.Api/GPW.CORE.Api.csproj
|
||||
stage: deploy
|
||||
tags:
|
||||
- win
|
||||
environment:
|
||||
name: production
|
||||
url: https://seriate.egalware.com/GPW/CORE.Smart
|
||||
variables:
|
||||
APP_NAME: GPW.CORE.Api
|
||||
SOL_NAME: GPW.CORE.WRKLOG
|
||||
only:
|
||||
- main
|
||||
needs: ["CORE.Api:build"]
|
||||
before_script:
|
||||
- *nuget-fix
|
||||
- dotnet restore "$env:SOL_NAME.sln"
|
||||
script:
|
||||
- dotnet build $env:APP_NAME/$env:APP_NAME.csproj
|
||||
# # IIS 02
|
||||
# - dotnet publish -p:PublishProfile=IIS02.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
|
||||
# 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
|
||||
|
||||
CORE.WLOG:deploy:
|
||||
stage: deploy
|
||||
tags:
|
||||
- win
|
||||
only:
|
||||
- main
|
||||
needs: ["CORE.WLOG:build"]
|
||||
script:
|
||||
# IIS 02
|
||||
- dotnet publish -p:PublishProfile=IIS02.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=viadante16 -p:AllowUntrustedCertificate=true GPW.CORE.WRKLOG/GPW.CORE.WRKLOG.csproj
|
||||
# IIS DEV
|
||||
- dotnet publish -p:PublishProfile=IIS03.pubxml -p:RunCodeAnalysis=false -p:Configuration=Release -p:username=jenkins -p:Password=viadante16 -p:AllowUntrustedCertificate=true GPW.CORE.WRKLOG/GPW.CORE.WRKLOG.csproj
|
||||
stage: deploy
|
||||
tags:
|
||||
- win
|
||||
variables:
|
||||
APP_NAME: GPW.CORE.WRKLOG
|
||||
SOL_NAME: GPW.CORE.WRKLOG
|
||||
only:
|
||||
- main
|
||||
needs: ["CORE.WLOG:build"]
|
||||
before_script:
|
||||
- *nuget-fix
|
||||
- dotnet restore "$env:SOL_NAME.sln"
|
||||
script:
|
||||
- dotnet build $env:APP_NAME/$env:APP_NAME.csproj
|
||||
# # IIS 02
|
||||
# - dotnet publish -p:PublishProfile=IIS02.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
|
||||
# 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
|
||||
|
||||
CORE.Smart:deploy:
|
||||
stage: deploy
|
||||
tags:
|
||||
- win
|
||||
variables:
|
||||
APP_NAME: GPW.CORE.Smart
|
||||
SOL_NAME: GPW.CORE.Smart
|
||||
only:
|
||||
- main
|
||||
needs: ["CORE.Smart:build"]
|
||||
before_script:
|
||||
- *nuget-fix
|
||||
- dotnet restore "$env:SOL_NAME.sln"
|
||||
script:
|
||||
- dotnet build $env:APP_NAME/$env:APP_NAME.csproj
|
||||
# IIS EXT
|
||||
- dotnet publish -p:PublishProfile=IIS-EXT.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
|
||||
# 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.Api:release:
|
||||
stage: release
|
||||
tags:
|
||||
- win
|
||||
variables:
|
||||
APP_NAME: GPW.CORE.Api
|
||||
SOL_NAME: GPW.CORE.WRKLOG
|
||||
only:
|
||||
- main
|
||||
except:
|
||||
- branches
|
||||
needs: ["CORE.Api:build"]
|
||||
before_script:
|
||||
- *nuget-fix
|
||||
- dotnet restore "$env:SOL_NAME.sln"
|
||||
artifacts:
|
||||
paths:
|
||||
- publish/
|
||||
script:
|
||||
- dotnet publish -c Release -o ./publish GPW.CORE.Api/GPW.CORE.Api.csproj
|
||||
|
||||
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.Api/GPW.CORE.Api.csproj
|
||||
|
||||
# ---------- RELEASE ----------
|
||||
CORE.WLOG:release:
|
||||
stage: release
|
||||
tags:
|
||||
- win
|
||||
variables:
|
||||
APP_NAME: GPW.CORE.WRKLOG
|
||||
SOL_NAME: GPW.CORE.WRKLOG
|
||||
only:
|
||||
- main
|
||||
except:
|
||||
@@ -128,5 +270,36 @@ CORE.WLOG:release:
|
||||
artifacts:
|
||||
paths:
|
||||
- publish/
|
||||
script:
|
||||
- dotnet publish -c Release -o ./publish GPW.CORE.WRKLOG/GPW.CORE.WRKLOG.csproj
|
||||
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
|
||||
|
||||
|
||||
CORE.Smart:release:
|
||||
stage: release
|
||||
tags:
|
||||
- win
|
||||
variables:
|
||||
APP_NAME: GPW.CORE.Smart
|
||||
SOL_NAME: GPW.CORE.Smart
|
||||
only:
|
||||
- main
|
||||
except:
|
||||
- branches
|
||||
needs: ["CORE.Smart: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
|
||||
@@ -34,7 +34,7 @@ namespace GPW.CORE.Api.Controllers
|
||||
_configuration = configuration;
|
||||
_emailSender = emailSender;
|
||||
dataService = DataService;
|
||||
Log.Info("Avviata classe CheckProj");
|
||||
Log.Info("Avviata classe ProjCheck");
|
||||
}
|
||||
|
||||
#endregion Public Constructors
|
||||
@@ -106,7 +106,7 @@ namespace GPW.CORE.Api.Controllers
|
||||
|
||||
protected async Task sendEmail(string subject, string message)
|
||||
{
|
||||
string emailRaw = _configuration["MailDest:ProjCheck"];
|
||||
string emailRaw = _configuration["MailDest:ProjCheck"] ?? "";
|
||||
List<string> emailDestList = emailRaw.Split(",").ToList();
|
||||
foreach (var dest in emailDestList)
|
||||
{
|
||||
@@ -136,7 +136,7 @@ namespace GPW.CORE.Api.Controllers
|
||||
int numFix = 0;
|
||||
int numProj = 0;
|
||||
int numFasi = 0;
|
||||
string enableChiudiRaw = _configuration["EnableChiudiFasi"];
|
||||
string enableChiudiRaw = _configuration["EnableChiudiFasi"]??"false";
|
||||
bool enableChiudi = false;
|
||||
if (!string.IsNullOrEmpty(enableChiudiRaw))
|
||||
{
|
||||
|
||||
@@ -0,0 +1,542 @@
|
||||
using GPW.CORE.Api.Data;
|
||||
using GPW.CORE.Data.DbModels;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NLog;
|
||||
using System.Text;
|
||||
|
||||
namespace GPW.CORE.Api.Controllers
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class TimbraCheckController : ControllerBase
|
||||
{
|
||||
|
||||
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private readonly IEmailSender _emailSender;
|
||||
|
||||
private IConfiguration _configuration;
|
||||
/// <summary>
|
||||
/// Avvio controller x CheckProgetti
|
||||
/// </summary>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="configuration"></param>
|
||||
/// <param name="emailSender"></param>
|
||||
/// <param name="DataService"></param>
|
||||
public TimbraCheckController(ILogger<ProjCheckController> logger, IConfiguration configuration, IEmailSender emailSender, ApiDataService DataService)
|
||||
{
|
||||
_configuration = configuration;
|
||||
_emailSender = emailSender;
|
||||
dataService = DataService;
|
||||
Log.Info("Avviata classe TimbraCheck");
|
||||
}
|
||||
|
||||
protected enum logType
|
||||
{
|
||||
none,
|
||||
local,
|
||||
trace,
|
||||
info,
|
||||
warn
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dataservice x accesso DB
|
||||
/// </summary>
|
||||
protected ApiDataService dataService { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Effettua log del tipo richiesto aggiungendo riga anche allo stringbuilder indicato
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="tipoLog"></param>
|
||||
/// <param name="currSB"></param>
|
||||
protected void doLog(string message, logType tipoLog, ref StringBuilder currSB)
|
||||
{
|
||||
bool doLine = true;
|
||||
switch (tipoLog)
|
||||
{
|
||||
case logType.info:
|
||||
Log.Info(message);
|
||||
break;
|
||||
|
||||
case logType.trace:
|
||||
Log.Trace(message);
|
||||
break;
|
||||
|
||||
case logType.warn:
|
||||
Log.Warn(message);
|
||||
break;
|
||||
|
||||
case logType.local:
|
||||
break;
|
||||
|
||||
default:
|
||||
case logType.none:
|
||||
doLine = false;
|
||||
break;
|
||||
}
|
||||
if (doLine)
|
||||
{
|
||||
currSB.AppendLine(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
currSB.Append(message);
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task sendEmail(string destList, string subject, string message)
|
||||
{
|
||||
List<string> emailDestList = destList.Split(",").ToList();
|
||||
foreach (var dest in emailDestList)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _emailSender.SendEmailAsync(dest, subject, message);
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Log.Error($"Eccezione durante invio email:{Environment.NewLine}dest: {dest} | subject {subject}{Environment.NewLine}{exc}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pagina di prova x validità chiamate API
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("Test")]
|
||||
public async Task<string> Test()
|
||||
{
|
||||
await Task.Delay(1);
|
||||
return "OK";
|
||||
}
|
||||
/// <summary>
|
||||
/// Effettua verifiche DailyDuties sulle timbrature
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("DailyCheck")]
|
||||
public async Task<string> Get()
|
||||
{
|
||||
string answ = "ND";
|
||||
// verifico se ci siano record check odierni...
|
||||
DateTime inizio = DateTime.Today;
|
||||
DateTime fine = inizio.AddDays(1);
|
||||
var dailyChecks = await dataService.RegEventiGetFilt(inizio, fine, "checkAnomalie");
|
||||
// cerco se sia già stato fatto altrimenti ripeto...
|
||||
if (dailyChecks != null && dailyChecks.Count > 0)
|
||||
{
|
||||
// loggo solo che è stato richeisto di nuovo...
|
||||
var currCheck = dailyChecks[0];
|
||||
answ = $"Already Done | {currCheck.DataOra} | {currCheck.Evento} | {currCheck.Commento}";
|
||||
Log.Info("DailyCheck non eseguito: già registrato per la giornata");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Info("Richiesto controllo anomalie!");
|
||||
// registro evento check effettuato...
|
||||
RegistroEventiModel newRec = new RegistroEventiModel()
|
||||
{
|
||||
DataOra = DateTime.Now,
|
||||
Evento = "dailyDuties",
|
||||
Commento = "-"
|
||||
|
||||
};
|
||||
bool fatto = await dataService.RegEventiUpdate(newRec);
|
||||
/*******************************************************
|
||||
* controllo le varie anomalie delle timbrature:
|
||||
*
|
||||
* (A) mancate approvazioni --> admin
|
||||
* (B) entrate <> uscite --> admin, user
|
||||
* (C) mancata copertura orario --> admin
|
||||
*
|
||||
* (D) mancata copertura commesse (2 be done)
|
||||
*
|
||||
* recupero elenco dip interessati x le varie anomalie con stp_DipendentiAndAnomalie
|
||||
* e poi da timbrExpl recupero le singole istanze di record errori
|
||||
*
|
||||
*******************************************************/
|
||||
|
||||
// oggetti base
|
||||
StringBuilder sbMain = new StringBuilder();
|
||||
DateTime oggi = DateTime.Today;
|
||||
DateTime oggiFine = oggi.AddDays(1).AddSeconds(-1);
|
||||
string adminDestEmail = _configuration.GetValue<string>("MailDest:TimbCheck") ?? "samuele@steamware.net";
|
||||
string baseUrl = _configuration.GetValue<string>("ServerConv:baseUrl") ?? "https://office.egalware.com/GPW/ADMIN/";
|
||||
bool checkAnomAppr = _configuration.GetValue<bool>("TimbraCheck:checkAnomAppr");
|
||||
bool checkAnomTimb = _configuration.GetValue<bool>("TimbraCheck:checkAnomTimb");
|
||||
bool checkAnomOreLav = _configuration.GetValue<bool>("TimbraCheck:checkAnomOreLav");
|
||||
bool checkAnomOreLavComm = _configuration.GetValue<bool>("TimbraCheck:checkAnomOreLavComm");
|
||||
bool checkAnomContinuato = _configuration.GetValue<bool>("TimbraCheck:checkAnomContinuato");
|
||||
bool sendEmailToUser = _configuration.GetValue<bool>("TimbraCheck:sendEmailToUser");
|
||||
bool includeDirectUrl = _configuration.GetValue<bool>("TimbraCheck:includeDirectUrl");
|
||||
int gg2Chk = _configuration.GetValue<int>("TimbraCheck:gg2Chk");
|
||||
int gg2ChkCont = _configuration.GetValue<int>("TimbraCheck:gg2ChkCont");
|
||||
int gg2ChkOreCaricate = _configuration.GetValue<int>("TimbraCheck:gg2ChkOreCaricate");
|
||||
int maxErrMin = _configuration.GetValue<int>("TimbraCheck:maxErrMin");
|
||||
int maxErrPlus = _configuration.GetValue<int>("TimbraCheck:maxErrPlus");
|
||||
string msgTopic = "";
|
||||
string msgBody = "";
|
||||
int numChk = 0;
|
||||
int numErr = 0;
|
||||
|
||||
string headRow = "style=\"background-color: #232323; color: #DEDEDE\"";
|
||||
string stripeRow = "style=\"background-color: #DEDEDE;\"";
|
||||
Dictionary<string, int> anomCount = new Dictionary<string, int>();
|
||||
int lastCount = 0;
|
||||
///elenco dipendenti (per tutti i casi ove necessario)
|
||||
var tabElencoDip = await dataService.DipendentiGetAll();
|
||||
|
||||
// (A) recupero mancate approvazioni, mando solo ad admin
|
||||
if (checkAnomAppr)
|
||||
{
|
||||
numChk++;
|
||||
sbMain = new StringBuilder();
|
||||
var tabTimbExpl = await dataService.TimbExplGetAnomalie(0, oggi.AddDays(-gg2Chk), oggiFine, true, false, false);
|
||||
// se ho trovato record...
|
||||
if (tabTimbExpl != null && tabTimbExpl.Count > 0)
|
||||
{
|
||||
doLog("Trovate anomalie mancate approvazioni, invio email ad admin", logType.info, ref sbMain);
|
||||
msgTopic = "Anomalie GPW: Approvazione Timbrature";
|
||||
if (includeDirectUrl)
|
||||
{
|
||||
doLog($"Risultano a sistema le seguenti anomalie:{Environment.NewLine}<a href=\"{baseUrl}approvTimbrature.aspx\">timbrature da approvare</a>{Environment.NewLine}", logType.info, ref sbMain);
|
||||
}
|
||||
else
|
||||
{
|
||||
doLog($"Risultano a sistema le seguenti anomalie: timbrature da approvare{Environment.NewLine}", logType.info, ref sbMain);
|
||||
}
|
||||
// tabella!
|
||||
doLog("<table cellpadding=\"0\" cellspacing=\"0\" border=\"1\" style=\"font-size: 1.3em; width:100%;\">", logType.none, ref sbMain);
|
||||
doLog($"<thead {headRow}><th>DATA</th><th>Dipendente</th></thead>", logType.none, ref sbMain);
|
||||
doLog("<tbody>", logType.none, ref sbMain);
|
||||
int nRow = 0;
|
||||
foreach (var riga in tabTimbExpl)
|
||||
{
|
||||
string sfondo = nRow % 2 == 0 ? "" : stripeRow;
|
||||
doLog($"<tr {sfondo}><td>{riga.DataLav:yyyy.MM.dd ddd}</td><td>{riga.CognomeNome}</td></tr>", logType.none, ref sbMain);
|
||||
numErr++;
|
||||
nRow++;
|
||||
}
|
||||
doLog("</tbody>", logType.none, ref sbMain);
|
||||
doLog("</table>", logType.none, ref sbMain);
|
||||
msgBody = sbMain.ToString();
|
||||
await sendEmail(adminDestEmail, msgTopic, msgBody.Replace($"{Environment.NewLine}", "<br/>"));
|
||||
// salvo
|
||||
anomCount.Add("Check A: Mancate approvazioni", numErr - lastCount);
|
||||
lastCount = numErr;
|
||||
}
|
||||
}
|
||||
|
||||
// (B1) recupero errori entrate/uscite, mando ad admin + utenti
|
||||
if (checkAnomTimb)
|
||||
{
|
||||
numChk++;
|
||||
sbMain = new StringBuilder();
|
||||
var tabDipAndAnom = await dataService.DipAndAnomGetAll(oggi.AddDays(-gg2Chk), oggi.AddHours(1), false, true, false);
|
||||
var tabTimbExpl = await dataService.TimbExplGetAnomalie(0, oggi.AddDays(-gg2Chk), oggiFine, false, true, false);
|
||||
// se ho trovato record...
|
||||
if (tabTimbExpl != null && tabTimbExpl.Count > 0)
|
||||
{
|
||||
doLog("Trovate anomalie timbrature IN/OUT non corrispondenti, invio email!", logType.info, ref sbMain);
|
||||
// mando email ad admin!
|
||||
msgTopic = "Anomalie GPW: Timbrature mancanti";
|
||||
if (includeDirectUrl)
|
||||
{
|
||||
doLog($"Risultano a sistema le seguenti anomalie:{Environment.NewLine}<a href=\"{baseUrl}reviewTimbrature.aspx\">timbrature mancanti</a>{Environment.NewLine}", logType.info, ref sbMain);
|
||||
}
|
||||
else
|
||||
{
|
||||
doLog($"Risultano a sistema le seguenti anomalie: timbrature mancanti{Environment.NewLine}", logType.info, ref sbMain);
|
||||
}
|
||||
// tabella!
|
||||
doLog("<table cellpadding=\"0\" cellspacing=\"0\" border=\"1\" style=\"font-size: 1.3em; width:100%;\">", logType.none, ref sbMain);
|
||||
doLog($"<thead {headRow}><th>DATA</th><th>Dipendente</th></thead>", logType.none, ref sbMain);
|
||||
doLog("<tbody>", logType.none, ref sbMain);
|
||||
int nRow = 0;
|
||||
foreach (var riga in tabTimbExpl)
|
||||
{
|
||||
string sfondo = nRow % 2 == 0 ? "" : stripeRow;
|
||||
doLog($"<tr {sfondo}><td>{riga.DataLav:yyyy.MM.dd ddd}</td><td>{riga.CognomeNome}</td></tr>", logType.none, ref sbMain);
|
||||
numErr++;
|
||||
nRow++;
|
||||
}
|
||||
doLog("</tbody>", logType.none, ref sbMain);
|
||||
doLog("</table>", logType.none, ref sbMain);
|
||||
msgBody = sbMain.ToString();
|
||||
await sendEmail(adminDestEmail, msgTopic, msgBody.Replace($"{Environment.NewLine}", "<br/>"));
|
||||
|
||||
|
||||
// re richiesto invio email utenti x warning entrate/uscrite
|
||||
if (sendEmailToUser)
|
||||
{
|
||||
// mando singole email ai dipendenti SE C'è EMAIL!!!!
|
||||
foreach (var rigaDip in tabDipAndAnom)
|
||||
{
|
||||
sbMain = new StringBuilder();
|
||||
if (!string.IsNullOrEmpty(rigaDip.email))
|
||||
{
|
||||
var tabTimbExplDip = tabTimbExpl.Where(x => x.IdxDipendente == rigaDip.IdxDipendente);
|
||||
// reimposto testo
|
||||
doLog($"Risultano a sistema le seguenti anomalie: timbrature mancanti{Environment.NewLine}", logType.info, ref sbMain);
|
||||
|
||||
// tabella!
|
||||
doLog("<table cellpadding=\"0\" cellspacing=\"0\" border=\"1\" style=\"font-size: 1.3em; width:100%;\">", logType.none, ref sbMain);
|
||||
doLog($"<thead {headRow}><th>DATA</th><th>Dipendente</th></thead>", logType.none, ref sbMain);
|
||||
doLog("<tbody>", logType.none, ref sbMain);
|
||||
nRow = 0;
|
||||
foreach (var riga in tabTimbExplDip)
|
||||
{
|
||||
string sfondo = nRow % 2 == 0 ? "" : stripeRow;
|
||||
doLog($"<tr {sfondo}><td>{riga.DataLav:yyyy.MM.dd ddd}</td><td>{riga.CognomeNome}</td></tr>", logType.none, ref sbMain);
|
||||
nRow++;
|
||||
}
|
||||
doLog("</tbody>", logType.none, ref sbMain);
|
||||
doLog("</table>", logType.none, ref sbMain);
|
||||
msgBody = sbMain.ToString();
|
||||
await sendEmail(rigaDip.email, msgTopic, msgBody.Replace($"{Environment.NewLine}", "<br/>"));
|
||||
}
|
||||
}
|
||||
}
|
||||
// salvo
|
||||
anomCount.Add("Check B1: Entrate/Uscite", numErr - lastCount);
|
||||
lastCount = numErr;
|
||||
}
|
||||
}
|
||||
|
||||
// (B2) recupero errori timbrature FUTURE, mando ad admin + utenti
|
||||
if (checkAnomTimb)
|
||||
{
|
||||
List<DipendentiModel> ElencoDip2Send = new List<DipendentiModel>();
|
||||
numChk++;
|
||||
sbMain = new StringBuilder();
|
||||
var tabTimbFuture = await dataService.TimbratureAnomalieFuture();
|
||||
// se ho trovato record...
|
||||
if (tabTimbFuture != null && tabTimbFuture.Count > 0)
|
||||
{
|
||||
doLog("Trovate anomalie timbrature FUTURE, invio email!", logType.info, ref sbMain);
|
||||
// mando email ad admin!
|
||||
msgTopic = "Anomalie GPW: Timbrature FUTURE";
|
||||
if (includeDirectUrl)
|
||||
{
|
||||
doLog($"Risultano a sistema le seguenti anomalie:{Environment.NewLine}<a href=\"{baseUrl}reviewTimbrature.aspx\">timbrature FUTURE</a>{Environment.NewLine}", logType.info, ref sbMain);
|
||||
}
|
||||
else
|
||||
{
|
||||
doLog($"Risultano a sistema le seguenti anomalie: timbrature FUTURE{Environment.NewLine}", logType.info, ref sbMain);
|
||||
}
|
||||
// tabella!
|
||||
doLog("<table cellpadding=\"0\" cellspacing=\"0\" border=\"1\" style=\"font-size: 1.3em; width:100%;\">", logType.none, ref sbMain);
|
||||
doLog($"<thead {headRow}><th>DATA</th><th>Dipendente</th></thead>", logType.none, ref sbMain);
|
||||
doLog("<tbody>", logType.none, ref sbMain);
|
||||
int nRow = 0;
|
||||
foreach (var riga in tabTimbFuture)
|
||||
{
|
||||
string sfondo = nRow % 2 == 0 ? "" : stripeRow;
|
||||
var rigaDip = tabElencoDip.Find(x => x.IdxDipendente == riga.IdxDipendente);
|
||||
if(rigaDip!=null)
|
||||
{
|
||||
ElencoDip2Send.Add(rigaDip);
|
||||
}
|
||||
string cognomeNome = rigaDip != null ? $"{rigaDip.Cognome} {rigaDip.Nome}" : $"idxDip: {riga.IdxDipendente}";
|
||||
doLog($"<tr {sfondo}><td>{riga.DataOra:yyyy.MM.dd ddd}</td><td>{cognomeNome}</td></tr>", logType.none, ref sbMain);
|
||||
numErr++;
|
||||
nRow++;
|
||||
}
|
||||
doLog("</tbody>", logType.none, ref sbMain);
|
||||
doLog("</table>", logType.none, ref sbMain);
|
||||
msgBody = sbMain.ToString();
|
||||
await sendEmail(adminDestEmail, msgTopic, msgBody.Replace($"{Environment.NewLine}", "<br/>"));
|
||||
|
||||
|
||||
// re richiesto invio email utenti x warning entrate/uscrite
|
||||
if (sendEmailToUser)
|
||||
{
|
||||
// mando singole email ai dipendenti SE C'è EMAIL!!!!
|
||||
foreach (var rigaDip in ElencoDip2Send)
|
||||
{
|
||||
sbMain = new StringBuilder();
|
||||
if (!string.IsNullOrEmpty(rigaDip.Email))
|
||||
{
|
||||
var tabTimbExplDip = tabTimbFuture.Where(x => x.IdxDipendente == rigaDip.IdxDipendente);
|
||||
// reimposto testo
|
||||
doLog($"Risultano a sistema le seguenti anomalie: timbrature FUTURE{Environment.NewLine}", logType.info, ref sbMain);
|
||||
|
||||
// tabella!
|
||||
doLog("<table cellpadding=\"0\" cellspacing=\"0\" border=\"1\" style=\"font-size: 1.3em; width:100%;\">", logType.none, ref sbMain);
|
||||
doLog($"<thead {headRow}><th>DATA</th><th>Dipendente</th></thead>", logType.none, ref sbMain);
|
||||
doLog("<tbody>", logType.none, ref sbMain);
|
||||
nRow = 0;
|
||||
foreach (var riga in tabTimbExplDip)
|
||||
{
|
||||
string sfondo = nRow % 2 == 0 ? "" : stripeRow;
|
||||
doLog($"<tr {sfondo}><td>{riga.DataOra:yyyy.MM.dd ddd}</td><td>{rigaDip.Cognome} {rigaDip.Nome}</td></tr>", logType.none, ref sbMain);
|
||||
nRow++;
|
||||
}
|
||||
doLog("</tbody>", logType.none, ref sbMain);
|
||||
doLog("</table>", logType.none, ref sbMain);
|
||||
msgBody = sbMain.ToString();
|
||||
await sendEmail(rigaDip.Email, msgTopic, msgBody.Replace($"{Environment.NewLine}", "<br/>"));
|
||||
}
|
||||
}
|
||||
}
|
||||
// salvo
|
||||
anomCount.Add("Check B2: Timbrature Future", numErr - lastCount);
|
||||
lastCount = numErr;
|
||||
}
|
||||
}
|
||||
|
||||
// (C) recupero errori mancata copertura orario, mando ad admin
|
||||
if (checkAnomOreLav)
|
||||
{
|
||||
numChk++;
|
||||
sbMain = new StringBuilder();
|
||||
var tabTimbExpl = await dataService.TimbExplGetAnomalie(0, oggi.AddDays(-gg2Chk), oggi.AddMinutes(-1), false, false, true);
|
||||
// se ho trovato record...
|
||||
if (tabTimbExpl != null && tabTimbExpl.Count > 0)
|
||||
{
|
||||
doLog("Trovate anomalie copertura orario, invio email!", logType.info, ref sbMain);
|
||||
// mando email ad admin!
|
||||
msgTopic = "Anomalie GPW: Ore timbrate";
|
||||
if (includeDirectUrl)
|
||||
{
|
||||
doLog($"Risultano a sistema le seguenti anomalie:{Environment.NewLine}<a href=\"{baseUrl}reviewTimbrature.aspx\">Orario timbrato non suff a copertura standard</a>{Environment.NewLine}", logType.info, ref sbMain);
|
||||
}
|
||||
else
|
||||
{
|
||||
doLog($"Risultano a sistema le seguenti anomalie: Orario timbrato non suff a copertura standard{Environment.NewLine}", logType.info, ref sbMain);
|
||||
}
|
||||
// tabella!
|
||||
doLog("<table cellpadding=\"0\" cellspacing=\"0\" border=\"1\" style=\"font-size: 1.3em; width:100%;\">", logType.none, ref sbMain);
|
||||
doLog($"<thead {headRow}><th>DATA</th><th>Dipendente</th></thead>", logType.none, ref sbMain);
|
||||
doLog("<tbody>", logType.none, ref sbMain);
|
||||
int nRow = 0;
|
||||
foreach (var riga in tabTimbExpl)
|
||||
{
|
||||
string sfondo = nRow % 2 == 0 ? "" : stripeRow;
|
||||
doLog($"<tr {sfondo}><td>{riga.DataLav:yyyy.MM.dd ddd}</td><td>{riga.CognomeNome}</td></tr>", logType.none, ref sbMain);
|
||||
numErr++;
|
||||
nRow++;
|
||||
}
|
||||
doLog("</tbody>", logType.none, ref sbMain);
|
||||
doLog("</table>", logType.none, ref sbMain);
|
||||
msgBody = sbMain.ToString();
|
||||
await sendEmail(adminDestEmail, msgTopic, msgBody.Replace($"{Environment.NewLine}", "<br/>"));
|
||||
// salvo
|
||||
anomCount.Add("Check C: Copertura Orario", numErr - lastCount);
|
||||
lastCount = numErr;
|
||||
}
|
||||
}
|
||||
|
||||
// (D) recupero errori copertura ore lavorate / ore caricate a commessa...
|
||||
if (checkAnomOreLavComm)
|
||||
{
|
||||
numChk++;
|
||||
sbMain = new StringBuilder();
|
||||
var tabTimbRegAtt = await dataService.TeRaExplGetAll(0, oggi.AddDays(-gg2ChkOreCaricate), oggi.AddHours(1), false, true, maxErrMin, maxErrPlus);
|
||||
// sulla tabella seleziono SE NON E' OK colonna okLavCom
|
||||
var listErrCopertura = tabTimbRegAtt.Where(x => x.okLAvCom == 0).ToList();
|
||||
if (listErrCopertura != null && listErrCopertura.Count() > 0)
|
||||
{
|
||||
doLog("Trovate anomalie ore lavorate / commesse caricate, invio email!", logType.info, ref sbMain);
|
||||
// mando email ad admin!
|
||||
msgTopic = "Anomalie GPW: Ore Caricate a commessa";
|
||||
if (includeDirectUrl)
|
||||
{
|
||||
doLog($"Risultano a sistema le seguenti anomalie:{Environment.NewLine}<a href=\"{baseUrl}reviewTimbrature.aspx\">Ore caricate a commessa non corrispondenti ad ore lavorate secondo standard</a>{Environment.NewLine}", logType.info, ref sbMain);
|
||||
}
|
||||
else
|
||||
{
|
||||
doLog($"Risultano a sistema le seguenti anomalie: Ore caricate a commessa non corrispondenti ad ore lavorate secondo standard{Environment.NewLine}", logType.info, ref sbMain);
|
||||
}
|
||||
// tabella!
|
||||
doLog("<table cellpadding=\"0\" cellspacing=\"0\" border=\"1\" style=\"font-size: 1.3em; width:100%;\">", logType.none, ref sbMain);
|
||||
doLog($"<thead {headRow}><th>DATA</th><th>Dipendente</th></thead>", logType.none, ref sbMain);
|
||||
doLog("<tbody>", logType.none, ref sbMain);
|
||||
int nRow = 0;
|
||||
foreach (var riga in listErrCopertura)
|
||||
{
|
||||
string sfondo = nRow % 2 == 0 ? "" : stripeRow;
|
||||
doLog($"<tr {sfondo}><td>{riga.DataLav:yyyy.MM.dd ddd}</td><td>{riga.CognomeNome}</td></tr>", logType.none, ref sbMain);
|
||||
numErr++;
|
||||
nRow++;
|
||||
}
|
||||
doLog("</tbody>", logType.none, ref sbMain);
|
||||
doLog("</table>", logType.none, ref sbMain);
|
||||
msgBody = sbMain.ToString();
|
||||
await sendEmail(adminDestEmail, msgTopic, msgBody.Replace($"{Environment.NewLine}", "<br/>"));
|
||||
// salvo
|
||||
anomCount.Add("Check D: Ore lavorate / Caricate", numErr - lastCount);
|
||||
lastCount = numErr;
|
||||
}
|
||||
}
|
||||
|
||||
// (E) cerco anomalie x orario continuato (no Pausa Pranzo, solo 1 IN, 1 OUT)
|
||||
if (checkAnomContinuato)
|
||||
{
|
||||
numChk++;
|
||||
sbMain = new StringBuilder();
|
||||
var tabTimbExpl = await dataService.TimbExplGetContinuato(0, oggi.AddDays(-gg2ChkCont), oggi.AddHours(1));
|
||||
// se ho trovato record...
|
||||
if (tabTimbExpl != null && tabTimbExpl.Count > 0)
|
||||
{
|
||||
doLog("Trovate anomalie orario continuato, invio email!", logType.info, ref sbMain);
|
||||
// mando email ad admin!
|
||||
msgTopic = "Anomalie GPW: Orario Continuato";
|
||||
if (includeDirectUrl)
|
||||
{
|
||||
doLog($"Risultano a sistema le seguenti anomalie:{Environment.NewLine}<a href=\"{baseUrl}approvTimbrature.aspx\">Orari continuati da approvare</a>{Environment.NewLine}", logType.info, ref sbMain);
|
||||
}
|
||||
else
|
||||
{
|
||||
doLog($"Risultano a sistema le seguenti anomalie: Orari continuati da approvare{Environment.NewLine}", logType.info, ref sbMain);
|
||||
}
|
||||
// tabella!
|
||||
doLog("<table cellpadding=\"0\" cellspacing=\"0\" border=\"1\" style=\"font-size: 1.3em; width:100%;\">", logType.none, ref sbMain);
|
||||
doLog($"<thead {headRow}><th>DATA</th><th>Dipendente</th></thead>", logType.none, ref sbMain);
|
||||
doLog("<tbody>", logType.none, ref sbMain);
|
||||
int nRow = 0;
|
||||
foreach (var riga in tabTimbExpl)
|
||||
{
|
||||
string sfondo = nRow % 2 == 0 ? "" : stripeRow;
|
||||
doLog($"<tr {sfondo}><td>{riga.DataLav:yyyy.MM.dd ddd}</td><td>{riga.CognomeNome}</td></tr>", logType.none, ref sbMain);
|
||||
numErr++;
|
||||
nRow++;
|
||||
}
|
||||
doLog("</tbody>", logType.none, ref sbMain);
|
||||
doLog("</table>", logType.none, ref sbMain);
|
||||
msgBody = sbMain.ToString();
|
||||
await sendEmail(adminDestEmail, msgTopic, msgBody.Replace($"{Environment.NewLine}", "<br/>"));
|
||||
// salvo
|
||||
anomCount.Add("Check E: Anomalia Continuato", numErr - lastCount);
|
||||
lastCount = numErr;
|
||||
}
|
||||
}
|
||||
|
||||
string resErrori = "";
|
||||
foreach (var item in anomCount)
|
||||
{
|
||||
resErrori += $"{item.Key}: {item.Value} | ";
|
||||
}
|
||||
// Summary di cosa fatto
|
||||
answ = numErr == 0 ? $"Check Anomalie Timbr ALL OK | effettuati {numChk} check" : $"Check Anomalie Timbr KO | effettuati {numChk} check | trovate {numErr} anomalie | {resErrori}";
|
||||
|
||||
// registro evento check effettuato...
|
||||
newRec = new RegistroEventiModel()
|
||||
{
|
||||
DataOra = DateTime.Now,
|
||||
Evento = "checkAnomalie",
|
||||
Commento = answ
|
||||
|
||||
};
|
||||
fatto = await dataService.RegEventiUpdate(newRec);
|
||||
}
|
||||
// restituisco esito
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,13 +108,13 @@ namespace GPW.CORE.Api.Controllers
|
||||
/// <param name="DecodedData"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPut]
|
||||
public async Task<VC19Check> Put(TestUser id)
|
||||
public async Task<VC19Check> Put(int id)
|
||||
{
|
||||
VC19Check answ = new VC19Check()
|
||||
{
|
||||
Result = "KO"
|
||||
};
|
||||
var result = await _DataService.InsertManual((int)id, "10.74.82.255");
|
||||
var result = await _DataService.InsertManual(id, "10.74.82.255");
|
||||
answ = new VC19Check
|
||||
{
|
||||
DTRecord = DateTime.Now,
|
||||
|
||||
+327
-178
@@ -1,61 +1,15 @@
|
||||
using GPW.CORE.Data.DbModels;
|
||||
using GPW.CORE.Data;
|
||||
using GPW.CORE.Data.DbModels;
|
||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||
using Newtonsoft.Json;
|
||||
using NLog;
|
||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||
using StackExchange.Redis.Extensions.Core;
|
||||
using StackExchange.Redis.Extensions.Core.Abstractions;
|
||||
using System.Diagnostics;
|
||||
using GPW.CORE.Data;
|
||||
using StackExchange.Redis;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace GPW.CORE.Api.Data
|
||||
{
|
||||
public class ApiDataService
|
||||
public class ApiDataService : IDisposable
|
||||
{
|
||||
#region Private Fields
|
||||
|
||||
private static IConfiguration _configuration = null!;
|
||||
|
||||
private static ILogger<ApiDataService> _logger = null!;
|
||||
|
||||
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private readonly IEmailSender _emailSender;
|
||||
|
||||
//private readonly IDistributedCache distributedCache;
|
||||
//private readonly IRedisCacheClient _redisCacheClient;
|
||||
|
||||
/// <summary>
|
||||
/// Oggetto per connessione a REDIS
|
||||
/// </summary>
|
||||
private ConnectionMultiplexer redisConn = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Oggetto DB redis da impiegare x chiamate R/W
|
||||
/// </summary>
|
||||
private IDatabase redisDb = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Elenco obj in cache
|
||||
/// </summary>
|
||||
private List<string> cachedDataList = new List<string>();
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Protected Fields
|
||||
|
||||
protected const string rKeyProjAct = "Check:ProjAct";
|
||||
protected const string rKeyFasiAct = "Check:FasiAct";
|
||||
protected const string rKeyCalcOreFase = "Check:OreFasi";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// TTL da 1 min x cache Redis
|
||||
/// </summary>
|
||||
protected const int shortTTL = 60 * 5;
|
||||
|
||||
#endregion Protected Fields
|
||||
|
||||
#region Public Fields
|
||||
|
||||
/// <summary>
|
||||
@@ -80,14 +34,20 @@ namespace GPW.CORE.Api.Data
|
||||
_logger = logger;
|
||||
_configuration = configuration;
|
||||
_emailSender = emailSender;
|
||||
//_redisCacheClient = redisCacheClient;
|
||||
// setup compoenti REDIS
|
||||
this.redisConn = ConnectionMultiplexer.Connect(_configuration.GetConnectionString("Redis"));
|
||||
this.redisDb = this.redisConn.GetDatabase();
|
||||
var redConnString = _configuration.GetConnectionString("Redis");
|
||||
if (redConnString == null)
|
||||
{
|
||||
_logger.LogError("REDIS ConnString empty!");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.redisConn = ConnectionMultiplexer.Connect(redConnString);
|
||||
this.redisDb = this.redisConn.GetDatabase();
|
||||
}
|
||||
|
||||
|
||||
// conf DB
|
||||
string connStrDB = _configuration.GetConnectionString("GPW.DB");
|
||||
// Conf DB
|
||||
var connStrDB = _configuration.GetConnectionString("GPW.DB");
|
||||
if (string.IsNullOrEmpty(connStrDB))
|
||||
{
|
||||
_logger.LogError("ConnString empty!");
|
||||
@@ -101,106 +61,8 @@ namespace GPW.CORE.Api.Data
|
||||
|
||||
#endregion Public Constructors
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Recupero chiave da redis
|
||||
/// </summary>
|
||||
/// <param name="rKey"></param>
|
||||
/// <returns></returns>
|
||||
protected async Task<string> getRSV(string rKey)
|
||||
{
|
||||
#if false
|
||||
//string answ = await _redisCacheClient.GetDbFromConfiguration().GetAsync<string>(rKey);
|
||||
#endif
|
||||
string answ = await redisDb.StringGetAsync(rKey);
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Salvataggio chiave in redis
|
||||
/// </summary>
|
||||
/// <param name="rKey"></param>
|
||||
/// <param name="rVal"></param>
|
||||
/// <param name="ttlSec"></param>
|
||||
/// <returns></returns>
|
||||
protected async Task<bool> setRSV(string rKey, string rVal, int ttlSec)
|
||||
{
|
||||
bool fatto = false;
|
||||
#if false
|
||||
//await _redisCacheClient.GetDbFromConfiguration().AddAsync(rKey, rVal, DateTimeOffset.Now.AddSeconds(ttlSec));
|
||||
#endif
|
||||
await redisDb.StringSetAsync(rKey, rVal, TimeSpan.FromSeconds(ttlSec));
|
||||
fatto = true;
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Salvataggio chiave in redis
|
||||
/// </summary>
|
||||
/// <param name="rKey"></param>
|
||||
/// <param name="rValInt"></param>
|
||||
/// <param name="ttlSec"></param>
|
||||
/// <returns></returns>
|
||||
protected async Task<bool> setRSV(string rKey, int rValInt, int ttlSec)
|
||||
{
|
||||
bool fatto = false;
|
||||
#if false
|
||||
await _redisCacheClient.GetDbFromConfiguration().AddAsync<int>(rKey, rValInt, DateTimeOffset.Now.AddSeconds(ttlSec));
|
||||
#endif
|
||||
await redisDb.StringSetAsync(rKey, rValInt, TimeSpan.FromSeconds(ttlSec));
|
||||
fatto = true;
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registra in cache chiave se non fosse già in elenco
|
||||
/// </summary>
|
||||
/// <param name="newKey"></param>
|
||||
protected void trackCache(string newKey)
|
||||
{
|
||||
if (!cachedDataList.Contains(newKey))
|
||||
{
|
||||
cachedDataList.Add(newKey);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Recupera l'elenco progetti (ATTIVI)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<AnagProgettiModel>> AnagProjActiv()
|
||||
{
|
||||
List<AnagProgettiModel>? dbResult = new List<AnagProgettiModel>();
|
||||
string cacheKey = $"{rKeyProjAct}";
|
||||
trackCache(cacheKey);
|
||||
string rawData = await getRSV(cacheKey);
|
||||
if (!string.IsNullOrEmpty(rawData))
|
||||
{
|
||||
dbResult = JsonConvert.DeserializeObject<List<AnagProgettiModel>>(rawData);
|
||||
}
|
||||
else
|
||||
{
|
||||
Stopwatch stopWatch = new Stopwatch();
|
||||
stopWatch.Start();
|
||||
dbResult = dbController.AnagProjAll(true);
|
||||
rawData = JsonConvert.SerializeObject(dbResult, Formatting.None, new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
|
||||
await setRSV(cacheKey, rawData, shortTTL);
|
||||
stopWatch.Stop();
|
||||
TimeSpan ts = stopWatch.Elapsed;
|
||||
Log.Trace($"Effettuata lettura da DB per AnagProjActiv: {ts.TotalMilliseconds} ms");
|
||||
}
|
||||
if (dbResult == null)
|
||||
{
|
||||
dbResult = new List<AnagProgettiModel>();
|
||||
}
|
||||
return await Task.FromResult(dbResult);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recupera l'elenco fasi (ATTIVE)
|
||||
/// </summary>
|
||||
@@ -234,14 +96,35 @@ namespace GPW.CORE.Api.Data
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Imposta stato di una fase
|
||||
/// Recupera l'elenco progetti (ATTIVI)
|
||||
/// </summary>
|
||||
/// <param name="idxFase">ID</param>
|
||||
/// <param name="isActive">Stato attivo true/false (se è amster -_> aggiorna sottofasi x trigger su DB</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> FasiSetActive(int idxFase, bool isActive)
|
||||
public async Task<List<AnagProgettiModel>> AnagProjActiv()
|
||||
{
|
||||
return await dbController.FasiSetActive(idxFase, isActive);
|
||||
List<AnagProgettiModel>? dbResult = new List<AnagProgettiModel>();
|
||||
string cacheKey = $"{rKeyProjAct}";
|
||||
trackCache(cacheKey);
|
||||
string rawData = await getRSV(cacheKey);
|
||||
if (!string.IsNullOrEmpty(rawData))
|
||||
{
|
||||
dbResult = JsonConvert.DeserializeObject<List<AnagProgettiModel>>(rawData);
|
||||
}
|
||||
else
|
||||
{
|
||||
Stopwatch stopWatch = new Stopwatch();
|
||||
stopWatch.Start();
|
||||
dbResult = dbController.AnagProjAll(true);
|
||||
rawData = JsonConvert.SerializeObject(dbResult, Formatting.None, new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
|
||||
await setRSV(cacheKey, rawData, shortTTL);
|
||||
stopWatch.Stop();
|
||||
TimeSpan ts = stopWatch.Elapsed;
|
||||
Log.Trace($"Effettuata lettura da DB per AnagProjActiv: {ts.TotalMilliseconds} ms");
|
||||
}
|
||||
if (dbResult == null)
|
||||
{
|
||||
dbResult = new List<AnagProgettiModel>();
|
||||
}
|
||||
return await Task.FromResult(dbResult);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -280,24 +163,6 @@ namespace GPW.CORE.Api.Data
|
||||
return await Task.FromResult(dbResult);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// invalida tutta la cache in caso di update
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task InvalidateAllCache()
|
||||
{
|
||||
foreach (var item in cachedDataList)
|
||||
{
|
||||
#if false
|
||||
await _redisCacheClient.GetDbFromConfiguration().RemoveAsync(item);
|
||||
#endif
|
||||
await redisDb.StringSetAsync(item, "", TimeSpan.FromMilliseconds(5));
|
||||
}
|
||||
cachedDataList = new List<string>();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public async Task<List<CheckVc19Model>> ChecksGetByDip(int idxDip)
|
||||
{
|
||||
DateTime dtFine = DateTime.Today.AddDays(1);
|
||||
@@ -325,12 +190,57 @@ namespace GPW.CORE.Api.Data
|
||||
return await Task.FromResult(dbResult);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recupera record anomalie dipendenti
|
||||
/// </summary>
|
||||
/// <param name="inizio"></param>
|
||||
/// <param name="fine"></param>
|
||||
/// <param name="notOkApp"></param>
|
||||
/// <param name="notOkTim"></param>
|
||||
/// <param name="notOkLav"></param>
|
||||
public async Task<List<DipendendiAndAnomalie>> DipAndAnomGetAll(DateTime inizio, DateTime fine, bool notOkApp, bool notOkTim, bool notOkLav)
|
||||
{
|
||||
List<DipendendiAndAnomalie> dbResult = new List<DipendendiAndAnomalie>();
|
||||
Stopwatch stopWatch = new Stopwatch();
|
||||
stopWatch.Start();
|
||||
dbResult = dbController.DipAndAnomGetAll(inizio, fine, notOkApp, notOkTim, notOkLav);
|
||||
stopWatch.Stop();
|
||||
TimeSpan ts = stopWatch.Elapsed;
|
||||
Log.Trace($"Effettuata lettura da DB per DipAndAnomGetAll: {ts.TotalMilliseconds} ms");
|
||||
return await Task.FromResult(dbResult);
|
||||
}
|
||||
|
||||
public async Task<List<DipendentiModel>> DipendentiGetAll()
|
||||
{
|
||||
List<DipendentiModel> dbResult = new List<DipendentiModel>();
|
||||
Stopwatch stopWatch = new Stopwatch();
|
||||
stopWatch.Start();
|
||||
dbResult = dbController.DipendentiGetAll();
|
||||
stopWatch.Stop();
|
||||
TimeSpan ts = stopWatch.Elapsed;
|
||||
Log.Trace($"Effettuata lettura da DB per DipendentiGetAll: {ts.TotalMilliseconds} ms");
|
||||
return await Task.FromResult(dbResult);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Clear database controller
|
||||
dbController.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Imposta stato di una fase
|
||||
/// </summary>
|
||||
/// <param name="idxFase">ID</param>
|
||||
/// <param name="isActive">
|
||||
/// Stato attivo true/false (se è amster -_> aggiorna sottofasi x trigger su DB
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> FasiSetActive(int idxFase, bool isActive)
|
||||
{
|
||||
return await dbController.FasiSetActive(idxFase, isActive);
|
||||
}
|
||||
|
||||
public async Task<bool> InsertCheck(DCCDecode updItem, string clientIp)
|
||||
{
|
||||
bool done = false;
|
||||
@@ -357,6 +267,245 @@ namespace GPW.CORE.Api.Data
|
||||
return await Task.FromResult(done);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// invalida tutta la cache in caso di update
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task InvalidateAllCache()
|
||||
{
|
||||
foreach (var item in cachedDataList)
|
||||
{
|
||||
await redisDb.StringSetAsync(item, "", TimeSpan.FromMilliseconds(5));
|
||||
}
|
||||
cachedDataList = new List<string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recupera eventi dato criteri filtro
|
||||
/// </summary>
|
||||
/// <param name="inizio"></param>
|
||||
/// <param name="fine"></param>
|
||||
/// <param name="evento"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<RegistroEventiModel>> RegEventiGetFilt(DateTime inizio, DateTime fine, string evento)
|
||||
{
|
||||
List<RegistroEventiModel> dbResult = new List<RegistroEventiModel>();
|
||||
Stopwatch stopWatch = new Stopwatch();
|
||||
stopWatch.Start();
|
||||
dbResult = dbController.RegEventiGetFilt(inizio, fine, evento);
|
||||
stopWatch.Stop();
|
||||
TimeSpan ts = stopWatch.Elapsed;
|
||||
Log.Trace($"Effettuata lettura da DB per RegEventiGetFilt: {ts.TotalMilliseconds} ms");
|
||||
|
||||
return await Task.FromResult(dbResult);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Insert/Update di un record in Registro Eventi
|
||||
/// </summary>
|
||||
/// <param name="currItem"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> RegEventiUpdate(RegistroEventiModel currItem)
|
||||
{
|
||||
bool done = false;
|
||||
Stopwatch stopWatch = new Stopwatch();
|
||||
stopWatch.Start();
|
||||
done = dbController.RegEventiUpdate(currItem);
|
||||
stopWatch.Stop();
|
||||
TimeSpan ts = stopWatch.Elapsed;
|
||||
Log.Trace($"Effettuata operazione RegEventiUpdate: {ts.TotalMilliseconds} ms");
|
||||
|
||||
return await Task.FromResult(done);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recupera record anomalie dipendenti
|
||||
/// </summary>
|
||||
/// <param name="idxDipendente">singolo idx oppure 0 = tutti</param>
|
||||
/// <param name="dataFrom"></param>
|
||||
/// <param name="dataTo"></param>
|
||||
/// <param name="inatt"></param>
|
||||
/// <param name="showWE"></param>
|
||||
/// <param name="maxErrMin"></param>
|
||||
/// <param name="maxErrPlus"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<TeRaExplModel>> TeRaExplGetAll(int idxDipendente, DateTime dataFrom, DateTime dataTo, bool inatt, bool showWE, int maxErrMin, int maxErrPlus)
|
||||
{
|
||||
List<TeRaExplModel> dbResult = new List<TeRaExplModel>();
|
||||
Stopwatch stopWatch = new Stopwatch();
|
||||
stopWatch.Start();
|
||||
dbResult = dbController.TeRaExplGetAll(idxDipendente, dataFrom, dataTo, inatt, showWE, maxErrMin, maxErrPlus);
|
||||
stopWatch.Stop();
|
||||
TimeSpan ts = stopWatch.Elapsed;
|
||||
Log.Trace($"Effettuata lettura da DB per TeRaExplGetAll: {ts.TotalMilliseconds} ms");
|
||||
|
||||
return await Task.FromResult(dbResult);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recupera record anomalie dipendenti
|
||||
/// </summary>
|
||||
/// <param name="idxDipendente">singolo idx oppure 0 = tutti</param>
|
||||
/// <param name="inizio"></param>
|
||||
/// <param name="fine"></param>
|
||||
/// <param name="notOkApp"></param>
|
||||
/// <param name="notOkTim"></param>
|
||||
/// <param name="notOkLav"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<TimbratureExplModel>> TimbExplGetAnomalie(int idxDipendente, DateTime inizio, DateTime fine, bool notOkApp, bool notOkTim, bool notOkLav)
|
||||
{
|
||||
List<TimbratureExplModel> dbResult = new List<TimbratureExplModel>();
|
||||
Stopwatch stopWatch = new Stopwatch();
|
||||
stopWatch.Start();
|
||||
dbResult = dbController.TimbExplGetAnomalie(idxDipendente, inizio, fine, notOkApp, notOkTim, notOkLav);
|
||||
stopWatch.Stop();
|
||||
TimeSpan ts = stopWatch.Elapsed;
|
||||
Log.Trace($"Effettuata lettura da DB per TimbExplGetAnomalie: {ts.TotalMilliseconds} ms");
|
||||
|
||||
return await Task.FromResult(dbResult);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recupera record anomalie dipendenti
|
||||
/// </summary>
|
||||
/// <param name="idxDipendente">singolo idx oppure 0 = tutti</param>
|
||||
/// <param name="inizio"></param>
|
||||
/// <param name="fine"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<TimbratureExplModel>> TimbExplGetContinuato(int idxDipendente, DateTime inizio, DateTime fine)
|
||||
{
|
||||
List<TimbratureExplModel> dbResult = new List<TimbratureExplModel>();
|
||||
Stopwatch stopWatch = new Stopwatch();
|
||||
stopWatch.Start();
|
||||
dbResult = dbController.TimbExplGetContinuato(idxDipendente, inizio, fine);
|
||||
stopWatch.Stop();
|
||||
TimeSpan ts = stopWatch.Elapsed;
|
||||
Log.Trace($"Effettuata lettura da DB per TimbExplGetContinuato: {ts.TotalMilliseconds} ms");
|
||||
|
||||
return await Task.FromResult(dbResult);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recupera elenco anomalie x timbrature future
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<TimbratureModel>> TimbratureAnomalieFuture()
|
||||
{
|
||||
List<TimbratureModel> dbResult = new List<TimbratureModel>();
|
||||
Stopwatch stopWatch = new Stopwatch();
|
||||
stopWatch.Start();
|
||||
dbResult = dbController.TimbratureAnomalieFuture();
|
||||
stopWatch.Stop();
|
||||
TimeSpan ts = stopWatch.Elapsed;
|
||||
Log.Trace($"Effettuata lettura da DB per TimbratureAnomalieFuture: {ts.TotalMilliseconds} ms");
|
||||
return await Task.FromResult(dbResult);
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#region Protected Fields
|
||||
|
||||
protected const string rKeyCalcOreFase = "Check:OreFasi";
|
||||
protected const string rKeyFasiAct = "Check:FasiAct";
|
||||
protected const string rKeyProjAct = "Check:ProjAct";
|
||||
|
||||
/// <summary>
|
||||
/// TTL da 1 min x cache Redis
|
||||
/// </summary>
|
||||
protected const int shortTTL = 60 * 5;
|
||||
|
||||
#endregion Protected Fields
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Recupero chiave da redis
|
||||
/// </summary>
|
||||
/// <param name="rKey"></param>
|
||||
/// <returns></returns>
|
||||
protected async Task<string> getRSV(string rKey)
|
||||
{
|
||||
string answ = "";
|
||||
var rawData = await redisDb.StringGetAsync(rKey);
|
||||
if (rawData.HasValue)
|
||||
{
|
||||
answ = $"{rawData}";
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Salvataggio chiave in redis
|
||||
/// </summary>
|
||||
/// <param name="rKey"></param>
|
||||
/// <param name="rVal"></param>
|
||||
/// <param name="ttlSec"></param>
|
||||
/// <returns></returns>
|
||||
protected async Task<bool> setRSV(string rKey, string rVal, int ttlSec)
|
||||
{
|
||||
bool fatto = false;
|
||||
await redisDb.StringSetAsync(rKey, rVal, TimeSpan.FromSeconds(ttlSec));
|
||||
fatto = true;
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Salvataggio chiave in redis
|
||||
/// </summary>
|
||||
/// <param name="rKey"></param>
|
||||
/// <param name="rValInt"></param>
|
||||
/// <param name="ttlSec"></param>
|
||||
/// <returns></returns>
|
||||
protected async Task<bool> setRSV(string rKey, int rValInt, int ttlSec)
|
||||
{
|
||||
bool fatto = false;
|
||||
await redisDb.StringSetAsync(rKey, rValInt, TimeSpan.FromSeconds(ttlSec));
|
||||
fatto = true;
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registra in cache chiave se non fosse già in elenco
|
||||
/// </summary>
|
||||
/// <param name="newKey"></param>
|
||||
protected void trackCache(string newKey)
|
||||
{
|
||||
if (!cachedDataList.Contains(newKey))
|
||||
{
|
||||
cachedDataList.Add(newKey);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private static IConfiguration _configuration = null!;
|
||||
|
||||
private static ILogger<ApiDataService> _logger = null!;
|
||||
|
||||
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private readonly IEmailSender _emailSender;
|
||||
|
||||
//private readonly IDistributedCache distributedCache;
|
||||
//private readonly IRedisCacheClient _redisCacheClient;
|
||||
|
||||
/// <summary>
|
||||
/// Elenco obj in cache
|
||||
/// </summary>
|
||||
private List<string> cachedDataList = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// Oggetto per connessione a REDIS
|
||||
/// </summary>
|
||||
private ConnectionMultiplexer redisConn = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Oggetto DB redis da impiegare x chiamate R/W
|
||||
/// </summary>
|
||||
private IDatabase redisDb = null!;
|
||||
|
||||
#endregion Private Fields
|
||||
}
|
||||
}
|
||||
@@ -7,24 +7,25 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_WebToolingArtifacts Remove="Properties\PublishProfiles\IIS-PROD.pubxml" />
|
||||
<_WebToolingArtifacts Remove="Properties\PublishProfiles\IIS03.pubxml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="Properties\PublishProfiles\IIS01.pubxml.user" />
|
||||
<None Include="Properties\PublishProfiles\IIS-PROD.pubxml.user" />
|
||||
<None Include="Properties\PublishProfiles\IIS03.pubxml.user" />
|
||||
<None Include="Properties\PublishProfiles\IIS02.pubxml.user" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="6.0.7" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="NLog.Web.AspNetCore" Version="5.0.0" />
|
||||
<PackageReference Include="StackExchange.Redis" Version="2.6.48" />
|
||||
<PackageReference Include="StackExchange.Redis.Extensions.AspNetCore" Version="8.0.5" />
|
||||
<PackageReference Include="StackExchange.Redis.Extensions.Core" Version="8.0.5" />
|
||||
<PackageReference Include="StackExchange.Redis.Extensions.Newtonsoft" Version="8.0.5" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.3.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="6.0.14" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="StackExchange.Redis" Version="2.7.27" />
|
||||
<PackageReference Include="StackExchange.Redis.Extensions.AspNetCore" Version="9.1.0" />
|
||||
<PackageReference Include="StackExchange.Redis.Extensions.Core" Version="9.1.0" />
|
||||
<PackageReference Include="StackExchange.Redis.Extensions.Newtonsoft" Version="9.1.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
+35
-9
@@ -1,9 +1,11 @@
|
||||
using GPW.CORE.Api.Data;
|
||||
using GPW.CORE.Data;
|
||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||
using Microsoft.AspNetCore.Localization;
|
||||
using StackExchange.Redis;
|
||||
using StackExchange.Redis.Extensions.Core.Configuration;
|
||||
using StackExchange.Redis.Extensions.Newtonsoft;
|
||||
using System.Globalization;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
@@ -11,7 +13,7 @@ var builder = WebApplication.CreateBuilder(args);
|
||||
// configuration setup
|
||||
ConfigurationManager configuration = builder.Configuration;
|
||||
// Redis
|
||||
string connStringRedis = configuration.GetConnectionString("Redis");
|
||||
var connStringRedis = configuration.GetConnectionString("Redis");
|
||||
string redisSrvAddr = connStringRedis.Substring(0, connStringRedis.IndexOf(":"));
|
||||
|
||||
// avvio oggetto shared x redis...
|
||||
@@ -25,15 +27,23 @@ builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
|
||||
// abilitazione x email management con MailKit
|
||||
builder.Services.AddTransient<IEmailSender, MailKitEmailSender>();
|
||||
//builder.Services.AddTransient<IEmailSender, MailKitEmailSender>();
|
||||
builder.Services.AddSingleton<IEmailSender, MailKitEmailSender>();
|
||||
// recupero email reversed
|
||||
string revPwd = configuration["ExternalProviders:MailKit:SMTP:Password"] ?? "";
|
||||
string pwd = "";
|
||||
foreach (char c in revPwd)
|
||||
{
|
||||
pwd = c + pwd;
|
||||
}
|
||||
builder.Services.Configure<MailKitEmailSenderOptions>(options =>
|
||||
{
|
||||
options.Host_Address = configuration["ExternalProviders:MailKit:SMTP:Address"];
|
||||
options.Host_Port = Convert.ToInt32(configuration["ExternalProviders:MailKit:SMTP:Port"]);
|
||||
options.Host_Username = configuration["ExternalProviders:MailKit:SMTP:Account"];
|
||||
options.Host_Password = configuration["ExternalProviders:MailKit:SMTP:Password"];
|
||||
options.Sender_EMail = configuration["ExternalProviders:MailKit:SMTP:SenderEmail"];
|
||||
options.Sender_Name = configuration["ExternalProviders:MailKit:SMTP:SenderName"];
|
||||
options.Host_Address = configuration["ExternalProviders:MailKit:SMTP:Address"] ?? "";
|
||||
options.Host_Port = Convert.ToInt32(configuration["ExternalProviders:MailKit:SMTP:Port"] ?? "");
|
||||
options.Host_Username = configuration["ExternalProviders:MailKit:SMTP:Account"] ?? "";
|
||||
options.Host_Password = pwd;
|
||||
options.Sender_EMail = configuration["ExternalProviders:MailKit:SMTP:SenderEmail"] ?? "";
|
||||
options.Sender_Name = configuration["ExternalProviders:MailKit:SMTP:SenderName"] ?? "";
|
||||
});
|
||||
|
||||
builder.Services.AddStackExchangeRedisCache(options =>
|
||||
@@ -49,7 +59,10 @@ builder.Services.AddStackExchangeRedisExtensions<NewtonsoftSerializer>((options)
|
||||
{
|
||||
List<RedisConfiguration> newConf = new List<RedisConfiguration>();
|
||||
var currConf = configuration.GetSection("Redis").Get<RedisConfiguration>();
|
||||
newConf.Add(currConf);
|
||||
if (currConf != null)
|
||||
{
|
||||
newConf.Add(currConf);
|
||||
}
|
||||
return newConf;
|
||||
//return configuration.GetSection("Redis").Get<RedisConfiguration>();
|
||||
});
|
||||
@@ -68,6 +81,19 @@ if (app.Environment.IsDevelopment())
|
||||
app.UseSwaggerUI();
|
||||
}
|
||||
|
||||
// cultura IT...
|
||||
var supportedCultures = new[]{
|
||||
new CultureInfo("it-IT")
|
||||
};
|
||||
app.UseRequestLocalization(new RequestLocalizationOptions
|
||||
{
|
||||
DefaultRequestCulture = new RequestCulture("it-IT"),
|
||||
SupportedCultures = supportedCultures,
|
||||
FallBackToParentCultures = false
|
||||
});
|
||||
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CreateSpecificCulture("it-IT");
|
||||
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseAuthorization();
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
|
||||
by editing this MSBuild file. In order to learn more about this please visit https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<AllowUntrustedCertificate>true</AllowUntrustedCertificate>
|
||||
<WebPublishMethod>MSDeploy</WebPublishMethod>
|
||||
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
|
||||
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
|
||||
<LastUsedPlatform>Any CPU</LastUsedPlatform>
|
||||
<SiteUrlToLaunchAfterPublish>https://office.egalware.com/GPW/Api</SiteUrlToLaunchAfterPublish>
|
||||
<ExcludeApp_Data>False</ExcludeApp_Data>
|
||||
<ProjectGuid>ef8d5a17-0d60-4ef0-9262-57afac574843</ProjectGuid>
|
||||
<SelfContained>false</SelfContained>
|
||||
<MSDeployServiceURL>https://office.egalware.com:8172/MsDeploy.axd</MSDeployServiceURL>
|
||||
<DeployIisAppPath>office.egalware.com/GPW/Api</DeployIisAppPath>
|
||||
<RemoteSitePhysicalPath />
|
||||
<SkipExtraFilesOnServer>True</SkipExtraFilesOnServer>
|
||||
<MSDeployPublishMethod>WMSVC</MSDeployPublishMethod>
|
||||
<EnableMSDeployBackup>True</EnableMSDeployBackup>
|
||||
<EnableMsDeployAppOffline>True</EnableMsDeployAppOffline>
|
||||
<UserName>jenkins</UserName>
|
||||
<_SavePWD>True</_SavePWD>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
|
||||
by editing this MSBuild file. In order to learn more about this please visit https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<TimeStampOfAssociatedLegacyPublishXmlFile />
|
||||
<EncryptedPassword>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAk75miMJLMkCTEelQutKpbwAAAAACAAAAAAADZgAAwAAAABAAAAB43BVhUmznhAu3pUfV1IfOAAAAAASAAACgAAAAEAAAAEV8hgbujDFfsMjS77NS2oYYAAAAUHPGFaVWgRqQPDU4wk5KGABmVHKko4/9FAAAANtaROBOcPHljx4RnmQHj5aHdtYk</EncryptedPassword>
|
||||
<History>True|2022-01-27T09:34:09.2346456Z;True|2022-01-27T10:13:36.3080675+01:00;True|2022-01-27T10:05:45.6649507+01:00;True|2022-01-26T14:34:16.5263189+01:00;True|2022-01-26T13:04:22.2336648+01:00;False|2022-01-26T13:04:06.0677616+01:00;True|2021-11-08T09:03:37.7855257+01:00;True|2021-11-08T09:03:34.8263479+01:00;True|2021-11-08T09:03:31.8889390+01:00;True|2021-10-29T16:19:33.6539408+02:00;True|2021-10-29T16:19:28.2082360+02:00;True|2021-10-26T16:12:11.7740950+02:00;True|2021-10-26T16:11:56.2014641+02:00;True|2021-10-26T16:11:22.2897842+02:00;False|2021-10-26T16:10:58.3733037+02:00;False|2021-10-26T16:10:29.4793991+02:00;True|2021-10-21T17:35:11.9761128+02:00;True|2021-10-18T20:22:00.9305399+02:00;True|2021-10-18T18:32:29.4558070+02:00;True|2021-10-18T18:32:22.8950294+02:00;True|2021-10-18T18:16:13.7563877+02:00;True|2021-10-18T18:15:48.5678387+02:00;True|2021-10-18T12:45:45.7228681+02:00;True|2021-10-18T12:14:22.3221605+02:00;True|2021-10-18T12:14:15.7373530+02:00;True|2021-10-18T12:10:43.8607301+02:00;</History>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:39480",
|
||||
"sslPort": 44359
|
||||
}
|
||||
},
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": true,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:39480",
|
||||
"sslPort": 44359
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"GPW.CORE.Api": {
|
||||
"commandName": "Project",
|
||||
|
||||
@@ -5,5 +5,19 @@
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"EnableChiudiFasi": "true"
|
||||
"EnableChiudiFasi": "true",
|
||||
"TimbraCheck": {
|
||||
"checkAnomAppr": true,
|
||||
"checkAnomTimb": true,
|
||||
"checkAnomOreLav": true,
|
||||
"checkAnomOreLavComm": true,
|
||||
"checkAnomContinuato": true,
|
||||
"sendEmailToUser": true,
|
||||
"includeDirectUrl": true,
|
||||
"gg2Chk": 60,
|
||||
"gg2ChkCont": 30,
|
||||
"gg2ChkOreCaricate": 30,
|
||||
"maxErrMin": -29,
|
||||
"maxErrPlus": 91
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"ConnectionStrings": {
|
||||
"GPW.DB": "Server=SQLSTEAM;Database=GPW;User ID=sa;Password=keyhammer;integrated security=False;MultipleActiveResultSets=True;App=LiMan.API;",
|
||||
"GPW.DB": "Server=W2019-SQL-STEAM;Database=GPW;User ID=sa;Password=keyhammer16;integrated security=False;MultipleActiveResultSets=True;App=LiMan.API;",
|
||||
"Redis": "localhost:6379,DefaultDatabase=15,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000"
|
||||
},
|
||||
"ExternalProviders": {
|
||||
@@ -16,7 +16,7 @@
|
||||
"Address": "smtp-mail.outlook.com",
|
||||
"Port": "587",
|
||||
"Account": "steamwarebot@outlook.it",
|
||||
"Password": "siamoInViaNazionale93",
|
||||
"Password": "!39elanoizaNaiVnIomais",
|
||||
"SenderEmail": "steamwarebot@outlook.it",
|
||||
"SenderName": "Steamware Email BOT"
|
||||
}
|
||||
@@ -24,7 +24,8 @@
|
||||
},
|
||||
"MailDest": {
|
||||
"Admin": "samuele@steamware.net",
|
||||
"ProjCheck": "samuele.locatelli@egalware.com,mara.baroni@egalware.com"
|
||||
"ProjCheck": "samuele.locatelli@egalware.com,mara.baroni@egalware.com",
|
||||
"TimbCheck": "samuele.locatelli@egalware.com,mara.baroni@egalware.com"
|
||||
},
|
||||
"EnableChiudiFasi": "false",
|
||||
"Redis": {
|
||||
@@ -42,5 +43,22 @@
|
||||
}
|
||||
],
|
||||
"Database": 15
|
||||
},
|
||||
"ServerConv": {
|
||||
"baseUrl": "https://office.egalware.com/GPW/ADMIN/"
|
||||
},
|
||||
"TimbraCheck": {
|
||||
"checkAnomAppr": true,
|
||||
"checkAnomTimb": true,
|
||||
"checkAnomOreLav": true,
|
||||
"checkAnomOreLavComm": true,
|
||||
"checkAnomContinuato": true,
|
||||
"sendEmailToUser": false,
|
||||
"includeDirectUrl": true,
|
||||
"gg2Chk": 60,
|
||||
"gg2ChkCont": 30,
|
||||
"gg2ChkOreCaricate": 30,
|
||||
"maxErrMin": -29,
|
||||
"maxErrPlus": 91
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.4.33205.214
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GPW.CORE.Comp", "GPW.CORE.Comp\GPW.CORE.Comp.csproj", "{056826D6-6B88-42AA-AD09-FC380955834D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GPW.CORE.Test", "GPW.CORE.Test\GPW.CORE.Test.csproj", "{9E5A3295-08BF-4603-9FA3-D38A2F1100E5}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{056826D6-6B88-42AA-AD09-FC380955834D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{056826D6-6B88-42AA-AD09-FC380955834D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{056826D6-6B88-42AA-AD09-FC380955834D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{056826D6-6B88-42AA-AD09-FC380955834D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9E5A3295-08BF-4603-9FA3-D38A2F1100E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9E5A3295-08BF-4603-9FA3-D38A2F1100E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9E5A3295-08BF-4603-9FA3-D38A2F1100E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9E5A3295-08BF-4603-9FA3-D38A2F1100E5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {B0B304CA-6B40-44FF-A9C3-F90A3C56B21A}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,54 @@
|
||||
@if (ItemMode == ColType.labelStart || ItemMode == ColType.labelEnd)
|
||||
{
|
||||
<svg viewBox="0 0 @vBox.Width @vBox.Height" xmlns="http://www.w3.org/2000/svg">
|
||||
@*<rect x="0" y="0" width="@vBox.Width" height="@vBox.Height" class="canv"></rect>*@
|
||||
@foreach (var item in LabelItems())
|
||||
{
|
||||
<g transform="translate(@(item.pX),@(item.pY))">
|
||||
<foreignObject x="0" y="0" width="@vBox.Width" height="@hFO">
|
||||
<div class="hour-label">@item.value</div>
|
||||
</foreignObject>
|
||||
</g>
|
||||
}
|
||||
</svg>
|
||||
}
|
||||
else
|
||||
{
|
||||
<svg viewBox="0 0 @vBox.Width @vBox.Height" xmlns="http://www.w3.org/2000/svg" style="border-top: 1px solid #000;border-left: 1px solid #000; border-bottom: 1px solid #000;">
|
||||
@*<rect x="0" y="0" width="@vBox.Width" height="@vBox.Height" class="canv"></rect>*@
|
||||
@foreach (var item in BoxItems())
|
||||
{
|
||||
@*<a data-bs-toggle="modal" data-bs-target="#detailModal" style="text-decoration: none;" @onclick="()=>selItem(item)">*@
|
||||
<a style="text-decoration: none;" @onclick="()=>selItem(item)">
|
||||
<g transform="translate(@(item.pX),@(item.pY))">
|
||||
<rect x="0" y="0" width="@item.width" height="@item.height" class="@item.cssClass" rx="30"></rect>
|
||||
<foreignObject x="@mFO" y="@mFO" width="@item.width" height="@item.height">
|
||||
<div class="event-title">@item.title</div>
|
||||
<div class="event-time">@($"{item.start:HH:mm}")-@($"{item.end:HH:mm}")</div>
|
||||
<div class="event-body">@item.value</div>
|
||||
</foreignObject>
|
||||
</g>
|
||||
</a>
|
||||
}
|
||||
</svg>
|
||||
}
|
||||
|
||||
<ToastDisplay DoShow="@showDetail" currPosition="ToastDisplay.DispPosition.midCenter" TitleSx="@titleSx" TitleDx="@titleDx" ReportClose="DetClosed">
|
||||
<ChildContent>
|
||||
@if (currData != null)
|
||||
{
|
||||
<div class="bg-dark p-3">
|
||||
<svg viewBox="0 0 @(vBox.Height/4) @(vBox.Height/4)" xmlns="http://www.w3.org/2000/svg" >
|
||||
<g>
|
||||
<rect x="0" y="0" width="@(vBox.Height/4)" height="@(vBox.Height/4)" class="@currData.cssClass" rx="30"></rect>
|
||||
<foreignObject x="@mFO" y="@mFO" width="@(vBox.Height/3)" height="@(vBox.Height/3)">
|
||||
<div class="event-title">@currData.title</div>
|
||||
<div class="event-time">@($"{currData.start:HH:mm}")-@($"{currData.end:HH:mm}")</div>
|
||||
<div class="event-body">@currData.value</div>
|
||||
</foreignObject>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
}
|
||||
</ChildContent>
|
||||
</ToastDisplay>
|
||||
@@ -0,0 +1,214 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Drawing;
|
||||
|
||||
namespace GPW.CORE.Comp
|
||||
{
|
||||
public partial class CalWeekColumn
|
||||
{
|
||||
#region Public Enums
|
||||
|
||||
public enum ColType
|
||||
{
|
||||
/// <summary>
|
||||
/// Tipo etichetta Start (SX)
|
||||
/// </summary>
|
||||
labelStart,
|
||||
|
||||
/// <summary>
|
||||
/// Tipo etichetta End (DX)
|
||||
/// </summary>
|
||||
labelEnd,
|
||||
|
||||
/// <summary>
|
||||
/// Colonna dati
|
||||
/// </summary>
|
||||
dataContainer
|
||||
}
|
||||
|
||||
#endregion Public Enums
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Lista etichette da mostrare (richiede tipo label...)
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public List<CalendarEvent> EventList { get; set; } = new List<CalendarEvent>();
|
||||
|
||||
/// <summary>
|
||||
/// Modalit� di disegno
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public ColType ItemMode { get; set; } = ColType.dataContainer;
|
||||
|
||||
[Parameter]
|
||||
public int ValMax { get; set; } = 19;
|
||||
|
||||
[Parameter]
|
||||
public int ValMin { get; set; } = 9;
|
||||
|
||||
/// <summary>
|
||||
/// Dimensioni viewbox
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Size vBox { get; set; } = new Size(1200, 3200);
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Protected Properties
|
||||
|
||||
protected boxData? currData { get; set; } = null;
|
||||
|
||||
protected int hFO
|
||||
{
|
||||
get => 100;// EventList.Count > 0 ? vBox.Height / EventList.Count : vBox.Height;
|
||||
}
|
||||
|
||||
protected int mFO
|
||||
{
|
||||
get => vBox.Width * 4 / 100;
|
||||
}
|
||||
|
||||
protected int wFO
|
||||
{
|
||||
get => vBox.Width * 98 / 100;
|
||||
}
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected List<boxData> BoxItems()
|
||||
{
|
||||
List<boxData> answ = new List<boxData>();
|
||||
int step = vBox.Height / (ValMax - ValMin);
|
||||
int numEv = EventList.Count;
|
||||
int evWidth = numEv > 1 ? (int)(1.2 * vBox.Width / numEv) : (int)(0.9 * vBox.Width);
|
||||
int offsetX = 1;
|
||||
int offsetY = 0;// step / 2;
|
||||
if (numEv > 0)
|
||||
{
|
||||
int xStep = evWidth / EventList.Count;
|
||||
int deltaX = 0;
|
||||
answ = EventList
|
||||
.OrderBy(x => x.Inizio)
|
||||
.Select(x => new boxData()
|
||||
{
|
||||
pX = offsetX + xStep * (deltaX++),
|
||||
//pY = offsetY + (x.Inizio.Hour - ValMin) * step,
|
||||
pY = offsetY + (int)(x.Inizio.AddHours(-ValMin).TimeOfDay.TotalHours * step),
|
||||
width = evWidth,
|
||||
height = offsetY + (int)(x.Fine.Subtract(x.Inizio).TotalHours * step),
|
||||
title = x.Type,
|
||||
value = x.Description,
|
||||
start = x.Inizio,
|
||||
end = x.Fine,
|
||||
cssClass = x.CssClass
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converte la stringa in formato markup valido
|
||||
/// </summary>
|
||||
/// <param name="rawData"></param>
|
||||
/// <returns></returns>
|
||||
protected MarkupString getMarkup(string rawData)
|
||||
{
|
||||
return new MarkupString(rawData);
|
||||
}
|
||||
|
||||
protected bool showDetail { get; set; } = false;
|
||||
protected string titleDx = "";
|
||||
protected string titleSx = "";
|
||||
|
||||
|
||||
protected async Task DetClosed(bool closed)
|
||||
{
|
||||
if (closed)
|
||||
{
|
||||
currData = null;
|
||||
showDetail = false;
|
||||
}
|
||||
await Task.Delay(1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Genera una lista di etichette con corrdinate
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected List<labelData> LabelItems()
|
||||
{
|
||||
int step = vBox.Height / numEv;// (ValMax - ValMin);
|
||||
int offset = 0;// step / 2;
|
||||
|
||||
List<labelData> answ = EventList
|
||||
.OrderBy(x => x.Inizio)
|
||||
.Select(x => new labelData()
|
||||
{
|
||||
pX = vBox.Width / 10,
|
||||
pY = offset + (int)(x.Inizio.AddHours(-ValMin).TimeOfDay.TotalHours * step),
|
||||
value = x.Title
|
||||
})
|
||||
.ToList();
|
||||
return answ;
|
||||
}
|
||||
|
||||
protected async void selItem(boxData item)
|
||||
{
|
||||
titleSx = $"{item.start:dddd dd}";
|
||||
titleDx = $"{item.start:MMMM yyyy}";
|
||||
|
||||
currData = item;
|
||||
showDetail = true;
|
||||
await Task.Delay(1);
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
protected string Messaggio = "";
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Protected Classes
|
||||
|
||||
protected class boxData
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
public string cssClass { get; set; } = "";
|
||||
public DateTime end { get; set; } = DateTime.Today;
|
||||
public int height { get; set; } = 0;
|
||||
public int pX { get; set; } = 0;
|
||||
public int pY { get; set; } = 0;
|
||||
public DateTime start { get; set; } = DateTime.Today;
|
||||
public string title { get; set; } = "";
|
||||
public string value { get; set; } = "";
|
||||
public int width { get; set; } = 0;
|
||||
|
||||
#endregion Public Properties
|
||||
}
|
||||
|
||||
protected class labelData
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
public int pX { get; set; } = 0;
|
||||
public int pY { get; set; } = 0;
|
||||
public string value { get; set; } = "";
|
||||
|
||||
#endregion Public Properties
|
||||
}
|
||||
|
||||
#endregion Protected Classes
|
||||
|
||||
#region Private Properties
|
||||
|
||||
private int numEv
|
||||
{
|
||||
get => EventList.Count > 0 ? EventList.Count : 1;
|
||||
}
|
||||
|
||||
#endregion Private Properties
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
.lblText {
|
||||
font-size: 0.3rem;
|
||||
fill: white;
|
||||
}
|
||||
.lblBoxTitle {
|
||||
font-size: 0.25rem;
|
||||
fill: white;
|
||||
}
|
||||
.lblBoxText {
|
||||
font-size: 0.2rem;
|
||||
fill: white;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
.heavy {
|
||||
font: bold 30px sans-serif;
|
||||
fill: white;
|
||||
}
|
||||
.canv {
|
||||
fill: #34495E;
|
||||
}
|
||||
.blockMal {
|
||||
fill: rgba(3, 155, 229, 0.75);
|
||||
stroke: rgba(3, 155, 229, 0.9);
|
||||
stroke-width: 0.5rem;
|
||||
}
|
||||
.blockPerm {
|
||||
fill: rgba(153, 102, 222, 0.75);
|
||||
stroke: rgba(153, 102, 222, 0.9);
|
||||
stroke-width: 0.5rem;
|
||||
}
|
||||
.blockFerie {
|
||||
fill: rgba(0, 185, 0, 0.75);
|
||||
stroke: rgba(0, 255, 0, 0.9);
|
||||
stroke-width: 0.5rem;
|
||||
}
|
||||
.block104 {
|
||||
fill: rgba(222, 0, 171, 0.75);
|
||||
stroke: rgba(222, 0, 171, 0.9);
|
||||
stroke-width: 0.5rem;
|
||||
}
|
||||
.blockChius {
|
||||
fill: rgba(165, 185, 0, 0.75);
|
||||
stroke: rgba(235, 255, 71, 0.9);
|
||||
stroke-width: 0.5rem;
|
||||
}
|
||||
.blockFest {
|
||||
fill: rgba(242, 35, 35, 0.75);
|
||||
stroke: rgba(242, 35, 35, 0.9);
|
||||
stroke-width: 0.5rem;
|
||||
}
|
||||
.event-title {
|
||||
color: #FFFFFF;
|
||||
font-size: 2rem;
|
||||
}
|
||||
.event-time {
|
||||
color: #69CDFF;
|
||||
font-size: 2rem;
|
||||
}
|
||||
.hour-label {
|
||||
color: #9ABCDE;
|
||||
font-size: 2rem;
|
||||
}
|
||||
.event-body {
|
||||
/*color: #C8DCFF;*/
|
||||
color: #A8BCFF;
|
||||
font-size: 1.9rem;
|
||||
word-break: break-word;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
.lblText {
|
||||
font-size: 0.3rem;
|
||||
fill: white;
|
||||
}
|
||||
|
||||
.lblBoxTitle {
|
||||
font-size: 0.25rem;
|
||||
fill: white;
|
||||
}
|
||||
|
||||
.lblBoxText {
|
||||
font-size: 0.2rem;
|
||||
fill: white;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.heavy {
|
||||
font: bold 30px sans-serif;
|
||||
fill: white;
|
||||
}
|
||||
|
||||
|
||||
.canv {
|
||||
fill: #34495E;
|
||||
}
|
||||
|
||||
.blockMal {
|
||||
fill: rgba(3, 155, 229, 0.75);
|
||||
stroke: rgba(3, 155, 229, 0.9);
|
||||
stroke-width: 0.5rem;
|
||||
}
|
||||
|
||||
.blockPerm {
|
||||
fill: rgba(153, 102, 222, 0.75);
|
||||
stroke: rgba(153, 102, 222, 0.9);
|
||||
stroke-width: 0.5rem;
|
||||
}
|
||||
|
||||
.blockFerie {
|
||||
fill: rgba(0, 185, 0, 0.75);
|
||||
stroke: rgba(0, 255, 0, 0.9);
|
||||
stroke-width: 0.5rem;
|
||||
}
|
||||
|
||||
.block104 {
|
||||
fill: rgba(222, 0, 171, 0.75);
|
||||
stroke: rgba(222, 0, 171, 0.9);
|
||||
stroke-width: 0.5rem;
|
||||
}
|
||||
|
||||
.blockChius {
|
||||
fill: rgba(165, 185, 0, 0.75);
|
||||
stroke: rgba(235, 255, 71, 0.9);
|
||||
stroke-width: 0.5rem;
|
||||
}
|
||||
|
||||
.blockFest {
|
||||
fill: rgba(242, 35, 35, 0.75);
|
||||
stroke: rgba(242, 35, 35, 0.9);
|
||||
stroke-width: 0.5rem;
|
||||
}
|
||||
|
||||
.event-title {
|
||||
color: #FFFFFF;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.event-time {
|
||||
color: #69CDFF;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.hour-label {
|
||||
color: #9ABCDE;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.event-body {
|
||||
/*color: #C8DCFF;*/
|
||||
color: #A8BCFF ;
|
||||
font-size: 1.9rem;
|
||||
word-break: break-word;
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
.lblText{font-size:.3rem;fill:white;}.lblBoxTitle{font-size:.25rem;fill:white;}.lblBoxText{font-size:.2rem;fill:white;word-wrap:break-word;}.heavy{font:bold 30px sans-serif;fill:white;}.canv{fill:#34495e;}.blockMal{fill:rgba(3,155,229,.75);stroke:rgba(3,155,229,.9);stroke-width:.5rem;}.blockPerm{fill:rgba(153,102,222,.75);stroke:rgba(153,102,222,.9);stroke-width:.5rem;}.blockFerie{fill:rgba(0,185,0,.75);stroke:rgba(0,255,0,.9);stroke-width:.5rem;}.block104{fill:rgba(222,0,171,.75);stroke:rgba(222,0,171,.9);stroke-width:.5rem;}.blockChius{fill:rgba(165,185,0,.75);stroke:rgba(235,255,71,.9);stroke-width:.5rem;}.blockFest{fill:rgba(242,35,35,.75);stroke:rgba(242,35,35,.9);stroke-width:.5rem;}.event-title{color:#fff;font-size:2rem;}.event-time{color:#69cdff;font-size:2rem;}.hour-label{color:#9abcde;font-size:2rem;}.event-body{color:#a8bcff;font-size:1.9rem;word-break:break-word;}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GPW.CORE.Comp
|
||||
{
|
||||
public class CalendarEvent
|
||||
{
|
||||
public int id { get; set; } = 0;
|
||||
public DateTime Inizio { get; set; } = DateTime.Today.AddHours(8);
|
||||
public DateTime Fine { get; set; } = DateTime.Today.AddHours(10);
|
||||
public string CssClass { get; set; } = "";
|
||||
public string Title { get; set; } = "";
|
||||
public string Description { get; set; } = "";
|
||||
public string Icon { get; set; } = "";
|
||||
public string Type { get; set; } = "";
|
||||
public string ToolTip { get; set; } = "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
@if (WeekRows == null || WeekRows.Count == 0)
|
||||
{
|
||||
<LoadingData></LoadingData>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="text-center cssTable" style="@HeadStyle">
|
||||
<thead>
|
||||
<tr class="row">
|
||||
@for (int i = 0; i < 7; i++)
|
||||
{
|
||||
<th class="col">@($"{DateList[i]:ddd}".Substring(0, 1).ToUpper())</th>
|
||||
}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@if (SingleWeek)
|
||||
{
|
||||
<tr class="row">
|
||||
@foreach (var giorno in SingleWeekRow)
|
||||
{
|
||||
<td class="col @singleDayCss(giorno)" @onclick="() => clickDay(giorno)">
|
||||
<span class="@singleDaySpanCss(giorno)">
|
||||
@($"{giorno:dd}")
|
||||
</span>
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
else
|
||||
{
|
||||
@foreach (var settim in WeekRows)
|
||||
{
|
||||
<tr class="row">
|
||||
@foreach (var giorno in settim)
|
||||
{
|
||||
<td class="col @dayCss(giorno)" @onclick="() => clickDay(giorno)">
|
||||
<span class="@spanCss(giorno)">
|
||||
@($"{giorno:dd}")
|
||||
</span>
|
||||
@if (!(giorno.DayOfWeek == DayOfWeek.Saturday || giorno.DayOfWeek == DayOfWeek.Sunday))
|
||||
{
|
||||
<div class="pallini">
|
||||
@if (hasDot(giorno, "MAL"))
|
||||
{
|
||||
<div class="malattie">
|
||||
|
||||
</div>
|
||||
}
|
||||
@if (hasDot(giorno, "FER"))
|
||||
{
|
||||
<div class="ferie">
|
||||
|
||||
</div>
|
||||
}
|
||||
@if (hasDot(giorno, "PERM"))
|
||||
{
|
||||
<div class="permessi">
|
||||
|
||||
</div>
|
||||
}
|
||||
@if (hasDot(giorno, "104"))
|
||||
{
|
||||
<div class="permessi104">
|
||||
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
@if (!SingleWeek)
|
||||
{
|
||||
<tr class="row">
|
||||
<td class="col ">
|
||||
<div colspan="7" class="meseAnno d-flex justify-content-around">
|
||||
<button class="containerBtnTemp" @onclick="()=> subtractMonth()"><i class="fa-solid fa-circle-chevron-left"></i></button>
|
||||
<div class="">
|
||||
@($"{DtRif: MMM yyyy}")
|
||||
</div>
|
||||
<button class="containerBtnTemp" @onclick="()=> addMonth()"><i class="fa-solid fa-circle-chevron-right"></i></button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tfoot>
|
||||
</table>
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,333 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace GPW.CORE.Comp
|
||||
{
|
||||
public partial class CalendarMonth
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<bool> backToCal { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Css giorno mese corrente
|
||||
/// default: text-danger
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string CurrMonthCss { get; set; } = "text-light";
|
||||
|
||||
/// <summary>
|
||||
/// Dizionario configurazione date (per check colori su data)
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Dictionary<DateTime, string>? DateCheck { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Dizionario configurazione date tipo BLOCK (es feste, chiusure aziendali)
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Dictionary<DateTime, string>? DateCheckBlock { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Evento selezione data valida (= entro il mese corrente/selezionato)
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<DateTime> DateSelected { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Day di riferimento (tipicamente = oggi) per disegnare calendario alla data corrente
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public DateTime DtRif { get; set; } = DateTime.Today;
|
||||
|
||||
/// <summary>
|
||||
/// Elenco eventi da mostrare sul calendario
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public List<CalendarEvent>? EventList { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Css titolo
|
||||
/// default: color: red
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string HeadStyle { get; set; } = "color: red";
|
||||
|
||||
/// <summary>
|
||||
/// Css sfondo principale
|
||||
/// default: table table-dark table-borderless opt alt: table-striped, table-responsive
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string MainCss { get; set; } = "table table-dark table-borderless";
|
||||
|
||||
/// <summary>
|
||||
/// Evento cambio di mese
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<DateTime> MonthChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Css giorno tipico
|
||||
/// default: text-danger
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string OtherMonthCss { get; set; } = "text-secondary";
|
||||
|
||||
/// <summary>
|
||||
/// Css giorno selezionato
|
||||
/// default: bg-danger text-warning
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string SelDayCss { get; set; } = "bg-danger text-warning rounded-top p-2";
|
||||
|
||||
/// <summary>
|
||||
/// Css dei giorni della settimana selezionata
|
||||
/// default: bg-danger text-warning
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string SelWeekCss { get; set; } = "text-light m-0 px-0";
|
||||
|
||||
/// <summary>
|
||||
/// Imposta di mostrare SOLO una singola settimana (per selezione data)
|
||||
/// default: false
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool SingleWeek { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Css per giorni weekend (sab-dom)
|
||||
/// default: text-danger
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string WeekEndCss { get; set; } = "bg-secondary text-light bg-opacity-75";
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
dtCurr = DateTime.Today;
|
||||
await Task.Delay(1);
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
await FixDate();
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Properties
|
||||
|
||||
/// <summary>
|
||||
/// Elenco date da mostrare
|
||||
/// </summary>
|
||||
private List<DateTime> DateList { get; set; } = new List<DateTime>();
|
||||
|
||||
private DateTime dtCurr { get; set; } = DateTime.Today;
|
||||
private DateTime MonthEnd { get; set; } = DateTime.Today.AddMonths(1);
|
||||
|
||||
private DateTime MonthStart { get; set; } = DateTime.Today;
|
||||
|
||||
/// <summary>
|
||||
/// Singola riga in caso di selezione...
|
||||
/// </summary>
|
||||
private List<DateTime> SingleWeekRow
|
||||
{
|
||||
get
|
||||
{
|
||||
List<DateTime> answ = new List<DateTime>();
|
||||
foreach (var item in WeekRows)
|
||||
{
|
||||
if (item.Contains(DtRif))
|
||||
{
|
||||
answ = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Righe da disegnare nel calendario
|
||||
/// </summary>
|
||||
private List<List<DateTime>> WeekRows { get; set; } = new List<List<DateTime>>();
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private async Task addMonth()
|
||||
{
|
||||
await FixDate();
|
||||
await MonthChanged.InvokeAsync(DtRif.AddMonths(1));
|
||||
}
|
||||
|
||||
private async Task clickDay(DateTime dtClick)
|
||||
{
|
||||
// se è mese prec/successivo --> sposto data rif
|
||||
if (dtClick < MonthStart)
|
||||
{
|
||||
DtRif = DtRif.AddMonths(-1);
|
||||
await FixDate();
|
||||
await MonthChanged.InvokeAsync(dtClick);
|
||||
}
|
||||
else if (dtClick > MonthEnd)
|
||||
{
|
||||
DtRif = DtRif.AddMonths(1);
|
||||
await FixDate();
|
||||
await MonthChanged.InvokeAsync(dtClick);
|
||||
}
|
||||
else
|
||||
{
|
||||
// altrimenti riporto evento
|
||||
await DateSelected.InvokeAsync(dtClick);
|
||||
if (EventList != null)
|
||||
{
|
||||
var eventListWeekly = EventList.Where(x => SingleWeekRow.Contains(dtClick)).ToList();
|
||||
}
|
||||
}
|
||||
await Task.Delay(1);
|
||||
}
|
||||
|
||||
private string dayCss(DateTime currDay)
|
||||
{
|
||||
string answ = CurrMonthCss;
|
||||
// se è fuori estremi mese --> grigio...
|
||||
if (currDay < MonthStart || currDay > MonthEnd)
|
||||
{
|
||||
answ = OtherMonthCss;
|
||||
}
|
||||
else
|
||||
{
|
||||
// cerco prima i valori BLOCK...
|
||||
if (DateCheckBlock != null && DateCheckBlock.ContainsKey(currDay))
|
||||
{
|
||||
answ = DateCheckBlock[currDay];
|
||||
}
|
||||
// se è weekend forzo quello
|
||||
else if (currDay.DayOfWeek == DayOfWeek.Saturday || currDay.DayOfWeek == DayOfWeek.Sunday)
|
||||
{
|
||||
answ = WeekEndCss;
|
||||
}
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sistemazione date x disegnare controlli
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task FixDate()
|
||||
{
|
||||
await Task.Delay(1);
|
||||
// disegno sempre 6 righe = 42 gg
|
||||
int numDD = 42;
|
||||
MonthStart = new DateTime(DtRif.Year, DtRif.Month, 1);
|
||||
MonthEnd = MonthStart.AddMonths(1).AddDays(-1);
|
||||
DateTime calStart = MonthStart;
|
||||
// calcolo date calendario in base al giorno dell'inizio mese...
|
||||
switch (MonthStart.DayOfWeek)
|
||||
{
|
||||
case DayOfWeek.Sunday:
|
||||
calStart = MonthStart.AddDays(-6);
|
||||
break;
|
||||
|
||||
case DayOfWeek.Monday:
|
||||
calStart = MonthStart.AddDays(-7);
|
||||
break;
|
||||
|
||||
case DayOfWeek.Tuesday:
|
||||
calStart = MonthStart.AddDays(-1);
|
||||
break;
|
||||
|
||||
case DayOfWeek.Wednesday:
|
||||
calStart = MonthStart.AddDays(-2);
|
||||
break;
|
||||
|
||||
case DayOfWeek.Thursday:
|
||||
calStart = MonthStart.AddDays(-3);
|
||||
break;
|
||||
|
||||
case DayOfWeek.Friday:
|
||||
calStart = MonthStart.AddDays(-4);
|
||||
break;
|
||||
|
||||
case DayOfWeek.Saturday:
|
||||
calStart = MonthStart.AddDays(-5);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// calcolo fine mese sapendo che sono cmq 7 x 6 week...
|
||||
int numEnd = numDD - MonthEnd.Subtract(calStart).Days;
|
||||
DateTime calEnd = MonthEnd.AddDays(numEnd);
|
||||
// calcolo elenco date (da disegnare)
|
||||
DateList = new List<DateTime>();
|
||||
for (int i = 0; i < numDD; i++)
|
||||
{
|
||||
DateList.Add(calStart.AddDays(i));
|
||||
}
|
||||
// ora sistemo le righe da disegnare...
|
||||
WeekRows = new List<List<DateTime>>();
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
WeekRows.Add(DateList.GetRange(i * 7, 7));
|
||||
}
|
||||
}
|
||||
|
||||
private bool hasDot(DateTime dtCurr, string type)
|
||||
{
|
||||
bool answ = false;
|
||||
if (EventList != null)
|
||||
{
|
||||
foreach (var item in EventList)
|
||||
{
|
||||
if (item.Inizio.Date == dtCurr.Date && item.Type == type)
|
||||
{
|
||||
answ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
private async Task resetCal()
|
||||
{
|
||||
await Task.Delay(1);
|
||||
}
|
||||
|
||||
private string singleDayCss(DateTime currDay)
|
||||
{
|
||||
string answ = SelWeekCss;
|
||||
return answ;
|
||||
}
|
||||
|
||||
private string singleDaySpanCss(DateTime currDay)
|
||||
{
|
||||
string answ = currDay == DtRif ? SelDayCss : CurrMonthCss;
|
||||
return answ;
|
||||
}
|
||||
|
||||
private string spanCss(DateTime currDay)
|
||||
{
|
||||
string answ = "";
|
||||
if (DateCheck != null && DateCheck.ContainsKey(currDay))
|
||||
{
|
||||
answ = DateCheck[currDay];
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
private async Task subtractMonth()
|
||||
{
|
||||
await FixDate();
|
||||
await MonthChanged.InvokeAsync(DtRif.AddMonths(-1));
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
.cssTable {
|
||||
border-radius: 12px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #34495E;
|
||||
transition: height 0.3s cubic-bezier(0.54, 0.57, 0.36, 0.98) 0.2s;
|
||||
}
|
||||
.cssTable tr {
|
||||
margin: 0 1rem 0 1rem;
|
||||
}
|
||||
.cssTable td {
|
||||
padding: 0.6rem 0rem 0.4rem 0rem;
|
||||
border: none;
|
||||
}
|
||||
.cssTable thead tr {
|
||||
margin-top: 0.625rem;
|
||||
}
|
||||
.meseAnno {
|
||||
text-transform: capitalize;
|
||||
color: #fff;
|
||||
}
|
||||
.containerBtnTemp {
|
||||
position: relative;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.selDate {
|
||||
background-color: #E67E22;
|
||||
color: #000;
|
||||
}
|
||||
.pallini {
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
.divAll {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
height: 0.3rem;
|
||||
border-radius: 50%;
|
||||
color: transparent;
|
||||
}
|
||||
@keyframes dotEntranceMal {
|
||||
0% {
|
||||
left: -50px;
|
||||
}
|
||||
100% {
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
@keyframes dotEntranceFer {
|
||||
0% {
|
||||
left: -50px;
|
||||
}
|
||||
100% {
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
@keyframes dotEntrancePerm {
|
||||
0% {
|
||||
left: -50px;
|
||||
}
|
||||
100% {
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
@keyframes dotEntranceCent {
|
||||
0% {
|
||||
left: -50px;
|
||||
}
|
||||
100% {
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
.malattie {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
height: 0.3rem;
|
||||
border-radius: 50%;
|
||||
color: transparent;
|
||||
background-color: #039BE5;
|
||||
position: relative;
|
||||
animation-name: dotEntranceMal;
|
||||
animation-duration: 1.1s;
|
||||
}
|
||||
.ferie {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
height: 0.3rem;
|
||||
border-radius: 50%;
|
||||
color: transparent;
|
||||
background-color: #00FF00;
|
||||
position: relative;
|
||||
animation-name: dotEntranceFer;
|
||||
animation-duration: 0.8s;
|
||||
}
|
||||
.permessi {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
height: 0.3rem;
|
||||
border-radius: 50%;
|
||||
color: transparent;
|
||||
background-color: #9966DE;
|
||||
position: relative;
|
||||
animation-name: dotEntrancePerm;
|
||||
animation-duration: 0.5s;
|
||||
}
|
||||
.permessi104 {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
height: 0.3rem;
|
||||
border-radius: 50%;
|
||||
color: transparent;
|
||||
background-color: #DE00AB;
|
||||
position: relative;
|
||||
animation-name: dotEntranceCent;
|
||||
animation-duration: 0.3s;
|
||||
}
|
||||
.containerBtnTemp {
|
||||
position: relative;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
color: #fff;
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
.cssTable {
|
||||
border-radius: 12px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #34495E;
|
||||
transition: height 0.3s cubic-bezier(0.54, 0.57, 0.36, 0.98) 0.2s;
|
||||
}
|
||||
|
||||
.cssTable tr {
|
||||
margin: 0 1rem 0 1rem;
|
||||
}
|
||||
.cssTable td {
|
||||
padding: 0.6rem 0rem 0.4rem 0rem;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.cssTable thead tr {
|
||||
margin-top: 0.625rem;
|
||||
}
|
||||
|
||||
.meseAnno{
|
||||
text-transform: capitalize;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.containerBtnTemp {
|
||||
position: relative;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.selDate {
|
||||
background-color: #E67E22;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
|
||||
.pallini {
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.divAll {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
height: 0.3rem;
|
||||
border-radius: 50%;
|
||||
color: transparent;
|
||||
}
|
||||
@keyframes dotEntranceMal {
|
||||
0% {
|
||||
left: -50px
|
||||
}
|
||||
|
||||
100% {
|
||||
left: 0
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes dotEntranceFer {
|
||||
0% {
|
||||
left: -50px
|
||||
}
|
||||
|
||||
100% {
|
||||
left: 0
|
||||
}
|
||||
}
|
||||
@keyframes dotEntrancePerm {
|
||||
0% {
|
||||
left: -50px
|
||||
}
|
||||
|
||||
100% {
|
||||
left: 0
|
||||
}
|
||||
}
|
||||
@keyframes dotEntranceCent {
|
||||
0% {
|
||||
left: -50px
|
||||
}
|
||||
|
||||
100% {
|
||||
left: 0
|
||||
}
|
||||
}
|
||||
|
||||
.malattie {
|
||||
.divAll;
|
||||
background-color: #039BE5;
|
||||
position: relative;
|
||||
animation-name: dotEntranceMal;
|
||||
animation-duration: 1.1s;
|
||||
}
|
||||
.ferie {
|
||||
.divAll;
|
||||
background-color: #00FF00;
|
||||
position: relative;
|
||||
animation-name: dotEntranceFer;
|
||||
animation-duration: 0.8s;
|
||||
}
|
||||
.permessi {
|
||||
.divAll;
|
||||
background-color: #9966DE;
|
||||
position: relative;
|
||||
animation-name: dotEntrancePerm;
|
||||
animation-duration: 0.5s;
|
||||
}
|
||||
.permessi104 {
|
||||
.divAll;
|
||||
background-color: #DE00AB;
|
||||
position: relative;
|
||||
animation-name: dotEntranceCent;
|
||||
animation-duration: 0.3s;
|
||||
}
|
||||
|
||||
.containerBtnTemp {
|
||||
position: relative;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
color: #fff;
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
.cssTable{border-radius:12px;width:100%;height:100%;background-color:#34495e;transition:height .3s cubic-bezier(.54,.57,.36,.98) .2s;}.cssTable tr{margin:0 1rem 0 1rem;}.cssTable td{padding:.6rem 0 .4rem 0;border:0;}.cssTable thead tr{margin-top:.625rem;}.meseAnno{text-transform:capitalize;color:#fff;}.containerBtnTemp{position:relative;align-items:center;display:flex;justify-content:center;}.selDate{background-color:#e67e22;color:#000;}.pallini{display:flex;justify-content:space-evenly;}.divAll{padding:0;margin:0;height:.3rem;border-radius:50%;color:transparent;}@keyframes dotEntranceMal{0%{left:-50px;}100%{left:0;}}@keyframes dotEntranceFer{0%{left:-50px;}100%{left:0;}}@keyframes dotEntrancePerm{0%{left:-50px;}100%{left:0;}}@keyframes dotEntranceCent{0%{left:-50px;}100%{left:0;}}.malattie{padding:0;margin:0;height:.3rem;border-radius:50%;color:transparent;background-color:#039be5;position:relative;animation-name:dotEntranceMal;animation-duration:1.1s;}.ferie{padding:0;margin:0;height:.3rem;border-radius:50%;color:transparent;background-color:#0f0;position:relative;animation-name:dotEntranceFer;animation-duration:.8s;}.permessi{padding:0;margin:0;height:.3rem;border-radius:50%;color:transparent;background-color:#9966de;position:relative;animation-name:dotEntrancePerm;animation-duration:.5s;}.permessi104{padding:0;margin:0;height:.3rem;border-radius:50%;color:transparent;background-color:#de00ab;position:relative;animation-name:dotEntranceCent;animation-duration:.3s;}.containerBtnTemp{position:relative;align-items:center;display:flex;justify-content:center;background-color:transparent;border:0;color:#fff;}
|
||||
@@ -0,0 +1,51 @@
|
||||
@if (DateList == null || DateList.Count == 0)
|
||||
{
|
||||
<LoadingData></LoadingData>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="cssTable" style="@HeadStyle">
|
||||
<thead>
|
||||
<tr class="">
|
||||
<th class="text-center text-light" @onclick="()=>openCalendarMonth()" style="width: @lblWidth;"><i class="fa-regular fa-circle-xmark"></i></th>
|
||||
@foreach (var item in DateList)
|
||||
{
|
||||
<th class="text-center" style="width: @dataWidth;">
|
||||
<div>
|
||||
@($"{item:ddd}".Substring(0, 1).ToUpper())
|
||||
</div>
|
||||
<div class="small">
|
||||
<sup>@($"{item:dd}")</sup>
|
||||
</div>
|
||||
</th>
|
||||
}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<CalWeekColumn ItemMode="CalWeekColumn.ColType.labelStart" vBox="vBoxLabel" EventList="@LabelList()" ValMin="8" ValMax="20"></CalWeekColumn>
|
||||
</td>
|
||||
@foreach (var item in DateList)
|
||||
{
|
||||
<td>
|
||||
<CalWeekColumn ItemMode="CalWeekColumn.ColType.dataContainer" vBox="vBoxCont" EventList="@DayEvent(item)" ValMin="8" ValMax="20"></CalWeekColumn>
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="@calcColSpan" class="meseAnno">
|
||||
<div class="d-flex justify-content-around">
|
||||
<button class="containerBtnTemp" @onclick="()=> changeWeek(-1)"><i class="fa-solid fa-circle-chevron-left"></i></button>
|
||||
<div class="">
|
||||
@($"{DtRif: MMM yyyy}") | <b>W@($"{weekNum(DtRif):00}")</b>
|
||||
</div>
|
||||
<button class="containerBtnTemp" @onclick="()=> changeWeek(1)"><i class="fa-solid fa-circle-chevron-right"></i></button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
using GPW.CORE.Data;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Drawing;
|
||||
|
||||
namespace GPW.CORE.Comp
|
||||
{
|
||||
public partial class CalendarWeek
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Periodo da mostrare (tipicamente 1 settimana)
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public List<DateTime> DateList { get; set; } = new List<DateTime>();
|
||||
|
||||
/// <summary>
|
||||
/// Eventi da inserire
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public List<CalendarEvent> EventList { get; set; } = new List<CalendarEvent>();
|
||||
|
||||
/// <summary>
|
||||
/// Evento selezione data valida (= entro il periodo selezionato)
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<DateTime> DateSelected { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<bool> backToCalendar{ get; set; }
|
||||
|
||||
|
||||
[Parameter]
|
||||
public int EndHour { get; set; } = 20;
|
||||
|
||||
/// <summary>
|
||||
/// Css titolo
|
||||
/// default: color: red
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string HeadStyle { get; set; } = "color: #E67E22";
|
||||
|
||||
/// <summary>
|
||||
/// Altezza di ogni blocco ora da mostrare
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int HeightHour { get; set; } = 20;
|
||||
|
||||
/// <summary>
|
||||
/// Larghezza calcolata delle etichette, minimo tra
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int labelWidth { get; set; } = 15;
|
||||
|
||||
[Parameter]
|
||||
public int StartHour { get; set; } = 8;
|
||||
|
||||
/// <summary>
|
||||
/// Dimensioni viewbox GLOBALE
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Size vBox { get; set; } = new Size(1200, 1600);
|
||||
|
||||
/// <summary>
|
||||
/// Evento richiesta modifica settimana
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<int> WeekChanged { get; set; }
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Protected Fields
|
||||
|
||||
protected List<int> HourSlot = new List<int>();
|
||||
|
||||
#endregion Protected Fields
|
||||
|
||||
#region Protected Properties
|
||||
|
||||
protected int calcColSpan
|
||||
{
|
||||
get => numDays + 1;
|
||||
}
|
||||
|
||||
protected DateTime DtRif
|
||||
{
|
||||
get
|
||||
{
|
||||
DateTime answ = DateTime.Today;
|
||||
if (DateList != null && DateList.Count > 0)
|
||||
{
|
||||
answ = DateList[0];
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
|
||||
protected int numDays
|
||||
{
|
||||
get => DateList.Count;
|
||||
}
|
||||
|
||||
protected int contWidth
|
||||
{
|
||||
get => (vBox.Width * 2) / (2 * numDays + 1);
|
||||
}
|
||||
|
||||
private string lblWidth
|
||||
{
|
||||
get => $"{(double)(vBox.Width - (contWidth * numDays)) / vBox.Width:P2}".Replace(",", ".");
|
||||
}
|
||||
private string dataWidth
|
||||
{
|
||||
get => $"{(double)contWidth / vBox.Width:P2}".Replace(",", ".");
|
||||
}
|
||||
|
||||
protected Size vBoxLabel
|
||||
{
|
||||
get
|
||||
{
|
||||
// label è MENO di 1/tot columns
|
||||
Size answ = new Size(contWidth / 2, vBox.Height);
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
protected Size vBoxCont
|
||||
{
|
||||
get
|
||||
{
|
||||
// label è MENO di 1/tot columns
|
||||
Size answ = new Size(contWidth, vBox.Height);
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
|
||||
//protected Size vBoxLabel
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
// // label è MENO di 1/tot columns
|
||||
// Size answ = new Size(labelWidth, vBox.Height);
|
||||
// return answ;
|
||||
// }
|
||||
//}
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Richiesta cambio sett di riferimento --> riporta evento
|
||||
/// </summary>
|
||||
/// <param name="delta"></param>
|
||||
/// <returns></returns>
|
||||
protected async Task changeWeek(int delta)
|
||||
{
|
||||
await WeekChanged.InvokeAsync(delta);
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
HourSlot = new List<int>();
|
||||
for (int i = StartHour; i <= EndHour; i++)
|
||||
{
|
||||
HourSlot.Add(i);
|
||||
}
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GetIso8601WeekOfYear
|
||||
/// </summary>
|
||||
/// <param name="DtReq"></param>
|
||||
/// <returns></returns>
|
||||
protected int weekNum(DateTime DtReq)
|
||||
{
|
||||
int wNum = WeekData.GetIso8601WeekOfYear(DtReq);
|
||||
return wNum;
|
||||
}
|
||||
|
||||
protected List<CalendarEvent> DayEvent(DateTime DtReq)
|
||||
{
|
||||
List<CalendarEvent> answ = new List<CalendarEvent>();
|
||||
if (EventList != null)
|
||||
{
|
||||
answ = EventList.Where(x => x.Inizio.Date == DtReq.Date).ToList();
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Genera etichette orarie (1 x ora)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected List<CalendarEvent> LabelList()
|
||||
{
|
||||
int idx = 0;
|
||||
List<CalendarEvent> answ = HourSlot.Select(x => new CalendarEvent()
|
||||
{
|
||||
id = idx++,
|
||||
Inizio = DtRif.AddHours(x),
|
||||
Fine = DtRif.AddHours(x),
|
||||
CssClass = "text-light",
|
||||
Title = $"{x:00}:00",
|
||||
Description = $"{x:00}:00"
|
||||
}).ToList();
|
||||
return answ;
|
||||
}
|
||||
|
||||
protected async Task openCalendarMonth()
|
||||
{
|
||||
await backToCalendar.InvokeAsync(true);
|
||||
}
|
||||
#endregion Protected Methods
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
.cssTable {
|
||||
border-radius: 12px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #34495E;
|
||||
}
|
||||
.cssTable tr {
|
||||
margin: 0 1rem 0 1rem;
|
||||
}
|
||||
.cssTable td {
|
||||
padding: 0.1rem 0rem 0.1rem 0rem;
|
||||
border: none;
|
||||
}
|
||||
.cssTable thead tr {
|
||||
margin-top: 0.625rem;
|
||||
}
|
||||
.meseAnno {
|
||||
text-transform: capitalize;
|
||||
color: #fff;
|
||||
}
|
||||
.containerBtnTemp {
|
||||
position: relative;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
color: #fff;
|
||||
}
|
||||
.selDate {
|
||||
background-color: #E67E22;
|
||||
color: #000;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
.cssTable {
|
||||
border-radius: 12px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #34495E;
|
||||
}
|
||||
|
||||
.cssTable tr {
|
||||
margin: 0 1rem 0 1rem;
|
||||
}
|
||||
|
||||
.cssTable td {
|
||||
padding: 0.1rem 0rem 0.1rem 0rem;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.cssTable thead tr {
|
||||
margin-top: 0.625rem;
|
||||
}
|
||||
|
||||
.meseAnno {
|
||||
text-transform: capitalize;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.containerBtnTemp {
|
||||
position: relative;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.selDate {
|
||||
background-color: #E67E22;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
.cssTable{border-radius:12px;width:100%;height:100%;background-color:#34495e;}.cssTable tr{margin:0 1rem 0 1rem;}.cssTable td{padding:.1rem 0 .1rem 0;border:0;}.cssTable thead tr{margin-top:.625rem;}.meseAnno{text-transform:capitalize;color:#fff;}.containerBtnTemp{position:relative;align-items:center;display:flex;justify-content:center;background-color:transparent;border:0;color:#fff;}.selDate{background-color:#e67e22;color:#000;}
|
||||
@@ -1,4 +1,5 @@
|
||||
@inject IJSRuntime JSRuntime
|
||||
@using Microsoft.JSInterop
|
||||
@inject IJSRuntime JSRuntime
|
||||
|
||||
<canvas id="@Id"></canvas>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
@using Microsoft.JSInterop
|
||||
@inject IJSRuntime JSRuntime
|
||||
|
||||
<canvas id="@Id"></canvas>
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace GPW.CORE.Comp
|
||||
{
|
||||
public partial class ChartHist
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
[Parameter]
|
||||
public string BackColor { get; set; } = "";
|
||||
|
||||
[Parameter]
|
||||
public string TextColor { get; set; } = "";
|
||||
|
||||
[Parameter]
|
||||
public string ChartLabel { get; set; } = "";
|
||||
|
||||
[Parameter]
|
||||
public string[]? Data { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Id { get; set; } = "MyHist";
|
||||
|
||||
[Parameter]
|
||||
public string[]? Labels { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string LineColor { get; set; } = "";
|
||||
|
||||
[Parameter]
|
||||
public string GridColor { get; set; } = "";
|
||||
|
||||
[Parameter]
|
||||
public int AnimationTime { get; set; } = 0;
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
await renderChart();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inizializzazione rendering componente
|
||||
///
|
||||
/// partendo da qui: https://www.williamleme.com/posts/2020/003-chartjs-blazor/
|
||||
/// https://www.puresourcecode.com/dotnet/blazor/using-chart-js-with-blazor/ https://www.tutorialsteacher.com/csharp/csharp-anonymous-type
|
||||
/// </summary>
|
||||
/// <param name="firstRender"></param>
|
||||
/// <returns></returns>
|
||||
protected async Task renderChart()
|
||||
{
|
||||
// creazione di un oggetto anonymous type con tutte le opzioni da passare a chart.js
|
||||
var config = new
|
||||
{
|
||||
type = "bar",
|
||||
options = new
|
||||
{
|
||||
responsive = true,
|
||||
scales = new
|
||||
{
|
||||
yAxes = new
|
||||
{
|
||||
suggestedMin = 0,
|
||||
display = true,
|
||||
grid = new
|
||||
{
|
||||
color = GridColor,
|
||||
display = true,
|
||||
},
|
||||
ticks = new
|
||||
{
|
||||
beginAtZero = true,
|
||||
color = TextColor,
|
||||
maxTicksLimit = 10,
|
||||
}
|
||||
},
|
||||
xAxes = new
|
||||
{
|
||||
grid = new
|
||||
{
|
||||
color = GridColor,
|
||||
display = true,
|
||||
},
|
||||
ticks = new
|
||||
{
|
||||
color = TextColor,
|
||||
}
|
||||
},
|
||||
},
|
||||
plugins = new
|
||||
{
|
||||
legend = new
|
||||
{
|
||||
display = true,
|
||||
labels = new
|
||||
{
|
||||
color = TextColor,
|
||||
},
|
||||
},
|
||||
},
|
||||
Animation = new
|
||||
{
|
||||
Duration = AnimationTime
|
||||
},
|
||||
},
|
||||
data = new
|
||||
{
|
||||
datasets = new[]{
|
||||
new
|
||||
{
|
||||
data = Data,
|
||||
|
||||
borderColor = LineColor,
|
||||
backgroundColor = BackColor,
|
||||
borderWidth = 1,
|
||||
color = TextColor,
|
||||
label = ChartLabel
|
||||
}
|
||||
},
|
||||
labels = Labels
|
||||
}
|
||||
};
|
||||
await JSRuntime.InvokeVoidAsync("setup", Id, config);
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
@using Microsoft.JSInterop
|
||||
@inject IJSRuntime JSRuntime
|
||||
|
||||
<canvas id="@Id"></canvas>
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace GPW.CORE.Comp
|
||||
{
|
||||
public partial class ChartTS
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
[Parameter]
|
||||
public int AnimationTime { get; set; } = 0;
|
||||
|
||||
[Parameter]
|
||||
public string BackColor { get; set; } = "";
|
||||
|
||||
[Parameter]
|
||||
public string TextColor { get; set; } = "";
|
||||
[Parameter]
|
||||
public string GridColor { get; set; } = "";
|
||||
|
||||
[Parameter]
|
||||
public string ChartLabel { get; set; } = "";
|
||||
|
||||
[Parameter]
|
||||
public List<chartJsData.chartJsTSerie> DataTS { get; set; } = null!;
|
||||
|
||||
[Parameter]
|
||||
public string Id { get; set; } = "MyTs";
|
||||
[Parameter]
|
||||
public string LineColor { get; set; } = "";
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Inizializzazione rendering componente
|
||||
///
|
||||
/// partendo da qui:
|
||||
/// https://www.williamleme.com/posts/2020/003-chartjs-blazor/
|
||||
/// https://www.puresourcecode.com/dotnet/blazor/using-chart-js-with-blazor/
|
||||
/// https://www.tutorialsteacher.com/csharp/csharp-anonymous-type
|
||||
/// </summary>
|
||||
/// <param name = "firstRender"></param>
|
||||
/// <returns></returns>
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
await renderChart();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inizializzazione rendering componente
|
||||
///
|
||||
/// partendo da qui:
|
||||
/// https://www.williamleme.com/posts/2020/003-chartjs-blazor/
|
||||
/// https://www.puresourcecode.com/dotnet/blazor/using-chart-js-with-blazor/
|
||||
/// https://www.tutorialsteacher.com/csharp/csharp-anonymous-type
|
||||
/// </summary>
|
||||
/// <param name = "firstRender"></param>
|
||||
/// <returns></returns>
|
||||
protected async Task renderChart()
|
||||
{
|
||||
// creazione di un oggetto anonymous type con tutte le opzioni da passare a chart.js
|
||||
var config = new
|
||||
{
|
||||
type = "line",
|
||||
options = new
|
||||
{
|
||||
responsive = true,
|
||||
scales = new
|
||||
{
|
||||
yAxes = new
|
||||
{
|
||||
display = true,
|
||||
grid = new
|
||||
{
|
||||
color = GridColor,
|
||||
display = true,
|
||||
},
|
||||
ticks = new
|
||||
{
|
||||
color = TextColor,
|
||||
maxTicksLimit = 10,
|
||||
}
|
||||
},
|
||||
xAxes = new
|
||||
{
|
||||
type = "timeseries",
|
||||
distribution = "linear",
|
||||
grid = new
|
||||
{
|
||||
color = GridColor,
|
||||
display = true,
|
||||
},
|
||||
ticks = new
|
||||
{
|
||||
color = TextColor,
|
||||
},
|
||||
}
|
||||
},
|
||||
plugins = new
|
||||
{
|
||||
legend = new
|
||||
{
|
||||
display = true,
|
||||
labels = new
|
||||
{
|
||||
color = TextColor,
|
||||
},
|
||||
},
|
||||
},
|
||||
Animation = new
|
||||
{
|
||||
Duration = AnimationTime
|
||||
},
|
||||
},
|
||||
data = new
|
||||
{
|
||||
datasets = new[]
|
||||
{
|
||||
new
|
||||
{
|
||||
data = DataTS,
|
||||
borderColor = LineColor,
|
||||
backgroundColor = BackColor,
|
||||
lineTension = 0,
|
||||
stepped = true,
|
||||
label = ChartLabel
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
await JSRuntime.InvokeVoidAsync("setup", Id, config);
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
<svg viewBox="0 0 200 200" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="100" cy="100" r="@innRad" fill="none" stroke="rgba(189, 195, 199, 0.5)" stroke-width="@sWidth" />
|
||||
<circle cx="100" cy="100" r="@innRad" fill="none" stroke="@strokeColorVal" stroke-width="@sWidth" stroke-linecap="round" transform="rotate(-90,100,100)" stroke-dasharray="calc(@innRad * 6.28 * @valInner / @maxVal) calc(@innRad * 6.28 * (@maxVal - @valInner) / @maxVal)" />
|
||||
<g transform="translate(100,100)">
|
||||
<text id="TitleElem" style="@StyleTitolo" x="0" y="0">@Titolo</text>
|
||||
<text x="0" y="30" style="@StyleTesto">@Testo</text>
|
||||
</g>
|
||||
@if (showOuter)
|
||||
{
|
||||
<circle cx="100" cy="100" r="@outRad" fill=none stroke="rgba(189, 195, 199, 0.5)" class="bg-opacity-25" stroke-width="@sWidth" />
|
||||
<circle cx="100" cy="100" r="@outRad" fill=none stroke="@strokeColorVal" stroke-width="@sWidth" stroke-linecap="round" transform="rotate(-90,100,100)" stroke-dasharray="calc(@outRad * 6.28 * @valOuter / @maxVal) calc(@outRad * 6.28 * (@maxVal - @valOuter) / @maxVal)" />
|
||||
}
|
||||
</svg>
|
||||
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
|
||||
namespace GPW.CORE.Comp
|
||||
{
|
||||
public partial class CircleGauge
|
||||
{
|
||||
[Parameter]
|
||||
public string Titolo { get; set; } = "Titolo";
|
||||
[Parameter]
|
||||
public string Testo { get; set; } = "Testo";
|
||||
[Parameter]
|
||||
public string StyleTitolo { get; set; } = "font-size: 3em; font-weight:bold; fill: white;";
|
||||
[Parameter]
|
||||
public string StyleTesto { get; set; } = "font-size: 1em; fill: gray;";
|
||||
[Parameter]
|
||||
public string strokeColorVal { get; set; } = "#00FF66";
|
||||
|
||||
/// <summary>
|
||||
/// Valore da rappresentare
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int currVal { get; set; } = 0;
|
||||
/// <summary>
|
||||
/// Valore MASSIMO da rappresentare (=100%)
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int maxVal { get; set; } = 0;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Spessore dei cerchida disegnare
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int sWidth { get; set; } = 10;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Raggio cerchio interno (0..100)
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int innRad { get; set; } = 70;
|
||||
|
||||
/// <summary>
|
||||
/// Raggio cerchio esterno (0..100)
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public int outRad { get; set; } = 85;
|
||||
|
||||
private bool showOuter
|
||||
{
|
||||
get => currVal > maxVal;
|
||||
}
|
||||
|
||||
private int valInner
|
||||
{
|
||||
get => currVal < maxVal ? currVal : maxVal;
|
||||
}
|
||||
private int valOuter
|
||||
{
|
||||
get => currVal < maxVal ? 0 : currVal - maxVal;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/* FIX per tyesto dentro SVG: https://www.fabiofranchino.com/blog/how-to-align-svg-text/ */
|
||||
text {
|
||||
text-anchor: middle;
|
||||
/* align center */
|
||||
dominant-baseline: middle;
|
||||
/* vertical alignment fix */
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
/* FIX per tyesto dentro SVG: https://www.fabiofranchino.com/blog/how-to-align-svg-text/ */
|
||||
text {
|
||||
text-anchor: middle; /* align center */
|
||||
dominant-baseline: middle; /* vertical alignment fix */
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
text{text-anchor:middle;dominant-baseline:middle;}
|
||||
@@ -0,0 +1,37 @@
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace GPW.CORE.Comp
|
||||
{
|
||||
// This class provides an example of how JavaScript functionality can be wrapped
|
||||
// in a .NET class for easy consumption. The associated JavaScript module is
|
||||
// loaded on demand when first needed.
|
||||
//
|
||||
// This class can be registered as scoped DI service and then injected into Blazor
|
||||
// components for use.
|
||||
|
||||
public class ExampleJsInterop : IAsyncDisposable
|
||||
{
|
||||
private readonly Lazy<Task<IJSObjectReference>> moduleTask;
|
||||
|
||||
public ExampleJsInterop(IJSRuntime jsRuntime)
|
||||
{
|
||||
moduleTask = new(() => jsRuntime.InvokeAsync<IJSObjectReference>(
|
||||
"import", "./_content/GPW.CORE.Comp/exampleJsInterop.js").AsTask());
|
||||
}
|
||||
|
||||
public async ValueTask<string> Prompt(string message)
|
||||
{
|
||||
var module = await moduleTask.Value;
|
||||
return await module.InvokeAsync<string>("showPrompt", message);
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (moduleTask.IsValueCreated)
|
||||
{
|
||||
var module = await moduleTask.Value;
|
||||
await module.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="bin\**" />
|
||||
<Content Remove="bin\**" />
|
||||
<EmbeddedResource Remove="bin\**" />
|
||||
<None Remove="bin\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="CircleGauge_2.razor.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Remove="CircleGauge_2.razor" />
|
||||
<Content Remove="compilerconfig.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="CircleGauge_2.razor.css" />
|
||||
<None Remove="CircleGauge_2.razor.less" />
|
||||
<None Remove="CircleGauge_2.razor.min.css" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="compilerconfig.json" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<SupportedPlatform Include="browser" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="6.0.14" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\GPW.CORE.Data\GPW.CORE.Data.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,11 @@
|
||||
// This file is used by Code Analysis to maintain SuppressMessage
|
||||
// attributes that are applied to this project.
|
||||
// Project-level suppressions either have no target or are given
|
||||
// a specific target and scoped to a namespace, type, member, etc.
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>", Scope = "member", Target = "~M:GPW.CORE.Comp.SteamCrypto.getHashStringMD5(System.String)~System.String")]
|
||||
[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>", Scope = "member", Target = "~M:GPW.CORE.Comp.SteamCrypto.EncryptString(System.String,System.String)~System.String")]
|
||||
[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>", Scope = "member", Target = "~M:GPW.CORE.Comp.IpUtils.getLocalIpv4(System.String)~System.String")]
|
||||
[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>", Scope = "member", Target = "~M:GPW.CORE.Comp.SteamCrypto.DecryptString(System.String,System.String)~System.String")]
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GPW.CORE.Comp
|
||||
{
|
||||
public class IpUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Restituisce l'IP v4 locale dato uno degli ip machcina (anche IPV6)
|
||||
/// </summary>
|
||||
/// <param name="firstIp"></param>
|
||||
/// <returns></returns>
|
||||
public static string getLocalIpv4(string firstIp)
|
||||
{
|
||||
string devIp = firstIp;
|
||||
IPAddress clientIP = IPAddress.Parse(devIp);
|
||||
try
|
||||
{
|
||||
IPHostEntry GetIPHost = Dns.GetHostEntry(clientIP);
|
||||
if (GetIPHost != null)
|
||||
{
|
||||
// se trovo + di 1 ip cerco il primo NON IPV6...
|
||||
if (GetIPHost.AddressList.Count() > 1)
|
||||
{
|
||||
foreach (IPAddress item in GetIPHost.AddressList)
|
||||
{
|
||||
if (item.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
devIp = item.ToString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
return devIp;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<div class="row p-3 m-2">
|
||||
<div class="col-12 text-center mt-5 py-5 alert alert-primary">
|
||||
<div class="row">
|
||||
<div class="col-6 text-end">
|
||||
<div class="spinner-grow" role="status" style="width: 3rem; height: 3rem;">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<h3>loading data</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace GPW.CORE.Comp
|
||||
{
|
||||
public class QHelper
|
||||
{
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Blazor: get query parm from the URL
|
||||
/// </summary>
|
||||
/// <param name="parmName"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetQueryParm(string fullUri, string parmName)
|
||||
{
|
||||
var uriBuilder = new UriBuilder(fullUri);
|
||||
var q = System.Web.HttpUtility.ParseQueryString(uriBuilder.Query);
|
||||
return q[parmName] ?? "";
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace GPW.CORE.Comp
|
||||
{
|
||||
/// <summary>
|
||||
/// utils x cifrature e Crypto
|
||||
/// </summary>
|
||||
public class SteamCrypto
|
||||
{
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// decifra un messaggio con una password
|
||||
/// </summary>
|
||||
/// <param name="Message"></param>
|
||||
/// <param name="Passphrase"></param>
|
||||
/// <returns></returns>
|
||||
public static string DecryptString(string Message, string Passphrase)
|
||||
{
|
||||
string answ = Message;
|
||||
byte[] Results = new byte[8];
|
||||
UTF8Encoding UTF8 = new UTF8Encoding();
|
||||
|
||||
// Step 1. We hash the passphrase using MD5 We use the MD5 hash generator as the result
|
||||
// is a 128 bit byte array which is a valid length for the TripleDES encoder we use below
|
||||
|
||||
var HashProvider = MD5.Create();
|
||||
//MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
|
||||
byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase));
|
||||
|
||||
// Step 2. Create a new TripleDESCryptoServiceProvider object
|
||||
var TDESAlgorithm = TripleDES.Create();
|
||||
//TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();
|
||||
|
||||
// Step 3. Setup the decoder
|
||||
TDESAlgorithm.Key = TDESKey;
|
||||
TDESAlgorithm.Mode = CipherMode.ECB;
|
||||
TDESAlgorithm.Padding = PaddingMode.PKCS7;
|
||||
|
||||
// Step 4. Convert the input string to a byte[]
|
||||
byte[] DataToDecrypt = new byte[8];
|
||||
try
|
||||
{
|
||||
DataToDecrypt = Convert.FromBase64String(Message);
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
if (DataToDecrypt != null)
|
||||
{
|
||||
// Step 5. Attempt to decrypt the string
|
||||
try
|
||||
{
|
||||
ICryptoTransform Decryptor = TDESAlgorithm.CreateDecryptor();
|
||||
Results = Decryptor.TransformFinalBlock(DataToDecrypt, 0, DataToDecrypt.Length);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Clear the TripleDes and Hashprovider services of any sensitive information
|
||||
TDESAlgorithm.Clear();
|
||||
HashProvider.Clear();
|
||||
}
|
||||
// Step 6. Return the decrypted string in UTF8 format
|
||||
answ = UTF8.GetString(Results);
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// cifra un messaggio con una password
|
||||
/// </summary>
|
||||
/// <param name="Message"></param>
|
||||
/// <param name="Passphrase"></param>
|
||||
/// <returns></returns>
|
||||
public static string EncryptString(string Message, string Passphrase)
|
||||
{
|
||||
byte[] Results;
|
||||
UTF8Encoding UTF8 = new UTF8Encoding();
|
||||
|
||||
// Step 1. We hash the passphrase using MD5 We use the MD5 hash generator as the result
|
||||
// is a 128 bit byte array which is a valid length for the TripleDES encoder we use below
|
||||
|
||||
var HashProvider = MD5.Create();
|
||||
//MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
|
||||
byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase));
|
||||
|
||||
// Step 2. Create a new TripleDESCryptoServiceProvider object
|
||||
var TDESAlgorithm = TripleDES.Create();
|
||||
//TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();
|
||||
|
||||
// Step 3. Setup the encoder
|
||||
TDESAlgorithm.Key = TDESKey;
|
||||
TDESAlgorithm.Mode = CipherMode.ECB;
|
||||
TDESAlgorithm.Padding = PaddingMode.PKCS7;
|
||||
|
||||
// Step 4. Convert the input string to a byte[]
|
||||
byte[] DataToEncrypt = UTF8.GetBytes(Message);
|
||||
|
||||
// Step 5. Attempt to encrypt the string
|
||||
try
|
||||
{
|
||||
ICryptoTransform Encryptor = TDESAlgorithm.CreateEncryptor();
|
||||
Results = Encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Clear the TripleDes and Hashprovider services of any sensitive information
|
||||
TDESAlgorithm.Clear();
|
||||
HashProvider.Clear();
|
||||
}
|
||||
|
||||
// Step 6. Return the encrypted string as a base64 encoded string
|
||||
return Convert.ToBase64String(Results);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// genera hash di una stringa in MD5 (es x hash gravatar)
|
||||
/// </summary>
|
||||
/// <param name="Message"></param>
|
||||
/// <returns></returns>
|
||||
public static string getHashStringMD5(string Message)
|
||||
{
|
||||
string hash = "";
|
||||
using (MD5 md5Hash = MD5.Create())
|
||||
{
|
||||
hash = GetMd5Hash(md5Hash, Message);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Crea un hash MD5
|
||||
/// </summary>
|
||||
/// <param name="md5Hash"></param>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetMd5Hash(MD5 md5Hash, string input)
|
||||
{
|
||||
// Convert the input string to a byte array and compute the hash.
|
||||
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
|
||||
|
||||
// Create a new Stringbuilder to collect the bytes and create a string.
|
||||
StringBuilder sBuilder = new StringBuilder();
|
||||
|
||||
// Loop through each byte of the hashed data and format each one as a hexadecimal string.
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
sBuilder.Append(data[i].ToString("x2"));
|
||||
}
|
||||
|
||||
// Return the hexadecimal string.
|
||||
return sBuilder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a random string with a given size
|
||||
/// </summary>
|
||||
/// <param name="size"></param>
|
||||
/// <param name="lowerCase"></param>
|
||||
/// <returns></returns>
|
||||
public static string RandomString(int size, bool lowerCase = false)
|
||||
{
|
||||
var builder = new StringBuilder(size);
|
||||
|
||||
// Unicode/ASCII Letters are divided into two blocks (Letters 65–90 / 97–122): The first
|
||||
// group containing the uppercase letters and the second group containing the lowercase.
|
||||
|
||||
// char is a single Unicode character
|
||||
char offset = lowerCase ? 'a' : 'A';
|
||||
const int lettersOffset = 26; // A...Z or a..z: length=26
|
||||
|
||||
for (var i = 0; i < size; i++)
|
||||
{
|
||||
var @char = (char)_random.Next(offset, offset + lettersOffset);
|
||||
builder.Append(@char);
|
||||
}
|
||||
|
||||
return lowerCase ? builder.ToString().ToLower() : builder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify a hash against a string.
|
||||
/// </summary>
|
||||
/// <param name="md5Hash"></param>
|
||||
/// <param name="input"></param>
|
||||
/// <param name="hash"></param>
|
||||
/// <returns></returns>
|
||||
public static bool VerifyMd5Hash(MD5 md5Hash, string input, string hash)
|
||||
{
|
||||
// Hash the input.
|
||||
string hashOfInput = GetMd5Hash(md5Hash, input);
|
||||
|
||||
// Create a StringComparer an compare the hashes.
|
||||
StringComparer comparer = StringComparer.OrdinalIgnoreCase;
|
||||
|
||||
if (0 == comparer.Compare(hashOfInput, hash))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private static readonly Random _random = new Random();
|
||||
|
||||
#endregion Private Fields
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<div class="toast-container p-3 @cssPosition">
|
||||
<div class="toast bg-light fade @toastCss" id="LiveToast" role="alert" aria-live="assertive" aria-atomic="true">
|
||||
<div class="toast-header">
|
||||
<span class="bg-primary px-2 text-light rounded me-2"><i class="fa-solid fa-clock"></i></span>
|
||||
<strong class="me-auto">@TitleSx</strong>
|
||||
<small>@TitleDx</small>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close" @onclick="() => doClose()"></button>
|
||||
</div>
|
||||
<div class="toast-body">
|
||||
@if (@ChildContent != null)
|
||||
{
|
||||
<div>
|
||||
@ChildContent
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,119 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace GPW.CORE.Comp
|
||||
{
|
||||
/// <summary>
|
||||
/// Gestione display Toast con Bootstrap 5+
|
||||
///
|
||||
/// https://getbootstrap.com/docs/5.2/components/toasts/
|
||||
/// </summary>
|
||||
public partial class ToastDisplay
|
||||
{
|
||||
#region Public Enums
|
||||
|
||||
public enum DispPosition
|
||||
{
|
||||
none = 0,
|
||||
topLeft,
|
||||
topCenter,
|
||||
topRight,
|
||||
midLeft,
|
||||
midCenter,
|
||||
midRight,
|
||||
bottomLeft,
|
||||
bottomCenter,
|
||||
bottomRight
|
||||
}
|
||||
|
||||
#endregion Public Enums
|
||||
|
||||
#region Public Properties
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment? ChildContent { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public DispPosition currPosition { get; set; } = DispPosition.none;
|
||||
|
||||
[Parameter]
|
||||
public bool DoShow { get; set; } = false;
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<bool> ReportClose { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string TitleDx { get; set; } = "";
|
||||
|
||||
[Parameter]
|
||||
public string TitleSx { get; set; } = "";
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected async Task doClose()
|
||||
{
|
||||
await ReportClose.InvokeAsync(true);
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Properties
|
||||
|
||||
private string cssPosition
|
||||
{
|
||||
get
|
||||
{
|
||||
string answ = "";
|
||||
switch (currPosition)
|
||||
{
|
||||
case DispPosition.topLeft:
|
||||
answ = "top-0 start-0";
|
||||
break;
|
||||
|
||||
case DispPosition.topCenter:
|
||||
answ = "top-0 start-50 translate-middle-x";
|
||||
break;
|
||||
|
||||
case DispPosition.topRight:
|
||||
answ = "top-0 end-0";
|
||||
break;
|
||||
|
||||
case DispPosition.midLeft:
|
||||
answ = "top-50 start-0 translate-middle-y";
|
||||
break;
|
||||
|
||||
case DispPosition.midCenter:
|
||||
answ = "top-50 start-50 translate-middle";
|
||||
break;
|
||||
|
||||
case DispPosition.midRight:
|
||||
answ = "top-50 end-0 translate-middle-y";
|
||||
break;
|
||||
|
||||
case DispPosition.bottomLeft:
|
||||
answ = "bottom-0 start-0";
|
||||
break;
|
||||
|
||||
case DispPosition.bottomCenter:
|
||||
answ = "bottom-0 start-50 translate-middle-x";
|
||||
break;
|
||||
|
||||
case DispPosition.bottomRight:
|
||||
answ = "bottom-0 end-0";
|
||||
break;
|
||||
|
||||
case DispPosition.none:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
|
||||
private string toastCss { get => DoShow ? "show" : ""; }
|
||||
|
||||
#endregion Private Properties
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<div class="input-group input-group-sm">
|
||||
<div class="input-group-text py-0 @placardCss">
|
||||
<span class="me-1 @leftStringCSS">@leftString</span>
|
||||
<div class="form-check form-check-sm form-switch py-1" title="@toolTip">
|
||||
<input class="form-check-input" type="checkbox" name="setupAlarms" checked @onclick="() => toggle()">
|
||||
</div>
|
||||
<span class="@rightStringCSS">@rightString</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,244 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace GPW.CORE.Comp
|
||||
{
|
||||
public partial class Toggler
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<SelectGlobalToggle> FilterChanged { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public SelectGlobalToggle SelFilter { get; set; } = new SelectGlobalToggle();
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Public Classes
|
||||
|
||||
/// <summary>
|
||||
/// Classe utility x toggle
|
||||
/// </summary>
|
||||
public class SelectGlobalToggle
|
||||
{
|
||||
#region Public Constructors
|
||||
|
||||
public SelectGlobalToggle()
|
||||
{ }
|
||||
|
||||
#endregion Public Constructors
|
||||
|
||||
#region Public Properties
|
||||
|
||||
/// <summary>
|
||||
/// Bool: indica se il toggleClosed � attivo
|
||||
/// </summary>
|
||||
public bool isActive { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// string: stringa da mostrare a sinistra (disattivo onInitialize)
|
||||
/// </summary>
|
||||
public string leftString { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// string: stile stringa da mostrare a sinistra (disattivo onInitialize)
|
||||
/// </summary>
|
||||
public string leftStringCSS { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// CSS specifico x placard
|
||||
/// </summary>
|
||||
public string placardCss { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// string: stringa da mostrare a destra (attivo onInitialize)
|
||||
/// </summary>
|
||||
public string rightString { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// string: stile stringa da mostrare a destra (attivo onInitialize)
|
||||
/// </summary>
|
||||
public string rightStringCSS { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Parametro da mostrare in tooltip
|
||||
/// </summary>
|
||||
public string toolTip { get; set; } = "";
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (!(obj is SelectGlobalToggle item))
|
||||
return false;
|
||||
|
||||
if (isActive != item.isActive)
|
||||
return false;
|
||||
|
||||
if (leftString != item.leftString)
|
||||
return false;
|
||||
|
||||
if (rightString != item.rightString)
|
||||
return false;
|
||||
|
||||
if (leftStringCSS != item.leftStringCSS)
|
||||
return false;
|
||||
|
||||
if (rightStringCSS != item.rightStringCSS)
|
||||
return false;
|
||||
|
||||
if (toolTip != item.toolTip)
|
||||
return false;
|
||||
|
||||
if (placardCss != item.placardCss)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
}
|
||||
|
||||
#endregion Public Classes
|
||||
|
||||
#region Protected Properties
|
||||
|
||||
protected bool isActive
|
||||
{
|
||||
get => SelFilter.isActive;
|
||||
set
|
||||
{
|
||||
SelFilter.isActive = value;
|
||||
reportChange();
|
||||
}
|
||||
}
|
||||
|
||||
protected string leftString
|
||||
{
|
||||
get => SelFilter.leftString;
|
||||
set
|
||||
{
|
||||
if (SelFilter.leftString != value)
|
||||
{
|
||||
SelFilter.leftString = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected string leftStringCSS
|
||||
{
|
||||
get => SelFilter.leftStringCSS;
|
||||
set
|
||||
{
|
||||
if (SelFilter.leftStringCSS != value)
|
||||
{
|
||||
SelFilter.leftStringCSS = value;
|
||||
reportChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected string placardCss
|
||||
{
|
||||
get => SelFilter.placardCss;
|
||||
set
|
||||
{
|
||||
if (SelFilter.placardCss != value)
|
||||
{
|
||||
SelFilter.placardCss = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected string rightString
|
||||
{
|
||||
get => SelFilter.rightString;
|
||||
set
|
||||
{
|
||||
if (SelFilter.rightString != value)
|
||||
{
|
||||
SelFilter.rightString = value;
|
||||
reportChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected string rightStringCSS
|
||||
{
|
||||
get => SelFilter.rightStringCSS;
|
||||
set
|
||||
{
|
||||
if (SelFilter.rightStringCSS != value)
|
||||
{
|
||||
SelFilter.rightStringCSS = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected string toolTip
|
||||
{
|
||||
get => SelFilter.toolTip;
|
||||
set
|
||||
{
|
||||
if (SelFilter.toolTip != value)
|
||||
{
|
||||
SelFilter.toolTip = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if (isActive)
|
||||
{
|
||||
rightStringCSS = "fw-bold";
|
||||
leftStringCSS = "text-secondary";
|
||||
}
|
||||
else
|
||||
{
|
||||
leftStringCSS = "fw-bold";
|
||||
rightStringCSS = "text-secondary";
|
||||
}
|
||||
await Task.Delay(1);
|
||||
}
|
||||
|
||||
protected void toggle()
|
||||
{
|
||||
var currFilt = SelFilter;
|
||||
currFilt.isActive = !currFilt.isActive;
|
||||
SelFilter = currFilt;
|
||||
if (isActive)
|
||||
{
|
||||
rightStringCSS = "fw-bold";
|
||||
leftStringCSS = "text-secondary";
|
||||
}
|
||||
else
|
||||
{
|
||||
leftStringCSS = "fw-bold";
|
||||
rightStringCSS = "text-secondary";
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private void reportChange()
|
||||
{
|
||||
FilterChanged.InvokeAsync(SelFilter);
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace GPW.CORE.WRKLOG
|
||||
namespace GPW.CORE.Comp
|
||||
{
|
||||
public class chartJsData
|
||||
{
|
||||
@@ -0,0 +1,26 @@
|
||||
[
|
||||
{
|
||||
"outputFile": "CircleGauge.razor.css",
|
||||
"inputFile": "CircleGauge.razor.less"
|
||||
},
|
||||
{
|
||||
"outputFile": "CmpTop.razor.css",
|
||||
"inputFile": "CmpTop.razor.less"
|
||||
},
|
||||
{
|
||||
"outputFile": "NavBottom.razor.css",
|
||||
"inputFile": "NavBottom.razor.less"
|
||||
},
|
||||
{
|
||||
"outputFile": "CalendarMonth.razor.css",
|
||||
"inputFile": "CalendarMonth.razor.less"
|
||||
},
|
||||
{
|
||||
"outputFile": "CalendarWeek.razor.css",
|
||||
"inputFile": "CalendarWeek.razor.less"
|
||||
},
|
||||
{
|
||||
"outputFile": "CalWeekColumn.razor.css",
|
||||
"inputFile": "CalWeekColumn.razor.less"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"compilers": {
|
||||
"less": {
|
||||
"autoPrefix": "",
|
||||
"cssComb": "none",
|
||||
"ieCompat": true,
|
||||
"math": null,
|
||||
"strictMath": false,
|
||||
"strictUnits": false,
|
||||
"relativeUrls": true,
|
||||
"rootPath": "",
|
||||
"sourceMapRoot": "",
|
||||
"sourceMapBasePath": "",
|
||||
"sourceMap": false
|
||||
},
|
||||
"sass": {
|
||||
"autoPrefix": "",
|
||||
"loadPaths": "",
|
||||
"style": "expanded",
|
||||
"relativeUrls": true,
|
||||
"sourceMap": false
|
||||
},
|
||||
"nodesass": {
|
||||
"autoPrefix": "",
|
||||
"includePath": "",
|
||||
"indentType": "space",
|
||||
"indentWidth": 2,
|
||||
"outputStyle": "nested",
|
||||
"precision": 5,
|
||||
"relativeUrls": true,
|
||||
"sourceMapRoot": "",
|
||||
"lineFeed": "",
|
||||
"sourceMap": false
|
||||
},
|
||||
"stylus": {
|
||||
"sourceMap": false
|
||||
},
|
||||
"babel": {
|
||||
"sourceMap": false
|
||||
},
|
||||
"coffeescript": {
|
||||
"bare": false,
|
||||
"runtimeMode": "node",
|
||||
"sourceMap": false
|
||||
},
|
||||
"handlebars": {
|
||||
"root": "",
|
||||
"noBOM": false,
|
||||
"name": "",
|
||||
"namespace": "",
|
||||
"knownHelpersOnly": false,
|
||||
"forcePartial": false,
|
||||
"knownHelpers": [],
|
||||
"commonjs": "",
|
||||
"amd": false,
|
||||
"sourceMap": false
|
||||
}
|
||||
},
|
||||
"minifiers": {
|
||||
"css": {
|
||||
"enabled": true,
|
||||
"termSemicolons": true,
|
||||
"gzip": false
|
||||
},
|
||||
"javascript": {
|
||||
"enabled": true,
|
||||
"termSemicolons": true,
|
||||
"gzip": false
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 378 B |
@@ -0,0 +1,6 @@
|
||||
// This is a JavaScript module that is loaded on demand. It can export any number of
|
||||
// functions, and may import other JavaScript modules if required.
|
||||
|
||||
export function showPrompt(message) {
|
||||
return prompt(message, 'Type anything here');
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GPW.CORE.Data
|
||||
{
|
||||
public class Const
|
||||
{
|
||||
#region Public Fields
|
||||
|
||||
public const string rPipeChRich = $"Channel_Rich";
|
||||
public const string rPipeChTimb = $"Channel_Timb";
|
||||
|
||||
#endregion Public Fields
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -16,11 +16,15 @@ namespace GPW.CORE.Data.DTO
|
||||
public int IdxDipendente { get; set; } = 0;
|
||||
public DateTime DtRif { get; set; } = DateTime.Today;
|
||||
|
||||
public List<RegAttivitaModel>? ListRA { get; set; }
|
||||
public List<TimbratureModel>? ListTimbr { get; set; }
|
||||
public TimbratureExplModel? TimbrExpl { get; set; }
|
||||
public List<RilievoTempModel>? ListRilTemp { get; set; }
|
||||
public List<CheckVc19Model>? ListCheckC19 { get; set; }
|
||||
public List<RegAttivitaModel>? ListRA { get; set; } = null;
|
||||
public List<TimbratureModel>? ListTimbr { get; set; } = null;
|
||||
public TimbratureExplModel? TimbrExpl { get; set; } = null;
|
||||
public List<RilievoTempModel>? ListRilTemp { get; set; } = null;
|
||||
public List<CheckVc19Model>? ListCheckC19 { get; set; } = null;
|
||||
public List<CalFesteFerieModel>? ListFermateAzienda { get; set; } = null;
|
||||
public List<RegMalattieModel>? ListMalattie { get; set; } = null;
|
||||
public List<RegRichiesteModel>? ListFerieDip { get; set; } = null;
|
||||
public List<RegRichiesteModel>? ListRichiesteDip { get; set; } = null;
|
||||
|
||||
public DateTime DtInizio
|
||||
{
|
||||
@@ -39,20 +43,22 @@ namespace GPW.CORE.Data.DTO
|
||||
}
|
||||
}
|
||||
|
||||
public double OreLav
|
||||
public double OreComm
|
||||
{
|
||||
get
|
||||
{
|
||||
double answ = 0;
|
||||
if (ListRA != null && ListRA.Count > 0)
|
||||
{
|
||||
answ = ListRA
|
||||
.Sum(x => x.OreTot == null ? 0 : (double)x.OreTot);
|
||||
answ = (double)ListRA.Sum(x => x.OreTot ?? 0);
|
||||
}
|
||||
// fix arrotondamento ai 5 minuti straight
|
||||
TimeSpan tSpan = Utils.TSpanRounded(TimeSpan.FromHours(answ), 5);
|
||||
answ = tSpan.TotalHours;
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
public double OreComm
|
||||
public double OreLav
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -60,12 +66,56 @@ namespace GPW.CORE.Data.DTO
|
||||
if (TimbrExpl != null && TimbrExpl.HLav != null)
|
||||
{
|
||||
answ = (double)TimbrExpl.HLav;
|
||||
if (DtRif == DateTime.Today)
|
||||
{
|
||||
if (ListTimbr != null)
|
||||
{
|
||||
// aggiungo ultima timb fino ad adesso...
|
||||
var lastIn = ListTimbr.Where(x => x.Entrata == true).OrderByDescending(x => x.DataOra).FirstOrDefault();
|
||||
var lastOut = ListTimbr.Where(x => x.Entrata == false).OrderByDescending(x => x.DataOra).FirstOrDefault();
|
||||
// se MANCA timb uscita finale...
|
||||
if (lastIn != null)
|
||||
{
|
||||
if (lastOut == null || lastOut.DataOra < lastIn.DataOra)
|
||||
{
|
||||
DateTime adesso = DateTime.Now;
|
||||
answ += adesso.Subtract(lastIn.DataOra).TotalHours;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// fix arrotondamento ai 5 minuti x difetto
|
||||
TimeSpan tSpan = Utils.TSpanRounded(TimeSpan.FromHours(answ), 5, true);
|
||||
answ = tSpan.TotalHours;
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
public int MinComm
|
||||
{
|
||||
get => (int)Math.Round(OreComm * 60);
|
||||
}
|
||||
public int MinLav
|
||||
{
|
||||
get => (int)Math.Round(OreLav * 60);
|
||||
}
|
||||
|
||||
public string OreMinLav
|
||||
{
|
||||
get
|
||||
{
|
||||
TimeSpan durTs = TimeSpan.FromHours(OreLav);
|
||||
return $"{durTs.Hours}:{durTs.Minutes:00}";
|
||||
}
|
||||
}
|
||||
public string OreMinComm
|
||||
{
|
||||
get
|
||||
{
|
||||
TimeSpan durTs = TimeSpan.FromHours(OreComm);
|
||||
return $"{durTs.Hours}:{durTs.Minutes:00}";
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
using EgwCoreLib.Utils;
|
||||
using GPW.CORE.Data.DbModels;
|
||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GPW.CORE.Data.DTO
|
||||
{
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
public class ReportDataDTO
|
||||
{
|
||||
public int IdxDipendente { get; set; } = 0;
|
||||
|
||||
public DtUtils.Periodo Periodo { get; set; } = new DtUtils.Periodo();
|
||||
|
||||
public List<RegAttivitaModel>? ListRA { get; set; } = null;
|
||||
|
||||
public List<TimbratureModel>? ListTimbr { get; set; } = null;
|
||||
|
||||
public List<TimbratureExplModel>? TimbrExpl { get; set; } = null;
|
||||
|
||||
public List<ProjData> ProjTotal { get; set; } = new List<ProjData>();
|
||||
|
||||
public void DoCalc()
|
||||
{
|
||||
// totalizzazione ore
|
||||
OreComm = OreCommCalc;
|
||||
OreLav = OreLavCalc;
|
||||
// calcolo totali x progetto...
|
||||
int idxProj = 0;
|
||||
string gruppo = "";
|
||||
string cliente = "";
|
||||
string nomeProj = "";
|
||||
string descProj = "";
|
||||
decimal durItem = 0;
|
||||
foreach (var recRA in ListRA)
|
||||
{
|
||||
idxProj = recRA.FasiNav.ProgettoNav.IdxProgetto;
|
||||
gruppo = recRA.FasiNav.ProgettoNav.Gruppo;
|
||||
cliente = recRA.FasiNav.ProgettoNav.ClienteNav?.RagSociale ?? $"{recRA.FasiNav.ProgettoNav.IdxCliente}";
|
||||
nomeProj = recRA.FasiNav.ProgettoNav.NomeProj;
|
||||
descProj = recRA.FasiNav.ProgettoNav.DescrProj;
|
||||
durItem = recRA.OreTot ?? 0;
|
||||
// cerco proj...
|
||||
var currProj = ProjTotal.FirstOrDefault(x => x.idxProj == idxProj);
|
||||
if (currProj != null)
|
||||
{
|
||||
currProj.TotOre += durItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
ProjData newProj = new ProjData()
|
||||
{
|
||||
NomeProj = nomeProj,
|
||||
TotOre = durItem,
|
||||
idxProj = idxProj,
|
||||
DescProj = descProj,
|
||||
Gruppo = gruppo,
|
||||
Cliente = cliente
|
||||
};
|
||||
ProjTotal.Add(newProj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public double OreComm { get; set; } = 0;
|
||||
public double OreLav { get; set; } = 0;
|
||||
|
||||
public double OreCommCalc
|
||||
{
|
||||
get
|
||||
{
|
||||
double answ = 0;
|
||||
if (ListRA != null && ListRA.Count > 0)
|
||||
{
|
||||
answ = (double)ListRA.Sum(x => x.OreTot ?? 0);
|
||||
}
|
||||
// fix arrotondamento ai 5 minuti straight
|
||||
TimeSpan tSpan = Utils.TSpanRounded(TimeSpan.FromHours(answ), 5);
|
||||
answ = tSpan.TotalHours;
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
public double OreLavCalc
|
||||
{
|
||||
get
|
||||
{
|
||||
double answ = 0;
|
||||
if (TimbrExpl != null && TimbrExpl.Count > 0)
|
||||
{
|
||||
answ = (double)TimbrExpl.Sum(x => x.HLav ?? 0);
|
||||
if (Periodo.Fine == DateTime.Today)
|
||||
{
|
||||
if (ListTimbr != null)
|
||||
{
|
||||
// aggiungo ultima timb fino ad adesso...
|
||||
var lastIn = ListTimbr.Where(x => x.Entrata == true).OrderByDescending(x => x.DataOra).FirstOrDefault();
|
||||
var lastOut = ListTimbr.Where(x => x.Entrata == false).OrderByDescending(x => x.DataOra).FirstOrDefault();
|
||||
// se MANCA timb uscita finale...
|
||||
if (lastIn != null)
|
||||
{
|
||||
if (lastOut == null || lastOut.DataOra < lastIn.DataOra)
|
||||
{
|
||||
DateTime adesso = DateTime.Now;
|
||||
answ += adesso.Subtract(lastIn.DataOra).TotalHours;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// fix arrotondamento ai 5 minuti x difetto
|
||||
TimeSpan tSpan = Utils.TSpanRounded(TimeSpan.FromHours(answ), 5, true);
|
||||
answ = tSpan.TotalHours;
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
public int MinComm
|
||||
{
|
||||
get => (int)Math.Round(OreComm * 60);
|
||||
}
|
||||
public int MinLav
|
||||
{
|
||||
get => (int)Math.Round(OreLav * 60);
|
||||
}
|
||||
|
||||
public string OreMinLav
|
||||
{
|
||||
get
|
||||
{
|
||||
TimeSpan durTs = TimeSpan.FromHours(OreLav);
|
||||
return $"{durTs.Hours}:{durTs.Minutes:00}";
|
||||
}
|
||||
}
|
||||
public string GiorniOreMinLav
|
||||
{
|
||||
get
|
||||
{
|
||||
TimeSpan durTs = TimeSpan.FromHours(OreLav);
|
||||
return $"{durTs.Days}gg {durTs.Hours}:{durTs.Minutes:00}";
|
||||
}
|
||||
}
|
||||
|
||||
public string GiorniOreMinComm
|
||||
{
|
||||
get
|
||||
{
|
||||
TimeSpan durTs = TimeSpan.FromHours(OreComm);
|
||||
return $"{durTs.Hours}:{durTs.Minutes:00}";
|
||||
|
||||
}
|
||||
}
|
||||
public string OreMinComm
|
||||
{
|
||||
get
|
||||
{
|
||||
TimeSpan durTs = TimeSpan.FromHours(OreComm);
|
||||
return $"{durTs.Days}gg {durTs.Hours}:{durTs.Minutes:00}";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class ProjData
|
||||
{
|
||||
public int idxProj { get; set; } = 0;
|
||||
|
||||
public string Gruppo { get; set; } = "";
|
||||
public string Cliente { get; set; } = "";
|
||||
public string NomeProj { get; set; } = "";
|
||||
public string DescProj { get; set; } = "";
|
||||
public decimal TotOre { get; set; } = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,11 +11,6 @@ namespace GPW.CORE.Data.DbModels
|
||||
[Table("AnagClienti")]
|
||||
public partial class AnagClientiModel
|
||||
{
|
||||
public AnagClientiModel()
|
||||
{
|
||||
ProgettiNav = new HashSet<AnagProgettiModel>();
|
||||
}
|
||||
|
||||
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public int IdxCliente { get; set; }
|
||||
public string? RagSociale { get; set; } = "";
|
||||
@@ -36,7 +31,5 @@ namespace GPW.CORE.Data.DbModels
|
||||
/// codice esterno
|
||||
/// </summary>
|
||||
public string? CodExt { get; set; } = "";
|
||||
|
||||
public virtual ICollection<AnagProgettiModel> ProgettiNav { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
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("AnagDevices")]
|
||||
public partial class AnagDeviceModel
|
||||
{
|
||||
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public int IdxDevice { get; set; }
|
||||
public string DeviceSecret { get; set; } = null!;
|
||||
public int IdxDipendente { get; set; }
|
||||
public string DeviceName { get; set; } = null!;
|
||||
public string Description { get; set; } = null!;
|
||||
public DateTime DataOraEnabled { get; set; }
|
||||
public DateTime DataOraLastSeen { get; set; }
|
||||
public string LastIpv4 { get; set; } = null!;
|
||||
public string ScreenSize { get; set; } = null!;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
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("AnagGiust")]
|
||||
public partial class AnagGiustModel
|
||||
{
|
||||
[Key]
|
||||
public string codGiust { get; set; } = null!;
|
||||
public string descrizione { get; set; } = "";
|
||||
public bool userSelectable { get; set; } = false;
|
||||
public bool showReq { get; set; } = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
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("CalendFesteFerie")]
|
||||
public partial class CalFesteFerieModel
|
||||
{
|
||||
[Key]
|
||||
public DateTime data { get; set; }
|
||||
public string codGiust { get; set; } = "";
|
||||
public string descrizione { get; set; } = "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
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("Config")]
|
||||
public partial class ConfigModel
|
||||
{
|
||||
[Key]
|
||||
public string chiave { get; set; } = null!;
|
||||
public string valore { get; set; } = "";
|
||||
public string valoreStd { get; set; } = "";
|
||||
public string note { get; set; } = "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace GPW.CORE.Data.DbModels
|
||||
{
|
||||
public partial class DipendendiAndAnomalie
|
||||
{
|
||||
[Key]
|
||||
public int IdxDipendente { get; set; }
|
||||
|
||||
public string CognomeNome { get; set; } = "";
|
||||
public string email { get; set; } = "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
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("Dipendenti2Ruoli")]
|
||||
public partial class Dipendenti2RuoliModel
|
||||
{
|
||||
public int IdxDipendente { get; set; }
|
||||
public string CodRuolo { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// Navigation property to Dipendente
|
||||
/// </summary>
|
||||
[ForeignKey("IdxDipendente")]
|
||||
public virtual DipendentiModel DipNav { get; set; } = null!;
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,7 @@ namespace GPW.CORE.Data.DbModels
|
||||
public DateTime? DataAssunzione { get; set; }
|
||||
public DateTime? DataCessazione { get; set; }
|
||||
public bool? Attivo { get; set; }
|
||||
public string Sigla { get; set; } = "";
|
||||
|
||||
public virtual ICollection<RegAttivitaModel> RegAttivitaNav { get; set; }
|
||||
public virtual ICollection<RilievoTempModel> RilievoTempNav { get; set; }
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace GPW.CORE.Data.DbModels
|
||||
{
|
||||
try
|
||||
{
|
||||
valore = Utils.TSpanRounded(TimeSpan.FromHours((double)OreTot), 5, true);
|
||||
valore = Utils.TSpanRounded(TimeSpan.FromHours((double)OreTot), 5, false);
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace GPW.CORE.Data.DbModels
|
||||
{
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
[Table("RegistroMalattie")]
|
||||
public partial class RegMalattieModel
|
||||
{
|
||||
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public int IdxRegMal { get; set; }
|
||||
public int IdxDipendente { get; set; }
|
||||
public DateTime DtInizio { get; set; } = DateTime.Today;
|
||||
public int NumGG { get; set; } = 1;
|
||||
public string CodCert { get; set; } = "";
|
||||
public bool Conf { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Navigation property to Dipendente
|
||||
/// </summary>
|
||||
[ForeignKey("IdxDipendente")]
|
||||
public virtual DipendentiModel DipNav { get; set; } = null!;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
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("RegistroRichieste")]
|
||||
public partial class RegRichiesteModel
|
||||
{
|
||||
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public int IdxRegRich { get; set; }
|
||||
public int IdxDipendente { get; set; }
|
||||
public string CodGiust { get; set; } = "";
|
||||
public DateTime DtStart { get; set; } = DateTime.Today.AddHours(9);
|
||||
public DateTime DtEnd { get; set; } = DateTime.Today.AddHours(17);
|
||||
public string Note { get; set; } = "";
|
||||
public bool Conf { get; set; } = false;
|
||||
|
||||
[NotMapped]
|
||||
public string CodGiustTrim
|
||||
{
|
||||
get => CodGiust.Length <= 3 ? CodGiust : CodGiust.Substring(0, 3);
|
||||
}
|
||||
|
||||
[NotMapped]
|
||||
public string Durata
|
||||
{
|
||||
get
|
||||
{
|
||||
string answ = "-";
|
||||
var durata = DtEnd.Subtract(DtStart);
|
||||
if (CodGiust == "FER")
|
||||
{
|
||||
answ = $"{durata.TotalDays + 1:N0}gg";
|
||||
}
|
||||
else
|
||||
{
|
||||
answ = $"{durata.TotalHours:N1}h";
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Navigation property to Dipendente
|
||||
/// </summary>
|
||||
[ForeignKey("IdxDipendente")]
|
||||
public virtual DipendentiModel? DipNav { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
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("RegistroEventi")]
|
||||
public partial class RegistroEventiModel
|
||||
{
|
||||
public DateTime DataOra { get; set; }
|
||||
public string Evento { get; set; } = null!;
|
||||
public string? Commento { get; set; } = "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace GPW.CORE.Data.DbModels
|
||||
{
|
||||
// <Auto-Generated>
|
||||
// This is here so CodeMaid doesn't reorganize this document
|
||||
// </Auto-Generated>
|
||||
public partial class StatsDayPresModel
|
||||
{
|
||||
[Key]
|
||||
public int IdxDipendente { get; set; }
|
||||
public DateTime LastOp { get; set; }
|
||||
public int NEnt { get; set; } = 0;
|
||||
public int NUsc { get; set; } = 0;
|
||||
public int IsPresent { get; set; } = 0;
|
||||
|
||||
#if false
|
||||
/// <summary>
|
||||
/// Navigation property to Dipendente
|
||||
/// </summary>
|
||||
[ForeignKey("IdxDipendente")]
|
||||
public virtual DipendentiModel DipNav { get; set; } = null!;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace GPW.CORE.Data.DbModels
|
||||
{
|
||||
public partial class TeRaExplModel
|
||||
{
|
||||
public DateTime DataLav { get; set; }
|
||||
public int IdxDipendente { get; set; }
|
||||
public string CognomeNome { get; set; } = "";
|
||||
public double h_lav { get; set; } = 0;
|
||||
public double h_giust { get; set; } = 0;
|
||||
public decimal h_com { get; set; } = 0;
|
||||
public string progetti { get; set; } = "";
|
||||
public int okLAvCom { get; set; } = 0;
|
||||
public bool isOkTim { get; set; } = false;
|
||||
public bool isOkApp { get; set; } = false;
|
||||
public int isOkLav { get; set; } = 0;
|
||||
public int isOk { get; set; } = 0;
|
||||
public bool block { get; set; } = false;
|
||||
public int minOrd { get; set; } = 0;
|
||||
public int minNonLav { get; set; } = 0;
|
||||
public int minStra { get; set; } = 0;
|
||||
public int minPerm { get; set; } = 0;
|
||||
public int minFer { get; set; } = 0;
|
||||
public int minMal { get; set; } = 0;
|
||||
public int minFest { get; set; } = 0;
|
||||
public int minRegAtt { get; set; } = 0;
|
||||
public DateTime? entrata_1 { get; set; }
|
||||
public DateTime? uscita_1 { get; set; }
|
||||
public DateTime? entrata_2 { get; set; }
|
||||
public DateTime? uscita_2 { get; set; }
|
||||
public DateTime? entrata_3 { get; set; }
|
||||
public DateTime? uscita_3 { get; set; }
|
||||
public DateTime? entrata_4 { get; set; }
|
||||
public DateTime? uscita_4 { get; set; }
|
||||
public int minArcoPres { get; set; } = 0;
|
||||
public string chkFunCod { get; set; } = "";
|
||||
public string chkFunRes { get; set; } = "";
|
||||
public int minMpp { get; set; } = 0;
|
||||
public int minCassa { get; set; } = 0;
|
||||
public int min104 { get; set; } = 0;
|
||||
public decimal TempRil { get; set; } = 0;
|
||||
public bool TagIsActive { get; set; } = false;
|
||||
public string CodTag { get; set; } = "";
|
||||
|
||||
}
|
||||
}
|
||||
+18
-18
@@ -11,22 +11,22 @@ namespace GPW.CORE.Data
|
||||
ND = 0,
|
||||
Lavoro = 1
|
||||
}
|
||||
public enum TestUser
|
||||
{
|
||||
LocatelliSamuele = 1,
|
||||
SalviMarco = 3,
|
||||
RottoliGiancarlo = 4,
|
||||
BaroniMara = 6,
|
||||
LocatelliMarco = 8,
|
||||
SassiDario = 10,
|
||||
SassiEmmanuele = 11,
|
||||
LanzaRenzo = 12,
|
||||
MangiaLorenzo = 13,
|
||||
PerdoncinSara = 14,
|
||||
PievaniNicola = 15,
|
||||
Tarri, Selene = 16,
|
||||
BaronchelliCarlo = 18,
|
||||
MonchiFilippo = 19,
|
||||
VivianiCarlo = 20
|
||||
}
|
||||
//public enum TestUser
|
||||
//{
|
||||
// LocatelliSamuele = 1,
|
||||
// SalviMarco = 3,
|
||||
// RottoliGiancarlo = 4,
|
||||
// BaroniMara = 6,
|
||||
// LocatelliMarco = 8,
|
||||
// SassiDario = 10,
|
||||
// SassiEmmanuele = 11,
|
||||
// LanzaRenzo = 12,
|
||||
// MangiaLorenzo = 13,
|
||||
// PerdoncinSara = 14,
|
||||
// PievaniNicola = 15,
|
||||
// Tarri, Selene = 16,
|
||||
// BaronchelliCarlo = 18,
|
||||
// MonchiFilippo = 19,
|
||||
// VivianiCarlo = 20
|
||||
//}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="EgwCoreLib.Utils" Version="1.5.2402.2411" />
|
||||
<PackageReference Include="MailKit" Version="3.5.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="6.0.14" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.14" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.14" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.14" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.14">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NLog" Version="5.2.2" />
|
||||
<PackageReference Include="StackExchange.Redis" Version="2.7.27" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -7,17 +7,19 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MailKit" Version="3.3.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="6.0.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.7">
|
||||
<PackageReference Include="EgwCoreLib.Utils" Version="1.5.2402.2411" />
|
||||
<PackageReference Include="MailKit" Version="3.5.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="6.0.14" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.14" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.14" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.14" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.14">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="NLog" Version="5.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NLog" Version="5.2.2" />
|
||||
<PackageReference Include="StackExchange.Redis" Version="2.7.27" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
+120
-2
@@ -55,6 +55,17 @@ namespace GPW.CORE.Data
|
||||
public virtual DbSet<AnagKeyValueModel> DbSetAnagKeyValue { get; set; } = null!;
|
||||
public virtual DbSet<AnagTipoTimbModel> DbSetAnagTipoTimb { get; set; } = null!;
|
||||
public virtual DbSet<Dipendenti2GruppiModel> DbSetDipendenti2Gruppi { get; set; } = null!;
|
||||
public virtual DbSet<CalFesteFerieModel> DbSetCalFesteFerie { get; set; } = null!;
|
||||
public virtual DbSet<RegMalattieModel> DbSetRegMalattie { get; set; } = null!;
|
||||
public virtual DbSet<RegRichiesteModel> DbSetRegRichieste { get; set; } = null!;
|
||||
public virtual DbSet<ConfigModel> DbSetConfig { get; set; } = null!;
|
||||
public virtual DbSet<AnagGiustModel> DbSetAnagGiust { get; set; } = null!;
|
||||
public virtual DbSet<AnagDeviceModel> DbSetAnagDevices { get; set; } = null!;
|
||||
public virtual DbSet<Dipendenti2RuoliModel> DbSetDip2Ruoli { get; set; } = null!;
|
||||
public virtual DbSet<RegistroEventiModel> DbSetRegEventi { get; set; } = null!;
|
||||
public virtual DbSet<DipendendiAndAnomalie> DbSetDipAndAnom { get; set; } = null!;
|
||||
public virtual DbSet<TeRaExplModel> DbSetTeRaExpl { get; set; } = null!;
|
||||
public virtual DbSet<StatsDayPresModel> DbSetStatsDayPres { get; set; } = null!;
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
@@ -67,8 +78,7 @@ namespace GPW.CORE.Data
|
||||
}
|
||||
else
|
||||
{
|
||||
optionsBuilder.UseSqlServer("Server=SQL2016DEV;Database=Sauder_NKC;Trusted_Connection=True;");
|
||||
optionsBuilder.UseSqlServer("Server=SQLSTEAM;Database=GPW;Trusted_Connection=True;");
|
||||
optionsBuilder.UseSqlServer("Server=SQLSTEAM;Database=GPW;Trusted_Connection=True;");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -233,6 +243,9 @@ namespace GPW.CORE.Data
|
||||
entity.Property(e => e.WolMac)
|
||||
.HasMaxLength(50)
|
||||
.HasColumnName("WOL_MAC");
|
||||
entity.Property(e => e.Sigla)
|
||||
.HasMaxLength(50)
|
||||
.HasColumnName("sigla");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<RegAttivitaModel>(entity =>
|
||||
@@ -772,6 +785,111 @@ namespace GPW.CORE.Data
|
||||
.HasColumnName("oraFine_3");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<CalFesteFerieModel>(entity =>
|
||||
{
|
||||
entity.Property(e => e.codGiust)
|
||||
.HasMaxLength(5);
|
||||
entity.Property(e => e.descrizione)
|
||||
.HasMaxLength(50);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<RegMalattieModel>(entity =>
|
||||
{
|
||||
entity.Property(e => e.CodCert)
|
||||
.HasMaxLength(250);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<RegRichiesteModel>(entity =>
|
||||
{
|
||||
entity.Property(e => e.CodGiust)
|
||||
.HasMaxLength(5);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<ConfigModel>(entity =>
|
||||
{
|
||||
entity.Property(e => e.chiave)
|
||||
.HasMaxLength(250);
|
||||
entity.Property(e => e.valore)
|
||||
.HasMaxLength(250);
|
||||
entity.Property(e => e.valoreStd)
|
||||
.HasMaxLength(250);
|
||||
entity.Property(e => e.note)
|
||||
.HasMaxLength(250);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<AnagGiustModel>(entity =>
|
||||
{
|
||||
entity.Property(e => e.codGiust)
|
||||
.HasMaxLength(5);
|
||||
entity.Property(e => e.descrizione)
|
||||
.HasMaxLength(50);
|
||||
});
|
||||
|
||||
|
||||
modelBuilder.Entity<AnagDeviceModel>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.IdxDevice);
|
||||
|
||||
entity.Property(e => e.DataOraEnabled)
|
||||
.HasColumnType("datetime")
|
||||
.HasColumnName("dataOraEnabled");
|
||||
|
||||
entity.Property(e => e.DataOraLastSeen)
|
||||
.HasColumnType("datetime")
|
||||
.HasColumnName("dataOraLastSeen");
|
||||
|
||||
entity.Property(e => e.Description)
|
||||
.HasMaxLength(500)
|
||||
.HasDefaultValueSql("('')");
|
||||
|
||||
entity.Property(e => e.DeviceName).HasMaxLength(50);
|
||||
|
||||
entity.Property(e => e.DeviceSecret).HasMaxLength(500);
|
||||
|
||||
entity.Property(e => e.IdxDipendente).HasColumnName("idxDipendente");
|
||||
|
||||
entity.Property(e => e.LastIpv4)
|
||||
.HasMaxLength(15)
|
||||
.HasColumnName("lastIPv4")
|
||||
.HasDefaultValueSql("('')");
|
||||
|
||||
entity.Property(e => e.ScreenSize)
|
||||
.HasMaxLength(50)
|
||||
.HasColumnName("screenSize")
|
||||
.HasDefaultValueSql("('')");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Dipendenti2RuoliModel>(entity =>
|
||||
{
|
||||
entity.HasKey(e => new { e.IdxDipendente, e.CodRuolo })
|
||||
.HasName("PK_Dipendenti2Ruoli");
|
||||
entity.Property(e => e.CodRuolo)
|
||||
.HasMaxLength(50);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<RegistroEventiModel>(entity =>
|
||||
{
|
||||
entity.HasKey(e => new { e.DataOra, e.Evento });
|
||||
|
||||
entity.ToTable("RegistroEventi");
|
||||
|
||||
entity.Property(e => e.DataOra).HasColumnType("datetime");
|
||||
|
||||
entity.Property(e => e.Evento)
|
||||
.HasMaxLength(50)
|
||||
.HasColumnName("evento");
|
||||
|
||||
entity.Property(e => e.Commento)
|
||||
.HasMaxLength(250)
|
||||
.HasColumnName("commento");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<TeRaExplModel>(entity =>
|
||||
{
|
||||
entity.HasKey(e => new { e.DataLav, e.IdxDipendente});
|
||||
|
||||
});
|
||||
|
||||
OnModelCreatingPartial(modelBuilder);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
using NLog;
|
||||
using StackExchange.Redis;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace GPW.CORE.Data
|
||||
{
|
||||
public class MessagePipe
|
||||
{
|
||||
#region Public Constructors
|
||||
|
||||
public MessagePipe(IConnectionMultiplexer redisConn, string channelName, bool enableLog = false)
|
||||
{
|
||||
_channel = channelName;
|
||||
redis = redisConn;
|
||||
redisDb = redis.GetDatabase();
|
||||
this.enableLog = enableLog;
|
||||
// aggiungo sottoscrittore
|
||||
setupSubscriber();
|
||||
}
|
||||
|
||||
#endregion Public Constructors
|
||||
|
||||
#region Public Events
|
||||
|
||||
public event EventHandler EA_NewMessage = delegate { };
|
||||
|
||||
#endregion Public Events
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Invio messaggio sul canale + salvataggio in cache REDIS
|
||||
/// </summary>
|
||||
/// <param name="memKey">Chiave REDIS x salvare valore</param>
|
||||
/// <param name="message">Messaggio serializzato da inviare</param>
|
||||
public bool saveAndSendMessage(string memKey, string message)
|
||||
{
|
||||
bool answ = false;
|
||||
Stopwatch stopWatch = new Stopwatch();
|
||||
stopWatch.Start();
|
||||
|
||||
// invio notifica tramite il canale richiesto
|
||||
answ = sendMessage(message);
|
||||
if (redisDb != null)
|
||||
{
|
||||
redisDb.StringSetAsync(memKey, message);
|
||||
}
|
||||
stopWatch.Stop();
|
||||
TimeSpan ts = stopWatch.Elapsed;
|
||||
if (numSent.ContainsKey(memKey))
|
||||
{
|
||||
numSent[memKey]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
numSent.Add(memKey, 1);
|
||||
}
|
||||
if (enableLog || numSent[memKey] > 30)
|
||||
{
|
||||
Log.Info($"saveAndSendMessage| mKey {memKey} x {numSent[memKey]} | {message.Length} size | {ts.TotalMilliseconds} ms");
|
||||
|
||||
numSent[memKey] = 0;
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invio messaggio sul canale
|
||||
/// </summary>
|
||||
/// <param name="newMess"></param>
|
||||
/// <returns></returns>
|
||||
public bool sendMessage(string newMess)
|
||||
{
|
||||
bool answ = false;
|
||||
ISubscriber sub = redis.GetSubscriber();
|
||||
sub.Publish(_channel, newMess);
|
||||
return answ;
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#region Protected Fields
|
||||
|
||||
protected static Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
#endregion Protected Fields
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private bool enableLog = false;
|
||||
private Dictionary<string, int> numSent = new Dictionary<string, int>();
|
||||
private IConnectionMultiplexer redis;
|
||||
private StackExchange.Redis.IDatabase redisDb;
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Private Properties
|
||||
|
||||
/// <summary>
|
||||
/// Canale associato al gestore pipeline messaggi
|
||||
/// </summary>
|
||||
private string _channel { get; set; } = "";
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private void setupSubscriber()
|
||||
{
|
||||
ISubscriber sub = redis.GetSubscriber();
|
||||
//Subscribe to the channel named messages
|
||||
sub.Subscribe(_channel, (channel, message) =>
|
||||
{
|
||||
if (enableLog)
|
||||
{
|
||||
Log.Trace($"req setup ch {channel} | {message}");
|
||||
}
|
||||
// messaggio
|
||||
PubSubEventArgs mea = new PubSubEventArgs(message);
|
||||
// se qualcuno ascolta sollevo evento nuovo valore...
|
||||
if (EA_NewMessage != null)
|
||||
{
|
||||
EA_NewMessage(this, mea);
|
||||
}
|
||||
});
|
||||
if (enableLog)
|
||||
{
|
||||
Log.Info($"Subscribed {_channel}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
|
||||
public class PubSubEventArgs : EventArgs
|
||||
{
|
||||
#region Public Constructors
|
||||
|
||||
public PubSubEventArgs(string messaggio)
|
||||
{
|
||||
this.newMessage = messaggio;
|
||||
}
|
||||
|
||||
#endregion Public Constructors
|
||||
|
||||
#region Public Properties
|
||||
|
||||
public string newMessage { get; set; } = "";
|
||||
|
||||
#endregion Public Properties
|
||||
}
|
||||
}
|
||||
@@ -61,6 +61,17 @@ namespace GPW.CORE.Data
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Costruisce una riga ripetendo un carattere molte volte
|
||||
/// </summary>
|
||||
/// <param name="padChar"></param>
|
||||
/// <param name="repNum"></param>
|
||||
/// <returns></returns>
|
||||
public static string charLine(char padChar, int repNum)
|
||||
{
|
||||
return new string(padChar, repNum);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua arrotondamento di un timespan ad un dato step di minuti
|
||||
///
|
||||
@@ -79,5 +90,18 @@ namespace GPW.CORE.Data
|
||||
TimeSpan answ = new TimeSpan(ticks * step.Ticks);
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inizializzazione con periodo e arrotondamento
|
||||
/// </summary>
|
||||
/// <param name="minRound"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime InitDatetime(DateTime dtRif, int minRound)
|
||||
{
|
||||
TimeSpan DayElapsed = dtRif.Subtract(dtRif.Date);
|
||||
int minDay = (int)Math.Ceiling((double)(DayElapsed.TotalMinutes / minRound)) * minRound;
|
||||
DateTime endRounded = DateTime.Today.AddMinutes(minDay);
|
||||
return endRounded;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-6
@@ -1,9 +1,11 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.4.33122.133
|
||||
VisualStudioVersion = 17.4.33205.214
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GPW.CORE.SMART", "GPW.CORE.SMART\GPW.CORE.SMART.csproj", "{1652B4B5-BB10-49F2-B85F-D24B27E15B3A}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GPW.CORE.Smart", "GPW.CORE.Smart\GPW.CORE.Smart.csproj", "{9E5A3295-08BF-4603-9FA3-D38A2F1100E5}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GPW.CORE.Data", "GPW.CORE.Data\GPW.CORE.Data.csproj", "{32DE3E46-CCED-4F7E-8EC1-A854DA4F51C1}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@@ -11,10 +13,14 @@ Global
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{1652B4B5-BB10-49F2-B85F-D24B27E15B3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1652B4B5-BB10-49F2-B85F-D24B27E15B3A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1652B4B5-BB10-49F2-B85F-D24B27E15B3A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1652B4B5-BB10-49F2-B85F-D24B27E15B3A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9E5A3295-08BF-4603-9FA3-D38A2F1100E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9E5A3295-08BF-4603-9FA3-D38A2F1100E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9E5A3295-08BF-4603-9FA3-D38A2F1100E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9E5A3295-08BF-4603-9FA3-D38A2F1100E5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{32DE3E46-CCED-4F7E-8EC1-A854DA4F51C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{32DE3E46-CCED-4F7E-8EC1-A854DA4F51C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{32DE3E46-CCED-4F7E-8EC1-A854DA4F51C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{32DE3E46-CCED-4F7E-8EC1-A854DA4F51C1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<div class="accordion mb-5" id="accordionExample">
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="headingThree">
|
||||
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseZero" aria-expanded="false" aria-controls="collapseZero">
|
||||
<b>Gestione Admin</b>
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapseZero" class="accordion-collapse collapse show" aria-labelledby="headingZero" data-bs-parent="#accordionExample">
|
||||
<div class="accordion-body small">
|
||||
Di seguito le procedure per resettare e reinviare via email l'authKey al dipendente, approvare le timbrature, mostrare il QRCode di login
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@if (!isAuthKeyAdmin && !isApprAdmin)
|
||||
{
|
||||
<div class="accordion-item">
|
||||
<LoadingData DisplayMode="LoadingData.SpinMode.Growl"></LoadingData>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
@if (isAuthKeyAdmin)
|
||||
{
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="headingThree">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
|
||||
<b>QRCode direct display</b>
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapseThree" class="accordion-collapse collapse" aria-labelledby="headingThree" data-bs-parent="#accordionExample">
|
||||
<div class="accordion-body">
|
||||
<UserQrCode></UserQrCode>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="headingOne">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="false" aria-controls="collapseOne">
|
||||
<b>ADMIN Reset AuthKey via e-mail</b>
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapseOne" class="accordion-collapse collapse" aria-labelledby="headingOne" data-bs-parent="#accordionExample">
|
||||
<div class="accordion-body p-1">
|
||||
<InvioLinkEmail IdxDipAdmin="@IdxDipendente"></InvioLinkEmail>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (isApprAdmin)
|
||||
{
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="headingTwo">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
|
||||
<b>Approvazione Timbrature</b>
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapseTwo" class="accordion-collapse collapse" aria-labelledby="headingThree" data-bs-parent="#accordionExample">
|
||||
<TimbAdmin IdxDipAdmin="@IdxDipendente"></TimbAdmin>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
using GPW.CORE.Data.DbModels;
|
||||
using GPW.CORE.Smart.Data;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace GPW.CORE.Smart.Components
|
||||
{
|
||||
public partial class AdminTask
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
[Parameter]
|
||||
public int IdxDipendente { get; set; } = 0;
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (IdxDipendente > 0)
|
||||
{
|
||||
await ReloadData();
|
||||
await Task.Delay(1);
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private bool isApprAdmin = false;
|
||||
|
||||
private bool isAuthKeyAdmin = false;
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Private Properties
|
||||
|
||||
[Inject]
|
||||
private CoreSmartDataService CDService { get; set; } = null!;
|
||||
|
||||
private List<Dipendenti2RuoliModel>? listaRuoli { get; set; } = new List<Dipendenti2RuoliModel>();
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private async Task ReloadData()
|
||||
{
|
||||
// verifico se il dip sia admin...
|
||||
listaRuoli = await CDService.Dip2RuoliGetAll();
|
||||
if (listaRuoli != null)
|
||||
{
|
||||
isAuthKeyAdmin = listaRuoli.FirstOrDefault(x => x.IdxDipendente == IdxDipendente && x.CodRuolo == "ResetAuthKey") != null;
|
||||
isApprAdmin = listaRuoli.FirstOrDefault(x => x.IdxDipendente == IdxDipendente && x.CodRuolo == "AppMancTimb") != null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
|
||||
//private async void MService_EA_DipUpdated()
|
||||
//{
|
||||
// //idxDipendente = MService.IdxDipendente;
|
||||
// await Task.Delay(1);
|
||||
// await ReloadData();
|
||||
// await Task.Delay(1);
|
||||
// await InvokeAsync(StateHasChanged);
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<div class="buttons">
|
||||
@if (IsRicTimb)
|
||||
{
|
||||
<button class="mancTimb" @onclick="() => doRichiesta(true)"><i class="fa-solid fa-right-to-bracket"></i> ENTRATA</button>
|
||||
<button class="mancTimb" @onclick="() => doRichiesta(false)">USCITA <i class="fa-solid fa-right-from-bracket"></i></button>
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@if (nextIsEntrata)
|
||||
{
|
||||
<button class="entrata" @onclick="() => registraTimbratura(true)"><i class="fa-solid fa-right-to-bracket"></i> ENTRATA</button>
|
||||
<button class="uscitaDisabled" disabled>USCITA <i class="fa-solid fa-right-from-bracket"></i></button>
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
<button class="entrataDisabled" disabled><i class="fa-solid fa-right-to-bracket"></i> ENTRATA</button>
|
||||
<button class="uscita" @onclick="() => registraTimbratura(false)">USCITA <i class="fa-solid fa-right-from-bracket"></i></button>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
|
||||
@if (isRecording && false)
|
||||
{
|
||||
<dialog class="modal fade show" tabindex="-1" style="display:block; background-color: rgba(10,10,10,.6);" aria-modal="true" role="dialog">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="col-12 text-center my-0 py-3 alert alert-primary">
|
||||
<div class="d-flex justify-content-between py-4">
|
||||
<div class="text-start">
|
||||
<h1><i class="fa-solid fa-database"></i> working</h1>
|
||||
<b>@lastAction</b>
|
||||
</div>
|
||||
<div>
|
||||
<div class="spinner-grow" role="status" style="width: 3rem; height: 3rem;">
|
||||
<span class="visually-hidden">Sending...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
}
|
||||
|
||||
<div class="toast-container p-3 bottom-0 start-50 translate-middle-x">
|
||||
<div class="toast bg-light fade @toastCss" id="LiveToast2" role="alert" aria-live="assertive" aria-atomic="true">
|
||||
<div class="toast-header">
|
||||
<span class="bg-primary px-2 text-light rounded me-2"><i class="fa-solid fa-clock"></i></span>
|
||||
<strong class="me-auto">Timbratura</strong>
|
||||
<small>@textDtAct</small>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="toast-body">
|
||||
@lastAction
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,277 @@
|
||||
using GPW.CORE.Data;
|
||||
using GPW.CORE.Data.DbModels;
|
||||
using GPW.CORE.Data.DTO;
|
||||
using GPW.CORE.Smart.Data;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
using System.Data;
|
||||
|
||||
namespace GPW.CORE.Smart.Components
|
||||
{
|
||||
public partial class BottoniEntrEsc : IDisposable
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
[Parameter]
|
||||
public int IdxDipendente { get; set; } = -1;
|
||||
|
||||
public bool isRecording { get; set; } = false;
|
||||
|
||||
[Parameter]
|
||||
public bool IsRicTimb { get; set; } = false;
|
||||
|
||||
[Parameter]
|
||||
public List<DailyDataDTO>? ListRecords
|
||||
{
|
||||
get => listRecords;
|
||||
set { listRecords = value; }
|
||||
}
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
listRecords = null;
|
||||
ListRecords = null;
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Inserimento record timbratura
|
||||
/// </summary>
|
||||
/// <param name="IsUscita"></param>
|
||||
/// <returns></returns>
|
||||
protected async Task<bool> DoAdd(bool IsUscita)
|
||||
{
|
||||
bool done = false;
|
||||
// var accessorie / base
|
||||
TimbratureModel currRecord = new TimbratureModel();
|
||||
string ipv4 = await MService.getDevIpAsync();
|
||||
int idxDip = MService.IdxDipendente;
|
||||
|
||||
// verifico se si trattasse di timbratura uscita da attivita' del giorno precedente...
|
||||
if (IsUscita)
|
||||
{
|
||||
// se il giorno precedente NON fosse stato chiuso...
|
||||
DateTime ieri = DataRif.Date.AddDays(-1);
|
||||
List<TimbratureModel> ListTimbIeri = await CDService.TimbratureDay(ieri, idxDip);
|
||||
// cerco ultima, se fosse entrata...
|
||||
if (ListTimbIeri != null && ListTimbIeri.Count > 0)
|
||||
{
|
||||
var isEntrata = false;
|
||||
var ultima = ListTimbIeri.OrderByDescending(x => x.DataOra).FirstOrDefault();
|
||||
if (ultima != null)
|
||||
{
|
||||
bool.TryParse($"{ultima.Entrata}", out isEntrata);
|
||||
if (isEntrata)
|
||||
{
|
||||
// chiedo verifica
|
||||
bool doSplit = await JSRuntime.InvokeAsync<bool>("confirm", "Sembra tu stia chiudendo un periodo iniziato in un giorno precedente, vuoi suddividere in set di timbrature per ogni giornata?");
|
||||
|
||||
// aggiungo chiusura alla timbratura di ieri alle 23.59
|
||||
currRecord = new TimbratureModel()
|
||||
{
|
||||
Entrata = false,
|
||||
Approv = false,
|
||||
CodTipoTimb = "Web",
|
||||
DataOra = ieri.AddDays(1).AddSeconds(-1),
|
||||
IdxDipendente = idxDip,
|
||||
Ipv4 = $"{ipv4}"
|
||||
};
|
||||
done = await CDService.TimbratureUpdate(currRecord);
|
||||
|
||||
if (done)
|
||||
{
|
||||
// aggiungo apertura ad oggi
|
||||
currRecord = new TimbratureModel()
|
||||
{
|
||||
Entrata = true,
|
||||
Approv = false,
|
||||
CodTipoTimb = "Web",
|
||||
DataOra = ieri.AddDays(1),
|
||||
IdxDipendente = idxDip,
|
||||
Ipv4 = $"{ipv4}"
|
||||
};
|
||||
done = await CDService.TimbratureUpdate(currRecord);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// seleziono data-ora timbratura
|
||||
DateTime dtTimb = DateTime.Now;
|
||||
bool preApprov = true;
|
||||
// effettuo controllo: se IP non fosse interno --> arrotondo 5 minuti!
|
||||
if (!ipv4.Contains(LocalNet))
|
||||
{
|
||||
// arrotondo ingresso/uscita ai 5 minuti secondo sia entrata o uscita...
|
||||
dtTimb = Utils.DateRounded(DataRif, 5, IsUscita);
|
||||
preApprov = false;
|
||||
}
|
||||
// altrimenti
|
||||
currRecord = new TimbratureModel()
|
||||
{
|
||||
Entrata = !IsUscita,
|
||||
Approv = preApprov,
|
||||
CodTipoTimb = "Web",
|
||||
DataOra = dtTimb,
|
||||
IdxDipendente = idxDip,
|
||||
Ipv4 = $"{ipv4}"
|
||||
};
|
||||
|
||||
// aggiorno
|
||||
done = await CDService.TimbratureUpdate(currRecord);
|
||||
await Task.Delay(1);
|
||||
await ReloadData();
|
||||
return done;
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await ReloadData();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
await ReloadData();
|
||||
await Task.Delay(1);
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private DateTime DataRif = DateTime.Now;
|
||||
private string LocalNet = "10.74";
|
||||
private string textDtAct = "";
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Private Properties
|
||||
|
||||
[Inject]
|
||||
private CoreSmartDataService CDService { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
private IHttpContextAccessor httpContextAccessor { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gestione timbrature interne/esterne (DA FARE!!!)
|
||||
/// </summary>
|
||||
private bool isInternal { get; set; } = false;
|
||||
|
||||
[Inject]
|
||||
private IJSRuntime JSRuntime { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Determina il tipo di chiamata ammessa successiva (entrata/uscita)
|
||||
/// </summary>
|
||||
private string lastAction
|
||||
{
|
||||
get => MService.LastAction;
|
||||
set => MService.LastAction = value;
|
||||
}
|
||||
|
||||
private List<DailyDataDTO>? listRecords { get; set; } = null;
|
||||
|
||||
[Inject]
|
||||
private MessageService MService { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
private NavigationManager NavManager { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Determina il tipo di chiamata ammessa successiva (entrata/uscita)
|
||||
/// </summary>
|
||||
private bool nextIsEntrata
|
||||
{
|
||||
get => MService.NextIsEntrata;
|
||||
set => MService.NextIsEntrata = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Orario in cui si fa richiesta
|
||||
/// </summary>
|
||||
private DateTime oraRichiestaTimb
|
||||
{
|
||||
get => MService.targetDateMancTimb;
|
||||
}
|
||||
|
||||
private string toastCss
|
||||
{
|
||||
get => isRecording ? "show" : "";
|
||||
}
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private async Task doRichiesta(bool isEntrata)
|
||||
{
|
||||
TimbratureModel currRecord = new TimbratureModel();
|
||||
// recupero ip...
|
||||
string ipv4 = await MService.getDevIpAsync();
|
||||
if (string.IsNullOrEmpty(ipv4))
|
||||
{
|
||||
if (httpContextAccessor.HttpContext != null)
|
||||
{
|
||||
var remoteIp = $"{httpContextAccessor.HttpContext.Connection?.RemoteIpAddress}";
|
||||
// provo a recuperare ipV4...
|
||||
ipv4 = EgwCoreLib.Razor.Data.IpUtils.getLocalIpv4(remoteIp);
|
||||
}
|
||||
}
|
||||
// arrotondo ingresso/uscita ai 5 minuti secondo sia entrata o uscita...
|
||||
var dtTimb = Utils.DateRounded(oraRichiestaTimb, 5, !isEntrata);
|
||||
// genero record
|
||||
currRecord = new TimbratureModel()
|
||||
{
|
||||
Entrata = isEntrata,
|
||||
Approv = false,
|
||||
CodTipoTimb = "NoTim",
|
||||
DataOra = dtTimb,
|
||||
IdxDipendente = MService.IdxDipendente,
|
||||
Ipv4 = $"{ipv4}"
|
||||
};
|
||||
|
||||
await CDService.TimbratureInsRichiesta(currRecord);
|
||||
|
||||
NavManager.NavigateTo(NavManager.Uri, true);
|
||||
}
|
||||
|
||||
private async Task registraTimbratura(bool isEntrata)
|
||||
{
|
||||
DateTime adesso = DateTime.Now;
|
||||
textDtAct = $"{adesso:dddd dd.MM.yyyy}";
|
||||
string lastAct = isEntrata ? "INGRESSO" : "USCITA";
|
||||
lastAction = $"Registrato evento {lastAct} alle {adesso:HH:mm}";
|
||||
// inidico inizio update
|
||||
isRecording = true;
|
||||
bool done = await DoAdd(!isEntrata);
|
||||
// solo se ha fatto mostro udpate
|
||||
if (done)
|
||||
{
|
||||
nextIsEntrata = !isEntrata;
|
||||
MService.ReportTimbratura();
|
||||
// chiudo visualizzazione stato update
|
||||
await Task.Delay(5000);
|
||||
}
|
||||
isRecording = false;
|
||||
}
|
||||
|
||||
private async Task ReloadData()
|
||||
{
|
||||
DataRif = DateTime.Now;
|
||||
var confNet = await CDService.ConfigGetKey("LocalNet");
|
||||
LocalNet = confNet != null ? confNet.valore : "10";
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
.buttons {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.buttonsAll {
|
||||
border-radius: 0.75rem;
|
||||
border: none;
|
||||
color: white;
|
||||
width: 100%;
|
||||
height: 2.5rem;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
font-size: 1rem;
|
||||
box-shadow: 0 0.3rem 0.45rem rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
.entrata {
|
||||
border-radius: 0.75rem;
|
||||
border: none;
|
||||
color: white;
|
||||
width: 100%;
|
||||
height: 2.5rem;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
font-size: 1rem;
|
||||
box-shadow: 0 0.3rem 0.45rem rgba(0, 0, 0, 0.8);
|
||||
background-color: #9B59B6;
|
||||
}
|
||||
.mancTimb {
|
||||
border-radius: 0.75rem;
|
||||
border: none;
|
||||
color: white;
|
||||
width: 100%;
|
||||
height: 2.5rem;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
font-size: 1rem;
|
||||
box-shadow: 0 0.3rem 0.45rem rgba(0, 0, 0, 0.8);
|
||||
background-color: #2980B9;
|
||||
}
|
||||
.uscita {
|
||||
border-radius: 0.75rem;
|
||||
border: none;
|
||||
color: white;
|
||||
width: 100%;
|
||||
height: 2.5rem;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
font-size: 1rem;
|
||||
box-shadow: 0 0.3rem 0.45rem rgba(0, 0, 0, 0.8);
|
||||
background-color: #4CAF50;
|
||||
}
|
||||
.entrataDisabled {
|
||||
border-radius: 0.75rem;
|
||||
border: none;
|
||||
color: white;
|
||||
width: 100%;
|
||||
height: 2.5rem;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
font-size: 1rem;
|
||||
box-shadow: 0 0.3rem 0.45rem rgba(0, 0, 0, 0.8);
|
||||
border-color: #9B59B6;
|
||||
color: #000;
|
||||
box-shadow: 0 0.1rem 0.2rem rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.uscitaDisabled {
|
||||
border-radius: 0.75rem;
|
||||
border: none;
|
||||
color: white;
|
||||
width: 100%;
|
||||
height: 2.5rem;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
font-size: 1rem;
|
||||
box-shadow: 0 0.3rem 0.45rem rgba(0, 0, 0, 0.8);
|
||||
border-color: #4CAF50;
|
||||
color: #000;
|
||||
box-shadow: 0 0.1rem 0.2rem rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
.buttons {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.buttonsAll {
|
||||
border-radius: 0.75rem;
|
||||
border: none;
|
||||
color: white;
|
||||
width: 100%;
|
||||
height: 2.5rem;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
font-size: 1rem;
|
||||
box-shadow: 0 0.3rem 0.45rem rgba(0,0,0,0.8);
|
||||
}
|
||||
|
||||
.entrata {
|
||||
.buttonsAll;
|
||||
background-color: #9B59B6;
|
||||
}
|
||||
.mancTimb {
|
||||
.buttonsAll;
|
||||
background-color: #2980B9;
|
||||
}
|
||||
.uscita {
|
||||
.buttonsAll;
|
||||
background-color: #4CAF50;
|
||||
}
|
||||
|
||||
|
||||
.entrataDisabled {
|
||||
.buttonsAll;
|
||||
border-color: #9B59B6;
|
||||
color: #000;
|
||||
box-shadow: 0 0.1rem 0.2rem rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.uscitaDisabled {
|
||||
.buttonsAll;
|
||||
border-color: #4CAF50;
|
||||
color: #000;
|
||||
box-shadow: 0 0.1rem 0.2rem rgba(0,0,0,0.3);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
.buttons{display:flex;justify-content:space-between;gap:1rem;width:100%;height:100%;}.buttonsAll{border-radius:.75rem;border:0;color:#fff;width:100%;height:2.5rem;text-align:center;display:inline-block;font-size:1rem;box-shadow:0 .3rem .45rem rgba(0,0,0,.8);}.entrata{border-radius:.75rem;border:0;color:#fff;width:100%;height:2.5rem;text-align:center;display:inline-block;font-size:1rem;box-shadow:0 .3rem .45rem rgba(0,0,0,.8);background-color:#9b59b6;}.mancTimb{border-radius:.75rem;border:0;color:#fff;width:100%;height:2.5rem;text-align:center;display:inline-block;font-size:1rem;box-shadow:0 .3rem .45rem rgba(0,0,0,.8);background-color:#2980b9;}.uscita{border-radius:.75rem;border:0;color:#fff;width:100%;height:2.5rem;text-align:center;display:inline-block;font-size:1rem;box-shadow:0 .3rem .45rem rgba(0,0,0,.8);background-color:#4caf50;}.entrataDisabled{border-radius:.75rem;border:0;color:#fff;width:100%;height:2.5rem;text-align:center;display:inline-block;font-size:1rem;box-shadow:0 .3rem .45rem rgba(0,0,0,.8);border-color:#9b59b6;color:#000;box-shadow:0 .1rem .2rem rgba(0,0,0,.3);}.uscitaDisabled{border-radius:.75rem;border:0;color:#fff;width:100%;height:2.5rem;text-align:center;display:inline-block;font-size:1rem;box-shadow:0 .3rem .45rem rgba(0,0,0,.8);border-color:#4caf50;color:#000;box-shadow:0 .1rem .2rem rgba(0,0,0,.3);}
|
||||
@@ -0,0 +1,216 @@
|
||||
@using GPW.CORE.Smart.Data
|
||||
|
||||
|
||||
@if (ListRecords == null)
|
||||
{
|
||||
<div class="row m-2 placeholder-glow">
|
||||
<span class="placeholder col-4 my-1"></span>
|
||||
<span class="placeholder col-7 my-1"></span>
|
||||
<span class="placeholder col-8 my-1"></span>
|
||||
<span class="placeholder col-3 my-1"></span>
|
||||
</div>
|
||||
<LoadingData DisplaySize="LoadingData.CtrlSize.Large" DisplayMode="LoadingData.SpinMode.Growl"></LoadingData>
|
||||
<div class="row m-2 placeholder-glow">
|
||||
<span class="placeholder col-4 my-1"></span>
|
||||
<span class="placeholder col-7 my-1"></span>
|
||||
<span class="placeholder col-8 my-1"></span>
|
||||
<span class="placeholder col-3 my-1"></span>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div style="background-color: #34495E; border-radius: 12px; width:100%" class="pb-1 mb-5">
|
||||
<CalendarMonth DtRif="@dtCurr" MainCss="table table-dark table-borderless" DateSelected="DisplayDate" MonthChanged="ReloadMonth" DateCheck="@DateCheck" DateCheckBlock="@DateCFF" SingleWeek="@showDetail" SelDayCss="selDate rounded-top p-2" HeadStyle="color: #E67E22"></CalendarMonth>
|
||||
@if (showDetail)
|
||||
{
|
||||
<div class="statsContainer m-2 mt-0">
|
||||
<div class="d-flex justify-content-between px-1 text-light small">
|
||||
@if (datiGiorno != null)
|
||||
{
|
||||
@if (datiGiorno.TimbrExpl != null)
|
||||
{
|
||||
@if (currMode == CalendarModeEnum.modoControllo.showGauge)
|
||||
{
|
||||
<div>
|
||||
<div type="button" class="d-flex justify-content-between text-center bg-transparent text-light border-0">
|
||||
<div class="pe-1 text-decoration-none">
|
||||
Entrata
|
||||
@if (datiGiorno.TimbrExpl.Entrata1 != null)
|
||||
{
|
||||
<div class="@cssChooseEntr(datiGiorno.TimbrExpl.Entrata1)">
|
||||
|
||||
@($"{datiGiorno.TimbrExpl.Entrata1:HH:mm}")
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="text-success">
|
||||
@emptyTime
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div>
|
||||
Uscita
|
||||
@if (datiGiorno.TimbrExpl.Uscita1 != null)
|
||||
{
|
||||
<div class="@cssChooseEsc(datiGiorno.TimbrExpl.Uscita1)">
|
||||
|
||||
@($"{datiGiorno.TimbrExpl.Uscita1:HH:mm}")
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="text-primary">
|
||||
@emptyTime
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button class="d-flex justify-content-between text-center bg-transparent text-light border-0">
|
||||
<div class="pe-1">
|
||||
Entrata
|
||||
@if (datiGiorno.TimbrExpl.Entrata2 != null)
|
||||
{
|
||||
<div class="@cssChooseEntr(datiGiorno.TimbrExpl.Entrata2)">
|
||||
|
||||
@($"{datiGiorno.TimbrExpl.Entrata2:HH:mm}")
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="text-success">
|
||||
@emptyTime
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div>
|
||||
Uscita
|
||||
@if (datiGiorno.TimbrExpl.Uscita2 != null)
|
||||
{
|
||||
<div class="@cssChooseEsc(datiGiorno.TimbrExpl.Uscita2)">
|
||||
|
||||
@($"{datiGiorno.TimbrExpl.Uscita2:HH:mm}")
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="text-primary">
|
||||
@emptyTime
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<button class="d-flex justify-content-between text-center bg-transparent text-light border-0">
|
||||
<div class="pe-1">
|
||||
Entrata
|
||||
@if (datiGiorno.TimbrExpl.Entrata3 != null)
|
||||
{
|
||||
<div class="@cssChooseEntr(datiGiorno.TimbrExpl.Entrata3)">
|
||||
|
||||
@($"{datiGiorno.TimbrExpl.Entrata3:HH:mm}")
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="text-success">
|
||||
@emptyTime
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div>
|
||||
Uscita
|
||||
@if (datiGiorno.TimbrExpl.Uscita3 != null)
|
||||
{
|
||||
<div class="@cssChooseEsc(datiGiorno.TimbrExpl.Uscita3)">
|
||||
|
||||
@($"{datiGiorno.TimbrExpl.Uscita3:HH:mm}")
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="text-primary">
|
||||
@emptyTime
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="alert bg-warning w-100 text-center mt-1 mb-2 p-1" @onclick="()=>setModeRichTimb()">
|
||||
NESSUN DATO DISPONIBILE
|
||||
</div>
|
||||
|
||||
}
|
||||
}
|
||||
</div>
|
||||
@if (datiGiorno != null)
|
||||
{
|
||||
@if (currMode == CalendarModeEnum.modoControllo.showGauge)
|
||||
{
|
||||
<div class="d-flex justify-content-between">
|
||||
<div @onclick="()=>setModeProgetti()">
|
||||
<CircleGauge Titolo="@datiGiorno.OreMinComm" Testo="Caricate" maxVal="480" currVal="@datiGiorno.MinComm" strokeColorVal="#F1C40F" StyleTitolo="font-size: 2.7rem; font-weight:bold; fill: white;" StyleTesto="font-size: 1rem; fill: #ACACAC;" ShowCircleBtn="true"></CircleGauge>
|
||||
</div>
|
||||
<div @onclick="()=>setModeRichTimb()">
|
||||
<CircleGauge Titolo="@datiGiorno.OreMinLav" Testo="Lavorate" maxVal="480" currVal="@datiGiorno.MinLav" strokeColorVal="#00FF00" StyleTitolo="font-size: 2.7rem; font-weight:bold; fill: white;" StyleTesto="font-size: 1rem; fill: #ACACAC;" ShowCircleBtn="true"></CircleGauge>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else if (currMode == CalendarModeEnum.modoControllo.showTimbr)
|
||||
{
|
||||
<div class="p-2 text-center text-light">
|
||||
<TimbUser IdxDipCurr="IdxDipendente" ListTimbRich="listTimb" ReqReload="ReloadTimb"></TimbUser>
|
||||
</div>
|
||||
}
|
||||
else if (currMode == CalendarModeEnum.modoControllo.showProj)
|
||||
{
|
||||
<div class="p-1 text-center text-light">
|
||||
<div>
|
||||
<CompProj ListProgetti="listaP" ReqReload="ForceReload" DtRif="@datiGiorno.DtRif"></CompProj>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else if (currMode == CalendarModeEnum.modoControllo.showTempRil)
|
||||
{
|
||||
<CheckTemp TargetDate="@datiGiorno.DtRif" IdxDipendente="@IdxDipendente"></CheckTemp>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="p-2 text-center text-light">
|
||||
N.A.
|
||||
</div>
|
||||
}
|
||||
}
|
||||
<div class="row p-2 pt-3">
|
||||
<div class="col-6 d-grid gap-2">
|
||||
<button class="btnReset" @onclick="()=>resetCal()"><i class="fa-solid fa-circle-chevron-left"></i> Mese</button>
|
||||
</div>
|
||||
<div class="col-6 d-grid gap-2">
|
||||
@if (currMode == CalendarModeEnum.modoControllo.showGauge)
|
||||
{
|
||||
<button class="btnTemp" @onclick="() => showTempRil()"><i class="fa-solid fa-temperature-low"></i> Temperatura</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button class="btnGiorno" @onclick="()=> backToGauge()"><i class="fa-solid fa-circle-chevron-left"></i> Giorno</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,383 @@
|
||||
using EgwCoreLib.Razor.Data;
|
||||
using GPW.CORE.Data;
|
||||
using GPW.CORE.Data.DbModels;
|
||||
using GPW.CORE.Data.DTO;
|
||||
using GPW.CORE.Smart.Data;
|
||||
using GPW.CORE.Smart.Pages;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace GPW.CORE.Smart.Components
|
||||
{
|
||||
public partial class Calendario : IDisposable
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
[Parameter]
|
||||
public CalendarModeEnum.modoControllo currMode { get; set; } = CalendarModeEnum.modoControllo.showCalendar;
|
||||
|
||||
[Parameter]
|
||||
public int IdxDipendente { get; set; } = -1;
|
||||
|
||||
[Parameter]
|
||||
public List<DailyDataDTO>? ListRecords
|
||||
{
|
||||
get => listRecords;
|
||||
set
|
||||
{
|
||||
if (listRecords != value)
|
||||
{
|
||||
listRecords = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
public List<CalFesteFerieModel>? ListFermateAzienda
|
||||
{
|
||||
get => listCFF;
|
||||
set
|
||||
{
|
||||
if (listCFF != value)
|
||||
{
|
||||
listCFF = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
public List<RegRichiesteModel>? ListRecordsRichieste
|
||||
{
|
||||
get => listRecordsRichieste;
|
||||
set
|
||||
{
|
||||
if (listRecordsRichieste != value)
|
||||
{
|
||||
listRecordsRichieste = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<bool> ReqReload { get; set; }
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
private Dictionary<DateTime, string> DateCFF = new Dictionary<DateTime, string>();
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DateCheck = new Dictionary<DateTime, string>();
|
||||
DateCFF = new Dictionary<DateTime, string>();
|
||||
ListRecords = null;
|
||||
listRecordsRichieste = null;
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#region Protected Fields
|
||||
|
||||
protected DailyDataDTO? datiGiorno = null;
|
||||
|
||||
protected string emptyTime = "--/--";
|
||||
|
||||
#endregion Protected Fields
|
||||
|
||||
#region Protected Properties
|
||||
|
||||
protected DateTime dtMancTimb { get; set; } = Utils.InitDatetime(DateTime.Now, 5);
|
||||
protected bool isApprovedEntr { get; set; } = true;
|
||||
protected bool isApprovedEsc { get; set; } = true;
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
ReloadData();
|
||||
await Task.Delay(1);
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private Dictionary<DateTime, string> DateCheck = new Dictionary<DateTime, string>();
|
||||
|
||||
private Dictionary<DateTime, string> DateFerFestCheck = new Dictionary<DateTime, string>();
|
||||
|
||||
private Dictionary<DateTime, string> DatePermCheck = new Dictionary<DateTime, string>();
|
||||
|
||||
private List<RegAttivitaModel>? listaP = new List<RegAttivitaModel>();
|
||||
|
||||
private List<List<RegAttivitaModel>?> listRA = null!;
|
||||
|
||||
private List<TimbratureModel>? listTimb = null;
|
||||
|
||||
#endregion Private Fields
|
||||
|
||||
#region Private Properties
|
||||
|
||||
[Inject]
|
||||
private CoreSmartDataService CDService { get; set; } = null!;
|
||||
|
||||
private DateTime dtCurr { get; set; } = DateTime.Today;
|
||||
|
||||
private List<DailyDataDTO>? listRecords { get; set; } = null;
|
||||
private List<CalFesteFerieModel>? listCFF { get; set; } = null;
|
||||
|
||||
private List<RegRichiesteModel>? listRecordsRichieste { get; set; } = null;
|
||||
|
||||
[Inject]
|
||||
private MessageService MService { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
private NavigationManager navManager { get; set; } = null!;
|
||||
|
||||
private bool showDetail { get; set; } = false;
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private async Task backToGauge()
|
||||
{
|
||||
setModeDetail();
|
||||
await Task.Delay(1);
|
||||
}
|
||||
|
||||
private string cssChooseEntr(DateTime? dtRif)
|
||||
{
|
||||
string answ = "";
|
||||
try
|
||||
{
|
||||
answ = (isApprovedEntr) ? "text-entrata" : "text-danger";
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
return answ;
|
||||
}
|
||||
|
||||
private string cssChooseEsc(DateTime? dtRif)
|
||||
{
|
||||
string answ = "";
|
||||
try
|
||||
{
|
||||
answ = (isApprovedEsc) ? "text-uscita" : "text-danger";
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
return answ;
|
||||
}
|
||||
|
||||
private void DisplayDate(DateTime dtSel)
|
||||
{
|
||||
dtCurr = dtSel;
|
||||
MService.targetDate = dtSel;
|
||||
MService.targetDateMancTimb = dtCurr;
|
||||
showDetail = true;
|
||||
// se sono in calendario --> mostro dettagli...
|
||||
if (currMode == CalendarModeEnum.modoControllo.showCalendar)
|
||||
{
|
||||
setModeDetail();
|
||||
}
|
||||
updateDetail();
|
||||
MService.ReportDateChange();
|
||||
}
|
||||
|
||||
/// <summary> Richiesta evento reload --> lo passa al componente superiore <param name="doForce"></param>
|
||||
private async Task ForceReload(bool doForce)
|
||||
{
|
||||
await ReqReload.InvokeAsync(doForce);
|
||||
}
|
||||
|
||||
private void ReloadData()
|
||||
{
|
||||
DateCheck = new Dictionary<DateTime, string>();
|
||||
DateCFF = new Dictionary<DateTime, string>();
|
||||
string cssOkComm = "bg-success text-light rounded-circle p-2";
|
||||
string cssOkLav = "bg-warning text-light rounded-circle p-2";
|
||||
string cssToday = "bg-info text-dark rounded-circle p-2";
|
||||
string cssFest = "bg-danger text-warning rounded-pill2 px-0 opacity-50";
|
||||
string cssChius = "bg-warning text-dark rounded-pill2 px-0 opacity-50";
|
||||
string cssFerie = "bg-success text-light px-0 opacity-50";
|
||||
|
||||
// recupero le fermate aziendali
|
||||
if (ListFermateAzienda != null && ListFermateAzienda.Count > 0)
|
||||
{
|
||||
string cssSpec = "";
|
||||
foreach (var item in ListFermateAzienda)
|
||||
{
|
||||
|
||||
cssSpec = item.codGiust == "FEST" ? cssFest : cssChius;
|
||||
if (!DateCFF.ContainsKey(item.data))
|
||||
{
|
||||
if (item.data.DayOfWeek != DayOfWeek.Saturday && item.data.DayOfWeek != DayOfWeek.Sunday)
|
||||
{
|
||||
DateCFF.Add(item.data, cssSpec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// aggiungo ferie dipendente
|
||||
if (ListRecordsRichieste != null && ListRecordsRichieste.Count > 0)
|
||||
{
|
||||
string cssSpec = "";
|
||||
foreach (var item in ListRecordsRichieste)
|
||||
{
|
||||
cssSpec = item.CodGiust == "FER" ? cssFerie : "";
|
||||
// creo il set di date
|
||||
int numDay = item.DtEnd.Subtract(item.DtStart).Days;
|
||||
for (int i = 0; i <= numDay; i++)
|
||||
{
|
||||
DateTime currDay = item.DtStart.AddDays(i);
|
||||
if (!DateCFF.ContainsKey(currDay))
|
||||
{
|
||||
if (currDay.DayOfWeek != DayOfWeek.Saturday && currDay.DayOfWeek != DayOfWeek.Sunday)
|
||||
{
|
||||
DateCFF.Add(currDay, cssSpec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (ListRecords != null)
|
||||
{
|
||||
string currCss = "";
|
||||
foreach (var giorno in ListRecords)
|
||||
{
|
||||
currCss = giorno.OreLav == 0 ? "" : cssOkLav;
|
||||
if (giorno.DtRif == DateTime.Today)
|
||||
{
|
||||
currCss = cssToday;
|
||||
}
|
||||
else if (Math.Abs((giorno.OreLav - giorno.OreComm)) < 0.5 && giorno.OreLav > 0)
|
||||
{
|
||||
currCss = cssOkComm;
|
||||
}
|
||||
DateCheck.Add(giorno.DtRif, currCss);
|
||||
}
|
||||
// aggiorno dettagli
|
||||
updateDetail();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ReloadMonth(DateTime dtSel)
|
||||
{
|
||||
dtCurr = dtSel;
|
||||
MService.targetDate = dtSel;
|
||||
showDetail = false;
|
||||
await Task.Delay(1);
|
||||
MService.ReportDateChange();
|
||||
}
|
||||
|
||||
// richiesta update + ritorno a gauge...
|
||||
private async Task ReloadTimb(bool doForce)
|
||||
{
|
||||
await ForceReload(doForce);
|
||||
await backToGauge();
|
||||
}
|
||||
|
||||
private async Task resetCal()
|
||||
{
|
||||
showDetail = false;
|
||||
MService.isRicTimb = false;
|
||||
MService.setModeCalendar();
|
||||
await Task.Delay(1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Imposta modalit� dettaglio (mostra i gauge)
|
||||
/// </summary>
|
||||
private void setModeDetail()
|
||||
{
|
||||
MService.isRicTimb = false;
|
||||
MService.setModeGauge();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Imposta modalit� progetti (x ora rimanda a pagina progetti)
|
||||
/// </summary>
|
||||
private void setModeProgetti()
|
||||
{
|
||||
MService.isRicTimb = false;
|
||||
MService.setModeProj();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Imposta modalit� mancate timbrature
|
||||
/// </summary>
|
||||
private void setModeRichTimb()
|
||||
{
|
||||
MService.isRicTimb = true;
|
||||
MService.setModeRichTimb();
|
||||
}
|
||||
|
||||
private void ShowTemp()
|
||||
{
|
||||
MService.targetDate = dtCurr;
|
||||
navManager.NavigateTo("TempRil");
|
||||
}
|
||||
|
||||
private void showTempRil()
|
||||
{
|
||||
MService.isRicTimb = false;
|
||||
MService.setModeTempRil();
|
||||
}
|
||||
|
||||
private async void updateDetail()
|
||||
{
|
||||
isApprovedEntr = true;
|
||||
isApprovedEsc = true;
|
||||
listaP.Clear();
|
||||
if (ListRecords != null)
|
||||
{
|
||||
datiGiorno = ListRecords.Where(x => x.DtRif == dtCurr).FirstOrDefault();
|
||||
listRA = ListRecords.Select(x => x.ListRA).ToList();
|
||||
|
||||
foreach (var item in listRA)
|
||||
{
|
||||
if (item != null)
|
||||
{
|
||||
foreach (var k in item)
|
||||
{
|
||||
if (k != null)
|
||||
{
|
||||
if (k.Inizio.Date == dtCurr.Date)
|
||||
{
|
||||
listaP.Add(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
listTimb = await CDService.TimbratureDay(dtCurr, IdxDipendente);
|
||||
if (listTimb != null)
|
||||
{
|
||||
if (listTimb.Count != 0)
|
||||
{
|
||||
foreach (var item in listTimb)
|
||||
{
|
||||
if (item.Approv == false && item.Entrata == true)
|
||||
{
|
||||
isApprovedEntr = false;
|
||||
}
|
||||
else if (item.Approv == false && item.Entrata == false)
|
||||
{
|
||||
isApprovedEsc = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
.statsContainer {
|
||||
border: 0.3rem solid #E67E22;
|
||||
border-radius: 0.8rem;
|
||||
/*border-radius: 0rem 0rem 0.8rem 0.8rem;*/
|
||||
/*margin: 0px 10px 20px 10px;*/
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.baseBtn {
|
||||
height: 2.5rem;
|
||||
border: none;
|
||||
border-radius: 0.8rem;
|
||||
color: #fff;
|
||||
}
|
||||
.btnReset {
|
||||
height: 2.5rem;
|
||||
border: none;
|
||||
border-radius: 0.8rem;
|
||||
color: #fff;
|
||||
background-color: #1AB7EA;
|
||||
}
|
||||
.btnGiorno {
|
||||
height: 2.5rem;
|
||||
border: none;
|
||||
border-radius: 0.8rem;
|
||||
color: #fff;
|
||||
background-color: #E67E22;
|
||||
}
|
||||
.btnTemp {
|
||||
height: 2.5rem;
|
||||
border: none;
|
||||
border-radius: 0.8rem;
|
||||
color: #fff;
|
||||
background-color: #1ABC9C;
|
||||
}
|
||||
.timeContainer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.timeContainer input {
|
||||
border: none;
|
||||
border-radius: 0.8rem;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
margin: 2rem;
|
||||
background-color: #d9d9d9;
|
||||
font-size: 3rem;
|
||||
}
|
||||
input[type="time"]::-webkit-calendar-picker-indicator {
|
||||
color: #fff;
|
||||
}
|
||||
.text-entrata {
|
||||
color: #38CF60;
|
||||
}
|
||||
.text-uscita {
|
||||
color: #40C4FF;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
|
||||
.statsContainer {
|
||||
border: 0.3rem solid #E67E22;
|
||||
border-radius: 0.8rem;
|
||||
/*border-radius: 0rem 0rem 0.8rem 0.8rem;*/
|
||||
/*margin: 0px 10px 20px 10px;*/
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.baseBtn{
|
||||
height: 2.5rem;
|
||||
border: none;
|
||||
border-radius: 0.8rem;
|
||||
color:#fff;
|
||||
}
|
||||
|
||||
.btnReset {
|
||||
.baseBtn;
|
||||
background-color: #1AB7EA;
|
||||
}
|
||||
.btnGiorno {
|
||||
.baseBtn;
|
||||
background-color: #E67E22;
|
||||
}
|
||||
.btnTemp {
|
||||
.baseBtn;
|
||||
background-color: #1ABC9C;
|
||||
}
|
||||
|
||||
|
||||
.timeContainer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.timeContainer input {
|
||||
border: none;
|
||||
border-radius: 0.8rem;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
margin: 2rem;
|
||||
background-color: #d9d9d9;
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
input[type="time"]::-webkit-calendar-picker-indicator {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.text-entrata{
|
||||
color: #38CF60;
|
||||
}
|
||||
|
||||
.text-uscita {
|
||||
color: #40C4FF;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
.statsContainer{border:.3rem solid #e67e22;border-radius:.8rem;padding-bottom:10px;}.baseBtn{height:2.5rem;border:0;border-radius:.8rem;color:#fff;}.btnReset{height:2.5rem;border:0;border-radius:.8rem;color:#fff;background-color:#1ab7ea;}.btnGiorno{height:2.5rem;border:0;border-radius:.8rem;color:#fff;background-color:#e67e22;}.btnTemp{height:2.5rem;border:0;border-radius:.8rem;color:#fff;background-color:#1abc9c;}.timeContainer{width:100%;height:100%;display:flex;justify-content:center;}.timeContainer input{border:0;border-radius:.8rem;padding-left:.5rem;padding-right:.5rem;margin:2rem;background-color:#d9d9d9;font-size:3rem;}input[type="time"]::-webkit-calendar-picker-indicator{color:#fff;}.text-entrata{color:#38cf60;}.text-uscita{color:#40c4ff;}
|
||||
@@ -0,0 +1,56 @@
|
||||
|
||||
<div class="row px-1">
|
||||
<div class="col-12">
|
||||
<div class="row my-1">
|
||||
<div class="col-6">
|
||||
@if (currRecord != null)
|
||||
{
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-text" style="width: 2.5em;">
|
||||
<i class="fas fa-thermometer-half"></i>
|
||||
<small>°C</small>
|
||||
</span>
|
||||
<input type="number" step="0.1" min="35" max="42" class="form-control text-end" @bind="@currRecord.TempRil"></input>
|
||||
<button class="btn btn-success" title="Salva temperatura" @onclick="() => DoSave()"><i class="far fa-save"></i></button>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<LoadingData DisplaySize="LoadingData.CtrlSize.Small"></LoadingData>
|
||||
}
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="input-group input-group-sm">
|
||||
<select @bind="@numDays" class="form-select text-end" title="finestra analisi">
|
||||
<option value="30">1 Mese</option>
|
||||
<option value="60">2 Mesi</option>
|
||||
<option value="90">3 Mesi</option>
|
||||
<option value="180">6 Mesi</option>
|
||||
<option value="365">1 Anno</option>
|
||||
<option value="730">2 Anno</option>
|
||||
<option value="1825">5 Anni</option>
|
||||
</select>
|
||||
<span class="input-group-text">
|
||||
<i class="far fa-calendar-alt"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="row mx-0">
|
||||
<div class="col-12">
|
||||
@if (listRilTemp != null)
|
||||
{
|
||||
<ChartTS Id="TempRil" DataTS="@listRilTemp" LineColor="rgb(7, 173, 236)" BackColor="rgba(107, 223, 255, 0.5)" ChartLabel="Temperatura Rilevata" AnimationTime="0" TextColor="rgba(255,255,255,.8)" GridColor="rgba(160,160,160,.4)"></ChartTS>
|
||||
<ChartHist Id="FreqTemp1" Data="@histData" Labels="@histLabel" LineColor="rgb(7, 173, 236)" BackColor="rgba(107, 213, 255, 0.5)" ChartLabel="Freq. Osservate" AnimationTime="0" TextColor="rgba(255,255,255,.8)" GridColor="rgba(200,200,255,.4)"></ChartHist>
|
||||
}
|
||||
else
|
||||
{
|
||||
<LoadingData DisplaySize="LoadingData.CtrlSize.Small"></LoadingData>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,152 @@
|
||||
using EgwCoreLib.Razor.Data;
|
||||
using GPW.CORE.Data.DbModels;
|
||||
using GPW.CORE.Smart.Data;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace GPW.CORE.Smart.Components
|
||||
{
|
||||
public partial class CheckTemp
|
||||
{
|
||||
#region Public Properties
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<bool> CloseReq { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public int IdxDipendente { get; set; } = -1;
|
||||
|
||||
[Parameter]
|
||||
public DateTime TargetDate
|
||||
{
|
||||
get
|
||||
{
|
||||
return _targetDate;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_targetDate = value;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Public Properties
|
||||
|
||||
#region Protected Fields
|
||||
|
||||
protected int _numDays = 30;
|
||||
|
||||
#endregion Protected Fields
|
||||
|
||||
#region Protected Properties
|
||||
|
||||
protected DateTime _targetDate { get; set; } = DateTime.Today;
|
||||
|
||||
protected RilievoTempModel? currRecord { get; set; } = null;
|
||||
|
||||
protected string[]? histData { get; set; } = null;
|
||||
|
||||
protected string[]? histLabel { get; set; } = null;
|
||||
|
||||
protected List<chartJsData.chartJsTSerie>? listRilTemp { get; set; } = null;
|
||||
|
||||
protected List<CheckVc19Model>? listVC19 { get; set; } = null;
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
protected async Task addDays(int numDay)
|
||||
{
|
||||
TargetDate = TargetDate.AddDays(numDay);
|
||||
await ReloadData();
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indico CurrItem selezionato
|
||||
/// </summary>
|
||||
protected async void DoClose()
|
||||
{
|
||||
await CloseReq.InvokeAsync(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua salvataggio misurazione temperatura
|
||||
/// </summary>
|
||||
protected async void DoSave()
|
||||
{
|
||||
// chiamo classe gestione che salva e resetta cache dati...
|
||||
if (currRecord != null)
|
||||
{
|
||||
await CDService.RilTempUpdate(currRecord);
|
||||
}
|
||||
|
||||
// chiamo chiusura!
|
||||
await CloseReq.InvokeAsync(true);
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
await ReloadData();
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
protected async Task ReloadData()
|
||||
{
|
||||
DateTime inizio = TargetDate.AddDays(1 - numDays);
|
||||
DateTime fine = TargetDate.AddDays(1);
|
||||
// recupero dati completi...
|
||||
var rawVC19 = await CDService.CheckVC19List(IdxDipendente, fine.AddDays(-15), fine);
|
||||
var rawData = await CDService.RilTempList(IdxDipendente, inizio, fine);
|
||||
|
||||
// calcolo dati derivati
|
||||
listVC19 = rawVC19.OrderByDescending(x => x.DtCheck).ToList();
|
||||
listRilTemp = rawData.Select(r => new chartJsData.chartJsTSerie()
|
||||
{ x = r.DtRilievo, y = r.TempRil }).ToList();
|
||||
|
||||
// calcolo hist frequenza con EFCore: https://entityframeworkcore.com/knowledge-base/60871048/group-by-and-to-dictionary-in-ef-core-3-1
|
||||
var histDict = rawData.GroupBy(r => r.TempRil.ToString("N1")).Select(g => new
|
||||
{
|
||||
g.Key,
|
||||
Count = g.Count()
|
||||
}).OrderBy(d => d.Key).ToDictionary(x => x.Key, x => x.Count.ToString());
|
||||
histData = histDict.Values.ToArray();
|
||||
histLabel = histDict.Keys.ToArray();
|
||||
// cerco se c'� dato odierno della temperatura...
|
||||
currRecord = rawData.Where(x => x.DtRilievo == TargetDate).FirstOrDefault();
|
||||
if (currRecord == null)
|
||||
{
|
||||
currRecord = new RilievoTempModel()
|
||||
{
|
||||
IdxDipendente = IdxDipendente,
|
||||
DtRilievo = TargetDate,
|
||||
TempRil = 0
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Properties
|
||||
|
||||
[Inject]
|
||||
private CoreSmartDataService CDService { get; set; } = null!;
|
||||
|
||||
private int numDays
|
||||
{
|
||||
get
|
||||
{
|
||||
return _numDays;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_numDays = value;
|
||||
var pUpd = Task.Run(async () => await ReloadData());
|
||||
pUpd.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Private Properties
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
<div class="container d-flex justify-content-between">
|
||||
<div class="title">TIMBRATURE</div>
|
||||
<div class="username">Majid Zaccaria [56]</div>
|
||||
<div class="title @homeCss" @onclick="ReturnHome">
|
||||
<i class="fa-solid fa-home"></i>
|
||||
<sub>@homeMessage</sub>
|
||||
</div>
|
||||
<div class="username" @onclick="ForceReset">@currDip</div>
|
||||
</div>
|
||||
|
||||
@@ -1,22 +1,325 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using EgwCoreLib.Razor.Data;
|
||||
using GPW.CORE.Data.DbModels;
|
||||
using GPW.CORE.Smart.Data;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Json;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
using Microsoft.AspNetCore.Components.Routing;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.AspNetCore.Components.Web.Virtualization;
|
||||
using Microsoft.AspNetCore.Components.WebAssembly.Http;
|
||||
using Microsoft.JSInterop;
|
||||
using GPW.CORE.SMART;
|
||||
using GPW.CORE.SMART.Shared;
|
||||
|
||||
namespace GPW.CORE.SMART.Components
|
||||
namespace GPW.CORE.Smart.Components
|
||||
{
|
||||
public partial class CmpTop
|
||||
public partial class CmpTop : IDisposable
|
||||
{
|
||||
#region Public Methods
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
MService.EA_DipUpdated -= MService_EA_DipUpdated;
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#region Protected Properties
|
||||
|
||||
[Inject]
|
||||
protected CoreSmartDataService CDService { get; set; } = null!;
|
||||
|
||||
protected string Cognome { get; set; } = "";
|
||||
|
||||
protected string currDip
|
||||
{
|
||||
get => $"{Cognome} {Nome} [{idxDipendente}]";
|
||||
}
|
||||
|
||||
protected int idxDipendente { get; set; } = 0;
|
||||
|
||||
[Inject]
|
||||
protected IJSRuntime JSRuntime { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected LicenseService LicServ { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected MessageService MService { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected NavigationManager navManager { get; set; } = null!;
|
||||
|
||||
protected string Nome { get; set; } = "";
|
||||
|
||||
#endregion Protected Properties
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Verifica informazioni condivise applicazione
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected async Task<bool> checkActivations()
|
||||
{
|
||||
bool allOk = false;
|
||||
if (LicServ.ValidData)
|
||||
{
|
||||
// se non fosse tutto ok
|
||||
if (!LicServ.HasActivData)
|
||||
{
|
||||
// chiamo refresh licenze da remoto
|
||||
allOk = await LicServ.RefreshLicense();
|
||||
}
|
||||
}
|
||||
|
||||
await Task.Delay(1);
|
||||
return allOk;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifica informazioni condivise applicazione
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected async Task<bool> checkSharedInfo()
|
||||
{
|
||||
bool allOk = false;
|
||||
if (!LicServ.ValidData)
|
||||
{
|
||||
// salvo cod app da Conf...
|
||||
LicServ.Applicazione = CDService.CodApp;
|
||||
// effettuo lettura dati preliminari da AKV (eventualmente in cache...)
|
||||
List<AnagKeyValueModel>? rawAkvList = await CDService.AKVList();
|
||||
if (rawAkvList != null)
|
||||
{
|
||||
LicServ.AKVList = rawAkvList;
|
||||
allOk = LicServ.InitAkv();
|
||||
}
|
||||
}
|
||||
|
||||
await Task.Delay(1);
|
||||
return allOk;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifica info specifiche utente
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected async Task<bool> checkUserLicense()
|
||||
{
|
||||
bool answ = false;
|
||||
// verifico utente attivo
|
||||
answ = MService.IsActive;
|
||||
if (answ)
|
||||
{
|
||||
var rawActList = LicServ.ActivList;
|
||||
// recupero hash utente
|
||||
string hashImpiego = MService.HashDip;
|
||||
// confronto con elenco attivazioni dello shared service...
|
||||
var foundRec = rawActList.Where(x => x.CodImpiego == hashImpiego);
|
||||
answ = foundRec.Count() > 0;
|
||||
// salvo status payloadOk
|
||||
MService.PayloadOk = answ;
|
||||
}
|
||||
|
||||
await Task.Delay(1);
|
||||
return answ;
|
||||
}
|
||||
|
||||
protected async Task DoVerifyActiv()
|
||||
{
|
||||
MService.PayloadOk = false;
|
||||
await Task.Delay(250);
|
||||
await VerifyActiv();
|
||||
}
|
||||
|
||||
protected async Task ForceReset()
|
||||
{
|
||||
string nextPage = navManager.ToBaseRelativePath(navManager.Uri);
|
||||
await Task.Delay(1);
|
||||
await DoVerifyActiv();
|
||||
navManager.NavigateTo($"ForceReset?nextPage={nextPage}", true);
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstrender)
|
||||
{
|
||||
await Task.Delay(1);
|
||||
if (firstrender)
|
||||
{
|
||||
if (!navManager.Uri.Contains("jumper"))
|
||||
{
|
||||
await checkUser();
|
||||
// verifico attivazione dipendente...
|
||||
await checkUserLicense();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
MService.EA_DipUpdated += MService_EA_DipUpdated;
|
||||
// lettura dati base
|
||||
await ReloadData();
|
||||
// verifica attivazione
|
||||
await VerifyActiv();
|
||||
}
|
||||
private async void MService_EA_DipUpdated()
|
||||
{
|
||||
// lettura dati base
|
||||
await ReloadData();
|
||||
// verifica attivazione
|
||||
await VerifyActiv();
|
||||
}
|
||||
|
||||
private string LocalNet = "10.74";
|
||||
private async Task ReloadData()
|
||||
{
|
||||
var confNet = await CDService.ConfigGetKey("LocalNet");
|
||||
LocalNet = confNet != null ? confNet.valore : "10";
|
||||
}
|
||||
|
||||
protected void ReturnHome()
|
||||
{
|
||||
navManager.NavigateTo("Home", true);
|
||||
}
|
||||
|
||||
protected async Task VerifyActiv()
|
||||
{
|
||||
// preliminarmente verifica shared info
|
||||
await checkSharedInfo();
|
||||
// refresh attivazioni se necessario
|
||||
await checkActivations();
|
||||
// verifico e salvo dati attivazione dipendente...
|
||||
await checkUserLicense();
|
||||
}
|
||||
|
||||
#endregion Protected Methods
|
||||
|
||||
#region Private Properties
|
||||
|
||||
[Inject]
|
||||
private IHttpContextAccessor httpContextAccessor { get; set; } = null!;
|
||||
|
||||
#endregion Private Properties
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private async Task checkOtherData()
|
||||
{
|
||||
currIpv4 = await MService.getDevIpAsync();
|
||||
if (string.IsNullOrEmpty(currIpv4))
|
||||
{
|
||||
// ricalcolo e salvo...
|
||||
if (httpContextAccessor.HttpContext != null)
|
||||
{
|
||||
var remoteIp = $"{httpContextAccessor.HttpContext.Connection?.RemoteIpAddress}";
|
||||
// provo a recuperare ipV4...
|
||||
currIpv4 = IpUtils.getLocalIpv4(remoteIp);
|
||||
await MService.setDevIpv4Async(currIpv4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected string currIpv4 = "";
|
||||
|
||||
/// <summary>
|
||||
/// Verifica se IP sia locale
|
||||
/// </summary>
|
||||
protected bool isIpLocal
|
||||
{
|
||||
get
|
||||
{
|
||||
bool answ = false;
|
||||
if (!string.IsNullOrEmpty(currIpv4))
|
||||
{
|
||||
answ = currIpv4.Contains(LocalNet);
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
}
|
||||
|
||||
protected string homeCss
|
||||
{
|
||||
get => isIpLocal ? "text-light" : "text-danger";
|
||||
}
|
||||
|
||||
protected string homeMessage
|
||||
{
|
||||
get => isIpLocal ? "INT" : "EXT";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifica dati utente e pagina
|
||||
/// </summary>
|
||||
private async Task checkUser()
|
||||
{
|
||||
// se idxDip NON valido
|
||||
if (MService.IdxDipendente <= 0)
|
||||
{
|
||||
await tryDeviceLogin();
|
||||
// verifico se ho dipendente...
|
||||
if (MService.IdxDipendente > 0)
|
||||
{
|
||||
// verifico o calcolo IP...
|
||||
await checkOtherData();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (idxDipendente <= 0)
|
||||
{
|
||||
await setupUserData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task setupUserData()
|
||||
{
|
||||
if (MService.RigaDip != null && MService.IdxDipendente > 0)
|
||||
{
|
||||
idxDipendente = MService.IdxDipendente;
|
||||
Cognome = MService.RigaDip?.Cognome ?? "ND";
|
||||
Nome = MService.RigaDip?.Nome ?? "-";
|
||||
|
||||
// verifico o calcolo IP...
|
||||
await checkOtherData();
|
||||
|
||||
// segnalo update...
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prova login da dati Device (in LocalStorage)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task tryDeviceLogin()
|
||||
{
|
||||
// cerco in localstorage il devicesecret
|
||||
string devSecret = await MService.getDevSecretAsync();
|
||||
await Task.Delay(50);
|
||||
if (!string.IsNullOrEmpty(devSecret))
|
||||
{
|
||||
// cerco sul DB...
|
||||
var rigaDev = await CDService.DeviceBySecret(devSecret);
|
||||
// se trovato
|
||||
if (rigaDev != null)
|
||||
{
|
||||
// recupero dati dip e inizializzo message service
|
||||
var elencoDip = await CDService.DipendentiGetAll();
|
||||
if (elencoDip != null)
|
||||
{
|
||||
var rigaDip = elencoDip.FirstOrDefault(x => x.IdxDipendente == rigaDev.IdxDipendente);
|
||||
MService.RigaDip = rigaDip;
|
||||
await setupUserData();
|
||||
MService.RigaDip = rigaDip;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
navManager.NavigateTo("RegNewDevice");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
navManager.NavigateTo("RegNewDevice");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user