mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Compare commits
3505 Commits
923-Drucke
...
3.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1847c6944e | ||
|
|
f743ce59fa | ||
|
|
99feb499a2 | ||
|
|
bb5b6e2e59 | ||
|
|
f57988f83e | ||
|
|
17a68b9dbb | ||
|
|
a0c8035dbb | ||
|
|
34e96f0751 | ||
|
|
9ba05253e9 | ||
|
|
98a9346c1a | ||
|
|
fa66d2389a | ||
|
|
6743c8e630 | ||
|
|
f62e198aed | ||
|
|
387e6b08ed | ||
|
|
721fd06c76 | ||
|
|
0fcdb308b5 | ||
|
|
5492329a21 | ||
|
|
f97253e82a | ||
|
|
b926efb635 | ||
|
|
cdc2553d73 | ||
|
|
8781c50e34 | ||
|
|
05eb3cc756 | ||
|
|
6e1c434edf | ||
|
|
ed8e937924 | ||
|
|
1bd17fd887 | ||
|
|
8900a77d7a | ||
|
|
4b10dd96d9 | ||
|
|
1126e4f0c1 | ||
|
|
e9f24a88d6 | ||
|
|
cb6779fc83 | ||
|
|
f2c95b6a16 | ||
|
|
d48680c59e | ||
|
|
775390b5df | ||
|
|
1788f566e3 | ||
|
|
d4e1088190 | ||
|
|
a8ecd1f07b | ||
|
|
2c239ac597 | ||
|
|
200eb7f217 | ||
|
|
694fc6d084 | ||
|
|
8ae990bcde | ||
|
|
301f5878c2 | ||
|
|
39c8a512f4 | ||
|
|
f37dfd41f1 | ||
|
|
a518fc50e2 | ||
|
|
c9236f191b | ||
|
|
d1584d1edb | ||
|
|
5f34b514ef | ||
|
|
7a1ef06a4c | ||
|
|
acc2f7f664 | ||
|
|
ad08e999a2 | ||
|
|
1d472ce3df | ||
|
|
92d760b8b4 | ||
|
|
1d19779dac | ||
|
|
294be5dcb4 | ||
|
|
90e671d285 | ||
|
|
9a2c520ab4 | ||
|
|
13d41a7a81 | ||
|
|
79b0a1324c | ||
|
|
0fd94273ce | ||
|
|
44abd4698e | ||
|
|
2b262cc8be | ||
|
|
5775e444b8 | ||
|
|
cdfe88c1cc | ||
|
|
c71d1f8886 | ||
|
|
a09eef038e | ||
|
|
f0a0189523 | ||
|
|
4d42c4ea45 | ||
|
|
cad2926c45 | ||
|
|
161d9c6fea | ||
|
|
1b33258728 | ||
|
|
73b6133306 | ||
|
|
eb6e93149e | ||
|
|
33fb44f20a | ||
|
|
8723f7aa7e | ||
|
|
03815586f7 | ||
|
|
86a11ff07a | ||
|
|
41be8533dc | ||
|
|
186afbc828 | ||
|
|
c3561339a9 | ||
|
|
5312073184 | ||
|
|
4dfe3bfa11 | ||
|
|
9b7a1b1c21 | ||
|
|
a290d3b249 | ||
|
|
ad348af551 | ||
|
|
f1bdba5d10 | ||
|
|
c4134e7f99 | ||
|
|
b7a16f5d30 | ||
|
|
4105709286 | ||
|
|
0c3b322fbd | ||
|
|
12096754c7 | ||
|
|
453d921a99 | ||
|
|
bad05fd098 | ||
|
|
363daf1e35 | ||
|
|
e0cb0974cf | ||
|
|
c3d9274766 | ||
|
|
bc16b841fb | ||
|
|
d5dc4e053d | ||
|
|
3c6833988c | ||
|
|
28fb4ebb48 | ||
|
|
2118bd996a | ||
|
|
8a6448cc17 | ||
|
|
f2c7d57ad6 | ||
|
|
9c9ddfaeec | ||
|
|
6eaa347de5 | ||
|
|
a16f355396 | ||
|
|
8b8db6e335 | ||
|
|
06e248d615 | ||
|
|
c68706b54f | ||
|
|
b271ce9711 | ||
|
|
94888213b1 | ||
|
|
1041d92486 | ||
|
|
43d8d220c9 | ||
|
|
e0993d9c46 | ||
|
|
82656d9b27 | ||
|
|
df36d0934d | ||
|
|
920b8eb8e3 | ||
|
|
4db28b1aa7 | ||
|
|
3a9820aa54 | ||
|
|
30ad99332e | ||
|
|
4b48275910 | ||
|
|
d3e3316459 | ||
|
|
4ef1bd4df6 | ||
|
|
0c2a23e5d2 | ||
|
|
36bd2c1eba | ||
|
|
a38d2eede6 | ||
|
|
ed7dc10246 | ||
|
|
f5251d9069 | ||
|
|
2bd21e168a | ||
|
|
3661bf7580 | ||
|
|
9f2a6633f7 | ||
|
|
3c4d0ea56c | ||
|
|
56bb784c83 | ||
|
|
c687570b1f | ||
|
|
afe5d3468a | ||
|
|
65f43d22ee | ||
|
|
67203a8506 | ||
|
|
92e522dedf | ||
|
|
fb46d329dc | ||
|
|
64d0a9fdb9 | ||
|
|
8f47163627 | ||
|
|
49f2a44461 | ||
|
|
a209d59ea9 | ||
|
|
03124d8736 | ||
|
|
a3330263f8 | ||
|
|
89092a5f6e | ||
|
|
42fa108bb6 | ||
|
|
2692588357 | ||
|
|
ec26b5f4c0 | ||
|
|
ff985bda64 | ||
|
|
ca255cb592 | ||
|
|
8df5052c76 | ||
|
|
c78ddb5c8c | ||
|
|
5d84b4a55a | ||
|
|
a6142a5d86 | ||
|
|
fdf50fe11e | ||
|
|
e8bf922a67 | ||
|
|
f202ff5291 | ||
|
|
0c25859b6b | ||
|
|
215cb89aff | ||
|
|
9256a79087 | ||
|
|
f1ff9c6c55 | ||
|
|
3f05e57554 | ||
|
|
2062bf3bab | ||
|
|
2d71a567ff | ||
|
|
547e615522 | ||
|
|
5d904e9d88 | ||
|
|
b7ccde4d44 | ||
|
|
b838f4c475 | ||
|
|
2bc97ee574 | ||
|
|
f054614cfe | ||
|
|
0aa1cddf72 | ||
|
|
d39521b9f2 | ||
|
|
f5468d7f8e | ||
|
|
4ad99270bd | ||
|
|
4e098ae962 | ||
|
|
8e00e646fb | ||
|
|
4fad5a7c2f | ||
|
|
5ece030ec8 | ||
|
|
54d7c525a9 | ||
|
|
41d4dc4663 | ||
|
|
c266c51572 | ||
|
|
4ea50f68d1 | ||
|
|
e5d61c8622 | ||
|
|
d06c64c08a | ||
|
|
91ebc3e27f | ||
|
|
d643c19642 | ||
|
|
afd1f5e302 | ||
|
|
4099aa0a57 | ||
|
|
ebe11b75d1 | ||
|
|
81f7270cf7 | ||
|
|
570a8800a0 | ||
|
|
25aecffafc | ||
|
|
7c48c63584 | ||
|
|
5bf32b2e72 | ||
|
|
f44fbe3fdb | ||
|
|
5df075f448 | ||
|
|
9cee33e286 | ||
|
|
42bf7e4120 | ||
|
|
77ff7ca1a8 | ||
|
|
7f195ee627 | ||
|
|
79bec55818 | ||
|
|
35093afaff | ||
|
|
358ba3963c | ||
|
|
d47e617f8c | ||
|
|
55bd001146 | ||
|
|
a9f11426a7 | ||
|
|
10b86756d2 | ||
|
|
262dd084c1 | ||
|
|
abc58c8a78 | ||
|
|
866cd23e41 | ||
|
|
fdcf12c022 | ||
|
|
432f1161af | ||
|
|
82dbce5744 | ||
|
|
a4b9f5fcf1 | ||
|
|
7ea9359c30 | ||
|
|
b9a4b0d315 | ||
|
|
7809e7a2b5 | ||
|
|
9a8c74b148 | ||
|
|
ad62e67771 | ||
|
|
6feb8079b7 | ||
|
|
7f8f48f393 | ||
|
|
0fe0c5242d | ||
|
|
d208bdaf97 | ||
|
|
dc80df4ad4 | ||
|
|
3020609682 | ||
|
|
5c3e1ed2ad | ||
|
|
e832feebc5 | ||
|
|
08580d782d | ||
|
|
2d07556341 | ||
|
|
9ad1256019 | ||
|
|
250002f057 | ||
|
|
0973b01bf0 | ||
|
|
d5254cc150 | ||
|
|
adc5a5a280 | ||
|
|
2ff033ea55 | ||
|
|
cbaac8ed9a | ||
|
|
f0b653fd0f | ||
|
|
14eba6e5ea | ||
|
|
803a8e316c | ||
|
|
83cab7796e | ||
|
|
c70dd30830 | ||
|
|
b28bb165d4 | ||
|
|
5073693fc2 | ||
|
|
f3cb6236a5 | ||
|
|
4ab9890313 | ||
|
|
32d8d81f53 | ||
|
|
0361aa63ff | ||
|
|
2f95c23910 | ||
|
|
a8cd6ce844 | ||
|
|
3bba23cc76 | ||
|
|
e25f176a7b | ||
|
|
a169d2a4e9 | ||
|
|
6a9caa432e | ||
|
|
389948c077 | ||
|
|
e7724ed8b9 | ||
|
|
c7f1b27fdf | ||
|
|
135f0255b8 | ||
|
|
65a7aa569d | ||
|
|
211eaa6175 | ||
|
|
8097c6ad9e | ||
|
|
b0d76b01d7 | ||
|
|
626fd0081f | ||
|
|
362fca74bc | ||
|
|
b8f0a29f79 | ||
|
|
f54400f00d | ||
|
|
54094695b1 | ||
|
|
1e3e9588da | ||
|
|
f04705b659 | ||
|
|
c22672fad0 | ||
|
|
59673a47db | ||
|
|
e56ea0bd4e | ||
|
|
f8c4d4a842 | ||
|
|
c4dd9214a3 | ||
|
|
4d74b3a89e | ||
|
|
b0b3fd40ce | ||
|
|
3404c930c5 | ||
|
|
abcd940ed3 | ||
|
|
c1756942b2 | ||
|
|
ea4d036066 | ||
|
|
101a34bd3f | ||
|
|
99bad149cb | ||
|
|
a0bff7164c | ||
|
|
0c4a4130b9 | ||
|
|
8dd1211729 | ||
|
|
a2f1b8b624 | ||
|
|
98a331ffe5 | ||
|
|
c0f97c9bae | ||
|
|
960ffa165f | ||
|
|
6bdfbe2eff | ||
|
|
80342e61ac | ||
|
|
6bf3894e4d | ||
|
|
aab29838bf | ||
|
|
856ca5651e | ||
|
|
a7d4b8d7fb | ||
|
|
62d260473c | ||
|
|
bde52a2526 | ||
|
|
6243b03cfc | ||
|
|
d24841800e | ||
|
|
f60628c769 | ||
|
|
034f697da5 | ||
|
|
ec9f80767b | ||
|
|
a5e569cf05 | ||
|
|
b62259f9b4 | ||
|
|
95baeaa8a8 | ||
|
|
a5b9115a91 | ||
|
|
1885c58d86 | ||
|
|
add55a47d6 | ||
|
|
129f49a9ee | ||
|
|
9560eb7ad6 | ||
|
|
772ba29a8e | ||
|
|
8ac8f6cc1f | ||
|
|
a0f496475c | ||
|
|
8979a388ee | ||
|
|
8b9a209c49 | ||
|
|
f4c3e3ceee | ||
|
|
5ca8a83f25 | ||
|
|
006011885f | ||
|
|
9c9e061f6d | ||
|
|
c9782a7d29 | ||
|
|
59de82def8 | ||
|
|
dc2617bb5d | ||
|
|
d80e621563 | ||
|
|
63c02e4605 | ||
|
|
3f93fe0869 | ||
|
|
9011f76e95 | ||
|
|
dd88e4ad3e | ||
|
|
a0869aa4a5 | ||
|
|
1107264d7c | ||
|
|
31512546d3 | ||
|
|
183e7b6945 | ||
|
|
fba465d573 | ||
|
|
dd6784e3b3 | ||
|
|
9caa0fc0fa | ||
|
|
1102fb4608 | ||
|
|
012cc6ac67 | ||
|
|
72de7efc1d | ||
|
|
b8c7bbec88 | ||
|
|
608513b6dc | ||
|
|
fa78eca087 | ||
|
|
77fda0f939 | ||
|
|
81d210a77b | ||
|
|
5ab4456040 | ||
|
|
2db45c900a | ||
|
|
705dc23908 | ||
|
|
9def487ab8 | ||
|
|
50e08f115a | ||
|
|
b15693a914 | ||
|
|
cbf23b6f30 | ||
|
|
fc45efb4af | ||
|
|
b4fbcd6d16 | ||
|
|
c54e5c27ae | ||
|
|
4b80765b26 | ||
|
|
d223e064c2 | ||
|
|
1f8d6c5898 | ||
|
|
66555e9c7e | ||
|
|
bb81b8f826 | ||
|
|
ecb5a77fdd | ||
|
|
6652c2f97e | ||
|
|
e9f16f72cb | ||
|
|
a687b1771f | ||
|
|
ec79e315e5 | ||
|
|
af10e66b1a | ||
|
|
2d8a0f514d | ||
|
|
02ade0a377 | ||
|
|
c2943037d9 | ||
|
|
c30d8fa5fd | ||
|
|
4fd10bc8a4 | ||
|
|
1d25fec9ff | ||
|
|
6f77527d59 | ||
|
|
7a2cd5cef8 | ||
|
|
d1de4d96d8 | ||
|
|
dd1652c3a6 | ||
|
|
66fd2eed81 | ||
|
|
f5d90f97e8 | ||
|
|
ade3800568 | ||
|
|
486e2e5a28 | ||
|
|
86d3b4e3f5 | ||
|
|
4d669731fb | ||
|
|
5bc81f7048 | ||
|
|
6cf6dec001 | ||
|
|
526d82752c | ||
|
|
7565b2bb54 | ||
|
|
692a32f4d7 | ||
|
|
4039ffdf20 | ||
|
|
cb39b3b79b | ||
|
|
fe3dfd00ab | ||
|
|
08a4b5a2ca | ||
|
|
e8a036b6df | ||
|
|
ff698ec6b2 | ||
|
|
8644ea515b | ||
|
|
10a77c25e9 | ||
|
|
25d3adc28c | ||
|
|
5cdbbb995f | ||
|
|
01a26ef57a | ||
|
|
3b337ea127 | ||
|
|
c66ef5ba91 | ||
|
|
b2edcf8a20 | ||
|
|
06af33e37e | ||
|
|
1a217d0870 | ||
|
|
d6c52baf53 | ||
|
|
f923fdefa4 | ||
|
|
bd674a0e14 | ||
|
|
bd3f8af924 | ||
|
|
5e720876ac | ||
|
|
8543db465b | ||
|
|
ec4951d8dd | ||
|
|
17f1846c69 | ||
|
|
6b71a544fe | ||
|
|
7f1f097179 | ||
|
|
a7003b84bf | ||
|
|
8a84e69ce3 | ||
|
|
3ebd50a8c1 | ||
|
|
1f7a952c91 | ||
|
|
560ef57915 | ||
|
|
4fb81526ae | ||
|
|
4bee8117ee | ||
|
|
66991684d2 | ||
|
|
06abcbff51 | ||
|
|
17197461f7 | ||
|
|
f036190019 | ||
|
|
e68975b0f7 | ||
|
|
692c1cb596 | ||
|
|
7ace3b7685 | ||
|
|
6d6077c54f | ||
|
|
b60913de3c | ||
|
|
357b89f1ea | ||
|
|
c37b05d4b8 | ||
|
|
94fe011d49 | ||
|
|
0e458e81d8 | ||
|
|
efbdb134a9 | ||
|
|
a97d87ed7b | ||
|
|
cb56cfcb00 | ||
|
|
d13cf0ef8d | ||
|
|
e6afd6887a | ||
|
|
7378b7db53 | ||
|
|
70f9bb0f73 | ||
|
|
2fa7451716 | ||
|
|
871aeaed1f | ||
|
|
09f0337489 | ||
|
|
51f36de7dd | ||
|
|
0999e1ea51 | ||
|
|
d079b276cf | ||
|
|
e1bd87418c | ||
|
|
d06af28e11 | ||
|
|
c123a29b1d | ||
|
|
1398a3bdee | ||
|
|
340e866aed | ||
|
|
9338162906 | ||
|
|
23d61bfa60 | ||
|
|
7409053cef | ||
|
|
0c372b0245 | ||
|
|
dd68405522 | ||
|
|
69e792ae41 | ||
|
|
02b507aca9 | ||
|
|
05f94c65fc | ||
|
|
8b6ebd1820 | ||
|
|
45cb411e17 | ||
|
|
dec66de61d | ||
|
|
e9a490d7f3 | ||
|
|
280b28a474 | ||
|
|
cfba5f34d4 | ||
|
|
582e2d988c | ||
|
|
4c627986d1 | ||
|
|
299dab43b9 | ||
|
|
ce0823a6fd | ||
|
|
e0963e9b65 | ||
|
|
a88552f975 | ||
|
|
66a7bab287 | ||
|
|
088d9e1b6f | ||
|
|
29619b2fec | ||
|
|
a5effc89a7 | ||
|
|
e7fe2a2676 | ||
|
|
53bb01db2d | ||
|
|
003d0cbcb2 | ||
|
|
a71c627a30 | ||
|
|
261c851514 | ||
|
|
58cfcba738 | ||
|
|
50dac899c9 | ||
|
|
9fe25f0f73 | ||
|
|
678c961ea9 | ||
|
|
f6b4633ac4 | ||
|
|
0ecd2916a2 | ||
|
|
e786b60bfc | ||
|
|
8c079e9064 | ||
|
|
3b08fe438b | ||
|
|
fedbdcc35c | ||
|
|
ac656ddc04 | ||
|
|
85d8d75da8 | ||
|
|
e6d389d848 | ||
|
|
664053f231 | ||
|
|
18b2230dd7 | ||
|
|
0876ed3acc | ||
|
|
7b4edbee8b | ||
|
|
05ef1edfeb | ||
|
|
fb8db78bbd | ||
|
|
aecc4a477f | ||
|
|
fd63ce8b3c | ||
|
|
423cd498cf | ||
|
|
b421c8b08c | ||
|
|
4304286f48 | ||
|
|
df308c98ff | ||
|
|
1d1221e8c5 | ||
|
|
e2a6eac0a2 | ||
|
|
4e54baf9fb | ||
|
|
7593e420de | ||
|
|
84ca80a1c9 | ||
|
|
7265f4d4ce | ||
|
|
fca1eacc6e | ||
|
|
384c32dd1f | ||
|
|
983d075d5a | ||
|
|
29ce32f3fe | ||
|
|
d9e67ec9be | ||
|
|
a1e7ee2997 | ||
|
|
653ed1c1b2 | ||
|
|
d7a3641fed | ||
|
|
71cd95587d | ||
|
|
4ca12ba5c7 | ||
|
|
bb189abe01 | ||
|
|
f4e6d14a9c | ||
|
|
a7f0522d57 | ||
|
|
cf38eef3b8 | ||
|
|
104179a2e6 | ||
|
|
4e2be8e397 | ||
|
|
732b5a7fb1 | ||
|
|
0441401d9f | ||
|
|
564afb7e32 | ||
|
|
5167ba21a6 | ||
|
|
b2319e8ea6 | ||
|
|
f8a2166967 | ||
|
|
6a70d149db | ||
|
|
306f5ed7f9 | ||
|
|
6a5d478e62 | ||
|
|
b440ddbe82 | ||
|
|
6b8051f9df | ||
|
|
f4df6e8799 | ||
|
|
e9a63fd553 | ||
|
|
a8535d5f3e | ||
|
|
23b77c7e48 | ||
|
|
878bf44d0b | ||
|
|
8b6188a6b5 | ||
|
|
822625a1c2 | ||
|
|
d6e0d92132 | ||
|
|
da6489eb7a | ||
|
|
819827cc4c | ||
|
|
d09b5b1ce7 | ||
|
|
cc03ef4f9c | ||
|
|
b4dbd8889d | ||
|
|
483faad86a | ||
|
|
0dbc745ed0 | ||
|
|
180e93a7da | ||
|
|
5c6f416391 | ||
|
|
d97b6afac8 | ||
|
|
771816f3af | ||
|
|
0626538aea | ||
|
|
a1ad4e4a05 | ||
|
|
6df48eb555 | ||
|
|
27ab4526e2 | ||
|
|
9a24b34fbc | ||
|
|
d01e01534b | ||
|
|
5bca1f2a81 | ||
|
|
807b300885 | ||
|
|
b16ffa4352 | ||
|
|
da79d04ef4 | ||
|
|
cf619df576 | ||
|
|
8054c96315 | ||
|
|
2363f424f5 | ||
|
|
6ab1ea2e70 | ||
|
|
c9ce7d6762 | ||
|
|
6ee1b0a7f8 | ||
|
|
d881920312 | ||
|
|
516465db37 | ||
|
|
08e95cec55 | ||
|
|
9671683a93 | ||
|
|
d909d6e804 | ||
|
|
15c50779b4 | ||
|
|
1d865c47d7 | ||
|
|
7afd476ac7 | ||
|
|
37b1e42c64 | ||
|
|
5bdfec7c3f | ||
|
|
2bddc3c621 | ||
|
|
6b0beba1d9 | ||
|
|
33904e9d26 | ||
|
|
8aafee672e | ||
|
|
9d886cd33f | ||
|
|
95d1ea3530 | ||
|
|
d3014e7e9a | ||
|
|
da143c3412 | ||
|
|
b10a7a923e | ||
|
|
08601203df | ||
|
|
526ba9f2a0 | ||
|
|
f1fc1d17a5 | ||
|
|
6e07c86eed | ||
|
|
14199391e0 | ||
|
|
bb834f6274 | ||
|
|
8688935f25 | ||
|
|
1b7d257e97 | ||
|
|
fff4b222cb | ||
|
|
c63dee8509 | ||
|
|
810653c4d1 | ||
|
|
607bc320fb | ||
|
|
72393ebca5 | ||
|
|
ecef17846b | ||
|
|
45265eedd4 | ||
|
|
04da34e677 | ||
|
|
1e504d9e0c | ||
|
|
75528d37d3 | ||
|
|
eddff0d93f | ||
|
|
f4579ef8dc | ||
|
|
fc5496fda6 | ||
|
|
5cf6f4da38 | ||
|
|
60fde8b103 | ||
|
|
734fe33f40 | ||
|
|
64da928c36 | ||
|
|
dba0b1b3c7 | ||
|
|
073746a9bc | ||
|
|
45c14e3b79 | ||
|
|
7023fe747b | ||
|
|
141c7fe1d6 | ||
|
|
44b406fad4 | ||
|
|
78e76818b5 | ||
|
|
f78a773fab | ||
|
|
60d007d9eb | ||
|
|
1ec253333e | ||
|
|
bd332b6bd9 | ||
|
|
bc9bdbebe3 | ||
|
|
0b471cc5bc | ||
|
|
c2eed61b83 | ||
|
|
2d403b4c56 | ||
|
|
b3e4ca90ee | ||
|
|
d4a3a4bc06 | ||
|
|
b674b5faf6 | ||
|
|
8416028113 | ||
|
|
edb21308d4 | ||
|
|
26ad0153d8 | ||
|
|
e9b2acca5b | ||
|
|
4180ee61d6 | ||
|
|
a442a50708 | ||
|
|
59e650a1f1 | ||
|
|
69b6470cda | ||
|
|
44b33c1e4c | ||
|
|
08f00c6578 | ||
|
|
51c4066222 | ||
|
|
6fb72e4b2f | ||
|
|
c9fbbd78a8 | ||
|
|
ce5388be61 | ||
|
|
02d60e9bd5 | ||
|
|
fce50daff6 | ||
|
|
35b7f5700f | ||
|
|
b954947bb7 | ||
|
|
ddd5d50c5d | ||
|
|
efec7ecb26 | ||
|
|
ee81f795fe | ||
|
|
ad557ff919 | ||
|
|
bf5fae08b2 | ||
|
|
88321928bf | ||
|
|
a7d50a9439 | ||
|
|
4c6dcd15da | ||
|
|
84f9d14be0 | ||
|
|
e2f173f250 | ||
|
|
fdd9617604 | ||
|
|
bc3cedfe50 | ||
|
|
78f9093931 | ||
|
|
a889c768d1 | ||
|
|
e36319a73e | ||
|
|
199ae95bcd | ||
|
|
30875f0491 | ||
|
|
95d9d17aa7 | ||
|
|
215d7ca341 | ||
|
|
1255df10e0 | ||
|
|
4c641adeda | ||
|
|
4bd4158dab | ||
|
|
4965976f6c | ||
|
|
b43f512887 | ||
|
|
e6f2b46fce | ||
|
|
01c84b361a | ||
|
|
ac35cc237e | ||
|
|
28ad07b372 | ||
|
|
6ade77d458 | ||
|
|
4187e13861 | ||
|
|
4fe5034e1c | ||
|
|
729451fa48 | ||
|
|
d77fe8c540 | ||
|
|
a257ddd8e0 | ||
|
|
90154bd497 | ||
|
|
f96224569f | ||
|
|
1c695104f9 | ||
|
|
ab9a35dd89 | ||
|
|
6daa96119d | ||
|
|
128a280dee | ||
|
|
475c885344 | ||
|
|
ee62649bf6 | ||
|
|
109999d66f | ||
|
|
9ec34b07c4 | ||
|
|
2fd2d701dd | ||
|
|
5574252b5b | ||
|
|
5e79d4dc52 | ||
|
|
bb91782079 | ||
|
|
2bbcb15740 | ||
|
|
216d302a86 | ||
|
|
e18b9a4200 | ||
|
|
310395d166 | ||
|
|
651f44914f | ||
|
|
4a97800a05 | ||
|
|
f2e124903c | ||
|
|
eec1cb5666 | ||
|
|
cb7334d63b | ||
|
|
b62e6e8e35 | ||
|
|
f98aac5231 | ||
|
|
9c4e94ce8d | ||
|
|
65a19feffc | ||
|
|
62a1be7abe | ||
|
|
ad4481cfc7 | ||
|
|
e4c20b953d | ||
|
|
e8044fae1b | ||
|
|
b845147050 | ||
|
|
c4818319aa | ||
|
|
6bc265a358 | ||
|
|
8cb25d6ca1 | ||
|
|
5a14e0afbd | ||
|
|
0804eeeccb | ||
|
|
f015169011 | ||
|
|
201ea2ee9c | ||
|
|
961211e638 | ||
|
|
22a494e31e | ||
|
|
75e24771b3 | ||
|
|
97b30d5b14 | ||
|
|
ca5dbb9d6f | ||
|
|
e065c1a8da | ||
|
|
fc76f34d38 | ||
|
|
98e963d782 | ||
|
|
27e5afacde | ||
|
|
8a4fe7aedd | ||
|
|
90268b4ec1 | ||
|
|
034693df98 | ||
|
|
5b31661f8d | ||
|
|
ba01807add | ||
|
|
3b89777648 | ||
|
|
bb510788eb | ||
|
|
d48b59b374 | ||
|
|
7d72fc56db | ||
|
|
90edb7dd7e | ||
|
|
7ee0c4d145 | ||
|
|
67f2ff54be | ||
|
|
1b85c8ff50 | ||
|
|
f0470d3faa | ||
|
|
4d5e81a638 | ||
|
|
7676ae8143 | ||
|
|
fb97db99b0 | ||
|
|
92aad95603 | ||
|
|
513cef2a66 | ||
|
|
bdf3bbc530 | ||
|
|
9a17f95026 | ||
|
|
e6b44d8365 | ||
|
|
874f8f4758 | ||
|
|
47baf2fa89 | ||
|
|
57bfc523ab | ||
|
|
23edea5fa4 | ||
|
|
7b12857a35 | ||
|
|
d6d919ed52 | ||
|
|
330c59f7e9 | ||
|
|
600687f652 | ||
|
|
0c65e9dace | ||
|
|
ed144f0a15 | ||
|
|
c0c2cc86d3 | ||
|
|
9b8ea11866 | ||
|
|
17aed38316 | ||
|
|
48a7cc4dd4 | ||
|
|
4417fd9f0d | ||
|
|
3e429cb261 | ||
|
|
48e30e795f | ||
|
|
953e528298 | ||
|
|
4276f427b9 | ||
|
|
4b2bfefc9b | ||
|
|
11e79c4830 | ||
|
|
264d914044 | ||
|
|
12f1e7c3af | ||
|
|
9eb4fbab65 | ||
|
|
8d1a63e47f | ||
|
|
e449e612c1 | ||
|
|
6ba65f031b | ||
|
|
f31ac4c2e3 | ||
|
|
f980f5aaf9 | ||
|
|
45989d7abd | ||
|
|
87a1e8a2c4 | ||
|
|
ae27da1127 | ||
|
|
ca21931d93 | ||
|
|
5bb9ebd6ec | ||
|
|
45ab1e9cc5 | ||
|
|
8d2685a8c3 | ||
|
|
d38c41a99d | ||
|
|
ff3dacde39 | ||
|
|
5c9f4c5b21 | ||
|
|
c134f645ef | ||
|
|
6f0933a350 | ||
|
|
c9a90211ee | ||
|
|
95d96dd295 | ||
|
|
86bf079f6f | ||
|
|
c202490555 | ||
|
|
da0100dd35 | ||
|
|
b634247463 | ||
|
|
84df6493f6 | ||
|
|
90b752e185 | ||
|
|
d3858c731c | ||
|
|
f247ac641c | ||
|
|
be1a9e8f7e | ||
|
|
d86f595b1f | ||
|
|
3ed9227508 | ||
|
|
74bf2133c6 | ||
|
|
e4570946c4 | ||
|
|
a8213d79fd | ||
|
|
13ec323ac4 | ||
|
|
9cfe8176d4 | ||
|
|
c544cebba9 | ||
|
|
74dffe8af2 | ||
|
|
3999b8f623 | ||
|
|
9d3bb9dcf3 | ||
|
|
05e58aa060 | ||
|
|
f74d14d573 | ||
|
|
741e651a20 | ||
|
|
4e1bd89378 | ||
|
|
c8f54b8be5 | ||
|
|
413d2f5178 | ||
|
|
503f44891f | ||
|
|
35c2a6a046 | ||
|
|
5bf326f680 | ||
|
|
1df201525c | ||
|
|
e7793b15e3 | ||
|
|
d2e16ca256 | ||
|
|
31164befc9 | ||
|
|
8f4dfa0674 | ||
|
|
eb7a01907a | ||
|
|
fb1fd1ec7c | ||
|
|
7528c7df63 | ||
|
|
e6ca19ab91 | ||
|
|
dc3e097dfd | ||
|
|
a5e8c06dda | ||
|
|
bf7fd13ef2 | ||
|
|
a424e015b4 | ||
|
|
c67fef64fe | ||
|
|
12055de1fc | ||
|
|
a2ad2f8c0b | ||
|
|
af7cebda66 | ||
|
|
2230cf2e7b | ||
|
|
aa048e8d22 | ||
|
|
4961fb9756 | ||
|
|
6801e3858a | ||
|
|
ef72dcf554 | ||
|
|
c228147c00 | ||
|
|
266358f0cc | ||
|
|
6717f0ee3d | ||
|
|
8880ed0df6 | ||
|
|
4b56b973c8 | ||
|
|
28a00b9f22 | ||
|
|
b1fe692de5 | ||
|
|
08b2f6cbc9 | ||
|
|
10e1db388f | ||
|
|
cd7f71b968 | ||
|
|
395fd544e5 | ||
|
|
2c10d6bf10 | ||
|
|
9361a631dd | ||
|
|
59c5abfd93 | ||
|
|
633c23a6f0 | ||
|
|
779e7323e2 | ||
|
|
6e7fbd940b | ||
|
|
6878b608fc | ||
|
|
a4fab8b64e | ||
|
|
21c0cc8794 | ||
|
|
7ea11ea0c4 | ||
|
|
d2c307b08a | ||
|
|
4dc98f7980 | ||
|
|
c89ee18db3 | ||
|
|
c4aa7999a6 | ||
|
|
778343f636 | ||
|
|
d2fb3b6c85 | ||
|
|
a8bfedcd5d | ||
|
|
4c7b5eec38 | ||
|
|
35068e23cd | ||
|
|
bc30b86cce | ||
|
|
461f166e33 | ||
|
|
628dbd5227 | ||
|
|
c05b290e49 | ||
|
|
696015b6a4 | ||
|
|
f2f70e1d83 | ||
|
|
b4d967f721 | ||
|
|
bf760677ef | ||
|
|
4d1dbaa2f3 | ||
|
|
595bb27d99 | ||
|
|
ad95faffa7 | ||
|
|
a0eb3c0459 | ||
|
|
fea435a6d2 | ||
|
|
7b72532c9e | ||
|
|
ea9920c4d5 | ||
|
|
6b756fe893 | ||
|
|
54c7f51766 | ||
|
|
94b787655e | ||
|
|
259d0f1648 | ||
|
|
872d3ff383 | ||
|
|
cf1c4d37b9 | ||
|
|
ada16bac6c | ||
|
|
d68055f8a9 | ||
|
|
8d98dcf7e7 | ||
|
|
c828a69f66 | ||
|
|
eefb6062c7 | ||
|
|
470a451168 | ||
|
|
e3b018c5f7 | ||
|
|
bd695e21d4 | ||
|
|
6311ebe467 | ||
|
|
f8a5ceed97 | ||
|
|
0420bda5da | ||
|
|
6dc532f40e | ||
|
|
0560d01f30 | ||
|
|
bc67ec3287 | ||
|
|
bed35a2377 | ||
|
|
aaf156cee3 | ||
|
|
e8020ffde6 | ||
|
|
8d6bd80902 | ||
|
|
8aa870dddd | ||
|
|
26a3c76d5f | ||
|
|
18f738f2c3 | ||
|
|
bba50ccbcc | ||
|
|
3eea3b913d | ||
|
|
2dbeec831e | ||
|
|
88a06628e3 | ||
|
|
37ceb30ffb | ||
|
|
ebd0515e96 | ||
|
|
ece5d0fa0d | ||
|
|
6be214c6cd | ||
|
|
c470453ea4 | ||
|
|
bbe9326954 | ||
|
|
27961bb4e5 | ||
|
|
4952c090ef | ||
|
|
74e4016625 | ||
|
|
c389008811 | ||
|
|
e6dcf22012 | ||
|
|
d067f925b9 | ||
|
|
8b5609f765 | ||
|
|
dd04a1f2af | ||
|
|
9caabb6cc0 | ||
|
|
33b28d5f41 | ||
|
|
475f9b5e34 | ||
|
|
60f1348ea5 | ||
|
|
533b6e1fcf | ||
|
|
8961730b74 | ||
|
|
5d580714c8 | ||
|
|
daf1ead75b | ||
|
|
aef2654a39 | ||
|
|
8243cd3528 | ||
|
|
447456d7a6 | ||
|
|
241a34d7a8 | ||
|
|
4e67b2e8b9 | ||
|
|
8bc2ea8373 | ||
|
|
00a6a113c8 | ||
|
|
dc04619128 | ||
|
|
e066da3762 | ||
|
|
ad96278956 | ||
|
|
83406277ad | ||
|
|
9e89348381 | ||
|
|
0fb7419598 | ||
|
|
1790298cb4 | ||
|
|
ffe8e39c85 | ||
|
|
67e0f4bd46 | ||
|
|
e7b3a58da3 | ||
|
|
598f9f3777 | ||
|
|
0a7dca2e12 | ||
|
|
4b342778df | ||
|
|
10e8fd904a | ||
|
|
1de342fd3b | ||
|
|
f4c1c3dd7f | ||
|
|
80bfc59356 | ||
|
|
3796f3ed5f | ||
|
|
f2e03d22d8 | ||
|
|
ef967b66e8 | ||
|
|
58ea70cc6c | ||
|
|
e4823950df | ||
|
|
8f9923ba5d | ||
|
|
72bbd2c36e | ||
|
|
9bdb902a56 | ||
|
|
bbc2e55ae3 | ||
|
|
6995bdb527 | ||
|
|
a7abc35316 | ||
|
|
772aed597b | ||
|
|
9e18825c27 | ||
|
|
27b7ffcf99 | ||
|
|
d804a744b6 | ||
|
|
fc5cf27bd1 | ||
|
|
355bba8966 | ||
|
|
e31c5f5a19 | ||
|
|
22837bbf8d | ||
|
|
6324486dca | ||
|
|
653100f539 | ||
|
|
d671ba583d | ||
|
|
fba324c6cb | ||
|
|
ccbec5bcff | ||
|
|
da1978bf21 | ||
|
|
1672b89775 | ||
|
|
d9a9db6ec8 | ||
|
|
0882bc2ca7 | ||
|
|
89b8d07bb4 | ||
|
|
c65c8edd2d | ||
|
|
5f7ce96919 | ||
|
|
d9a2601f75 | ||
|
|
37a04cadf8 | ||
|
|
ca10c01398 | ||
|
|
24f6ba117d | ||
|
|
7508144e27 | ||
|
|
9f0fec8046 | ||
|
|
67d70fac8e | ||
|
|
1775f6fd89 | ||
|
|
438c367101 | ||
|
|
cb9d8ffa91 | ||
|
|
2ecb0c5cf6 | ||
|
|
b01ce5b3b6 | ||
|
|
8a55d52b2b | ||
|
|
c7e6f00ddb | ||
|
|
85831ffe5d | ||
|
|
762a5a2072 | ||
|
|
405e1ed023 | ||
|
|
41177436d4 | ||
|
|
d1fca976a2 | ||
|
|
59cf407c26 | ||
|
|
e95828a514 | ||
|
|
8b915c7c83 | ||
|
|
ebc6a01b7a | ||
|
|
8cad3c4c14 | ||
|
|
a5537c21a1 | ||
|
|
edf96434b7 | ||
|
|
257df95c72 | ||
|
|
a268df503a | ||
|
|
a57ccbe4c2 | ||
|
|
7f37771dc7 | ||
|
|
3a753dde83 | ||
|
|
8e91b1363b | ||
|
|
e77929ab89 | ||
|
|
02031e97e3 | ||
|
|
ede1c505d4 | ||
|
|
5cd5b685d2 | ||
|
|
d856f1d1cc | ||
|
|
10bb912bda | ||
|
|
3b2135a570 | ||
|
|
9c5d209887 | ||
|
|
763a770bcf | ||
|
|
f8f3456ba3 | ||
|
|
4da7f02cf7 | ||
|
|
4772e24c78 | ||
|
|
c3a9b82abb | ||
|
|
4716940708 | ||
|
|
0eb09e2dbb | ||
|
|
111a33b12f | ||
|
|
bcff2272ab | ||
|
|
f30ae91854 | ||
|
|
7eaad843a9 | ||
|
|
cb367d32c3 | ||
|
|
b4cf88bd54 | ||
|
|
b8097fcd3a | ||
|
|
6db2238096 | ||
|
|
cd426d5534 | ||
|
|
c214d47aad | ||
|
|
c09c44ec5f | ||
|
|
f9f6d0d836 | ||
|
|
74a6c75c21 | ||
|
|
526ebc77bc | ||
|
|
addac44c0f | ||
|
|
303d575fde | ||
|
|
bf8438b229 | ||
|
|
ea8bbafbfa | ||
|
|
14815e79d5 | ||
|
|
4a3de35224 | ||
|
|
974f549c31 | ||
|
|
76596939c5 | ||
|
|
138974bca7 | ||
|
|
02aee02694 | ||
|
|
e2ada75611 | ||
|
|
78b757c55b | ||
|
|
dfd273e7bf | ||
|
|
1a72c23412 | ||
|
|
55a92ad029 | ||
|
|
aea6a0d131 | ||
|
|
e76e031675 | ||
|
|
ed095a95f0 | ||
|
|
3cdb3d6294 | ||
|
|
06fe8b3742 | ||
|
|
6ba7c54089 | ||
|
|
e2bc284091 | ||
|
|
66bf91e177 | ||
|
|
6039545f9d | ||
|
|
cc6f70e834 | ||
|
|
55d7687561 | ||
|
|
90866e2bea | ||
|
|
2059e4eba4 | ||
|
|
243a288061 | ||
|
|
623155be92 | ||
|
|
a404469085 | ||
|
|
b0e12b717b | ||
|
|
fdc1dadd36 | ||
|
|
872db4085c | ||
|
|
8af8cbacd3 | ||
|
|
01beef4312 | ||
|
|
a91ffd9ad7 | ||
|
|
dc42107668 | ||
|
|
670012676c | ||
|
|
8910ce47cd | ||
|
|
bc76ecba46 | ||
|
|
e50707e1dd | ||
|
|
a03c6fe0cb | ||
|
|
d5c17b08cc | ||
|
|
656bab3d48 | ||
|
|
cc6e01bd05 | ||
|
|
a9479db5be | ||
|
|
d4546a2865 | ||
|
|
7e0dd05f3d | ||
|
|
3bbefd3dfc | ||
|
|
fdca2ecfee | ||
|
|
ae08e46b30 | ||
|
|
bf18b83a75 | ||
|
|
393172ec9f | ||
|
|
781e9df148 | ||
|
|
2691a217db | ||
|
|
b421f74d1a | ||
|
|
e3bd33ffc3 | ||
|
|
38c2fd07ae | ||
|
|
77ebafd018 | ||
|
|
dfab7e3540 | ||
|
|
262e0c5e11 | ||
|
|
e4410fe2c7 | ||
|
|
8718dd8231 | ||
|
|
0274b2af3b | ||
|
|
1dbd3fd274 | ||
|
|
abdbab807d | ||
|
|
718077025d | ||
|
|
08161c29d3 | ||
|
|
942f84dfcf | ||
|
|
41defdc291 | ||
|
|
2e286b2de3 | ||
|
|
168847b24a | ||
|
|
69c23a55f7 | ||
|
|
045b8e162a | ||
|
|
f344c2b0e8 | ||
|
|
11819e59c6 | ||
|
|
caf7331d28 | ||
|
|
68e5926568 | ||
|
|
9d46f49634 | ||
|
|
daae9323e8 | ||
|
|
80c425aa6f | ||
|
|
1cbe309778 | ||
|
|
e3d7813edb | ||
|
|
189dc64a0f | ||
|
|
2f0ede7170 | ||
|
|
c7e444d446 | ||
|
|
f5ac916663 | ||
|
|
b3b9f0223e | ||
|
|
70455df6d3 | ||
|
|
b89889a3e9 | ||
|
|
7ec00925ed | ||
|
|
d3e3d127b3 | ||
|
|
11c4d8fb72 | ||
|
|
9b02a19b9c | ||
|
|
57262919b8 | ||
|
|
f787a15347 | ||
|
|
bc74eac86d | ||
|
|
0a1df250cb | ||
|
|
8a7b9de29d | ||
|
|
8efb87a1f7 | ||
|
|
27ee667bfb | ||
|
|
c64ff772e7 | ||
|
|
313efebb8b | ||
|
|
9eee4fff6c | ||
|
|
b5a7c96181 | ||
|
|
5bea71e19e | ||
|
|
751e533dce | ||
|
|
9e58e8aad9 | ||
|
|
d62a7d704a | ||
|
|
f8d7d12d61 | ||
|
|
2ad71cad78 | ||
|
|
689d8ead24 | ||
|
|
b6a7df76f6 | ||
|
|
41e8145858 | ||
|
|
3a5b80657c | ||
|
|
41c6897224 | ||
|
|
8d644cdd65 | ||
|
|
7a68229432 | ||
|
|
4dab0ef6f6 | ||
|
|
75cad811bc | ||
|
|
0709f1dd6a | ||
|
|
478950c446 | ||
|
|
b5e5601671 | ||
|
|
0ee86faa00 | ||
|
|
fa7b204f89 | ||
|
|
22f9ba80fe | ||
|
|
065878a6e9 | ||
|
|
5df433d603 | ||
|
|
21375855dd | ||
|
|
b847ca6b3e | ||
|
|
50caf9811d | ||
|
|
f0df9e1157 | ||
|
|
3e1347f17e | ||
|
|
86082bbfda | ||
|
|
6e6551ceae | ||
|
|
08ef5f0853 | ||
|
|
92131453e8 | ||
|
|
888a95d2a0 | ||
|
|
ab745cba18 | ||
|
|
dfe6b3977f | ||
|
|
e7e8b71a70 | ||
|
|
c158e16bd3 | ||
|
|
464fac660b | ||
|
|
79b1920b15 | ||
|
|
f071e7b2d5 | ||
|
|
3afb8d6ed1 | ||
|
|
87a2e94dd6 | ||
|
|
d711d4a816 | ||
|
|
a4b4aeed64 | ||
|
|
3707572bd8 | ||
|
|
aef5c06f0a | ||
|
|
a021ac0da3 | ||
|
|
1e4e6da44e | ||
|
|
6b0d9774c5 | ||
|
|
e1720e6023 | ||
|
|
3078724ced | ||
|
|
f3eb0a67f6 | ||
|
|
65d7a6f5a4 | ||
|
|
b2b5456400 | ||
|
|
a598be069d | ||
|
|
bf61f2c982 | ||
|
|
63225491f1 | ||
|
|
0dbc773775 | ||
|
|
47b7d42dd3 | ||
|
|
d713c787e6 | ||
|
|
68a2eab425 | ||
|
|
886f063d1b | ||
|
|
ed6ee36509 | ||
|
|
ab345dae0d | ||
|
|
fbb1e6c4a2 | ||
|
|
4ede9226b4 | ||
|
|
fbfecbd8ae | ||
|
|
3c4612d15c | ||
|
|
7fa2e7862d | ||
|
|
114267362c | ||
|
|
4050e9605d | ||
|
|
fdd5373aaf | ||
|
|
2dfe7ec05b | ||
|
|
82513b5dde | ||
|
|
14d1bb6ac8 | ||
|
|
d589c94681 | ||
|
|
eca19bb507 | ||
|
|
282ff30b3e | ||
|
|
5d0b810674 | ||
|
|
e32482c634 | ||
|
|
650026b0c0 | ||
|
|
cd25d6da38 | ||
|
|
9dd0954967 | ||
|
|
fdaceb9bf8 | ||
|
|
4ab3a3b3cf | ||
|
|
eb8b54dc63 | ||
|
|
4703aee60c | ||
|
|
93b0d43bd7 | ||
|
|
1029310e0d | ||
|
|
c083684db2 | ||
|
|
d6775aad69 | ||
|
|
3eff10bbb4 | ||
|
|
e4cbab8365 | ||
|
|
18212e7a4c | ||
|
|
0cd0b1abfd | ||
|
|
a66137873c | ||
|
|
469110eabf | ||
|
|
55474fa4e3 | ||
|
|
3bdcdee031 | ||
|
|
246c5a61dd | ||
|
|
0c8bfba515 | ||
|
|
3c8d9bb1e5 | ||
|
|
da2c1c8316 | ||
|
|
0334b2dd33 | ||
|
|
96356042af | ||
|
|
21adff8d0c | ||
|
|
35def2a7c7 | ||
|
|
e3d82794a3 | ||
|
|
20cbac8f17 | ||
|
|
6067e02729 | ||
|
|
eb77664ea1 | ||
|
|
8b1baf9ebd | ||
|
|
12fb774b73 | ||
|
|
d79dbb11fe | ||
|
|
19ccb29248 | ||
|
|
199c4f30e7 | ||
|
|
732c0d4e35 | ||
|
|
fa1769da9f | ||
|
|
029997d624 | ||
|
|
d2546409cb | ||
|
|
cb2bc8d65b | ||
|
|
57bd8d4dd4 | ||
|
|
cc1e210799 | ||
|
|
4bee08d483 | ||
|
|
8cfb160989 | ||
|
|
6325167eda | ||
|
|
8925eae4c5 | ||
|
|
9282bcd779 | ||
|
|
5aa6499598 | ||
|
|
f766781928 | ||
|
|
02834b7102 | ||
|
|
a9e3430505 | ||
|
|
4b9a23001a | ||
|
|
8de7ec9124 | ||
|
|
19a0a3c7c3 | ||
|
|
42a7d6e4b7 | ||
|
|
66818b1647 | ||
|
|
bc8ba9adc8 | ||
|
|
4ae5759361 | ||
|
|
b5cfcf8036 | ||
|
|
061982cf2c | ||
|
|
0e1422c2c4 | ||
|
|
3e534029a0 | ||
|
|
8d9ee9fe5c | ||
|
|
675aa04564 | ||
|
|
88c8885a81 | ||
|
|
151760aef9 | ||
|
|
6c89969b60 | ||
|
|
0fd5e66c33 | ||
|
|
c8aa526e4d | ||
|
|
f2c492c6ea | ||
|
|
11cf845235 | ||
|
|
ae6fbc7c64 | ||
|
|
71eda539f6 | ||
|
|
f43b948ac9 | ||
|
|
1b77020b6a | ||
|
|
1f62040560 | ||
|
|
cc5c3167b1 | ||
|
|
b9b79b949f | ||
|
|
a0d729fe6d | ||
|
|
f618dd3865 | ||
|
|
3fd3f972db | ||
|
|
2311655e5e | ||
|
|
c589836097 | ||
|
|
dbc641cfce | ||
|
|
f13bc58925 | ||
|
|
94d5892cf1 | ||
|
|
8e32b15f26 | ||
|
|
fe5f0ef2eb | ||
|
|
daa27d5f2d | ||
|
|
bb7626609e | ||
|
|
9ed58b685b | ||
|
|
4eb81ad30a | ||
|
|
a1f2cb57b3 | ||
|
|
62b8e387ca | ||
|
|
07498db711 | ||
|
|
2adc8c6f5d | ||
|
|
f15a43f303 | ||
|
|
e35aea5a7e | ||
|
|
0e1ed9d8cc | ||
|
|
f62ef06e51 | ||
|
|
30f4d4588f | ||
|
|
e102396dab | ||
|
|
f60815ef63 | ||
|
|
7b11b53774 | ||
|
|
abff7715ee | ||
|
|
83c0a20d61 | ||
|
|
a4de2391e9 | ||
|
|
732566eacd | ||
|
|
2c98128531 | ||
|
|
9a45823bdb | ||
|
|
fa43a08831 | ||
|
|
6fb8bdaff1 | ||
|
|
35e6d60ac0 | ||
|
|
ecfc241fb5 | ||
|
|
866a5100b9 | ||
|
|
3d972fd740 | ||
|
|
59c9275cc4 | ||
|
|
3ada83efff | ||
|
|
e263048a35 | ||
|
|
63980298b6 | ||
|
|
b904e94156 | ||
|
|
78f91b937f | ||
|
|
1ecd08d053 | ||
|
|
8c03accae7 | ||
|
|
456d3f2f3a | ||
|
|
fa2838ea5c | ||
|
|
e228490812 | ||
|
|
13d0ac0cbd | ||
|
|
09bed1456e | ||
|
|
c6827e499e | ||
|
|
d54cc7a2fd | ||
|
|
67dae94524 | ||
|
|
3273a21246 | ||
|
|
b40b61a46c | ||
|
|
813f611843 | ||
|
|
1abacb75be | ||
|
|
42028a2777 | ||
|
|
0a25eeadbe | ||
|
|
70a4451f90 | ||
|
|
d859395f50 | ||
|
|
97948df14e | ||
|
|
dc84efb3ef | ||
|
|
12676a4314 | ||
|
|
3aafb9f8e7 | ||
|
|
4518db2bdd | ||
|
|
2cb161b62e | ||
|
|
9d052284be | ||
|
|
98d9029dde | ||
|
|
040c67215e | ||
|
|
d577312b24 | ||
|
|
fa10bc9c30 | ||
|
|
055339956a | ||
|
|
6cffa53ea9 | ||
|
|
fe83ef56ea | ||
|
|
abd1cacdc0 | ||
|
|
85b448ab85 | ||
|
|
5749f0018c | ||
|
|
b65d2c5ff3 | ||
|
|
348b2c4aca | ||
|
|
dfc3f32086 | ||
|
|
68d331864d | ||
|
|
24a008b20d | ||
|
|
0e5c35fae4 | ||
|
|
4d4b989dcd | ||
|
|
2983d5a068 | ||
|
|
efdc365b90 | ||
|
|
c4a8e3eb96 | ||
|
|
8cb3c98b8d | ||
|
|
9c12eda210 | ||
|
|
90afcc008d | ||
|
|
7409d096fe | ||
|
|
a4c4a3c0c8 | ||
|
|
2148af7b63 | ||
|
|
d984bc04ec | ||
|
|
1b7dfcc3ac | ||
|
|
c762871cce | ||
|
|
007ea92bd5 | ||
|
|
688b758da2 | ||
|
|
39147d7afa | ||
|
|
50cc17a44b | ||
|
|
73f592df74 | ||
|
|
821042d8b6 | ||
|
|
7123f6cc15 | ||
|
|
6c2e9906b0 | ||
|
|
37648b79c3 | ||
|
|
6b00c2c81a | ||
|
|
cd5599ff1c | ||
|
|
e870eb241b | ||
|
|
fbf8c282e8 | ||
|
|
811e363dd4 | ||
|
|
d206ba1606 | ||
|
|
c529134cd2 | ||
|
|
dafb1d335e | ||
|
|
445899e731 | ||
|
|
b21fbc974c | ||
|
|
4c98a73204 | ||
|
|
e99d669086 | ||
|
|
913ffbda97 | ||
|
|
ec2bd0bd5d | ||
|
|
08fefb1c4b | ||
|
|
e7f20bc553 | ||
|
|
f5993ca5c4 | ||
|
|
9f0c81c20f | ||
|
|
42199c8cda | ||
|
|
bc525fbffc | ||
|
|
dd6821642f | ||
|
|
b2dd96f044 | ||
|
|
0ca8a1fabf | ||
|
|
d46643cf8c | ||
|
|
fc3bea28e8 | ||
|
|
b29323864e | ||
|
|
c4cad5d56f | ||
|
|
1d83c82919 | ||
|
|
1228698fcf | ||
|
|
d1eba5f1e2 | ||
|
|
08ac71dc1b | ||
|
|
da579ecc3a | ||
|
|
f286dd1e1b | ||
|
|
0c5aedfee8 | ||
|
|
b7d7c88fc6 | ||
|
|
8c2671e2fb | ||
|
|
b281f7c25b | ||
|
|
750caa522e | ||
|
|
62ed8affb1 | ||
|
|
92e0e90120 | ||
|
|
9b0dea213e | ||
|
|
a73acfa4e8 | ||
|
|
833542f303 | ||
|
|
b666e4b38c | ||
|
|
32f2fd0754 | ||
|
|
04cd5e9437 | ||
|
|
3785ad614f | ||
|
|
4e9b4064a6 | ||
|
|
319d8b96bb | ||
|
|
272824e236 | ||
|
|
4b3e80cadb | ||
|
|
f6675b67e8 | ||
|
|
6974324c9b | ||
|
|
c805106759 | ||
|
|
5448ac034b | ||
|
|
79667ae4b6 | ||
|
|
336a98e576 | ||
|
|
4e4dc47ad6 | ||
|
|
ee02e89fa7 | ||
|
|
7e6f5a7837 | ||
|
|
7b824bd13b | ||
|
|
146ad7b20a | ||
|
|
f657a088d4 | ||
|
|
c4ed8d0648 | ||
|
|
810a7d0a8f | ||
|
|
25d5f183c5 | ||
|
|
9052fe25db | ||
|
|
776115fbed | ||
|
|
962f0bc2c6 | ||
|
|
c184df717d | ||
|
|
26a7348d25 | ||
|
|
cf5052cbe5 | ||
|
|
be848123a1 | ||
|
|
04232b85a7 | ||
|
|
09bb84c34e | ||
|
|
4449992442 | ||
|
|
39c40f2e13 | ||
|
|
9813575584 | ||
|
|
b0af718cbc | ||
|
|
550544cbe4 | ||
|
|
3ec3cf0e5b | ||
|
|
0b79464e52 | ||
|
|
a1642c5749 | ||
|
|
148aab1495 | ||
|
|
2f78f2685f | ||
|
|
6dde5682a9 | ||
|
|
af8a3d89af | ||
|
|
ec97d1e84a | ||
|
|
eea412abd3 | ||
|
|
cf65ba3e6b | ||
|
|
3d4445bb46 | ||
|
|
94753ceac4 | ||
|
|
af16542ce5 | ||
|
|
e4c82441b8 | ||
|
|
8783802483 | ||
|
|
8ad28a16b0 | ||
|
|
f9403649e6 | ||
|
|
698af2ecc3 | ||
|
|
c92649a8d4 | ||
|
|
dfd1847a2d | ||
|
|
eeaafec80a | ||
|
|
896e91d4d9 | ||
|
|
d6507b428f | ||
|
|
6ff4d204c2 | ||
|
|
8145436d1d | ||
|
|
25f22b46c5 | ||
|
|
558d846812 | ||
|
|
05916031ad | ||
|
|
ffad6aa939 | ||
|
|
cb22a39ffc | ||
|
|
c6130dcffb | ||
|
|
c9f4143204 | ||
|
|
fa0e1d7d60 | ||
|
|
621b545e34 | ||
|
|
53e3d90064 | ||
|
|
c175826fd3 | ||
|
|
c6b584d637 | ||
|
|
d992ce87a9 | ||
|
|
a87072e542 | ||
|
|
eff0388b8f | ||
|
|
9c517810ba | ||
|
|
882cbddec0 | ||
|
|
d188272cbf | ||
|
|
72b3688365 | ||
|
|
0f81914875 | ||
|
|
e8e895d7b1 | ||
|
|
f0cc76f180 | ||
|
|
91b3f44c1e | ||
|
|
43859599f0 | ||
|
|
4dff0b1e6a | ||
|
|
f5fcee4e4a | ||
|
|
9ffb0b9a97 | ||
|
|
34698aca5e | ||
|
|
4fcf9fabbf | ||
|
|
fd907cf0cc | ||
|
|
cb543c7c98 | ||
|
|
02ee730080 | ||
|
|
5cccc5fedd | ||
|
|
9b6f4d1ecf | ||
|
|
022e8e9e73 | ||
|
|
a81581e67f | ||
|
|
5823f57e03 | ||
|
|
96f2233421 | ||
|
|
ac1a772b21 | ||
|
|
04851dbe39 | ||
|
|
29181469db | ||
|
|
cb447e13f9 | ||
|
|
04a3b1767a | ||
|
|
20f1a5c77e | ||
|
|
c979b48592 | ||
|
|
88ebc39d65 | ||
|
|
9aa3820e95 | ||
|
|
722ed6ade6 | ||
|
|
8f7448a095 | ||
|
|
5e9b3b56d4 | ||
|
|
95656b20d7 | ||
|
|
12fe8b46c3 | ||
|
|
92958f4b22 | ||
|
|
05a3bbef7a | ||
|
|
03467fcb83 | ||
|
|
e96c98e344 | ||
|
|
c660c5626d | ||
|
|
b443c7a5de | ||
|
|
578f3fee7a | ||
|
|
caddcd0e2b | ||
|
|
cce810d4e3 | ||
|
|
2f060e6209 | ||
|
|
df94c1ab59 | ||
|
|
9c2ed96331 | ||
|
|
b462e39a51 | ||
|
|
8340649292 | ||
|
|
1d2df695d3 | ||
|
|
f46ef394d9 | ||
|
|
fcf016ea85 | ||
|
|
e2ebba9f9f | ||
|
|
d9460df0ca | ||
|
|
9d988e18be | ||
|
|
949ee7da6e | ||
|
|
736f402179 | ||
|
|
e5c4eb6a8e | ||
|
|
c93233674b | ||
|
|
02abf0852e | ||
|
|
cf3e5ce9a3 | ||
|
|
da71454070 | ||
|
|
08a8575025 | ||
|
|
a99494b6ea | ||
|
|
52ab4fccbd | ||
|
|
2ab1599fa3 | ||
|
|
f220dde3b2 | ||
|
|
d027df8856 | ||
|
|
1dc979baaf | ||
|
|
f9908eaa57 | ||
|
|
8e8150e246 | ||
|
|
19fe83ed25 | ||
|
|
3c033a1f0d | ||
|
|
be031fb702 | ||
|
|
34a6c6d997 | ||
|
|
fa2c0d101f | ||
|
|
c3f6cef14e | ||
|
|
67bcb25106 | ||
|
|
6cfbce4f16 | ||
|
|
cc65a29b05 | ||
|
|
79d1cb7e87 | ||
|
|
925b0e75db | ||
|
|
85b6439d5f | ||
|
|
8d75d2e9c9 | ||
|
|
af7e2298b5 | ||
|
|
11fd851f21 | ||
|
|
2360a63fcb | ||
|
|
20e8433963 | ||
|
|
c655c1b90b | ||
|
|
215e542516 | ||
|
|
680ab2d92a | ||
|
|
c162c00c8d | ||
|
|
e5dfc2484b | ||
|
|
1962f47f81 | ||
|
|
6b9ea288d1 | ||
|
|
baeaec54c5 | ||
|
|
7272415ed4 | ||
|
|
c75d956c52 | ||
|
|
99d8084fe3 | ||
|
|
e61601fca2 | ||
|
|
0cfeabb0f2 | ||
|
|
d059646ebe | ||
|
|
553c5cd1c1 | ||
|
|
ba0a4f1bf9 | ||
|
|
614e8f0ccc | ||
|
|
428a905caa | ||
|
|
6193306255 | ||
|
|
b2913f9fa0 | ||
|
|
ce5ec1d961 | ||
|
|
96725d1730 | ||
|
|
eec018de3c | ||
|
|
f753d33731 | ||
|
|
ffd69fbc75 | ||
|
|
5997e67322 | ||
|
|
fe60370c0a | ||
|
|
cfee8e571e | ||
|
|
b4a7d3c879 | ||
|
|
9c1565dfcc | ||
|
|
a8b8573734 | ||
|
|
c09e559430 | ||
|
|
cbc1b85d92 | ||
|
|
d6f3ae7179 | ||
|
|
12c87aaa25 | ||
|
|
67a0230b7b | ||
|
|
539a6d420e | ||
|
|
f1baa7c0d2 | ||
|
|
36ac3776b7 | ||
|
|
a6b50631dc | ||
|
|
71fdedb2d9 | ||
|
|
f4be47a0d7 | ||
|
|
295400892a | ||
|
|
5c3d28033f | ||
|
|
229cb55b46 | ||
|
|
99fea8c2df | ||
|
|
1d7fd4fab1 | ||
|
|
76e1b7d320 | ||
|
|
0d4ca1b6a6 | ||
|
|
9050f33fcc | ||
|
|
8a1b151740 | ||
|
|
f088098159 | ||
|
|
d9462a2d17 | ||
|
|
eec72499e7 | ||
|
|
93016af766 | ||
|
|
5d699dff8f | ||
|
|
12e4f48460 | ||
|
|
68ad3cd407 | ||
|
|
c19c4d471d | ||
|
|
9cf5f23b5a | ||
|
|
b71d383c74 | ||
|
|
5086c3c82d | ||
|
|
d98c30506e | ||
|
|
6a4e5a121f | ||
|
|
15a8d2151e | ||
|
|
025672bd91 | ||
|
|
a925050912 | ||
|
|
a4a4fc344a | ||
|
|
bc1fc27a5d | ||
|
|
acfd88ec55 | ||
|
|
3745583e1c | ||
|
|
60f1a89984 | ||
|
|
cbfa2fc98c | ||
|
|
7c37a0bb05 | ||
|
|
699745526e | ||
|
|
ef9573a74d | ||
|
|
7efe8196a5 | ||
|
|
f1ed3f7438 | ||
|
|
30bdc0ee54 | ||
|
|
8c7217ad56 | ||
|
|
4f15bc257d | ||
|
|
4c25c5769a | ||
|
|
30a9225227 | ||
|
|
4a0d79b138 | ||
|
|
8856c984dc | ||
|
|
0198e635b3 | ||
|
|
f477411667 | ||
|
|
963aaa974e | ||
|
|
49bb23805e | ||
|
|
a1dea02498 | ||
|
|
e7eef7f169 | ||
|
|
072045ed59 | ||
|
|
9078c57909 | ||
|
|
abb15a9e28 | ||
|
|
2766751c79 | ||
|
|
d9df337ff0 | ||
|
|
5d2cfaf269 | ||
|
|
4a9b5ace01 | ||
|
|
e475ab6047 | ||
|
|
e2d78ff89e | ||
|
|
1260d29324 | ||
|
|
bed12304c0 | ||
|
|
c2ede383dd | ||
|
|
0e6f56230a | ||
|
|
ac7705442f | ||
|
|
b5a3ee19a4 | ||
|
|
29c8cc2062 | ||
|
|
098f314b83 | ||
|
|
5885aa759d | ||
|
|
c0dec7729c | ||
|
|
8d26d94b9f | ||
|
|
a207fc90dc | ||
|
|
13e0e4b5fa | ||
|
|
4c95bb8354 | ||
|
|
a4a39f643c | ||
|
|
744ee451cf | ||
|
|
c44af0d61e | ||
|
|
6cf385a6f0 | ||
|
|
c30d81dfa5 | ||
|
|
77a645bfe9 | ||
|
|
c6a0e87fdd | ||
|
|
990927d9d5 | ||
|
|
342db106fe | ||
|
|
43b56351ad | ||
|
|
a212a4fa90 | ||
|
|
1c7c79451d | ||
|
|
27a9d446ef | ||
|
|
0115e235c2 | ||
|
|
e838964860 | ||
|
|
8c2862cc80 | ||
|
|
445ba6ba20 | ||
|
|
5793094187 | ||
|
|
861333d748 | ||
|
|
75a45de060 | ||
|
|
b87485a56f | ||
|
|
8612f335ac | ||
|
|
cd56bc1fc0 | ||
|
|
bf768b970f | ||
|
|
1e083d0e64 | ||
|
|
2dc8141bbc | ||
|
|
a9bbc672c9 | ||
|
|
b51590e374 | ||
|
|
21f609053a | ||
|
|
0fe3e324cb | ||
|
|
921144c1f9 | ||
|
|
af2ab8f104 | ||
|
|
5c3539c820 | ||
|
|
6bdb758bc6 | ||
|
|
1d36c1b55d | ||
|
|
a4daa8b36d | ||
|
|
dd91b7c023 | ||
|
|
472716d06d | ||
|
|
5f34fa811c | ||
|
|
9538c364d4 | ||
|
|
b3f0c08e2c | ||
|
|
406ec89625 | ||
|
|
d0c930c080 | ||
|
|
85b3636cee | ||
|
|
d3a477425e | ||
|
|
62439f9e7d | ||
|
|
b0581c2f2b | ||
|
|
9dd7da7630 | ||
|
|
0e9edf0aba | ||
|
|
42583d306b | ||
|
|
11593091fd | ||
|
|
947da3d647 | ||
|
|
a6502a23af | ||
|
|
abeb6ea5a2 | ||
|
|
ff749f8892 | ||
|
|
2c3115dc47 | ||
|
|
d96729fb89 | ||
|
|
7b49fbc85c | ||
|
|
436936ff41 | ||
|
|
0f4c2c84d2 | ||
|
|
02f8f747e1 | ||
|
|
26d538adf2 | ||
|
|
ba3618d58a | ||
|
|
72568c3ae2 | ||
|
|
3f6b0447b9 | ||
|
|
be81bdf0b4 | ||
|
|
19340905db | ||
|
|
1f5cbd8579 | ||
|
|
bd0535fdc4 | ||
|
|
343bed6a6b | ||
|
|
816232d993 | ||
|
|
2ab8faa9eb | ||
|
|
144d105a13 | ||
|
|
f35b83368d | ||
|
|
00fb992f23 | ||
|
|
fec1f1ef43 | ||
|
|
83c36aff02 | ||
|
|
5f477f2665 | ||
|
|
ca74eea880 | ||
|
|
5808cbd0d9 | ||
|
|
50f9cb7405 | ||
|
|
b9e28dfdcd | ||
|
|
288f2fc920 | ||
|
|
1d42a2cf6c | ||
|
|
4fda2a4770 | ||
|
|
39169b338a | ||
|
|
d67a05b71d | ||
|
|
cdcf90c4c3 | ||
|
|
9fef39924e | ||
|
|
2f1584436a | ||
|
|
5041be7831 | ||
|
|
df19fc5ace | ||
|
|
9ce527aa3b | ||
|
|
ac27bb1fde | ||
|
|
d311dab698 | ||
|
|
5ab8c2b4f5 | ||
|
|
3729e81005 | ||
|
|
c3d0ead801 | ||
|
|
2658ef19a5 | ||
|
|
34e66e6a49 | ||
|
|
e9881fa9c5 | ||
|
|
da92de1990 | ||
|
|
1e2b527a80 | ||
|
|
7b71c0e343 | ||
|
|
658e64cbbc | ||
|
|
eabf8838c7 | ||
|
|
d3d4ef5e4d | ||
|
|
8239e553e7 | ||
|
|
83a24045be | ||
|
|
54b87db9c6 | ||
|
|
4961e580c5 | ||
|
|
a07be1ffd4 | ||
|
|
7c10dde089 | ||
|
|
04f74b6628 | ||
|
|
898374cdeb | ||
|
|
0db8688f19 | ||
|
|
286024739f | ||
|
|
771fb802ec | ||
|
|
9e34b35888 | ||
|
|
08a2abb773 | ||
|
|
dd904a863e | ||
|
|
15f5aa7d10 | ||
|
|
647f5a06be | ||
|
|
f501bab5d2 | ||
|
|
19539da8aa | ||
|
|
33173f88f3 | ||
|
|
a75febfeed | ||
|
|
d786adb604 | ||
|
|
96e147d26c | ||
|
|
1e66a624ef | ||
|
|
9bc93396d4 | ||
|
|
af307b7691 | ||
|
|
65c9539e80 | ||
|
|
16ca761e3d | ||
|
|
6e9c5a4300 | ||
|
|
7c2b556b0b | ||
|
|
4a0c1269cb | ||
|
|
7920c8acd1 | ||
|
|
4e8b5557fc | ||
|
|
50ae31a0b5 | ||
|
|
f6da92ee92 | ||
|
|
3482b68f29 | ||
|
|
e907784528 | ||
|
|
26dc615a8c | ||
|
|
aef54b9f83 | ||
|
|
f0a4006ef0 | ||
|
|
ab93bccb00 | ||
|
|
20c95a8a26 | ||
|
|
4adb5f074e | ||
|
|
6aa98b8de6 | ||
|
|
17214b41d5 | ||
|
|
80a75df458 | ||
|
|
d3ac8d3ab5 | ||
|
|
9e76cfecfd | ||
|
|
f26becc505 | ||
|
|
09ac9bee7a | ||
|
|
e728860dd4 | ||
|
|
6c52fcd555 | ||
|
|
7ad7177f89 | ||
|
|
870b60320f | ||
|
|
df3340afef | ||
|
|
b8e409e92b | ||
|
|
0fa8f36144 | ||
|
|
3cdec75079 | ||
|
|
6d4373ae14 | ||
|
|
0883012a67 | ||
|
|
c4a5f21869 | ||
|
|
da8bcffd0b | ||
|
|
bf53c30d24 | ||
|
|
fe1c59607f | ||
|
|
5d0915ffd6 | ||
|
|
061b962359 | ||
|
|
9449a90ec8 | ||
|
|
7b08134bc7 | ||
|
|
d627a263c3 | ||
|
|
d500bd047a | ||
|
|
590407d04a | ||
|
|
236d81de15 | ||
|
|
8c3e3ed309 | ||
|
|
7cf8201b48 | ||
|
|
b34f7ad5f0 | ||
|
|
850743e2ee | ||
|
|
e46c6f258a | ||
|
|
89cc11d9c5 | ||
|
|
355be3bddb | ||
|
|
a7e310b931 | ||
|
|
2b500784c4 | ||
|
|
79a62b4db9 | ||
|
|
f19df87ba0 | ||
|
|
b0ac76fa36 | ||
|
|
ec33987f74 | ||
|
|
7de8ae9892 | ||
|
|
ad6d1db28a | ||
|
|
83bee04e1d | ||
|
|
be25060134 | ||
|
|
8cb9fb8ce1 | ||
|
|
0d809bef04 | ||
|
|
8b2c115482 | ||
|
|
80af6a16a4 | ||
|
|
7bf85060c5 | ||
|
|
1a2960cbde | ||
|
|
afcc76b8af | ||
|
|
26029defb0 | ||
|
|
e1d19483ba | ||
|
|
e606d84700 | ||
|
|
19cedb10fc | ||
|
|
2536e6a8ae | ||
|
|
9430b00988 | ||
|
|
d04b93e417 | ||
|
|
5c3d8f6d87 | ||
|
|
eaab1529ec | ||
|
|
1a2ec3d257 | ||
|
|
83fa71a91d | ||
|
|
d160d0f3c6 | ||
|
|
e36f506336 | ||
|
|
d454771c77 | ||
|
|
4e478f2fc5 | ||
|
|
e036893436 | ||
|
|
84bff1aeac | ||
|
|
0a4b7dca0d | ||
|
|
ea1bc51430 | ||
|
|
610d2a171b | ||
|
|
a567152580 | ||
|
|
932efecd63 | ||
|
|
61195fa673 | ||
|
|
a0277b879b | ||
|
|
50f66d2949 | ||
|
|
cfea1a916c | ||
|
|
25085eb314 | ||
|
|
a703be64fc | ||
|
|
17eabd6cf4 | ||
|
|
0b5a4fe255 | ||
|
|
63a8edbced | ||
|
|
66a1906977 | ||
|
|
913b68f08d | ||
|
|
579a5a013a | ||
|
|
d59b7a9475 | ||
|
|
c0da3f0f8c | ||
|
|
658a0615d7 | ||
|
|
370ee15bdb | ||
|
|
7b42fd285e | ||
|
|
a7b9dce96c | ||
|
|
1dbce8ffd8 | ||
|
|
0fec3a7305 | ||
|
|
c906d0b423 | ||
|
|
dd7f371dc7 | ||
|
|
e3a164e2fa | ||
|
|
5232dcbb5a | ||
|
|
3a50793b49 | ||
|
|
255b211688 | ||
|
|
aefeceb65f | ||
|
|
94303230f9 | ||
|
|
2397f13edf | ||
|
|
beba077408 | ||
|
|
e76a8299ed | ||
|
|
43ebda6bb2 | ||
|
|
f38f0954c6 | ||
|
|
91bf4cbc54 | ||
|
|
f14937f18f | ||
|
|
d331eadd33 | ||
|
|
e7fa87f695 | ||
|
|
30d279ea3d | ||
|
|
4bb2ecdab1 | ||
|
|
bef79e3a9b | ||
|
|
ed1d521aa8 | ||
|
|
e360a9bc22 | ||
|
|
708650cb55 | ||
|
|
6a55b7cdde | ||
|
|
0b29647e9c | ||
|
|
aab0f0720b | ||
|
|
07fb68666a | ||
|
|
93210c35b9 | ||
|
|
075a84ab73 | ||
|
|
3af93ff4a5 | ||
|
|
679842b624 | ||
|
|
298fb819fb | ||
|
|
f6f3de6e4c | ||
|
|
70ec7ad4a5 | ||
|
|
1fc4030b6d | ||
|
|
ebf40bfe3a | ||
|
|
cd7f371e46 | ||
|
|
691d18f296 | ||
|
|
0b5cdd7e19 | ||
|
|
0e10a40bc9 | ||
|
|
bdf3e5a5fe | ||
|
|
83e3da58c7 | ||
|
|
ce4a09d2f8 | ||
|
|
4497b78b03 | ||
|
|
800ebb94f0 | ||
|
|
afc7165fe8 | ||
|
|
4f5a98eed1 | ||
|
|
19c4632605 | ||
|
|
d375b7abf6 | ||
|
|
d9cc58c332 | ||
|
|
1e68fe7c3c | ||
|
|
84025f9879 | ||
|
|
120c44e6ab | ||
|
|
85a90aba48 | ||
|
|
efadbeedf9 | ||
|
|
fd31b20ab9 | ||
|
|
81553b0065 | ||
|
|
28ba2bddd7 | ||
|
|
608833e2f4 | ||
|
|
909945b3f2 | ||
|
|
f23d6ae634 | ||
|
|
b0bb686a35 | ||
|
|
43876e2ceb | ||
|
|
c748bb8f50 | ||
|
|
80cda4960e | ||
|
|
52ccdd9dd0 | ||
|
|
8c018be9e6 | ||
|
|
fc9805d43e | ||
|
|
77d8b10062 | ||
|
|
2475d8810a | ||
|
|
a2e706ef07 | ||
|
|
fff90e5bc7 | ||
|
|
6fba3b3a10 | ||
|
|
b545d48d68 | ||
|
|
b66fc7e1fd | ||
|
|
eb73359281 | ||
|
|
341cf4fad2 | ||
|
|
d7dfeb8774 | ||
|
|
131cc0a40a | ||
|
|
f40d93f178 | ||
|
|
f1065e8592 | ||
|
|
4422a62f92 | ||
|
|
19ec8dae4d | ||
|
|
196276aa04 | ||
|
|
59e789603f | ||
|
|
a22d8e3aa8 | ||
|
|
9d11211cf2 | ||
|
|
fa9a034a9f | ||
|
|
4bf59eeffa | ||
|
|
0d640f307c | ||
|
|
aed47402c6 | ||
|
|
531bd3dad2 | ||
|
|
b29f34f4a8 | ||
|
|
68a877eff5 | ||
|
|
b34babc622 | ||
|
|
407d2b0c1c | ||
|
|
f4a317228b | ||
|
|
18e017419b | ||
|
|
67bd078c4c | ||
|
|
109e2c4d59 | ||
|
|
7f439573b3 | ||
|
|
b61ea10fe3 | ||
|
|
e0be3f1948 | ||
|
|
beda3ffe44 | ||
|
|
720fe3e5c0 | ||
|
|
fdc9093466 | ||
|
|
16e3a4c0d6 | ||
|
|
12c4f2e77b | ||
|
|
d825e3cf10 | ||
|
|
ed572de3ce | ||
|
|
1404be4cf6 | ||
|
|
d7c65efdc4 | ||
|
|
7dcb279a6b | ||
|
|
7783f41d19 | ||
|
|
cca13d0b03 | ||
|
|
93abeb0693 | ||
|
|
22b80d5d32 | ||
|
|
5a26a67dff | ||
|
|
4a669c284f | ||
|
|
c22deb8967 | ||
|
|
19fb5718aa | ||
|
|
8aa0a21d86 | ||
|
|
a7177df37f | ||
|
|
223520f35e | ||
|
|
665618490a | ||
|
|
43f1bfa49f | ||
|
|
e0ecf7a871 | ||
|
|
fa73631441 | ||
|
|
4d57191a6a | ||
|
|
79a0199234 | ||
|
|
22e77f7fd0 | ||
|
|
eb07edaa8f | ||
|
|
b76b23ed51 | ||
|
|
76b68e7c8a | ||
|
|
58536ef3f7 | ||
|
|
751a175673 | ||
|
|
3b83c8f14e | ||
|
|
15d3da7b01 | ||
|
|
65ae3ef6e7 | ||
|
|
c8e0457b67 | ||
|
|
d71e30bedc | ||
|
|
fd26415c2a | ||
|
|
ca80013212 | ||
|
|
09cce0c609 | ||
|
|
9a637ba1ea | ||
|
|
06151fa380 | ||
|
|
aea2511fa2 | ||
|
|
350e68d961 | ||
|
|
967a7f3205 | ||
|
|
aad2f47154 | ||
|
|
e3e5340251 | ||
|
|
c82d676742 | ||
|
|
a85ddaa3a9 | ||
|
|
1eba91d308 | ||
|
|
d16c20ce57 | ||
|
|
414d08146d | ||
|
|
aa5d86aab4 | ||
|
|
dba3e77aee | ||
|
|
4e91ea6f85 | ||
|
|
acadada245 | ||
|
|
5143e13ebe | ||
|
|
26308847d1 | ||
|
|
7932e08c12 | ||
|
|
a3ec341ac3 | ||
|
|
63d89d17a1 | ||
|
|
a7b8c1963b | ||
|
|
e8ebdbddb6 | ||
|
|
06274408dd | ||
|
|
45c7e14d25 | ||
|
|
955dcf11c7 | ||
|
|
f67bfce710 | ||
|
|
46832d9855 | ||
|
|
c6946229a8 | ||
|
|
749b8afded | ||
|
|
7a55131d1f | ||
|
|
b027c150e2 | ||
|
|
91fb5be6bd | ||
|
|
cfe9aa680d | ||
|
|
c415c8a220 | ||
|
|
a8e114da38 | ||
|
|
09a69a748c | ||
|
|
9742a58792 | ||
|
|
69c8f9fe8c | ||
|
|
fc4bf51b51 | ||
|
|
6a329196d6 | ||
|
|
2110eb59f9 | ||
|
|
61a385c2a0 | ||
|
|
0b0fba44e6 | ||
|
|
2219f2fcb9 | ||
|
|
2d3fd78144 | ||
|
|
1c0e7fe5f3 | ||
|
|
dd9ed664df | ||
|
|
db6fb718d8 | ||
|
|
d00098ae9a | ||
|
|
6c1b452314 | ||
|
|
b612eecad3 | ||
|
|
80c45d2cf7 | ||
|
|
daa7964436 | ||
|
|
8921e50b40 | ||
|
|
f86040ad9f | ||
|
|
829fea5a51 | ||
|
|
87b8c06e36 | ||
|
|
8c0ad9f220 | ||
|
|
62634d231c | ||
|
|
9eacd1fba2 | ||
|
|
708dea26df | ||
|
|
59e4f0f1d1 | ||
|
|
b6b78245e1 | ||
|
|
2294cd2788 | ||
|
|
246630f081 | ||
|
|
f22f26b11d | ||
|
|
04359c608d | ||
|
|
221b79c365 | ||
|
|
c15bd04c67 | ||
|
|
ad097a6fe3 | ||
|
|
2fd44e7fe5 | ||
|
|
6ce6b3979b | ||
|
|
2c12d247fb | ||
|
|
1efbc8a28c | ||
|
|
c5d45d0f0b | ||
|
|
f584f9c381 | ||
|
|
cd5715eac7 | ||
|
|
51cc1792d3 | ||
|
|
0b81eab636 | ||
|
|
937c19882c | ||
|
|
ab40f0d18d | ||
|
|
78eb1502cd | ||
|
|
c62e9c6136 | ||
|
|
550bd52e61 | ||
|
|
c66a946e00 | ||
|
|
977171a332 | ||
|
|
e3dacdd4a4 | ||
|
|
5096c1af91 | ||
|
|
1e2b206f13 | ||
|
|
cbed1e25cb | ||
|
|
2309e99d64 | ||
|
|
16de5046c5 | ||
|
|
2209bb5a78 | ||
|
|
b4f60bc3c9 | ||
|
|
490ce0c26a | ||
|
|
bab96a9c1a | ||
|
|
eb936c7d3f | ||
|
|
cfcc6c8cce | ||
|
|
9da304fd2b | ||
|
|
af16385c82 | ||
|
|
8c72c83c69 | ||
|
|
2f784a2392 | ||
|
|
f6b26aab80 | ||
|
|
80ca02a9ba | ||
|
|
36bb7b241b | ||
|
|
e6082a3012 | ||
|
|
7b24efd958 | ||
|
|
26ae722504 | ||
|
|
2279b05e4b | ||
|
|
35a424a78e | ||
|
|
eabba753a1 | ||
|
|
e70eea0271 | ||
|
|
97985bb2d3 | ||
|
|
e53340e5c7 | ||
|
|
d71e506c07 | ||
|
|
2f0807396d | ||
|
|
bc2a2b6d91 | ||
|
|
f7dfd16d9b | ||
|
|
b840268847 | ||
|
|
3433893aa0 | ||
|
|
aea5e4f680 | ||
|
|
ab5b67ce88 | ||
|
|
ebbe4b1d98 | ||
|
|
61f5262fab | ||
|
|
7e80fbc638 | ||
|
|
38d1722127 | ||
|
|
3021e9b710 | ||
|
|
5241f8b77e | ||
|
|
15d74333c3 | ||
|
|
1c6911dda5 | ||
|
|
530af69a6d | ||
|
|
424939b5f3 | ||
|
|
699fd7db45 | ||
|
|
db19797715 | ||
|
|
463613b877 | ||
|
|
524c946bc2 | ||
|
|
3afbf28843 | ||
|
|
bc60c63c70 | ||
|
|
8a76504bd1 | ||
|
|
25b8af236e | ||
|
|
925f12bf9d | ||
|
|
8cac8512ab | ||
|
|
634465ce1a | ||
|
|
5bbc3e3b1e | ||
|
|
0e9c9d4cfd | ||
|
|
823f580c73 | ||
|
|
53892e25d7 | ||
|
|
ae23b37759 | ||
|
|
7c01a1c31e | ||
|
|
661351911f | ||
|
|
a622b3dc0c | ||
|
|
fcc88e2ec5 | ||
|
|
de5a2349f5 | ||
|
|
bf58203fd2 | ||
|
|
706003cce6 | ||
|
|
8148013567 | ||
|
|
5509a2940c | ||
|
|
ab9787ad5e | ||
|
|
0d69a8a78e | ||
|
|
340ab46072 | ||
|
|
d72ad20e2a | ||
|
|
01d2cae045 | ||
|
|
e4102a76ab | ||
|
|
5c82d9d14c | ||
|
|
dd3a259dc0 | ||
|
|
4ce08a5a1a | ||
|
|
65d473b823 | ||
|
|
9c6b142524 | ||
|
|
dca4f497cc | ||
|
|
fbdbb80587 | ||
|
|
16966bce88 | ||
|
|
eb32e11a6e | ||
|
|
406ab2e4c4 | ||
|
|
e8e4bb4347 | ||
|
|
c949438745 | ||
|
|
b7723e944c | ||
|
|
7734396b81 | ||
|
|
808bbea62a | ||
|
|
bacf1bec37 | ||
|
|
d17b19689e | ||
|
|
3c6a67b532 | ||
|
|
42713b8aca | ||
|
|
313aa13d80 | ||
|
|
2a9172b9ef | ||
|
|
a6a77ca7b0 | ||
|
|
4575f2750b | ||
|
|
fd60dca5ab | ||
|
|
cd0dcca911 | ||
|
|
f4056d33a6 | ||
|
|
7f93088ffb | ||
|
|
dce5e2f702 | ||
|
|
9d8eec616f | ||
|
|
83eaf8e1e8 | ||
|
|
e952691a4a | ||
|
|
45b51de2e8 | ||
|
|
4c43c56ac5 | ||
|
|
3061abefc5 | ||
|
|
4f26bc46b7 | ||
|
|
823631516c | ||
|
|
6ce662c56e | ||
|
|
0e7a4950d1 | ||
|
|
0301aabee7 | ||
|
|
650d7be1c1 | ||
|
|
da32e46544 | ||
|
|
687f6ee0f8 | ||
|
|
d9084760a6 | ||
|
|
f2590a8c1d | ||
|
|
e0ead15223 | ||
|
|
130a0f460b | ||
|
|
a1708ca5a5 | ||
|
|
458b0aa3d3 | ||
|
|
43121fd53b | ||
|
|
fa085bc214 | ||
|
|
c9dc0c0da0 | ||
|
|
25d532ba0a | ||
|
|
952ce3d99e | ||
|
|
2b1c441ff9 | ||
|
|
7204a47d44 | ||
|
|
7e0e0447da | ||
|
|
5c069c1975 | ||
|
|
3222f019d9 | ||
|
|
6e84c116b6 | ||
|
|
94c1df1b3d | ||
|
|
9926d1a3bb | ||
|
|
53563c86fd | ||
|
|
1a96f9ed16 | ||
|
|
48eb4e792d | ||
|
|
663563aff2 | ||
|
|
78693b0b03 | ||
|
|
898df561bd | ||
|
|
846bc0b72c | ||
|
|
68fb60a7ee | ||
|
|
9054d63ce9 | ||
|
|
438968f390 | ||
|
|
ed4be3c94f | ||
|
|
b576a3dec2 | ||
|
|
ae4fde64f9 | ||
|
|
8b1620c663 | ||
|
|
9fbc07a3e0 | ||
|
|
9c7d3dba46 | ||
|
|
fa8d12e1e4 | ||
|
|
de77eaeb11 | ||
|
|
0f4d1a2835 | ||
|
|
ba139660eb | ||
|
|
3baa7d839e | ||
|
|
4f3f3009c7 | ||
|
|
a83897ecdd | ||
|
|
0dbddeead4 | ||
|
|
ff419a26a5 | ||
|
|
f00cdc7575 | ||
|
|
ae1411bae7 | ||
|
|
bb841a1254 | ||
|
|
9c121a951a | ||
|
|
05c688f725 | ||
|
|
e8014c0092 | ||
|
|
ead10720e8 | ||
|
|
b618c615db | ||
|
|
d73884ab8d | ||
|
|
2abd75fa92 | ||
|
|
aeb79c8bee | ||
|
|
67f93b98db | ||
|
|
f66e5fcffe | ||
|
|
4b27444fe7 | ||
|
|
c879c7e5ea | ||
|
|
45340fbddb | ||
|
|
4193a6a702 | ||
|
|
f06931be72 | ||
|
|
0a7c8351da | ||
|
|
aa7b535566 | ||
|
|
8dc206c126 | ||
|
|
492fd6f3f8 | ||
|
|
bc64c01d6c | ||
|
|
2da011cb7f | ||
|
|
26f5a116b6 | ||
|
|
ed671f1fad | ||
|
|
c19ad0de3e | ||
|
|
a7e88fbe30 | ||
|
|
0fe76c3692 | ||
|
|
5095c96a15 | ||
|
|
06aab6eefc | ||
|
|
0ecfe80a3e | ||
|
|
81d8ca097c | ||
|
|
981a18b584 | ||
|
|
e0d70bd70c | ||
|
|
48e1ff42b6 | ||
|
|
8d9f0427e8 | ||
|
|
f44b1a2971 | ||
|
|
88cb1d9473 | ||
|
|
0348018575 | ||
|
|
237c36a3b1 | ||
|
|
7a788b64c3 | ||
|
|
743a238a29 | ||
|
|
fb2370ee6a | ||
|
|
7ab97712f5 | ||
|
|
7f472d714b | ||
|
|
32e5ac4a30 | ||
|
|
e22c66c50b | ||
|
|
57439729ab | ||
|
|
b030592157 | ||
|
|
59d7345ea8 | ||
|
|
5e5214f994 | ||
|
|
cbf0ea1712 | ||
|
|
ce6d2f1612 | ||
|
|
784efc2cda | ||
|
|
1d95f5574b | ||
|
|
3dc29818eb | ||
|
|
6f4942ac38 | ||
|
|
f566af6f1b | ||
|
|
f51f5a966b | ||
|
|
fd56bc115a | ||
|
|
b473cf547c | ||
|
|
7bca62a5b6 | ||
|
|
57f76554de | ||
|
|
c68f037a81 | ||
|
|
4cd3b5d8da | ||
|
|
bacf79d547 | ||
|
|
ff72d3d6be | ||
|
|
fcbd341367 | ||
|
|
c124a6a6b8 | ||
|
|
556e0c3188 | ||
|
|
e6af31e438 | ||
|
|
c0ca8c1056 | ||
|
|
f0d3b5e6fc | ||
|
|
25d80976b6 | ||
|
|
2b3bfd637b | ||
|
|
e7c2250174 | ||
|
|
ee883d6a72 | ||
|
|
be0312d726 | ||
|
|
519c527cf4 | ||
|
|
d9b5998c07 | ||
|
|
64f8d1aa9e | ||
|
|
c886d89f7f | ||
|
|
6ddf4d0150 | ||
|
|
92825bf5a9 | ||
|
|
ac09c816e5 | ||
|
|
f845c9b013 | ||
|
|
1f2694b93b | ||
|
|
9eb41f298e | ||
|
|
8f2d1a4614 | ||
|
|
e873a0a5e7 | ||
|
|
7f6d0e54ac | ||
|
|
5fd440b2aa | ||
|
|
d9c5dbf92a | ||
|
|
d27c046380 | ||
|
|
b3439784b1 | ||
|
|
25351a7c0b | ||
|
|
8feac56493 | ||
|
|
cbae78b4b2 | ||
|
|
f333d00528 | ||
|
|
7f71fb9197 | ||
|
|
986179d7a0 | ||
|
|
cf3d45e142 | ||
|
|
441ddd0ab2 | ||
|
|
7c240eaa65 | ||
|
|
b09c6a68b2 | ||
|
|
83e090cb60 | ||
|
|
e6d3e219d6 | ||
|
|
91e5c2e751 | ||
|
|
f930834299 | ||
|
|
d9802191fa | ||
|
|
c3b80a7e11 | ||
|
|
21026daece | ||
|
|
a1d6e18509 | ||
|
|
bd859c1d62 | ||
|
|
8e055305a3 | ||
|
|
d641dfe37a | ||
|
|
575fc0324d | ||
|
|
a7579198bb | ||
|
|
1226be740a | ||
|
|
0358e1b994 | ||
|
|
14852ca2b7 | ||
|
|
60ed6e5d8e | ||
|
|
40c87ab093 | ||
|
|
9f1a6f4d47 | ||
|
|
3ad23d431f | ||
|
|
b619535339 | ||
|
|
68b234659a | ||
|
|
05173f69a7 | ||
|
|
3c5ce435b3 | ||
|
|
66b781d11b | ||
|
|
a234f565da | ||
|
|
4afbb065e6 | ||
|
|
6e09e3dc67 | ||
|
|
98e6c73b8f | ||
|
|
065b7f0e63 | ||
|
|
5e3a45c691 | ||
|
|
14645a2ec1 | ||
|
|
37c6abf4f0 | ||
|
|
f4b69cd5e2 | ||
|
|
364d6506b5 | ||
|
|
e3d516d6c2 | ||
|
|
6f42c3ce8f | ||
|
|
0fd700ce77 | ||
|
|
fdb52cb505 | ||
|
|
47bb1d948a | ||
|
|
d285627878 | ||
|
|
2884e61ccd | ||
|
|
c6d8aab825 | ||
|
|
db850d7f82 | ||
|
|
741570735f | ||
|
|
9d08ae3a00 | ||
|
|
0df61b41d4 | ||
|
|
e5fd01b0c6 | ||
|
|
6fdc48fd7f | ||
|
|
f881d6ef23 | ||
|
|
d7688dc8d8 | ||
|
|
bf0c17e640 | ||
|
|
33b5d65af1 | ||
|
|
2d38e738b3 | ||
|
|
775452604b | ||
|
|
91f04d156e | ||
|
|
7832b2cc69 | ||
|
|
a3d73da872 | ||
|
|
043123ff26 | ||
|
|
4bded05928 | ||
|
|
64accd8d08 | ||
|
|
877c3d9f31 | ||
|
|
32943dc9f6 | ||
|
|
384b4f00a6 | ||
|
|
28ec1068ca | ||
|
|
215b0c18e1 | ||
|
|
fea4cfaed1 | ||
|
|
10818c6d09 | ||
|
|
08d7c04a2d | ||
|
|
45ee316197 | ||
|
|
9f8d8f154f | ||
|
|
2ea7510925 | ||
|
|
42e6a8caaa | ||
|
|
204c93a5dc | ||
|
|
2f8e18af1f | ||
|
|
f54fd21054 | ||
|
|
733bdf8400 | ||
|
|
28f8ab52ef | ||
|
|
5bde17da2a | ||
|
|
813ad4afad | ||
|
|
673de26a8c | ||
|
|
321505c771 | ||
|
|
62e4317ee9 | ||
|
|
778e9cf049 | ||
|
|
5ef4a2d4c5 | ||
|
|
eb7496a09d | ||
|
|
5dd77c1535 | ||
|
|
e642e7d0aa | ||
|
|
2edd44192b | ||
|
|
9931df8b5a | ||
|
|
cdda509e9e | ||
|
|
e3e8a8f785 | ||
|
|
3daa06bcef | ||
|
|
eef4d42f32 | ||
|
|
11f7ccdf14 | ||
|
|
ce138cdd2a | ||
|
|
28cdc33f7c | ||
|
|
7ae16e19bb | ||
|
|
71bb6d6e98 | ||
|
|
c9390a0d3d | ||
|
|
a14fa7e2fe | ||
|
|
0b3d4c60b5 | ||
|
|
a41ce54e33 | ||
|
|
f4a22ad26d | ||
|
|
f3c67dd659 | ||
|
|
f18332664c | ||
|
|
3510ca0c3d | ||
|
|
3caef7c3ec | ||
|
|
9caccb652d | ||
|
|
12fb971185 | ||
|
|
ef05364c18 | ||
|
|
e423df62d7 | ||
|
|
55cf7f8309 | ||
|
|
3753c9aff5 | ||
|
|
6eeac511c6 | ||
|
|
f6731fac55 | ||
|
|
21977187ba | ||
|
|
208a5fe803 | ||
|
|
09178a81a9 | ||
|
|
c59210e9e0 | ||
|
|
3be6b0cd49 | ||
|
|
24b2800286 | ||
|
|
88dd8bc926 | ||
|
|
4355cdc7d0 | ||
|
|
dced6b399c | ||
|
|
ff4ff84b32 | ||
|
|
7e71403f06 | ||
|
|
7474df83d7 | ||
|
|
80dbda2f4b | ||
|
|
86d9eebd82 | ||
|
|
fecef982fa | ||
|
|
5afea3a224 | ||
|
|
244e2d0570 | ||
|
|
37738fbdf3 | ||
|
|
8dcd92d87a | ||
|
|
ca77ca3954 | ||
|
|
4c1f2c226a | ||
|
|
c999697645 | ||
|
|
2230b83c65 | ||
|
|
678238da6d | ||
|
|
073710d0e2 | ||
|
|
4d1350dc97 | ||
|
|
854515308b | ||
|
|
104bc50613 | ||
|
|
41248c9d08 | ||
|
|
35ba0b8dfc | ||
|
|
2699866f02 | ||
|
|
f4d5d6bdb6 | ||
|
|
b470b66943 | ||
|
|
0d49f9e914 | ||
|
|
9b6b781437 | ||
|
|
54f0d16767 | ||
|
|
5b6e5d05fc | ||
|
|
338f0f4e49 | ||
|
|
804b4f8ea0 | ||
|
|
93ff308786 | ||
|
|
7e5c1cae5c | ||
|
|
39d7d52b4d | ||
|
|
3627a7c556 | ||
|
|
b45cb45417 | ||
|
|
a91cf2a06f | ||
|
|
f9d99ea6b9 | ||
|
|
1b29de184d | ||
|
|
3355c3a4f2 | ||
|
|
78cf05f875 | ||
|
|
9815d063ae | ||
|
|
fecd27cab9 | ||
|
|
22632ae204 | ||
|
|
bfeeefaad8 | ||
|
|
9db195d649 | ||
|
|
7e6c8263b0 | ||
|
|
6fff867df0 | ||
|
|
6df12b8468 | ||
|
|
c03f0382ed | ||
|
|
83e4f4ee12 | ||
|
|
b333d182b6 | ||
|
|
88bfca6dc3 | ||
|
|
9ee30230bd | ||
|
|
e1fe5a4ba4 | ||
|
|
01ef455eb5 | ||
|
|
6b7c5868c2 | ||
|
|
8e6b80f2ab | ||
|
|
9c4a6b31ed | ||
|
|
f91faaa921 | ||
|
|
2c6e939bd9 | ||
|
|
5fc004a49e | ||
|
|
c4c2b89cae | ||
|
|
cc08d8161e | ||
|
|
4be20e5536 | ||
|
|
f093baf8b9 | ||
|
|
2a225d3621 | ||
|
|
0f11f6e2d9 | ||
|
|
e6e29d5f1b | ||
|
|
2278402a83 | ||
|
|
5d0e3ca3b2 | ||
|
|
c33258522c | ||
|
|
5f6cbf18a1 | ||
|
|
e1c360921c | ||
|
|
82b931e064 | ||
|
|
d3719daa47 | ||
|
|
2682365edb | ||
|
|
dbb531550b | ||
|
|
5b2e96b113 | ||
|
|
e157c4ee2c | ||
|
|
5871b2835c | ||
|
|
f459e53f92 | ||
|
|
1e668beb1a | ||
|
|
93632b3c86 | ||
|
|
6e8d06c0a9 | ||
|
|
3db7ef7e6a | ||
|
|
acaeea9efc | ||
|
|
b0a36829cd | ||
|
|
5483949df3 | ||
|
|
519adfb866 | ||
|
|
e8edab21ec | ||
|
|
7d4796aa85 | ||
|
|
3afcbc8e43 | ||
|
|
3bf518ece6 | ||
|
|
3be2c0d2c2 | ||
|
|
3fe14b6f78 | ||
|
|
463df1178d | ||
|
|
4490842cff | ||
|
|
6e623a26bc | ||
|
|
7b637be2fa | ||
|
|
de65a4cd86 | ||
|
|
194cab551f | ||
|
|
2a41ec9011 | ||
|
|
89f69976e0 | ||
|
|
ef902fc187 | ||
|
|
8c6e0aee94 | ||
|
|
15a8006b9e | ||
|
|
c1e9a10811 | ||
|
|
aafeca823a | ||
|
|
5195a48730 | ||
|
|
8b6d3140c8 | ||
|
|
f9c4563229 | ||
|
|
65446b19cb | ||
|
|
a537437046 | ||
|
|
0c3c9fdb05 | ||
|
|
2a875fa4e0 | ||
|
|
48713a3e17 | ||
|
|
8e98f9efd0 | ||
|
|
ea49c4ec12 | ||
|
|
f8210c3049 | ||
|
|
bc35c533a4 | ||
|
|
f01aaf5622 | ||
|
|
73162e2430 | ||
|
|
0e203d9633 | ||
|
|
8c3ab0f346 | ||
|
|
daf0a18c17 | ||
|
|
e9cc0b5032 | ||
|
|
636f901e89 | ||
|
|
416a19ca9d | ||
|
|
5026db9aaf | ||
|
|
658dc4f2fe | ||
|
|
68eaefefaa | ||
|
|
ad315c39a1 | ||
|
|
6c04a5b3b6 | ||
|
|
d5df65ab43 | ||
|
|
30cb62cd06 | ||
|
|
a2914f3ccd | ||
|
|
195532d14b | ||
|
|
66d6ef8e40 | ||
|
|
d06512160a | ||
|
|
6f936072d0 | ||
|
|
4c67792f08 | ||
|
|
edd79e055a | ||
|
|
8767158bd9 | ||
|
|
8c2db7db0d | ||
|
|
ea1ba91fed | ||
|
|
da65a23a79 | ||
|
|
8c59305ac4 | ||
|
|
f3b603130c | ||
|
|
ce4b09b067 | ||
|
|
becd0a1f2c | ||
|
|
8b3213cc8c | ||
|
|
2542cc90c4 | ||
|
|
f5a614c735 | ||
|
|
bd89cfb8f1 | ||
|
|
7dbba2b5ba | ||
|
|
8c187378e0 | ||
|
|
21adae7141 | ||
|
|
64a9a457db | ||
|
|
0588612adb | ||
|
|
3bf52b7ce3 | ||
|
|
0723f80051 | ||
|
|
1eec0afa8f | ||
|
|
802b59bcd2 | ||
|
|
4d9c8c3cea | ||
|
|
bd53dcb52c | ||
|
|
608d95b77f | ||
|
|
50505f8a7b | ||
|
|
c2dc51b9ed | ||
|
|
702cdaad4f | ||
|
|
ae11d47438 | ||
|
|
1e92e1bf20 | ||
|
|
a57109ac60 | ||
|
|
9704ecd9d2 | ||
|
|
415999bb58 | ||
|
|
6fa7f93e3d | ||
|
|
50f945a91b | ||
|
|
0688b995c6 | ||
|
|
5d8feadeb4 | ||
|
|
c4d1e80965 | ||
|
|
bdd375e876 | ||
|
|
0340e04f47 | ||
|
|
84e2037cff | ||
|
|
32aa147124 | ||
|
|
9fa97d94fc | ||
|
|
339232fea5 | ||
|
|
8be789062a | ||
|
|
b2c617f375 | ||
|
|
2897facf9d | ||
|
|
20d262b9fa | ||
|
|
db8d209c75 | ||
|
|
21dd70d4aa | ||
|
|
92f089ccad | ||
|
|
da117e3070 | ||
|
|
0c5e856240 | ||
|
|
c12e319ce0 | ||
|
|
71b0302333 | ||
|
|
e693009491 | ||
|
|
1abbcc8174 | ||
|
|
5f32de6c59 | ||
|
|
acad176c8c | ||
|
|
32b1a750d4 | ||
|
|
b0a146cda3 | ||
|
|
5375862093 | ||
|
|
8054af1dc9 | ||
|
|
d0b87def98 | ||
|
|
774dc4ac12 | ||
|
|
fddedc09f6 | ||
|
|
d6839f4884 | ||
|
|
0101ccb8f6 | ||
|
|
347a78f658 | ||
|
|
f869232f3b | ||
|
|
1758761085 | ||
|
|
1550eea5ac | ||
|
|
7e3fc0ac4d | ||
|
|
c0a475bc44 | ||
|
|
f72e9de980 | ||
|
|
51f2ec6d73 | ||
|
|
cea4dbf329 | ||
|
|
26aac3a1f5 | ||
|
|
3035175943 | ||
|
|
0c76ef6463 | ||
|
|
9e664837d9 | ||
|
|
93647dc748 | ||
|
|
89679a94b0 | ||
|
|
3be5897f5b | ||
|
|
961c69f318 | ||
|
|
865cdd8076 | ||
|
|
dba5e19b84 | ||
|
|
f4868585b5 | ||
|
|
4465bf8787 | ||
|
|
cebbd27ef6 | ||
|
|
0a9de9eaab | ||
|
|
3cdf1656d7 | ||
|
|
f85f31a46e | ||
|
|
f747b6aad7 | ||
|
|
865e10ef16 | ||
|
|
ea32037991 | ||
|
|
1c5c6bfdf1 | ||
|
|
239f940b28 | ||
|
|
b1884e4c05 | ||
|
|
6ec6d04fbc | ||
|
|
982fd1066b | ||
|
|
749e38d634 | ||
|
|
5a7d13202b | ||
|
|
52db2ba39e | ||
|
|
a8ff13dd60 | ||
|
|
078c8b74fa | ||
|
|
50b8b1e042 | ||
|
|
0a6e92075f | ||
|
|
173696f82e | ||
|
|
877a0f9f79 | ||
|
|
7b4f35caed | ||
|
|
6bee9ac8c0 | ||
|
|
c7968177e8 | ||
|
|
d8cf263bb7 | ||
|
|
85dc13771f | ||
|
|
312da5a73b | ||
|
|
23c44241ae | ||
|
|
4ab7210e26 | ||
|
|
4a8034d8fb | ||
|
|
04043e3fd8 | ||
|
|
26fd7183f7 | ||
|
|
7cfe74b84e | ||
|
|
d137d1db31 | ||
|
|
d837f90527 | ||
|
|
414328cf49 | ||
|
|
f7dddfdd80 | ||
|
|
18cc0e63ad | ||
|
|
1736fbd838 | ||
|
|
084afb6971 | ||
|
|
8a1173aaca | ||
|
|
e8c28e4728 | ||
|
|
07198b4ede | ||
|
|
2c2825a88f | ||
|
|
c70e9c4202 | ||
|
|
b19a47d044 | ||
|
|
def80dcf76 | ||
|
|
7683887387 | ||
|
|
dda86d9975 | ||
|
|
27c15fab46 | ||
|
|
5a182bf07b | ||
|
|
abf8c0b0dd | ||
|
|
0ec7e45179 | ||
|
|
a74859c2d2 | ||
|
|
dfa8e94e26 | ||
|
|
53232d4a63 | ||
|
|
b671ea0b03 | ||
|
|
92ef685474 | ||
|
|
bf25d9c716 | ||
|
|
36ae4e06b9 | ||
|
|
f9b6addafd | ||
|
|
8312942ffd | ||
|
|
8293d80004 | ||
|
|
ee365eaa1e | ||
|
|
11fa26e68a | ||
|
|
f23bb2f096 | ||
|
|
5c10d1548b | ||
|
|
4664d7d2e7 | ||
|
|
f49756f839 | ||
|
|
57aa15a710 | ||
|
|
0edd316195 | ||
|
|
a246c39be3 | ||
|
|
3d7173d50f | ||
|
|
2ed4c608a0 | ||
|
|
d4c35a255c | ||
|
|
b5b75ac967 | ||
|
|
e30d36b93a | ||
|
|
d56f3e8221 | ||
|
|
c491b47114 | ||
|
|
61ba54066c | ||
|
|
4dba96683f | ||
|
|
bb4d344737 | ||
|
|
75e6cb9d3f | ||
|
|
9b7aebd9fa | ||
|
|
63c5967b6f | ||
|
|
60b7913c7a | ||
|
|
c8a9e73b8b | ||
|
|
8a4c18df43 | ||
|
|
b15d158617 | ||
|
|
972de14e20 | ||
|
|
3332c7e23c | ||
|
|
647129bbf2 | ||
|
|
ca2f2cc24f | ||
|
|
84c68da6f6 | ||
|
|
014741e25a | ||
|
|
df4493a5c3 | ||
|
|
e59f2747b1 | ||
|
|
23c0690fd4 | ||
|
|
a508c587cb | ||
|
|
42d0bf9d99 | ||
|
|
2d4413e7c7 | ||
|
|
b8ea8ed625 | ||
|
|
602fb4fa4f | ||
|
|
e249bcca5f | ||
|
|
694779d9ff | ||
|
|
9af1bec78b | ||
|
|
3eaad281d3 | ||
|
|
808fd95783 | ||
|
|
5d4b0b684c | ||
|
|
2b5c737377 | ||
|
|
512e6fecdb | ||
|
|
9a34cb0cff | ||
|
|
d8ea34d88a | ||
|
|
7b8b3c10a6 | ||
|
|
4cab1ad4a3 | ||
|
|
6f7b3def90 | ||
|
|
7dc05b3065 | ||
|
|
d42fad4281 | ||
|
|
81bc59ff7a | ||
|
|
a02281fb7a | ||
|
|
e609675349 | ||
|
|
fd220eb19f | ||
|
|
1434323130 | ||
|
|
c4c9a0a46d | ||
|
|
08103ab552 | ||
|
|
e8b068e5a0 | ||
|
|
cc8cc57a48 | ||
|
|
d2093cc9d6 | ||
|
|
e05c14a2ce | ||
|
|
68217ad2bb | ||
|
|
b86c8fc083 | ||
|
|
7bf7a0a70b | ||
|
|
6da59ab62c | ||
|
|
0a8632381d | ||
|
|
3f45c80f60 | ||
|
|
b1d7c81ee1 | ||
|
|
890e09ac69 | ||
|
|
f6a4a873fd | ||
|
|
267b8ed977 | ||
|
|
f5e9ea81bf | ||
|
|
c97990217c | ||
|
|
deb70faa8a | ||
|
|
581c542848 | ||
|
|
7fd5eb4c8e | ||
|
|
3a4c9d7bd4 | ||
|
|
0d019d6ab7 | ||
|
|
255d6bbb9d | ||
|
|
4a7032fb1b | ||
|
|
e2a58242f9 | ||
|
|
00887b3889 | ||
|
|
4da22194af | ||
|
|
2a9edff9c3 | ||
|
|
8d0e6484b9 | ||
|
|
cfa15b59f6 | ||
|
|
fddb74ca26 | ||
|
|
d5a3fd47a7 | ||
|
|
c896d61016 | ||
|
|
5cf9eced6b | ||
|
|
749d5bba02 | ||
|
|
6f5c6fa51c | ||
|
|
d5699fdd05 | ||
|
|
395526027b | ||
|
|
a6dd070b4e | ||
|
|
7013638631 | ||
|
|
136906ff1a | ||
|
|
36c8d2517a | ||
|
|
a2101328e7 | ||
|
|
d96e14a154 | ||
|
|
3be12ad944 | ||
|
|
0716388141 | ||
|
|
1260a1e9f8 | ||
|
|
56ddf5b8b9 | ||
|
|
725307c022 | ||
|
|
8a94ea3d82 | ||
|
|
90d17ef359 | ||
|
|
f866db3097 | ||
|
|
7f13b79547 | ||
|
|
42d22dd514 | ||
|
|
b521e9dea0 | ||
|
|
6f38011312 | ||
|
|
f1bc141a4e | ||
|
|
0236459495 | ||
|
|
5c892a6fd6 | ||
|
|
e5e3ba7df2 | ||
|
|
7a6eabfda0 | ||
|
|
f2a14194bc | ||
|
|
0f405c812c | ||
|
|
b1da89717d | ||
|
|
57aa5701ad | ||
|
|
c43264f71c | ||
|
|
bc0e4d5633 | ||
|
|
aaff8be246 | ||
|
|
e84b73c6ec | ||
|
|
4ee7455169 | ||
|
|
b773cb2d25 | ||
|
|
5c141d3bbe | ||
|
|
7a2a9237f7 | ||
|
|
c38c94cd36 | ||
|
|
75fb2045db | ||
|
|
1aafe81b37 | ||
|
|
ca5798e244 | ||
|
|
3458b0a642 | ||
|
|
8d905cf94d | ||
|
|
768eac723d | ||
|
|
da03e220ed | ||
|
|
1985d4df51 | ||
|
|
a28d2c05b3 | ||
|
|
7b77e8c234 | ||
|
|
cc667c13bb | ||
|
|
ca4803fda2 | ||
|
|
df058030b0 | ||
|
|
d31db9f430 | ||
|
|
6d1d7ed65c | ||
|
|
b2f3e58b59 | ||
|
|
824f3babc4 | ||
|
|
349259a3bd | ||
|
|
e2af856a24 | ||
|
|
9debb4a4e2 | ||
|
|
f68f4ae9fa | ||
|
|
c532123a2c | ||
|
|
4d196aa4eb | ||
|
|
6e76c0d48e | ||
|
|
25270474e7 | ||
|
|
97ddbac01e | ||
|
|
fd55d3a65e | ||
|
|
ca8c1b5f6b | ||
|
|
ec5f494ba5 | ||
|
|
152feb010f | ||
|
|
c93e568ea1 | ||
|
|
31b3d67974 | ||
|
|
a969ed775e | ||
|
|
3ea3f54286 | ||
|
|
c241545bd1 | ||
|
|
196a0c309a | ||
|
|
288737aed3 | ||
|
|
edc3329f5a | ||
|
|
6813eadced | ||
|
|
5a069e5fce | ||
|
|
7189cc31d1 | ||
|
|
d1570d2079 | ||
|
|
1f60ee2eb9 | ||
|
|
c9d078047e | ||
|
|
76fce84661 | ||
|
|
ecf4437cf6 | ||
|
|
c04ad8fd4d | ||
|
|
56c2b16916 | ||
|
|
e6d03dc5ea | ||
|
|
d2998d42f3 | ||
|
|
af31afac17 | ||
|
|
73fa821f19 | ||
|
|
f83e0bc88c | ||
|
|
2d1a5aad44 | ||
|
|
fdd18e656c | ||
|
|
7d2d0a1af4 | ||
|
|
77cccd225f | ||
|
|
bb591b8fca | ||
|
|
81b59440eb | ||
|
|
9809e75b33 | ||
|
|
c588ed7784 | ||
|
|
21d9b67086 | ||
|
|
774815966b | ||
|
|
f6bf2d21ee | ||
|
|
1b9f5bf0b9 | ||
|
|
39655965e8 | ||
|
|
faecc6f857 | ||
|
|
edbc5279b3 | ||
|
|
2aa7acad6a | ||
|
|
a74c05be60 | ||
|
|
038cb6c7a8 | ||
|
|
7e33832197 | ||
|
|
1e83a3efbe | ||
|
|
732bc9e4aa | ||
|
|
d05ff90031 | ||
|
|
f36050882f | ||
|
|
07bcddf7b5 | ||
|
|
efaa5d1106 | ||
|
|
2f4f8bd95c | ||
|
|
ddc92958ac | ||
|
|
c4b254b26c | ||
|
|
ce9efd3f28 | ||
|
|
e06099f1a4 | ||
|
|
3d67ebf6f1 | ||
|
|
f33bc7ee50 | ||
|
|
624eb87467 | ||
|
|
1bdbaa5c31 | ||
|
|
63d65c3679 | ||
|
|
4ef6cc7d3e | ||
|
|
7ebaf68117 | ||
|
|
0b0f0706b7 | ||
|
|
b8924fbf43 | ||
|
|
f043d9a019 | ||
|
|
038cfc6862 | ||
|
|
0e33288a2a | ||
|
|
c3682f2c05 | ||
|
|
0c5e7430f6 | ||
|
|
ae89a4e3db | ||
|
|
dffa0e3627 | ||
|
|
2d384debd6 | ||
|
|
3cc35fef03 | ||
|
|
f3c8e9024f | ||
|
|
9c175efa5f | ||
|
|
84777be5cf | ||
|
|
484ffda3ef | ||
|
|
5643da6693 | ||
|
|
5c0b057e4c | ||
|
|
6d6c3073fb | ||
|
|
fe3915be9f | ||
|
|
a1ded4ff38 | ||
|
|
2be18e4b56 | ||
|
|
91613997d3 | ||
|
|
ad9defeeb9 | ||
|
|
774ed0a30f | ||
|
|
be565cbc74 | ||
|
|
be4c91b2a7 | ||
|
|
9a3ca38b7a | ||
|
|
f3c2df64c9 | ||
|
|
3b101a9e1a | ||
|
|
e4c12f575b | ||
|
|
211fd78dc7 | ||
|
|
60971792ec | ||
|
|
77e0dad4a2 | ||
|
|
4783dfbd48 | ||
|
|
7dc22689d6 | ||
|
|
740206fd08 | ||
|
|
853e49a231 | ||
|
|
86496869c5 | ||
|
|
dfb96c735d | ||
|
|
7023635c2d | ||
|
|
90cde380d2 | ||
|
|
8c98fbb564 | ||
|
|
60a794a6ab | ||
|
|
3b23a6af7b | ||
|
|
ee4ccd9e84 | ||
|
|
4c8006c836 | ||
|
|
f4c9fe355a | ||
|
|
283803d55a | ||
|
|
a8016b0c7d | ||
|
|
bf75dc5db7 | ||
|
|
16dfcab4a7 | ||
|
|
62acbdecc5 | ||
|
|
6e2ff83336 | ||
|
|
66a2fd772a | ||
|
|
aca691fe2e | ||
|
|
9c4f2b8395 | ||
|
|
d529ed0b17 | ||
|
|
c5e73bf578 | ||
|
|
9aa9e2155b | ||
|
|
c7407c5036 | ||
|
|
7bd2e51148 | ||
|
|
8c988f0917 | ||
|
|
3b19f5c6ab | ||
|
|
79a1a5befc | ||
|
|
b2496e1c57 | ||
|
|
6a5546d0f2 | ||
|
|
c72de1f08b | ||
|
|
1ac67cf1e5 | ||
|
|
ad1cb0ff5d | ||
|
|
0270216f49 | ||
|
|
881ee9d8c7 | ||
|
|
6cd15f8eba | ||
|
|
03e4bcf760 | ||
|
|
a3c53096ad | ||
|
|
39de228eff | ||
|
|
7597832cbf | ||
|
|
cc69a0a24e | ||
|
|
29160abb97 | ||
|
|
a68d9bc906 | ||
|
|
2bf7987280 | ||
|
|
3e81c825cf | ||
|
|
342dd04452 | ||
|
|
9bc9be8538 | ||
|
|
41791981d7 | ||
|
|
3fb6cd29f7 | ||
|
|
c2d021104c | ||
|
|
4b3aedc685 | ||
|
|
0454d7e687 | ||
|
|
cfdf151b56 | ||
|
|
6cd85bcb58 | ||
|
|
be05cf7fdd | ||
|
|
e4a58baba0 | ||
|
|
1620df76b9 | ||
|
|
a1c7167e50 | ||
|
|
6e7925a18c | ||
|
|
053e28483e | ||
|
|
b5d7f084f2 | ||
|
|
1c1a6c05c2 | ||
|
|
3ebe35a0f6 | ||
|
|
bd0d9765fd | ||
|
|
b8faf2f2d6 | ||
|
|
eb280d4533 | ||
|
|
720efdb3a4 | ||
|
|
994ff7b31a | ||
|
|
cc55656b76 | ||
|
|
5f1733e147 | ||
|
|
d9c25dacf3 | ||
|
|
a762c6b1b4 | ||
|
|
570f237399 | ||
|
|
cea4d9e4fb | ||
|
|
1518c0e41b | ||
|
|
8ac66c12cb | ||
|
|
8a2df5d060 | ||
|
|
65aa27e64f | ||
|
|
6e78b4bacd | ||
|
|
b3509b510e | ||
|
|
e143067a52 | ||
|
|
b1a5e0827a | ||
|
|
c7549b8594 | ||
|
|
a79e84fad8 | ||
|
|
c9d7faf9a1 | ||
|
|
d87ceb1f74 | ||
|
|
c8fa18ed29 | ||
|
|
87885cb0bd | ||
|
|
ad929324df | ||
|
|
ee2805332b | ||
|
|
c1c2f3c41f | ||
|
|
a618ff0b63 | ||
|
|
47e468b585 | ||
|
|
891d2723c8 | ||
|
|
1b65354900 | ||
|
|
5a8c6111ff | ||
|
|
fd1e2bfd84 | ||
|
|
e388ca553e | ||
|
|
cf6fbf9799 | ||
|
|
56a2fce2b3 | ||
|
|
87397a9c1a | ||
|
|
8c2a7c0800 | ||
|
|
a177c78dda | ||
|
|
5a8b9a8c12 | ||
|
|
8859265986 | ||
|
|
eadbbff776 | ||
|
|
91541e7282 | ||
|
|
bad1a4de6a | ||
|
|
6a7cc2f5c5 | ||
|
|
fa2da7d37b | ||
|
|
442c4a7b92 | ||
|
|
ab62bc5de8 | ||
|
|
aae2039f3b | ||
|
|
607c770d7d | ||
|
|
eafff18078 | ||
|
|
66973323e9 | ||
|
|
e86c3a9355 | ||
|
|
4d2d653cfa | ||
|
|
685e401e2d | ||
|
|
6f99586bd5 | ||
|
|
918298f5fa | ||
|
|
9dd0d00cd7 | ||
|
|
c491896291 | ||
|
|
15264399d3 | ||
|
|
cb80c8d02c | ||
|
|
1b02f2a9d3 | ||
|
|
7fd7c2625b | ||
|
|
c885942690 | ||
|
|
118a987b4e | ||
|
|
6b91b232ac | ||
|
|
69556e3f06 | ||
|
|
6e435685e4 | ||
|
|
2da58b28d9 | ||
|
|
9139c5e135 | ||
|
|
b23b58925c | ||
|
|
17785bf0d4 | ||
|
|
e78c2fa8a0 | ||
|
|
ef656eef67 | ||
|
|
283f3da39d | ||
|
|
a36f0cc0a3 | ||
|
|
a2194ef191 | ||
|
|
f6f36eba23 | ||
|
|
259266d138 | ||
|
|
30eb82cca7 | ||
|
|
f87ebc2e55 | ||
|
|
23535b63aa | ||
|
|
eb80bd8447 | ||
|
|
a63fa7cebd | ||
|
|
d239ddf651 | ||
|
|
469340a305 | ||
|
|
77e771980c | ||
|
|
294712f6e0 | ||
|
|
2e6f7a828b | ||
|
|
6475f509f6 | ||
|
|
2e3bcf3cf4 | ||
|
|
1e7ffce711 | ||
|
|
ebd0d31948 | ||
|
|
203fd91b5f | ||
|
|
386dd9263d | ||
|
|
9c779e4027 | ||
|
|
98666063ce | ||
|
|
50aa8716ae | ||
|
|
3fa8fc8fd1 | ||
|
|
407a812ce4 | ||
|
|
8ed6d60ad5 | ||
|
|
22d6cae3a6 | ||
|
|
96b9f8cf16 | ||
|
|
7647503cc6 | ||
|
|
8d3d095500 | ||
|
|
0aaf1d8f40 | ||
|
|
10cc8e75b8 | ||
|
|
2409651dc7 | ||
|
|
31a4774ba0 | ||
|
|
543cf21354 | ||
|
|
f13a3e4782 | ||
|
|
dee2f77151 | ||
|
|
72bebedd70 | ||
|
|
9c4ea77045 | ||
|
|
57be60e452 | ||
|
|
cef1fa1e6f | ||
|
|
653a0f8b51 | ||
|
|
21d91b99d5 | ||
|
|
fcaf694f0a | ||
|
|
c45344f6b2 | ||
|
|
245528a548 | ||
|
|
8a3271a3de | ||
|
|
e0115348a4 | ||
|
|
59405c41f6 | ||
|
|
f6a4e3e413 | ||
|
|
f701c7dd46 | ||
|
|
c868ccc761 | ||
|
|
d48cc25f96 | ||
|
|
9fdcc5bfad | ||
|
|
bc6e5774c6 | ||
|
|
f7d951d95e | ||
|
|
c1c51eb45c | ||
|
|
b08fab4266 | ||
|
|
7a645d3b94 | ||
|
|
fb751b0094 | ||
|
|
807928c67a | ||
|
|
b1f1fe4133 | ||
|
|
bec683c654 | ||
|
|
7885ed3207 | ||
|
|
27a3b02ae3 | ||
|
|
86817060f3 | ||
|
|
74053040bc | ||
|
|
321470797b | ||
|
|
86cde05804 | ||
|
|
d011bebba5 | ||
|
|
470c58a165 | ||
|
|
0a02bfca1d | ||
|
|
76afd571df | ||
|
|
1dbdd0b5d4 | ||
|
|
1bcbaca4bc | ||
|
|
03f77de3d7 | ||
|
|
93359a8f10 | ||
|
|
bbb476329f | ||
|
|
0c74a80c56 | ||
|
|
f588e23b7a | ||
|
|
03e46f33a7 | ||
|
|
72236cbec2 | ||
|
|
ccaefc4a03 | ||
|
|
4bdff93db9 | ||
|
|
0b706743b8 | ||
|
|
5f16f8ec64 | ||
|
|
3e6733f75b | ||
|
|
e54c842c48 | ||
|
|
2187775833 | ||
|
|
9ffe988573 | ||
|
|
a0470d24f7 | ||
|
|
c1b12297bb | ||
|
|
e96826c175 | ||
|
|
aa587de5ac | ||
|
|
47e9518353 | ||
|
|
b8c717a071 | ||
|
|
9c6e1e063c | ||
|
|
91f52b22cd | ||
|
|
f15cbbaf93 | ||
|
|
8d68647d45 | ||
|
|
6a34553c9f | ||
|
|
8df2ee5018 | ||
|
|
006a124e4b | ||
|
|
b0a42948c8 | ||
|
|
6795bc560e | ||
|
|
8c25634fd0 | ||
|
|
53d8213002 | ||
|
|
7f8b31f8f3 | ||
|
|
d8e04dd50d | ||
|
|
3f83e2c08d | ||
|
|
60c3cbc44d | ||
|
|
5d3a503d86 | ||
|
|
46f85de55c | ||
|
|
36a2770d1d | ||
|
|
fb6c69fd89 | ||
|
|
5aa9e26be7 | ||
|
|
affdf6fe05 | ||
|
|
3a571ab3f9 | ||
|
|
0bda33a327 | ||
|
|
a012599f27 | ||
|
|
e382e1a562 | ||
|
|
1fd09e5ded | ||
|
|
6930f44633 | ||
|
|
cccf7d1d70 | ||
|
|
7aa258ac9e | ||
|
|
03bb8c3484 | ||
|
|
98ccc48424 | ||
|
|
8c246803ad | ||
|
|
b0eae87a5d | ||
|
|
03e441f5af | ||
|
|
4f16bef6e3 | ||
|
|
e9061b4ef0 | ||
|
|
3e387a3390 | ||
|
|
ba7be52b85 | ||
|
|
a2c35ec67b | ||
|
|
4ab9603238 | ||
|
|
c8e22cb19c | ||
|
|
f41a7142e3 | ||
|
|
720e6c293e | ||
|
|
24c4df5b9f | ||
|
|
f23140cba5 | ||
|
|
613c928ec4 | ||
|
|
0f80935e76 | ||
|
|
ce43e0261e | ||
|
|
0dd86af01d | ||
|
|
bf8a11ea08 | ||
|
|
46cbda0357 | ||
|
|
2f42c6c8c8 | ||
|
|
923e8a1dd4 | ||
|
|
50694b1e26 | ||
|
|
1d09cf0dc2 | ||
|
|
d3e61d5ab8 | ||
|
|
4add376957 | ||
|
|
86e802f4b8 | ||
|
|
1bddf2b4f1 | ||
|
|
6b8423e5c5 | ||
|
|
3717f56665 | ||
|
|
45fca71f3b | ||
|
|
f8faffca41 | ||
|
|
93e9b232cf | ||
|
|
18df1c7a96 | ||
|
|
cdeade29d7 | ||
|
|
235023ae9f | ||
|
|
aadf5efc5e | ||
|
|
04389de476 | ||
|
|
a2da0da586 | ||
|
|
969e5d74e5 | ||
|
|
1fbbe1161b | ||
|
|
711cb2cce7 | ||
|
|
8226bd69f5 | ||
|
|
157d1f8942 | ||
|
|
e50afa3306 | ||
|
|
baa8b21a15 | ||
|
|
6ac461be61 | ||
|
|
1b46534bf0 | ||
|
|
ed59777e04 | ||
|
|
fe300effa8 | ||
|
|
489dc9a014 | ||
|
|
9c5c4b4880 | ||
|
|
3b26c27a80 | ||
|
|
e5732e70b7 | ||
|
|
91939a0fc9 | ||
|
|
91432a649b | ||
|
|
9b94d716e7 | ||
|
|
a618beb8e6 | ||
|
|
e9bef54215 |
7
.browserslistrc
Normal file
7
.browserslistrc
Normal file
@@ -0,0 +1,7 @@
|
||||
last 1 Chrome version
|
||||
last 1 Firefox version
|
||||
last 2 Edge major versions
|
||||
last 2 iOS major versions
|
||||
safari > 11
|
||||
Firefox ESR
|
||||
not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line.
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -5,6 +5,8 @@
|
||||
/tmp
|
||||
/out-tsc
|
||||
|
||||
/
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
@@ -31,9 +33,11 @@ speed-measure-plugin.json
|
||||
.history/*
|
||||
|
||||
# misc
|
||||
/.angular/cache
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage
|
||||
/testresults
|
||||
/libpeerconnection.log
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
@@ -45,4 +49,5 @@ testem.log
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
libs/swagger/src/lib/*
|
||||
libs/swagger/src/lib/*
|
||||
*storybook.log
|
||||
1
.husky/pre-commit
Normal file
1
.husky/pre-commit
Normal file
@@ -0,0 +1 @@
|
||||
npm run pretty-quick
|
||||
14
.npmrc
14
.npmrc
@@ -1,13 +1 @@
|
||||
registry=https://pkgs.dev.azure.com/hugendubel/_packaging/hugendubel%40Local/npm/registry/
|
||||
|
||||
always-auth=true
|
||||
; Treat this auth token like a password. Do not share it with anyone, including Microsoft support. This token expires on or before 25.08.2020.
|
||||
; begin auth token
|
||||
//pkgs.dev.azure.com/hugendubel/_packaging/hugendubel%40Local/npm/registry/:username=hugendubel
|
||||
//pkgs.dev.azure.com/hugendubel/_packaging/hugendubel%40Local/npm/registry/:_password=M2JkaDdwNjIzbWVoZGlmeDU3N2Ficjc3M252NXBkaWg1M2VtaW94dXp5amwyejNkaW5yYQ==
|
||||
//pkgs.dev.azure.com/hugendubel/_packaging/hugendubel%40Local/npm/registry/:email=npm requires email to be set but doesn't use the value
|
||||
//pkgs.dev.azure.com/hugendubel/_packaging/hugendubel%40Local/npm/:username=hugendubel
|
||||
//pkgs.dev.azure.com/hugendubel/_packaging/hugendubel%40Local/npm/:_password=M2JkaDdwNjIzbWVoZGlmeDU3N2Ficjc3M252NXBkaWg1M2VtaW94dXp5amwyejNkaW5yYQ==
|
||||
//pkgs.dev.azure.com/hugendubel/_packaging/hugendubel%40Local/npm/:email=npm requires email to be set but doesn't use the value
|
||||
; end auth token
|
||||
|
||||
@paragondata:registry=https://npm.pkg.github.com
|
||||
10
.prettierignore
Normal file
10
.prettierignore
Normal file
@@ -0,0 +1,10 @@
|
||||
# Add files here to ignore them from prettier formatting
|
||||
|
||||
/dist
|
||||
/coverage
|
||||
/helmvalues
|
||||
/apps/swagger
|
||||
/ng-swagger-gen
|
||||
|
||||
*.json
|
||||
*.yml
|
||||
5
.prettierrc.json
Normal file
5
.prettierrc.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"printWidth": 140
|
||||
}
|
||||
|
||||
7
.vscode/extensions.json
vendored
Normal file
7
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"johnpapa.angular2",
|
||||
"esbenp.prettier-vscode",
|
||||
"angular.ng-template",
|
||||
]
|
||||
}
|
||||
35
.vscode/launch.json
vendored
35
.vscode/launch.json
vendored
@@ -1,22 +1,15 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.11.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"name": "Launch Chrome",
|
||||
"url": "https://192.168.2.112:4200",
|
||||
"webRoot": "${workspaceFolder}",
|
||||
"sourceMaps": true,
|
||||
"sourceMapPathOverrides": {
|
||||
"/./*": "${webRoot}/*",
|
||||
"/src/*": "${webRoot}/*",
|
||||
"/*": "*",
|
||||
"/./~/*": "${webRoot}/node_modules/*"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"name": "ISA-App Chrome",
|
||||
"url": "https://localhost:4200",
|
||||
"webRoot": "${workspaceFolder}",
|
||||
}
|
||||
]
|
||||
}
|
||||
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@@ -8,5 +8,8 @@
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
}
|
||||
},
|
||||
"css.validate": false,
|
||||
"less.validate": false,
|
||||
"scss.validate": false
|
||||
}
|
||||
|
||||
26
Dockerfile
26
Dockerfile
@@ -1,13 +1,29 @@
|
||||
#stage 1
|
||||
FROM node:10-stretch as node
|
||||
FROM node:18 as base
|
||||
ARG IS_PRODUCTION=false
|
||||
ARG SEMVERSION=1.0.0
|
||||
ARG BuildUniqueID
|
||||
LABEL build.uniqueid="${BuildUniqueID:-1}"
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN umask 0022
|
||||
RUN npm version ${SEMVERSION}
|
||||
RUN npm install --always-auth=false
|
||||
RUN if [ "${IS_PRODUCTION}" = "true" ] ; then npm run-script build-prod ; else npm run-script build ; fi
|
||||
|
||||
# stage 2
|
||||
FROM nginx:alpine
|
||||
COPY --from=node /app/dist/sales /usr/share/nginx/html
|
||||
COPY --from=node /app/nginx.conf /etc/nginx/conf.d/default.conf
|
||||
# stage final
|
||||
FROM nginx:alpine as publish
|
||||
ARG BuildUniqueID
|
||||
LABEL build.uniqueid="${BuildUniqueID:-1}"
|
||||
COPY --from=base /app/dist/isa-app /usr/share/nginx/html
|
||||
COPY --from=base /app/nginx.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
# stage npm test
|
||||
FROM base as test
|
||||
ARG BuildUniqueID
|
||||
LABEL build.uniqueid="${BuildUniqueID:-1}"
|
||||
RUN wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb -q -O /tmp/chrome.deb && apt update && apt install -y /tmp/chrome.deb
|
||||
# ignore exitcode, sonst gibts keinen container
|
||||
RUN npm run ci || true
|
||||
ENTRYPOINT [ "/bin/sleep", "60000" ]
|
||||
|
||||
|
||||
555
angular.json
555
angular.json
@@ -3,495 +3,162 @@
|
||||
"version": 1,
|
||||
"newProjectRoot": "apps",
|
||||
"projects": {
|
||||
"ui": {
|
||||
"root": "libs/ui",
|
||||
"sourceRoot": "libs/ui",
|
||||
"projectType": "library",
|
||||
"prefix": "lib",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||
"options": {
|
||||
"tsConfig": "libs/ui/tsconfig.lib.json",
|
||||
"project": "libs/ui/ng-package.json"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "libs/ui/src/test.ts",
|
||||
"tsConfig": "libs/ui/tsconfig.spec.json",
|
||||
"karmaConfig": "libs/ui/karma.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"libs/ui/tsconfig.lib.json",
|
||||
"libs/ui/tsconfig.spec.json"
|
||||
],
|
||||
"exclude": ["**/node_modules/**"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sales": {
|
||||
"root": "apps/sales/",
|
||||
"sourceRoot": "apps/sales/src",
|
||||
"isa-app": {
|
||||
"projectType": "application",
|
||||
"schematics": {
|
||||
"@schematics/angular:component": {
|
||||
"style": "scss"
|
||||
},
|
||||
"@schematics/angular:application": {
|
||||
"strict": true
|
||||
}
|
||||
},
|
||||
"root": "apps/isa-app",
|
||||
"sourceRoot": "apps/isa-app/src",
|
||||
"prefix": "app",
|
||||
"schematics": {},
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "dist/sales",
|
||||
"index": "apps/sales/src/index.html",
|
||||
"main": "apps/sales/src/main.ts",
|
||||
"polyfills": "apps/sales/src/polyfills.ts",
|
||||
"tsConfig": "apps/sales/tsconfig.app.json",
|
||||
"assets": [
|
||||
"apps/sales/src/favicon.ico",
|
||||
"apps/sales/src/assets",
|
||||
"apps/sales/src/manifest.webmanifest",
|
||||
"apps/sales/src/silent-refresh.html"
|
||||
"allowedCommonJsDependencies": [
|
||||
"lodash",
|
||||
"moment",
|
||||
"jsrsasign",
|
||||
"pdfjs-dist/build/pdf",
|
||||
"pdfjs-dist/web/pdf_viewer",
|
||||
"pdfjs-dist/es5/build/pdf",
|
||||
"pdfjs-dist/es5/web/pdf_viewer"
|
||||
],
|
||||
"styles": ["apps/sales/src/styles.scss"],
|
||||
"stylePreprocessorOptions": {
|
||||
"includePaths": ["apps/sales/src/scss"]
|
||||
},
|
||||
"scripts": []
|
||||
"outputPath": "dist/isa-app",
|
||||
"index": "apps/isa-app/src/index.html",
|
||||
"main": "apps/isa-app/src/main.ts",
|
||||
"polyfills": "apps/isa-app/src/polyfills.ts",
|
||||
"tsConfig": "apps/isa-app/tsconfig.app.json",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": [
|
||||
"apps/isa-app/src/favicon.ico",
|
||||
"apps/isa-app/src/assets",
|
||||
"apps/isa-app/src/config",
|
||||
"apps/isa-app/src/silent-refresh.html",
|
||||
"apps/isa-app/src/manifest.webmanifest",
|
||||
{
|
||||
"glob": "**/*",
|
||||
"input": "node_modules/scandit-web-datacapture-barcode/build/engine",
|
||||
"output": "scandit"
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"apps/isa-app/src/styles.scss"
|
||||
],
|
||||
"scripts": [],
|
||||
"serviceWorker": true,
|
||||
"ngswConfigPath": "apps/isa-app/ngsw-config.json"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "2mb",
|
||||
"maximumError": "5mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "25kb"
|
||||
}
|
||||
],
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "apps/sales/src/environments/environment.ts",
|
||||
"with": "apps/sales/src/environments/environment.prod.ts"
|
||||
"replace": "apps/isa-app/src/environments/environment.ts",
|
||||
"with": "apps/isa-app/src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": false,
|
||||
"extractCss": true,
|
||||
"namedChunks": false,
|
||||
"aot": true,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": true,
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "2mb",
|
||||
"maximumError": "5mb"
|
||||
}
|
||||
],
|
||||
"serviceWorker": true
|
||||
"outputHashing": "all"
|
||||
},
|
||||
"development": {
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": false,
|
||||
"extractCss": true,
|
||||
"namedChunks": false,
|
||||
"aot": true,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": true,
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "2mb",
|
||||
"maximumError": "5mb"
|
||||
}
|
||||
],
|
||||
"serviceWorker": true
|
||||
"buildOptimizer": false,
|
||||
"optimization": false,
|
||||
"vendorChunk": true,
|
||||
"extractLicenses": false,
|
||||
"sourceMap": true,
|
||||
"namedChunks": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "production"
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"options": {
|
||||
"browserTarget": "sales:build"
|
||||
},
|
||||
"configurations": {
|
||||
"test": {
|
||||
"browserTarget": "sales:build:test"
|
||||
},
|
||||
"integration": {
|
||||
"browserTarget": "sales:build:integration"
|
||||
},
|
||||
"staging": {
|
||||
"browserTarget": "sales:build:staging"
|
||||
},
|
||||
"production": {
|
||||
"browserTarget": "sales:build:production"
|
||||
"buildTarget": "isa-app:build:production"
|
||||
},
|
||||
"development": {
|
||||
"buildTarget": "isa-app:build:development"
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "development"
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "sales:build"
|
||||
"buildTarget": "isa-app:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "apps/sales/src/test.ts",
|
||||
"polyfills": "apps/sales/src/polyfills.ts",
|
||||
"tsConfig": "apps/sales/tsconfig.spec.json",
|
||||
"karmaConfig": "apps/sales/karma.conf.js",
|
||||
"styles": ["apps/sales/src/styles.scss"],
|
||||
"scripts": [],
|
||||
"tsConfig": "apps/isa-app/tsconfig.spec.json",
|
||||
"karmaConfig": "karma.conf.js",
|
||||
"polyfills": [
|
||||
"zone.js",
|
||||
"zone.js/testing"
|
||||
],
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": [
|
||||
"apps/sales/src/favicon.ico",
|
||||
"apps/sales/src/assets",
|
||||
"apps/sales/src/manifest.webmanifest"
|
||||
]
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"apps/sales/tsconfig.app.json",
|
||||
"apps/sales/tsconfig.spec.json"
|
||||
"apps/isa-app/src/favicon.ico",
|
||||
"apps/isa-app/src/assets",
|
||||
"apps/isa-app/src/manifest.webmanifest"
|
||||
],
|
||||
"exclude": ["**/node_modules/**"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sales-e2e": {
|
||||
"root": "apps/sales-e2e/",
|
||||
"projectType": "application",
|
||||
"prefix": "",
|
||||
"architect": {
|
||||
"e2e": {
|
||||
"builder": "@angular-devkit/build-angular:protractor",
|
||||
"options": {
|
||||
"protractorConfig": "apps/sales-e2e/protractor.conf.js",
|
||||
"devServerTarget": "sales:serve"
|
||||
},
|
||||
"configurations": {
|
||||
"integration": {
|
||||
"devServerTarget": "sales:serve:integration"
|
||||
},
|
||||
"production": {
|
||||
"devServerTarget": "sales:serve:production"
|
||||
}
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": "apps/sales-e2e/tsconfig.e2e.json",
|
||||
"exclude": ["**/node_modules/**"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sso": {
|
||||
"root": "libs/sso",
|
||||
"sourceRoot": "libs/sso/src",
|
||||
"projectType": "library",
|
||||
"prefix": "lib",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||
"options": {
|
||||
"tsConfig": "libs/sso/tsconfig.lib.json",
|
||||
"project": "libs/sso/ng-package.json"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "libs/sso/src/test.ts",
|
||||
"tsConfig": "libs/sso/tsconfig.spec.json",
|
||||
"karmaConfig": "libs/sso/karma.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"libs/sso/tsconfig.lib.json",
|
||||
"libs/sso/tsconfig.spec.json"
|
||||
"styles": [
|
||||
"apps/isa-app/src/styles.scss"
|
||||
],
|
||||
"exclude": ["**/node_modules/**"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@swagger/availability": {
|
||||
"root": "apps/swagger/availability",
|
||||
"sourceRoot": "apps/swagger/availability/src",
|
||||
"projectType": "library",
|
||||
"prefix": "lib",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||
"options": {
|
||||
"tsConfig": "apps/swagger/availability/tsconfig.lib.json",
|
||||
"project": "apps/swagger/availability/ng-package.json"
|
||||
"scripts": []
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"storybook": {
|
||||
"builder": "@storybook/angular:start-storybook",
|
||||
"options": {
|
||||
"main": "apps/swagger/availability/src/test.ts",
|
||||
"tsConfig": "apps/swagger/availability/tsconfig.spec.json",
|
||||
"karmaConfig": "apps/swagger/availability/karma.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"apps/swagger/availability/tsconfig.lib.json",
|
||||
"apps/swagger/availability/tsconfig.spec.json"
|
||||
"configDir": "apps/isa-app/.storybook",
|
||||
"browserTarget": "isa-app:build",
|
||||
"compodoc": true,
|
||||
"compodocArgs": [
|
||||
"-e",
|
||||
"json",
|
||||
"-d",
|
||||
"apps/isa-app"
|
||||
],
|
||||
"exclude": ["**/node_modules/**"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@swagger/checkout": {
|
||||
"root": "apps/swagger/checkout",
|
||||
"sourceRoot": "apps/swagger/checkout/src",
|
||||
"projectType": "library",
|
||||
"prefix": "lib",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||
"options": {
|
||||
"tsConfig": "apps/swagger/checkout/tsconfig.lib.json",
|
||||
"project": "apps/swagger/checkout/ng-package.json"
|
||||
"port": 6006
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"build-storybook": {
|
||||
"builder": "@storybook/angular:build-storybook",
|
||||
"options": {
|
||||
"main": "apps/swagger/checkout/src/test.ts",
|
||||
"tsConfig": "apps/swagger/checkout/tsconfig.spec.json",
|
||||
"karmaConfig": "apps/swagger/checkout/karma.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"apps/swagger/checkout/tsconfig.lib.json",
|
||||
"apps/swagger/checkout/tsconfig.spec.json"
|
||||
"configDir": "apps/isa-app/.storybook",
|
||||
"browserTarget": "isa-app:build",
|
||||
"compodoc": true,
|
||||
"compodocArgs": [
|
||||
"-e",
|
||||
"json",
|
||||
"-d",
|
||||
"apps/isa-app"
|
||||
],
|
||||
"exclude": ["**/node_modules/**"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@swagger/crm": {
|
||||
"root": "apps/swagger/crm",
|
||||
"sourceRoot": "apps/swagger/crm/src",
|
||||
"projectType": "library",
|
||||
"prefix": "lib",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||
"options": {
|
||||
"tsConfig": "apps/swagger/crm/tsconfig.lib.json",
|
||||
"project": "apps/swagger/crm/ng-package.json"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "apps/swagger/crm/src/test.ts",
|
||||
"tsConfig": "apps/swagger/crm/tsconfig.spec.json",
|
||||
"karmaConfig": "apps/swagger/crm/karma.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"apps/swagger/crm/tsconfig.lib.json",
|
||||
"apps/swagger/crm/tsconfig.spec.json"
|
||||
],
|
||||
"exclude": ["**/node_modules/**"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@swagger/isa": {
|
||||
"root": "apps/swagger/isa",
|
||||
"sourceRoot": "apps/swagger/isa/src",
|
||||
"projectType": "library",
|
||||
"prefix": "lib",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||
"options": {
|
||||
"tsConfig": "apps/swagger/isa/tsconfig.lib.json",
|
||||
"project": "apps/swagger/isa/ng-package.json"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "apps/swagger/isa/src/test.ts",
|
||||
"tsConfig": "apps/swagger/isa/tsconfig.spec.json",
|
||||
"karmaConfig": "apps/swagger/isa/karma.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"apps/swagger/isa/tsconfig.lib.json",
|
||||
"apps/swagger/isa/tsconfig.spec.json"
|
||||
],
|
||||
"exclude": ["**/node_modules/**"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@swagger/oms": {
|
||||
"root": "apps/swagger/oms",
|
||||
"sourceRoot": "apps/swagger/oms/src",
|
||||
"projectType": "library",
|
||||
"prefix": "lib",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||
"options": {
|
||||
"tsConfig": "apps/swagger/oms/tsconfig.lib.json",
|
||||
"project": "apps/swagger/oms/ng-package.json"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "apps/swagger/oms/src/test.ts",
|
||||
"tsConfig": "apps/swagger/oms/tsconfig.spec.json",
|
||||
"karmaConfig": "apps/swagger/oms/karma.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"apps/swagger/oms/tsconfig.lib.json",
|
||||
"apps/swagger/oms/tsconfig.spec.json"
|
||||
],
|
||||
"exclude": ["**/node_modules/**"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@swagger/print": {
|
||||
"root": "apps/swagger/print",
|
||||
"sourceRoot": "apps/swagger/print/src",
|
||||
"projectType": "library",
|
||||
"prefix": "lib",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||
"options": {
|
||||
"tsConfig": "apps/swagger/print/tsconfig.lib.json",
|
||||
"project": "apps/swagger/print/ng-package.json"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "apps/swagger/print/src/test.ts",
|
||||
"tsConfig": "apps/swagger/print/tsconfig.spec.json",
|
||||
"karmaConfig": "apps/swagger/print/karma.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"apps/swagger/print/tsconfig.lib.json",
|
||||
"apps/swagger/print/tsconfig.spec.json"
|
||||
],
|
||||
"exclude": ["**/node_modules/**"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@swagger/cat": {
|
||||
"root": "apps/swagger/cat",
|
||||
"sourceRoot": "apps/swagger/cat/src",
|
||||
"projectType": "library",
|
||||
"prefix": "lib",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||
"options": {
|
||||
"tsConfig": "apps/swagger/cat/tsconfig.lib.json",
|
||||
"project": "apps/swagger/cat/ng-package.json"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "apps/swagger/cat/src/test.ts",
|
||||
"tsConfig": "apps/swagger/cat/tsconfig.spec.json",
|
||||
"karmaConfig": "apps/swagger/cat/karma.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"apps/swagger/cat/tsconfig.lib.json",
|
||||
"apps/swagger/cat/tsconfig.spec.json"
|
||||
],
|
||||
"exclude": ["**/node_modules/**"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"native-container": {
|
||||
"projectType": "library",
|
||||
"root": "apps/native-container",
|
||||
"sourceRoot": "apps/native-container/src",
|
||||
"prefix": "lib",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||
"options": {
|
||||
"tsConfig": "apps/native-container/tsconfig.lib.json",
|
||||
"project": "apps/native-container/ng-package.json"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "apps/native-container/src/test.ts",
|
||||
"tsConfig": "apps/native-container/tsconfig.spec.json",
|
||||
"karmaConfig": "apps/native-container/karma.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"apps/native-container/tsconfig.lib.json",
|
||||
"apps/native-container/tsconfig.spec.json"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
"outputDir": "storybook-static"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultProject": "sales"
|
||||
}
|
||||
"cli": {
|
||||
"analytics": false
|
||||
}
|
||||
}
|
||||
17
apps/isa-app/.storybook/main.ts
Normal file
17
apps/isa-app/.storybook/main.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import type { StorybookConfig } from '@storybook/angular';
|
||||
|
||||
const config: StorybookConfig = {
|
||||
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
|
||||
addons: [
|
||||
'@storybook/addon-onboarding',
|
||||
'@storybook/addon-links',
|
||||
'@storybook/addon-essentials',
|
||||
'@chromatic-com/storybook',
|
||||
'@storybook/addon-interactions',
|
||||
],
|
||||
framework: {
|
||||
name: '@storybook/angular',
|
||||
options: {},
|
||||
},
|
||||
};
|
||||
export default config;
|
||||
17
apps/isa-app/.storybook/preview.ts
Normal file
17
apps/isa-app/.storybook/preview.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import type { Preview } from '@storybook/angular';
|
||||
import { setCompodocJson } from '@storybook/addon-docs/angular';
|
||||
import docJson from '../documentation.json';
|
||||
setCompodocJson(docJson);
|
||||
|
||||
const preview: Preview = {
|
||||
parameters: {
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/i,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default preview;
|
||||
10
apps/isa-app/.storybook/tsconfig.doc.json
Normal file
10
apps/isa-app/.storybook/tsconfig.doc.json
Normal file
@@ -0,0 +1,10 @@
|
||||
// This tsconfig is used by Compodoc to generate the documentation for the project.
|
||||
// If Compodoc is not used, this file can be deleted.
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
// Exclude all files that are not needed for documentation generation.
|
||||
"exclude": ["../src/test.ts", "../src/**/*.spec.ts", "../src/**/*.stories.ts"],
|
||||
// Please make sure to include all files from which Compodoc should generate documentation.
|
||||
"include": ["../src/**/*"],
|
||||
"files": ["./typings.d.ts"]
|
||||
}
|
||||
11
apps/isa-app/.storybook/tsconfig.json
Normal file
11
apps/isa-app/.storybook/tsconfig.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"extends": "../tsconfig.app.json",
|
||||
"compilerOptions": {
|
||||
"types": ["node"],
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"exclude": ["../src/test.ts", "../src/**/*.spec.ts"],
|
||||
"include": ["../src/**/*.stories.*", "./preview.ts", "../src/polyfills.ts"],
|
||||
"files": ["./typings.d.ts"]
|
||||
}
|
||||
4
apps/isa-app/.storybook/typings.d.ts
vendored
Normal file
4
apps/isa-app/.storybook/typings.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
declare module '*.md' {
|
||||
const content: string;
|
||||
export default content;
|
||||
}
|
||||
373381
apps/isa-app/documentation.json
Normal file
373381
apps/isa-app/documentation.json
Normal file
File diff suppressed because one or more lines are too long
32
apps/isa-app/ngsw-config.json
Normal file
32
apps/isa-app/ngsw-config.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"$schema": "../../node_modules/@angular/service-worker/config/schema.json",
|
||||
"index": "/index.html",
|
||||
"navigationRequestStrategy": "freshness",
|
||||
"assetGroups": [
|
||||
{
|
||||
"name": "app",
|
||||
"installMode": "prefetch",
|
||||
"resources": {
|
||||
"files": [
|
||||
"/favicon.ico",
|
||||
"/index.html",
|
||||
"/manifest.webmanifest",
|
||||
"/*.css",
|
||||
"/*.js",
|
||||
"/*.json"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "assets",
|
||||
"installMode": "lazy",
|
||||
"updateMode": "prefetch",
|
||||
"resources": {
|
||||
"files": [
|
||||
"/assets/**",
|
||||
"/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2)"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
44
apps/isa-app/src/adapter/scan/dev.scan-adapter.ts
Normal file
44
apps/isa-app/src/adapter/scan/dev.scan-adapter.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { EnvironmentService } from '@core/environment';
|
||||
import { PromptModalData, UiModalService, UiPromptModalComponent } from '@ui/modal';
|
||||
import { Observable } from 'rxjs';
|
||||
import { ScanAdapter } from './scan-adapter';
|
||||
|
||||
@Injectable()
|
||||
export class DevScanAdapter implements ScanAdapter {
|
||||
readonly name = 'Dev';
|
||||
|
||||
private _modal = inject(UiModalService);
|
||||
|
||||
async init(): Promise<boolean> {
|
||||
return Promise.resolve(false);
|
||||
// return new Promise((resolve, reject) => {
|
||||
// resolve(isDevMode());
|
||||
// });
|
||||
}
|
||||
|
||||
scan(): Observable<string> {
|
||||
return new Observable((observer) => {
|
||||
const modalRef = this._modal.open({
|
||||
content: UiPromptModalComponent,
|
||||
title: 'Scannen',
|
||||
data: {
|
||||
message: 'Diese Eingabemaske dient nur zu Entwicklungs und Testzwecken.',
|
||||
placeholder: 'Scan Code',
|
||||
confirmText: 'weiter',
|
||||
cancelText: 'abbrechen',
|
||||
} as PromptModalData,
|
||||
});
|
||||
|
||||
const sub = modalRef.afterClosed$.subscribe((result) => {
|
||||
observer.next(result.data);
|
||||
observer.complete();
|
||||
});
|
||||
|
||||
return () => {
|
||||
modalRef.close();
|
||||
sub.unsubscribe();
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
5
apps/isa-app/src/adapter/scan/dummy.spec.ts
Normal file
5
apps/isa-app/src/adapter/scan/dummy.spec.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
describe('Dummy', () => {
|
||||
it('should work', () => {
|
||||
expect(true).toBeTruthy();
|
||||
});
|
||||
});
|
||||
7
apps/isa-app/src/adapter/scan/index.ts
Normal file
7
apps/isa-app/src/adapter/scan/index.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export * from './dev.scan-adapter';
|
||||
export * from './native.scan-adapter';
|
||||
export * from './scan-adapter';
|
||||
export * from './scan.module';
|
||||
export * from './scan.service';
|
||||
export * from './scandit';
|
||||
export * from './tokens';
|
||||
30
apps/isa-app/src/adapter/scan/native.scan-adapter.ts
Normal file
30
apps/isa-app/src/adapter/scan/native.scan-adapter.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { NativeContainerService } from '@external/native-container';
|
||||
import { Observable } from 'rxjs';
|
||||
import { filter, map, take } from 'rxjs/operators';
|
||||
import { ScanAdapter } from './scan-adapter';
|
||||
|
||||
/**
|
||||
* @deprecated This service will be removed in future versions.
|
||||
* Please use the new ScanService instead.
|
||||
*/
|
||||
@Injectable()
|
||||
export class NativeScanAdapter implements ScanAdapter {
|
||||
readonly name = 'Native';
|
||||
|
||||
constructor(private readonly nativeContainerService: NativeContainerService) {}
|
||||
|
||||
init(): Promise<boolean> {
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve(this.nativeContainerService.isNative);
|
||||
});
|
||||
}
|
||||
|
||||
scan(): Observable<string> {
|
||||
return this.nativeContainerService.openScanner('scanBook').pipe(
|
||||
filter((result) => result.status === 'SUCCESS'),
|
||||
map((result) => result.data),
|
||||
take(1),
|
||||
);
|
||||
}
|
||||
}
|
||||
18
apps/isa-app/src/adapter/scan/scan-adapter.ts
Normal file
18
apps/isa-app/src/adapter/scan/scan-adapter.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
export interface ScanAdapter {
|
||||
/**
|
||||
* Name to identify the adapter
|
||||
*/
|
||||
readonly name: string;
|
||||
|
||||
/**
|
||||
* @returns true if this adapter can be used
|
||||
*/
|
||||
init(): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* scan for a barcode
|
||||
*/
|
||||
scan(): Observable<string>;
|
||||
}
|
||||
19
apps/isa-app/src/adapter/scan/scan.module.ts
Normal file
19
apps/isa-app/src/adapter/scan/scan.module.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { DevScanAdapter } from './dev.scan-adapter';
|
||||
import { NativeScanAdapter } from './native.scan-adapter';
|
||||
import { SCAN_ADAPTER } from './tokens';
|
||||
|
||||
@NgModule({})
|
||||
export class ScanAdapterModule {
|
||||
static forRoot() {
|
||||
return {
|
||||
ngModule: ScanAdapterModule,
|
||||
providers: [
|
||||
{ provide: SCAN_ADAPTER, useClass: NativeScanAdapter, multi: true },
|
||||
{ provide: SCAN_ADAPTER, useClass: DevScanAdapter, multi: true },
|
||||
],
|
||||
// Use for testing:
|
||||
// providers: [{ provide: SCAN_ADAPTER, useClass: dev ? DevScanAdapter : NativeScanAdapter, multi: true }],
|
||||
};
|
||||
}
|
||||
}
|
||||
52
apps/isa-app/src/adapter/scan/scan.service.ts
Normal file
52
apps/isa-app/src/adapter/scan/scan.service.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { Observable, throwError } from 'rxjs';
|
||||
import { ScanAdapter } from './scan-adapter';
|
||||
import { SCAN_ADAPTER } from './tokens';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ScanAdapterService {
|
||||
private _readyAdapters: Record<string, boolean> = {};
|
||||
|
||||
constructor(@Inject(SCAN_ADAPTER) private readonly scanAdapters: ScanAdapter[]) {}
|
||||
|
||||
async init(): Promise<void> {
|
||||
for (const adapter of this.scanAdapters) {
|
||||
const isReady = await adapter.init();
|
||||
this._readyAdapters[adapter.name] = isReady;
|
||||
}
|
||||
}
|
||||
|
||||
adapters(): ScanAdapter[] {
|
||||
return [...this.scanAdapters];
|
||||
}
|
||||
|
||||
getAdapter(name: string): ScanAdapter | undefined {
|
||||
return this._readyAdapters[name] && this.scanAdapters.find((adapter) => adapter.name === name);
|
||||
}
|
||||
|
||||
isReady(): boolean {
|
||||
return Object.values(this._readyAdapters).some((ready) => ready);
|
||||
}
|
||||
|
||||
scan(): Observable<string> {
|
||||
const adapterOrder = ['Native', 'Scandit', 'Dev'];
|
||||
|
||||
let adapter: ScanAdapter;
|
||||
|
||||
for (const name of adapterOrder) {
|
||||
adapter = this.getAdapter(name);
|
||||
|
||||
if (adapter) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!adapter) {
|
||||
return throwError('No adapter found');
|
||||
}
|
||||
|
||||
return adapter.scan();
|
||||
}
|
||||
}
|
||||
3
apps/isa-app/src/adapter/scan/scandit/index.ts
Normal file
3
apps/isa-app/src/adapter/scan/scandit/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from './scandit-overlay.component';
|
||||
export * from './scandit-scan-adapter.module';
|
||||
export * from './scandit.scan-adapter';
|
||||
@@ -0,0 +1,22 @@
|
||||
:host {
|
||||
@apply block relative;
|
||||
}
|
||||
|
||||
.scanner-container {
|
||||
/* width: 100vw;
|
||||
height: 100vh;
|
||||
max-width: 100vh;
|
||||
max-height: 100vh; */
|
||||
}
|
||||
|
||||
.close-scanner {
|
||||
@apply absolute bottom-12 left-[50%] -translate-x-[50%] block px-6 py-4 bg-white text-brand border-2 border-solid border-brand rounded-full text-lg font-bold mx-auto mt-4;
|
||||
@apply whitespace-nowrap;
|
||||
}
|
||||
|
||||
@screen desktop {
|
||||
.scanner-container {
|
||||
max-width: 900px;
|
||||
max-height: 900px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<div class="scanner-container" #scanContainer></div>
|
||||
<button class="close-scanner" type="button" (click)="close()">Scan abbrechen</button>
|
||||
@@ -0,0 +1,95 @@
|
||||
import { Component, ChangeDetectionStrategy, ElementRef, ViewChild, NgZone, AfterViewInit, OnDestroy, OnInit } from '@angular/core';
|
||||
import { BarcodeCapture, BarcodeCaptureSettings, Symbology } from 'scandit-web-datacapture-barcode';
|
||||
import { Camera, DataCaptureContext, DataCaptureView, FrameSourceState } from 'scandit-web-datacapture-core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-scandit-overlay',
|
||||
templateUrl: 'scandit-overlay.component.html',
|
||||
styleUrls: ['scandit-overlay.component.css'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ScanditOverlayComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
private dataCaptureContext: DataCaptureContext;
|
||||
private dataCaptureView: DataCaptureView;
|
||||
private barcodeCapture: BarcodeCapture;
|
||||
private camera: Camera;
|
||||
|
||||
private _onScan?: (code: string) => void;
|
||||
|
||||
private _onClose?: () => void;
|
||||
|
||||
@ViewChild('scanContainer', { read: ElementRef, static: true }) scanContainer: ElementRef;
|
||||
|
||||
constructor(private _zone: NgZone) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.dataCaptureView = new DataCaptureView();
|
||||
|
||||
this.dataCaptureView.connectToElement(this.scanContainer.nativeElement);
|
||||
|
||||
this.dataCaptureView.showProgressBar();
|
||||
}
|
||||
|
||||
async ngAfterViewInit() {
|
||||
this.dataCaptureContext = await DataCaptureContext.create();
|
||||
|
||||
this.dataCaptureView.setContext(this.dataCaptureContext);
|
||||
|
||||
this.barcodeCapture = await BarcodeCapture.forContext(this.dataCaptureContext, this.getScanSettings());
|
||||
|
||||
this.barcodeCapture.addListener({
|
||||
didScan: (_, session, __) => {
|
||||
this._zone.run(() => {
|
||||
const result = session.newlyRecognizedBarcode;
|
||||
|
||||
const code = result?.data ?? '';
|
||||
|
||||
this._onScan?.(code);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
this.camera = Camera.default;
|
||||
|
||||
this.dataCaptureContext.setFrameSource(this.camera);
|
||||
|
||||
await this.camera.switchToDesiredState(FrameSourceState.On);
|
||||
this.dataCaptureView.hideProgressBar();
|
||||
}
|
||||
|
||||
getScanSettings(): BarcodeCaptureSettings {
|
||||
const settings = new BarcodeCaptureSettings();
|
||||
|
||||
settings.enableSymbologies([
|
||||
Symbology.EAN8,
|
||||
Symbology.EAN13UPCA,
|
||||
Symbology.UPCE,
|
||||
Symbology.Code128,
|
||||
Symbology.Code39,
|
||||
Symbology.Code93,
|
||||
Symbology.InterleavedTwoOfFive,
|
||||
Symbology.QR,
|
||||
]);
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
onScan(fn: (code: string) => void) {
|
||||
this._onScan = fn;
|
||||
}
|
||||
|
||||
onClose(fn: () => void) {
|
||||
this._onClose = fn;
|
||||
}
|
||||
|
||||
close() {
|
||||
this._onClose?.();
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this._zone.runOutsideAngular(() => {
|
||||
this.barcodeCapture?.setEnabled(false);
|
||||
this.camera?.switchToDesiredState(FrameSourceState.Off);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { ScanditOverlayComponent } from './scandit-overlay.component';
|
||||
import { ScanditScanAdapter } from './scandit.scan-adapter';
|
||||
import { SCAN_ADAPTER } from '../tokens';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule],
|
||||
exports: [ScanditOverlayComponent],
|
||||
declarations: [ScanditOverlayComponent],
|
||||
})
|
||||
export class ScanditScanAdapterModule {
|
||||
static forRoot() {
|
||||
return {
|
||||
ngModule: ScanditScanAdapterModule,
|
||||
providers: [{ provide: SCAN_ADAPTER, useClass: ScanditScanAdapter, multi: true }],
|
||||
};
|
||||
}
|
||||
}
|
||||
103
apps/isa-app/src/adapter/scan/scandit/scandit.scan-adapter.ts
Normal file
103
apps/isa-app/src/adapter/scan/scandit/scandit.scan-adapter.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable, Subscriber } from 'rxjs';
|
||||
import { ScanAdapter } from '../scan-adapter';
|
||||
import { Overlay } from '@angular/cdk/overlay';
|
||||
|
||||
import { configure } from 'scandit-web-datacapture-core';
|
||||
import { barcodeCaptureLoader } from 'scandit-web-datacapture-barcode';
|
||||
|
||||
// import { ScanditModalComponent } from './scandit-modal';
|
||||
import { Config } from '@core/config';
|
||||
import { ComponentPortal } from '@angular/cdk/portal';
|
||||
import { ScanditOverlayComponent } from './scandit-overlay.component';
|
||||
import { EnvironmentService } from '@core/environment';
|
||||
import { injectNetworkStatus$ } from 'apps/isa-app/src/app/services/network-status.service';
|
||||
import { toSignal } from '@angular/core/rxjs-interop';
|
||||
|
||||
@Injectable()
|
||||
export class ScanditScanAdapter implements ScanAdapter {
|
||||
readonly name = 'Scandit';
|
||||
|
||||
private $networkStatus = toSignal(injectNetworkStatus$());
|
||||
|
||||
constructor(
|
||||
private readonly _config: Config,
|
||||
private _overlay: Overlay,
|
||||
private _environmentService: EnvironmentService,
|
||||
) {}
|
||||
|
||||
async init(): Promise<boolean> {
|
||||
if (this._environmentService.isTablet()) {
|
||||
try {
|
||||
await configure({
|
||||
licenseKey: this._config.get('licence.scandit'),
|
||||
libraryLocation: new URL('scandit', document.baseURI).toString(),
|
||||
moduleLoaders: [barcodeCaptureLoader()],
|
||||
});
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('ScanditScanAdapter.init', error);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
scan(): Observable<string> {
|
||||
return new Observable((observer) => {
|
||||
if (this.$networkStatus() === 'offline') {
|
||||
observer.error(new Error('No network connection'));
|
||||
return;
|
||||
}
|
||||
|
||||
const overlay = this.createOverlay();
|
||||
|
||||
const portal = this.createPortal();
|
||||
|
||||
const ref = overlay.attach(portal);
|
||||
|
||||
const sub = new Subscriber();
|
||||
|
||||
const complete = () => {
|
||||
overlay.detach();
|
||||
ref.destroy();
|
||||
sub.unsubscribe();
|
||||
sub.complete();
|
||||
observer.complete();
|
||||
};
|
||||
|
||||
sub.add(
|
||||
overlay.backdropClick().subscribe(() => {
|
||||
complete();
|
||||
}),
|
||||
);
|
||||
|
||||
ref.instance.onScan((code) => {
|
||||
observer.next(code);
|
||||
complete();
|
||||
});
|
||||
|
||||
ref.instance.onClose(() => {
|
||||
complete();
|
||||
});
|
||||
|
||||
return complete;
|
||||
});
|
||||
}
|
||||
|
||||
createOverlay() {
|
||||
const overlay = this._overlay.create({
|
||||
positionStrategy: this._overlay.position().global().centerHorizontally().centerVertically(),
|
||||
hasBackdrop: true,
|
||||
});
|
||||
|
||||
return overlay;
|
||||
}
|
||||
|
||||
createPortal() {
|
||||
const portal = new ComponentPortal(ScanditOverlayComponent);
|
||||
|
||||
return portal;
|
||||
}
|
||||
}
|
||||
4
apps/isa-app/src/adapter/scan/tokens.ts
Normal file
4
apps/isa-app/src/adapter/scan/tokens.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { InjectionToken } from '@angular/core';
|
||||
import { ScanAdapter } from './scan-adapter';
|
||||
|
||||
export const SCAN_ADAPTER = new InjectionToken<ScanAdapter>('SCAN_ADAPTER');
|
||||
19
apps/isa-app/src/app/app-domain.module.ts
Normal file
19
apps/isa-app/src/app/app-domain.module.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { DomainAvailabilityModule } from '@domain/availability';
|
||||
import { DomainCatalogModule } from '@domain/catalog';
|
||||
import { DomainIsaModule } from '@domain/isa';
|
||||
import { DomainCheckoutModule } from '@domain/checkout';
|
||||
import { DomainOmsModule } from '@domain/oms';
|
||||
import { DomainRemissionModule } from '@domain/remission';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
DomainIsaModule.forRoot(),
|
||||
DomainCatalogModule.forRoot(),
|
||||
DomainAvailabilityModule.forRoot(),
|
||||
DomainCheckoutModule.forRoot(),
|
||||
DomainOmsModule.forRoot(),
|
||||
DomainRemissionModule.forRoot(),
|
||||
],
|
||||
})
|
||||
export class AppDomainModule {}
|
||||
159
apps/isa-app/src/app/app-routing.module.ts
Normal file
159
apps/isa-app/src/app/app-routing.module.ts
Normal file
@@ -0,0 +1,159 @@
|
||||
import { isDevMode, NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import {
|
||||
CanActivateCartGuard,
|
||||
CanActivateCartWithProcessIdGuard,
|
||||
CanActivateCustomerGuard,
|
||||
CanActivateCustomerOrdersGuard,
|
||||
CanActivateCustomerOrdersWithProcessIdGuard,
|
||||
CanActivateCustomerWithProcessIdGuard,
|
||||
CanActivateGoodsInGuard,
|
||||
CanActivateProductGuard,
|
||||
CanActivateProductWithProcessIdGuard,
|
||||
CanActivateRemissionGuard,
|
||||
CanActivateTaskCalendarGuard,
|
||||
IsAuthenticatedGuard,
|
||||
} from './guards';
|
||||
import { CanActivateAssortmentGuard } from './guards/can-activate-assortment.guard';
|
||||
import { CanActivatePackageInspectionGuard } from './guards/can-activate-package-inspection.guard';
|
||||
import { MainComponent } from './main.component';
|
||||
import { PreviewComponent } from './preview';
|
||||
import { BranchSectionResolver, CustomerSectionResolver, ProcessIdResolver } from './resolvers';
|
||||
import { TokenLoginComponent, TokenLoginModule } from './token-login';
|
||||
import { ProcessIdGuard } from './guards/process-id.guard';
|
||||
import { ActivateProcessIdGuard, ActivateProcessIdWithConfigKeyGuard } from './guards/activate-process-id.guard';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: 'login',
|
||||
children: [
|
||||
{ path: ':token', component: TokenLoginComponent },
|
||||
{ path: '**', redirectTo: 'kunde', pathMatch: 'full' },
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
canActivate: [IsAuthenticatedGuard],
|
||||
children: [
|
||||
{
|
||||
path: 'kunde',
|
||||
component: MainComponent,
|
||||
children: [
|
||||
{
|
||||
path: 'dashboard',
|
||||
loadChildren: () => import('@page/dashboard').then((m) => m.DashboardModule),
|
||||
},
|
||||
{
|
||||
path: 'product',
|
||||
loadChildren: () => import('@page/catalog').then((m) => m.PageCatalogModule),
|
||||
canActivate: [CanActivateProductGuard],
|
||||
},
|
||||
{
|
||||
path: ':processId/product',
|
||||
loadChildren: () => import('@page/catalog').then((m) => m.PageCatalogModule),
|
||||
canActivate: [CanActivateProductWithProcessIdGuard],
|
||||
resolve: { processId: ProcessIdResolver },
|
||||
},
|
||||
{
|
||||
path: 'order',
|
||||
loadChildren: () => import('@page/customer-order').then((m) => m.CustomerOrderModule),
|
||||
canActivate: [CanActivateCustomerOrdersGuard],
|
||||
},
|
||||
{
|
||||
path: ':processId/order',
|
||||
loadChildren: () => import('@page/customer-order').then((m) => m.CustomerOrderModule),
|
||||
canActivate: [CanActivateCustomerOrdersWithProcessIdGuard],
|
||||
resolve: { processId: ProcessIdResolver },
|
||||
},
|
||||
{
|
||||
path: 'customer',
|
||||
loadChildren: () => import('@page/customer').then((m) => m.CustomerModule),
|
||||
canActivate: [CanActivateCustomerGuard],
|
||||
},
|
||||
{
|
||||
path: ':processId/customer',
|
||||
loadChildren: () => import('@page/customer').then((m) => m.CustomerModule),
|
||||
canActivate: [CanActivateCustomerWithProcessIdGuard],
|
||||
resolve: { processId: ProcessIdResolver },
|
||||
},
|
||||
{
|
||||
path: 'cart',
|
||||
loadChildren: () => import('@page/checkout').then((m) => m.PageCheckoutModule),
|
||||
canActivate: [CanActivateCartGuard],
|
||||
},
|
||||
{
|
||||
path: ':processId/cart',
|
||||
loadChildren: () => import('@page/checkout').then((m) => m.PageCheckoutModule),
|
||||
canActivate: [CanActivateCartWithProcessIdGuard],
|
||||
},
|
||||
{
|
||||
path: 'pickup-shelf',
|
||||
canActivate: [ProcessIdGuard],
|
||||
// NOTE: This is a workaround for the canActivate guard not being called
|
||||
loadChildren: () => import('@page/pickup-shelf').then((m) => m.PickupShelfOutModule),
|
||||
},
|
||||
{
|
||||
path: ':processId/pickup-shelf',
|
||||
canActivate: [ActivateProcessIdGuard],
|
||||
loadChildren: () => import('@page/pickup-shelf').then((m) => m.PickupShelfOutModule),
|
||||
},
|
||||
{ path: '**', redirectTo: 'dashboard', pathMatch: 'full' },
|
||||
],
|
||||
resolve: { section: CustomerSectionResolver },
|
||||
},
|
||||
{
|
||||
path: 'filiale',
|
||||
component: MainComponent,
|
||||
children: [
|
||||
{
|
||||
path: 'task-calendar',
|
||||
loadChildren: () => import('@page/task-calendar').then((m) => m.PageTaskCalendarModule),
|
||||
canActivate: [CanActivateTaskCalendarGuard],
|
||||
},
|
||||
{
|
||||
path: 'pickup-shelf',
|
||||
canActivate: [ActivateProcessIdWithConfigKeyGuard('pickupShelf')],
|
||||
// NOTE: This is a workaround for the canActivate guard not being called
|
||||
loadChildren: () => import('@page/pickup-shelf').then((m) => m.PickupShelfInModule),
|
||||
},
|
||||
{
|
||||
path: 'goods/in',
|
||||
loadChildren: () => import('@page/goods-in').then((m) => m.GoodsInModule),
|
||||
canActivate: [CanActivateGoodsInGuard],
|
||||
},
|
||||
{
|
||||
path: 'remission',
|
||||
loadChildren: () => import('@page/remission').then((m) => m.PageRemissionModule),
|
||||
canActivate: [CanActivateRemissionGuard],
|
||||
},
|
||||
{
|
||||
path: 'package-inspection',
|
||||
loadChildren: () => import('@page/package-inspection').then((m) => m.PackageInspectionModule),
|
||||
canActivate: [CanActivatePackageInspectionGuard],
|
||||
},
|
||||
{
|
||||
path: 'assortment',
|
||||
loadChildren: () => import('@page/assortment').then((m) => m.AssortmentModule),
|
||||
canActivate: [CanActivateAssortmentGuard],
|
||||
},
|
||||
{ path: '**', redirectTo: 'task-calendar', pathMatch: 'full' },
|
||||
],
|
||||
resolve: { section: BranchSectionResolver },
|
||||
},
|
||||
{ path: '**', redirectTo: 'kunde', pathMatch: 'full' },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
if (isDevMode()) {
|
||||
routes.unshift({
|
||||
path: 'preview',
|
||||
component: PreviewComponent,
|
||||
});
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes), TokenLoginModule],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class AppRoutingModule {}
|
||||
34
apps/isa-app/src/app/app-store.module.ts
Normal file
34
apps/isa-app/src/app/app-store.module.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { EffectsModule } from '@ngrx/effects';
|
||||
import { ActionReducer, MetaReducer, StoreModule } from '@ngrx/store';
|
||||
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
|
||||
import { storeFreeze } from 'ngrx-store-freeze';
|
||||
import packageInfo from 'packageJson';
|
||||
import { environment } from '../environments/environment';
|
||||
import { RootStateService } from './store/root-state.service';
|
||||
import { rootReducer } from './store/root.reducer';
|
||||
import { RootState } from './store/root.state';
|
||||
|
||||
export function storeInLocalStorage(reducer: ActionReducer<any>): ActionReducer<any> {
|
||||
return function (state, action) {
|
||||
if (action.type === 'HYDRATE') {
|
||||
const initialState = RootStateService.LoadFromLocalStorage();
|
||||
|
||||
if (initialState?.version === packageInfo.version) {
|
||||
return reducer(initialState, action);
|
||||
}
|
||||
}
|
||||
return reducer(state, action);
|
||||
};
|
||||
}
|
||||
|
||||
export const metaReducers: MetaReducer<RootState>[] = !environment.production ? [storeFreeze, storeInLocalStorage] : [storeInLocalStorage];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
StoreModule.forRoot(rootReducer, { metaReducers }),
|
||||
EffectsModule.forRoot([]),
|
||||
StoreDevtoolsModule.instrument({ name: 'ISA Ngrx Application Store', connectInZone: true }),
|
||||
],
|
||||
})
|
||||
export class AppStoreModule {}
|
||||
34
apps/isa-app/src/app/app-swagger.module.ts
Normal file
34
apps/isa-app/src/app/app-swagger.module.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Config } from '@core/config';
|
||||
import { AvConfiguration } from '@swagger/availability';
|
||||
import { CatConfiguration } from '@swagger/cat';
|
||||
import { CheckoutConfiguration } from '@swagger/checkout';
|
||||
import { CrmConfiguration } from '@swagger/crm';
|
||||
import { EisConfiguration } from '@swagger/eis';
|
||||
import { IsaConfiguration } from '@swagger/isa';
|
||||
import { OmsConfiguration } from '@swagger/oms';
|
||||
import { PrintConfiguration } from '@swagger/print';
|
||||
import { RemiConfiguration } from '@swagger/remi';
|
||||
import { WwsConfiguration } from '@swagger/wws';
|
||||
|
||||
export function createConfigurationFactory(name: string) {
|
||||
return function (config: Config): { rootUrl: string } {
|
||||
return config.get(`@swagger/${name}`);
|
||||
};
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
providers: [
|
||||
{ provide: AvConfiguration, useFactory: createConfigurationFactory('av'), deps: [Config] },
|
||||
{ provide: CatConfiguration, useFactory: createConfigurationFactory('cat'), deps: [Config] },
|
||||
{ provide: CheckoutConfiguration, useFactory: createConfigurationFactory('checkout'), deps: [Config] },
|
||||
{ provide: CrmConfiguration, useFactory: createConfigurationFactory('crm'), deps: [Config] },
|
||||
{ provide: EisConfiguration, useFactory: createConfigurationFactory('eis'), deps: [Config] },
|
||||
{ provide: IsaConfiguration, useFactory: createConfigurationFactory('isa'), deps: [Config] },
|
||||
{ provide: OmsConfiguration, useFactory: createConfigurationFactory('oms'), deps: [Config] },
|
||||
{ provide: PrintConfiguration, useFactory: createConfigurationFactory('print'), deps: [Config] },
|
||||
{ provide: RemiConfiguration, useFactory: createConfigurationFactory('remi'), deps: [Config] },
|
||||
{ provide: WwsConfiguration, useFactory: createConfigurationFactory('wws'), deps: [Config] },
|
||||
],
|
||||
})
|
||||
export class AppSwaggerModule {}
|
||||
28
apps/isa-app/src/app/app.component.html
Normal file
28
apps/isa-app/src/app/app.component.html
Normal file
@@ -0,0 +1,28 @@
|
||||
@if ($offlineBannerVisible()) {
|
||||
<div [@fadeInOut] class="bg-brand text-white text-center fixed inset-x-0 top-0 z-tooltip p-4">
|
||||
<h3 class="font-bold grid grid-flow-col items-center justify-center text-xl gap-4">
|
||||
<div>
|
||||
<ng-icon name="matWifiOff"></ng-icon>
|
||||
</div>
|
||||
|
||||
<div>Sie sind offline, keine Verbindung zum Netzwerk.</div>
|
||||
</h3>
|
||||
<p>Bereits geladene Ihnalte werden angezeigt, Interaktionen sind aktuell nicht möglich.</p>
|
||||
</div>
|
||||
}
|
||||
@if ($onlineBannerVisible()) {
|
||||
<div [@fadeInOut] class="bg-green-500 text-white text-center fixed inset-x-0 top-0 z-tooltip p-4">
|
||||
<h3 class="font-bold grid grid-flow-col items-center justify-center text-xl gap-4">
|
||||
<div>
|
||||
<ng-icon name="matWifi"></ng-icon>
|
||||
</div>
|
||||
|
||||
<div>Sie sind wieder online.</div>
|
||||
</h3>
|
||||
<button class="fixed top-2 right-4 text-3xl w-12 h-12" type="button" (click)="$onlineBannerVisible.set(false)">
|
||||
<ng-icon name="matClose"></ng-icon>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
<router-outlet></router-outlet>
|
||||
3
apps/isa-app/src/app/app.component.scss
Normal file
3
apps/isa-app/src/app/app.component.scss
Normal file
@@ -0,0 +1,3 @@
|
||||
:host {
|
||||
@apply block;
|
||||
}
|
||||
137
apps/isa-app/src/app/app.component.spec.ts
Normal file
137
apps/isa-app/src/app/app.component.spec.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
import { Spectator, createComponentFactory, SpyObject, createSpyObject } from '@ngneat/spectator';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
import { Config } from '@core/config';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { of } from 'rxjs';
|
||||
import { Renderer2 } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { SwUpdate } from '@angular/service-worker';
|
||||
import { NotificationsHub } from '@hub/notifications';
|
||||
import { UserStateService } from '@swagger/isa';
|
||||
import { UiModalService } from '@ui/modal';
|
||||
import { AuthService } from '@core/auth';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
let spectator: Spectator<AppComponent>;
|
||||
let config: SpyObject<Config>;
|
||||
let renderer: SpyObject<Renderer2>;
|
||||
let applicationServiceMock: SpyObject<ApplicationService>;
|
||||
let notificationsHubMock: SpyObject<NotificationsHub>;
|
||||
let swUpdateMock: SpyObject<SwUpdate>;
|
||||
const createComponent = createComponentFactory({
|
||||
component: AppComponent,
|
||||
imports: [CommonModule, RouterTestingModule],
|
||||
providers: [],
|
||||
mocks: [Config, SwUpdate, UserStateService, UiModalService, AuthService],
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
applicationServiceMock = createSpyObject(ApplicationService);
|
||||
applicationServiceMock.getSection$.and.returnValue(of('customer'));
|
||||
applicationServiceMock.getActivatedProcessId$.and.returnValue(of(undefined));
|
||||
renderer = jasmine.createSpyObj('Renderer2', ['addClass', 'removeClass']);
|
||||
|
||||
notificationsHubMock = createSpyObject(NotificationsHub);
|
||||
notificationsHubMock.notifications$ = of({});
|
||||
swUpdateMock = createSpyObject(SwUpdate);
|
||||
|
||||
spectator = createComponent({
|
||||
providers: [
|
||||
{ provide: ApplicationService, useValue: applicationServiceMock },
|
||||
{
|
||||
provide: Renderer2,
|
||||
useValue: renderer,
|
||||
},
|
||||
{ provide: NotificationsHub, useValue: notificationsHubMock },
|
||||
{ provide: SwUpdate, useValue: swUpdateMock },
|
||||
],
|
||||
});
|
||||
config = spectator.inject(Config);
|
||||
});
|
||||
|
||||
it('should create the app', () => {
|
||||
expect(spectator.component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should have a router outlet', () => {
|
||||
expect(spectator.query('router-outlet')).toExist();
|
||||
});
|
||||
|
||||
describe('ngOnInit', () => {
|
||||
it('should call setTitle', () => {
|
||||
const spy = spyOn(spectator.component, 'setTitle');
|
||||
spectator.component.ngOnInit();
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call logVersion', () => {
|
||||
const spy = spyOn(spectator.component, 'logVersion');
|
||||
spectator.component.ngOnInit();
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('setTitle', () => {
|
||||
it('should call Title.setTitle()', () => {
|
||||
const spyTitleSetTitle = spyOn(spectator.component['_title'], 'setTitle');
|
||||
config.get.and.returnValue('test');
|
||||
spectator.component.setTitle();
|
||||
expect(spyTitleSetTitle).toHaveBeenCalledWith('test');
|
||||
});
|
||||
});
|
||||
|
||||
describe('logVersion', () => {
|
||||
it('should call console.log()', () => {
|
||||
const spyConsoleLog = spyOn(console, 'log');
|
||||
config.get.and.returnValue('test');
|
||||
spectator.component.logVersion();
|
||||
expect(spyConsoleLog).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Unit Tests Implementation for Angular Version 13.x.x
|
||||
|
||||
// describe('updateClient()', () => {
|
||||
// it('should call checkForUpdate() if SwUpdate.isEnabled is True', () => {
|
||||
// spyOn(spectator.component, 'checkForUpdate');
|
||||
// spyOn(spectator.component, 'initialCheckForUpdate');
|
||||
// (swUpdateMock as any).isEnabled = true;
|
||||
// spectator.component.updateClient();
|
||||
// expect(spectator.component.initialCheckForUpdate).toHaveBeenCalled();
|
||||
// expect(spectator.component.checkForUpdate).toHaveBeenCalled();
|
||||
// });
|
||||
|
||||
// it('should not call checkForUpdate() if SwUpdate.isEnabled is False', () => {
|
||||
// spyOn(spectator.component, 'checkForUpdate');
|
||||
// spyOn(spectator.component, 'initialCheckForUpdate');
|
||||
// (swUpdateMock as any).isEnabled = false;
|
||||
// spectator.component.updateClient();
|
||||
// expect(spectator.component.initialCheckForUpdate).not.toHaveBeenCalled();
|
||||
// expect(spectator.component.checkForUpdate).not.toHaveBeenCalled();
|
||||
// });
|
||||
// });
|
||||
|
||||
// describe('checkForUpdate', () => {
|
||||
// it('should call swUpdate.checkForUpdate() and notifications.updateNotification() every second', fakeAsync(() => {
|
||||
// swUpdateMock.checkForUpdate.and.returnValue(Promise.resolve());
|
||||
// spectator.component.checkForUpdates = 1000;
|
||||
// spectator.component.checkForUpdate();
|
||||
|
||||
// spectator.detectChanges();
|
||||
// tick(1100);
|
||||
|
||||
// expect(notificationsHubMock.updateNotification).toHaveBeenCalled();
|
||||
// discardPeriodicTasks();
|
||||
// }));
|
||||
// });
|
||||
|
||||
// describe('initialCheckForUpdate', () => {
|
||||
// it('should call swUpdate.checkForUpdate()', () => {
|
||||
// swUpdateMock.checkForUpdate.and.returnValue(new Promise(undefined));
|
||||
// spectator.component.initialCheckForUpdate();
|
||||
// expect(swUpdateMock.checkForUpdate).toHaveBeenCalled();
|
||||
// });
|
||||
// });
|
||||
});
|
||||
194
apps/isa-app/src/app/app.component.ts
Normal file
194
apps/isa-app/src/app/app.component.ts
Normal file
@@ -0,0 +1,194 @@
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { Component, effect, HostListener, Inject, OnInit, Renderer2, signal, untracked } from '@angular/core';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { SwUpdate } from '@angular/service-worker';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { Config } from '@core/config';
|
||||
import { NotificationsHub } from '@hub/notifications';
|
||||
import packageInfo from 'packageJson';
|
||||
import { asapScheduler, interval, Subscription } from 'rxjs';
|
||||
import { UserStateService } from '@swagger/isa';
|
||||
import { IsaLogProvider } from './providers';
|
||||
import { EnvironmentService } from '@core/environment';
|
||||
import { AuthService } from '@core/auth';
|
||||
import { UiMessageModalComponent, UiModalService } from '@ui/modal';
|
||||
import { injectOnline$ } from './services/network-status.service';
|
||||
import { toSignal } from '@angular/core/rxjs-interop';
|
||||
import { animate, style, transition, trigger } from '@angular/animations';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.scss'],
|
||||
animations: [
|
||||
trigger('fadeInOut', [
|
||||
transition(':enter', [
|
||||
// :enter wird ausgelöst, wenn das Element zum DOM hinzugefügt wird
|
||||
style({ opacity: 0, transform: 'translateY(-100%)' }),
|
||||
animate('300ms', style({ opacity: 1, transform: 'translateY(0)' })),
|
||||
]),
|
||||
transition(':leave', [
|
||||
// :leave wird ausgelöst, wenn das Element aus dem DOM entfernt wird
|
||||
animate('300ms', style({ opacity: 0, transform: 'translateY(-100%)' })),
|
||||
]),
|
||||
]),
|
||||
],
|
||||
})
|
||||
export class AppComponent implements OnInit {
|
||||
$online = toSignal(injectOnline$());
|
||||
|
||||
$offlineBannerVisible = signal(false);
|
||||
|
||||
$onlineBannerVisible = signal(false);
|
||||
|
||||
private onlineBannerDismissTimeout: any;
|
||||
|
||||
onlineEffects = effect(() => {
|
||||
const online = this.$online();
|
||||
const offlineBannerVisible = this.$offlineBannerVisible();
|
||||
|
||||
untracked(() => {
|
||||
this.$offlineBannerVisible.set(!online);
|
||||
|
||||
if (!online) {
|
||||
this.$onlineBannerVisible.set(false);
|
||||
clearTimeout(this.onlineBannerDismissTimeout);
|
||||
}
|
||||
|
||||
if (offlineBannerVisible && online) {
|
||||
this.$onlineBannerVisible.set(true);
|
||||
this.onlineBannerDismissTimeout = setTimeout(() => this.$onlineBannerVisible.set(false), 5000);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
private _checkForUpdates: number = this._config.get('checkForUpdates');
|
||||
|
||||
get checkForUpdates(): number {
|
||||
return this._checkForUpdates ?? 60 * 60 * 1000; // default 1 hour
|
||||
}
|
||||
|
||||
// For Unit Testing
|
||||
set checkForUpdates(time: number) {
|
||||
this._checkForUpdates = time;
|
||||
}
|
||||
|
||||
subscriptions = new Subscription();
|
||||
|
||||
constructor(
|
||||
private readonly _config: Config,
|
||||
private readonly _title: Title,
|
||||
private readonly _appService: ApplicationService,
|
||||
@Inject(DOCUMENT) private readonly _document: Document,
|
||||
private readonly _renderer: Renderer2,
|
||||
private readonly _swUpdate: SwUpdate,
|
||||
private readonly _notifications: NotificationsHub,
|
||||
private infoService: UserStateService,
|
||||
private readonly _environment: EnvironmentService,
|
||||
private readonly _authService: AuthService,
|
||||
private readonly _modal: UiModalService,
|
||||
) {
|
||||
this.updateClient();
|
||||
IsaLogProvider.InfoService = this.infoService;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.setTitle();
|
||||
this.logVersion();
|
||||
asapScheduler.schedule(() => this.determinePlatform(), 250);
|
||||
this._appService.getSection$().subscribe(this.sectionChangeHandler.bind(this));
|
||||
|
||||
this.setupSilentRefresh();
|
||||
}
|
||||
|
||||
// Setup interval for silent refresh
|
||||
setupSilentRefresh() {
|
||||
const silentRefreshInterval = this._config.get('silentRefresh.interval');
|
||||
if (silentRefreshInterval > 0) {
|
||||
interval(silentRefreshInterval).subscribe(() => {
|
||||
if (this._authService.isAuthenticated()) {
|
||||
this._authService.refresh();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
setTitle() {
|
||||
this._title.setTitle(this._config.get('title'));
|
||||
}
|
||||
|
||||
logVersion() {
|
||||
console.log(`%c${this._config.get('title')}\r\nVersion: ${packageInfo.version}`, 'font-weight: bold; font-size: 20px;');
|
||||
}
|
||||
|
||||
determinePlatform() {
|
||||
if (this._environment.isNative()) {
|
||||
this._renderer.addClass(this._document.body, 'tablet-native');
|
||||
} else if (this._environment.isTablet()) {
|
||||
this._renderer.addClass(this._document.body, 'tablet-browser');
|
||||
}
|
||||
if (this._environment.isTablet()) {
|
||||
this._renderer.addClass(this._document.body, 'tablet');
|
||||
}
|
||||
if (this._environment.isDesktop()) {
|
||||
this._renderer.addClass(this._document.body, 'desktop');
|
||||
}
|
||||
}
|
||||
|
||||
sectionChangeHandler(section: string) {
|
||||
if (section === 'customer') {
|
||||
this._renderer.removeClass(this._document.body, 'branch');
|
||||
this._renderer.addClass(this._document.body, 'customer');
|
||||
} else if (section === 'branch') {
|
||||
this._renderer.removeClass(this._document.body, 'customer');
|
||||
this._renderer.addClass(this._document.body, 'branch');
|
||||
}
|
||||
}
|
||||
|
||||
updateClient() {
|
||||
if (!this._swUpdate.isEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.initialCheckForUpdate();
|
||||
this.checkForUpdate();
|
||||
}
|
||||
|
||||
checkForUpdate() {
|
||||
interval(this._checkForUpdates).subscribe(() => {
|
||||
this._swUpdate.checkForUpdate().then((value) => {
|
||||
console.log('check for update', value);
|
||||
if (value) {
|
||||
this._notifications.updateNotification();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
initialCheckForUpdate() {
|
||||
this._swUpdate.checkForUpdate().then((value) => {
|
||||
console.log('initial check for update', value);
|
||||
if (value) {
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@HostListener('window:visibilitychange', ['$event'])
|
||||
onVisibilityChange(event: Event) {
|
||||
// refresh token when app is in background
|
||||
if (this._document.hidden && this._authService.isAuthenticated()) {
|
||||
this._authService.refresh();
|
||||
} else if (!this._authService.isAuthenticated()) {
|
||||
return this._modal
|
||||
.open({
|
||||
content: UiMessageModalComponent,
|
||||
title: 'Sie sind nicht mehr angemeldet',
|
||||
data: { message: 'Sie werden neu angemeldet' },
|
||||
})
|
||||
.afterClosed$.subscribe(() => {
|
||||
this._authService.login();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
188
apps/isa-app/src/app/app.module.ts
Normal file
188
apps/isa-app/src/app/app.module.ts
Normal file
@@ -0,0 +1,188 @@
|
||||
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
|
||||
import { APP_INITIALIZER, ErrorHandler, Injector, LOCALE_ID, NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { PlatformModule } from '@angular/cdk/platform';
|
||||
|
||||
import { Config, ConfigModule, JsonConfigLoader } from '@core/config';
|
||||
import { AuthModule, AuthService } from '@core/auth';
|
||||
import { CoreCommandModule } from '@core/command';
|
||||
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { AppComponent } from './app.component';
|
||||
import { CoreApplicationModule } from '@core/application';
|
||||
import { AppStoreModule } from './app-store.module';
|
||||
import { ServiceWorkerModule } from '@angular/service-worker';
|
||||
import { environment } from '../environments/environment';
|
||||
import { AppSwaggerModule } from './app-swagger.module';
|
||||
import { AppDomainModule } from './app-domain.module';
|
||||
import { UiModalModule } from '@ui/modal';
|
||||
import { NotificationsHubModule, NOTIFICATIONS_HUB_OPTIONS } from '@hub/notifications';
|
||||
import { SignalRHubOptions } from '@core/signalr';
|
||||
import { CoreBreadcrumbModule } from '@core/breadcrumb';
|
||||
import { UiCommonModule } from '@ui/common';
|
||||
import { registerLocaleData } from '@angular/common';
|
||||
|
||||
import localeDe from '@angular/common/locales/de';
|
||||
import localeDeExtra from '@angular/common/locales/extra/de';
|
||||
import { HttpErrorInterceptor } from './interceptors';
|
||||
import { CoreLoggerModule, LOG_PROVIDER } from '@core/logger';
|
||||
import { IsaLogProvider } from './providers';
|
||||
import { IsaErrorHandler } from './providers/isa.error-handler';
|
||||
import { ScanAdapterModule, ScanAdapterService, ScanditScanAdapterModule } from '@adapter/scan';
|
||||
import { RootStateService } from './store/root-state.service';
|
||||
import * as Commands from './commands';
|
||||
import { PreviewComponent } from './preview';
|
||||
import { NativeContainerService } from '@external/native-container';
|
||||
import { ShellModule } from '@shared/shell';
|
||||
import { MainComponent } from './main.component';
|
||||
import { IconModule } from '@shared/components/icon';
|
||||
import { NgIconsModule } from '@ng-icons/core';
|
||||
import { matClose, matWifi, matWifiOff } from '@ng-icons/material-icons/baseline';
|
||||
import { NetworkStatusService } from './services/network-status.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
registerLocaleData(localeDe, localeDeExtra);
|
||||
registerLocaleData(localeDe, 'de', localeDeExtra);
|
||||
|
||||
export function _appInitializerFactory(
|
||||
config: Config,
|
||||
auth: AuthService,
|
||||
injector: Injector,
|
||||
scanAdapter: ScanAdapterService,
|
||||
nativeContainer: NativeContainerService,
|
||||
networkStatus: NetworkStatusService,
|
||||
) {
|
||||
return async () => {
|
||||
const statusElement = document.querySelector('#init-status');
|
||||
const laoderElement = document.querySelector('#init-loader');
|
||||
|
||||
try {
|
||||
let online = false;
|
||||
|
||||
while (!online) {
|
||||
online = await firstValueFrom(networkStatus.online$);
|
||||
|
||||
if (!online) {
|
||||
statusElement.innerHTML =
|
||||
'<b>Warte auf Netzwerkverbindung (WLAN)</b><br><br>Bitte prüfen Sie die Netzwerkverbindung (WLAN).<br>Sobald eine Netzwerkverbindung besteht, wird die App automatisch neu geladen.';
|
||||
await new Promise((resolve) => setTimeout(resolve, 250));
|
||||
}
|
||||
}
|
||||
|
||||
statusElement.innerHTML = 'Konfigurationen werden geladen...';
|
||||
await config.init();
|
||||
statusElement.innerHTML = 'Authentifizierung wird geprüft...';
|
||||
await auth.init();
|
||||
|
||||
if (auth.isAuthenticated()) {
|
||||
statusElement.innerHTML = 'App wird initialisiert...';
|
||||
const state = injector.get(RootStateService);
|
||||
await state.init();
|
||||
}
|
||||
|
||||
statusElement.innerHTML = 'Native Container wird initialisiert...';
|
||||
await nativeContainer.init();
|
||||
statusElement.innerHTML = 'Scanner wird initialisiert...';
|
||||
await scanAdapter.init();
|
||||
} catch (error) {
|
||||
laoderElement.remove();
|
||||
statusElement.classList.add('text-xl');
|
||||
statusElement.innerHTML +=
|
||||
'⚡<br><br><b>Fehler bei der Initialisierung</b><br><br>Bitte prüfen Sie die Netzwerkverbindung (WLAN).<br><br>';
|
||||
|
||||
const reload = document.createElement('button');
|
||||
reload.classList.add('bg-brand', 'text-white', 'p-2', 'rounded', 'cursor-pointer');
|
||||
reload.innerHTML = 'App neu laden';
|
||||
reload.onclick = () => window.location.reload();
|
||||
statusElement.appendChild(reload);
|
||||
|
||||
const preLabel = document.createElement('div');
|
||||
preLabel.classList.add('mt-12');
|
||||
preLabel.innerHTML = 'Fehlermeldung:';
|
||||
|
||||
statusElement.appendChild(preLabel);
|
||||
|
||||
const pre = document.createElement('pre');
|
||||
pre.classList.add('mt-4', 'text-wrap');
|
||||
pre.innerHTML = error.message;
|
||||
|
||||
statusElement.appendChild(pre);
|
||||
|
||||
console.error('Error during app initialization', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function _notificationsHubOptionsFactory(config: Config, auth: AuthService): SignalRHubOptions {
|
||||
const options = { ...config.get('hubs').notifications };
|
||||
options.httpOptions.accessTokenFactory = () => auth.getToken();
|
||||
return options;
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
declarations: [AppComponent, MainComponent],
|
||||
bootstrap: [AppComponent],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
BrowserAnimationsModule,
|
||||
ShellModule.forRoot(),
|
||||
AppRoutingModule,
|
||||
AppSwaggerModule,
|
||||
AppDomainModule,
|
||||
CoreBreadcrumbModule.forRoot(),
|
||||
ConfigModule.forRoot({
|
||||
useConfigLoader: JsonConfigLoader,
|
||||
jsonConfigLoaderUrl: '/config/config.json',
|
||||
}),
|
||||
CoreCommandModule.forRoot(Object.values(Commands)),
|
||||
CoreLoggerModule.forRoot(),
|
||||
AppStoreModule,
|
||||
PreviewComponent,
|
||||
AuthModule.forRoot(),
|
||||
CoreApplicationModule.forRoot(),
|
||||
UiModalModule.forRoot(),
|
||||
UiCommonModule.forRoot(),
|
||||
NotificationsHubModule.forRoot(),
|
||||
ServiceWorkerModule.register('ngsw-worker.js', {
|
||||
enabled: environment.production,
|
||||
registrationStrategy: 'registerWhenStable:30000',
|
||||
}),
|
||||
ScanAdapterModule.forRoot(),
|
||||
ScanditScanAdapterModule.forRoot(),
|
||||
PlatformModule,
|
||||
IconModule.forRoot(),
|
||||
NgIconsModule.withIcons({ matWifiOff, matClose, matWifi }),
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: _appInitializerFactory,
|
||||
multi: true,
|
||||
deps: [Config, AuthService, Injector, ScanAdapterService, NativeContainerService, NetworkStatusService],
|
||||
},
|
||||
{
|
||||
provide: NOTIFICATIONS_HUB_OPTIONS,
|
||||
useFactory: _notificationsHubOptionsFactory,
|
||||
deps: [Config, AuthService],
|
||||
},
|
||||
{
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
useClass: HttpErrorInterceptor,
|
||||
multi: true,
|
||||
},
|
||||
{
|
||||
provide: LOG_PROVIDER,
|
||||
useClass: IsaLogProvider,
|
||||
multi: true,
|
||||
},
|
||||
{
|
||||
provide: ErrorHandler,
|
||||
useClass: IsaErrorHandler,
|
||||
},
|
||||
{ provide: LOCALE_ID, useValue: 'de-DE' },
|
||||
provideHttpClient(withInterceptorsFromDi()),
|
||||
],
|
||||
})
|
||||
export class AppModule {}
|
||||
14
apps/isa-app/src/app/commands/close.command.ts
Normal file
14
apps/isa-app/src/app/commands/close.command.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActionHandler } from '@core/command';
|
||||
|
||||
/** Dummy Command um Fehlermeldungen aus dem Diloag zu verhinden */
|
||||
@Injectable()
|
||||
export class CloseCommand extends ActionHandler<any> {
|
||||
constructor() {
|
||||
super('CLOSE');
|
||||
}
|
||||
|
||||
handler(ctx: any): any {
|
||||
return ctx;
|
||||
}
|
||||
}
|
||||
35
apps/isa-app/src/app/commands/create-customer.command.ts
Normal file
35
apps/isa-app/src/app/commands/create-customer.command.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { ActionHandler } from '@core/command';
|
||||
import { Result } from '@domain/defs';
|
||||
import { CustomerInfoDTO } from '@swagger/crm';
|
||||
|
||||
@Injectable()
|
||||
export class CreateCustomerCommand extends ActionHandler<Result<CustomerInfoDTO[]>> {
|
||||
constructor(private _router: Router, private _application: ApplicationService) {
|
||||
super('CREATE_CUSTOMER');
|
||||
}
|
||||
|
||||
async handler(data: Result<CustomerInfoDTO[]>): Promise<Result<CustomerInfoDTO[]>> {
|
||||
let customerType: string;
|
||||
if (data.result.length > 0) {
|
||||
const customerInfo = data.result[0];
|
||||
if (customerInfo.features) {
|
||||
if (customerInfo.features.some((f) => f.key === 'store')) {
|
||||
customerType = 'store';
|
||||
}
|
||||
if (customerInfo.features.some((f) => f.key === 'webshop')) {
|
||||
customerType = 'webshop';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!customerType) {
|
||||
customerType = 'store';
|
||||
}
|
||||
|
||||
await this._router.navigate(['/kunde', this._application.activatedProcessId, 'customer', 'create', customerType]);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { ActionHandler } from '@core/command';
|
||||
import { Result } from '@domain/defs';
|
||||
import { encodeFormData, mapCustomerInfoDtoToCustomerCreateFormData } from '@page/customer';
|
||||
import { CustomerInfoDTO } from '@swagger/crm';
|
||||
|
||||
@Injectable()
|
||||
export class CreateKubiCustomerCommand extends ActionHandler<Result<CustomerInfoDTO[]>> {
|
||||
constructor(
|
||||
private _router: Router,
|
||||
private _application: ApplicationService,
|
||||
) {
|
||||
super('CREATE_KUBI_CUSTOMER');
|
||||
}
|
||||
|
||||
async handler(data: Result<CustomerInfoDTO[]>): Promise<Result<CustomerInfoDTO[]>> {
|
||||
let customerType: string;
|
||||
let formData: string;
|
||||
if (data.result.length > 0) {
|
||||
const customerInfo = data.result[0];
|
||||
const fd = mapCustomerInfoDtoToCustomerCreateFormData(customerInfo);
|
||||
formData = encodeFormData({
|
||||
...fd,
|
||||
agb: true,
|
||||
});
|
||||
|
||||
if (customerInfo.features) {
|
||||
if (customerInfo.features.some((f) => f.key === 'store')) {
|
||||
customerType = 'store';
|
||||
}
|
||||
if (customerInfo.features.some((f) => f.key === 'webshop')) {
|
||||
customerType = 'webshop';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!customerType) {
|
||||
customerType = 'store';
|
||||
}
|
||||
|
||||
await this._router.navigate(['/kunde', this._application.activatedProcessId, 'customer', 'create', `${customerType}-p4m`], {
|
||||
queryParams: { formData },
|
||||
});
|
||||
return data;
|
||||
}
|
||||
}
|
||||
5
apps/isa-app/src/app/commands/index.ts
Normal file
5
apps/isa-app/src/app/commands/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export * from './close.command';
|
||||
export * from './create-customer.command';
|
||||
export * from './create-kubi-customer.command';
|
||||
export * from './print-kubi-agb.command';
|
||||
export * from './remit.command';
|
||||
34
apps/isa-app/src/app/commands/print-kubi-agb.command.ts
Normal file
34
apps/isa-app/src/app/commands/print-kubi-agb.command.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActionHandler } from '@core/command';
|
||||
import { Result } from '@domain/defs';
|
||||
import { DomainPrinterService } from '@domain/printer';
|
||||
import { PrintModalComponent, PrintModalData } from '@modal/printer';
|
||||
import { CustomerInfoDTO } from '@swagger/crm';
|
||||
import { UiModalService } from '@ui/modal';
|
||||
|
||||
@Injectable()
|
||||
export class PrintKubiCustomerCommand extends ActionHandler<Result<CustomerInfoDTO[]>> {
|
||||
constructor(private _uiModal: UiModalService, private _printerService: DomainPrinterService) {
|
||||
super('PRINT_KUBI_AGB');
|
||||
}
|
||||
|
||||
async handler(data: Result<CustomerInfoDTO[]>): Promise<Result<CustomerInfoDTO[]>> {
|
||||
const customerInfo = data.result ? data.result[0] : undefined;
|
||||
let p4mCode: string;
|
||||
if (customerInfo) {
|
||||
p4mCode = customerInfo.features.find((f) => f.key === 'p4mUser').value;
|
||||
}
|
||||
|
||||
await this._uiModal
|
||||
.open({
|
||||
content: PrintModalComponent,
|
||||
config: { showScrollbarY: false },
|
||||
data: {
|
||||
printerType: 'Label',
|
||||
print: (printer) => this._printerService.printKubiAgb({ printer, p4mCode }).toPromise(),
|
||||
} as PrintModalData,
|
||||
})
|
||||
.afterClosed$.toPromise();
|
||||
return data;
|
||||
}
|
||||
}
|
||||
14
apps/isa-app/src/app/commands/remit.command.ts
Normal file
14
apps/isa-app/src/app/commands/remit.command.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActionHandler } from '@core/command';
|
||||
|
||||
/** Dummy Command um Fehlermeldungen aus dem Diloag zu verhinden */
|
||||
@Injectable()
|
||||
export class RemitCommand extends ActionHandler<any> {
|
||||
constructor() {
|
||||
super('remit');
|
||||
}
|
||||
|
||||
handler(ctx: any): any {
|
||||
return ctx;
|
||||
}
|
||||
}
|
||||
11
apps/isa-app/src/app/debug/debug.component.html
Normal file
11
apps/isa-app/src/app/debug/debug.component.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<div class="odd:bg-slate-200 grid grid-flow-col justify-start" *ngFor="let log of logs$ | async">
|
||||
<div class="p-2 w-100 grow-0">
|
||||
{{ log.timestamp | date }}
|
||||
</div>
|
||||
<div class="p-2 w-50 grow-0">
|
||||
{{ log.type }}
|
||||
</div>
|
||||
<div class="p-2 grow">
|
||||
{{ log.args | json }}
|
||||
</div>
|
||||
</div>
|
||||
6
apps/isa-app/src/app/debug/debug.component.scss
Normal file
6
apps/isa-app/src/app/debug/debug.component.scss
Normal file
@@ -0,0 +1,6 @@
|
||||
:host {
|
||||
@apply block;
|
||||
}
|
||||
:host {
|
||||
@apply grid grid-flow-row bg-white overflow-scroll;
|
||||
}
|
||||
17
apps/isa-app/src/app/debug/debug.component.ts
Normal file
17
apps/isa-app/src/app/debug/debug.component.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { DebugService } from './debug.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-debug',
|
||||
templateUrl: 'debug.component.html',
|
||||
styleUrls: ['debug.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [CommonModule],
|
||||
})
|
||||
export class DebugComponent {
|
||||
logs$ = this.debugService.logs$;
|
||||
|
||||
constructor(private debugService: DebugService) {}
|
||||
}
|
||||
25
apps/isa-app/src/app/debug/debug.service.ts
Normal file
25
apps/isa-app/src/app/debug/debug.service.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject, fromEvent } from 'rxjs';
|
||||
|
||||
export interface ConsoleLog {
|
||||
timestamp?: Date;
|
||||
type: 'log' | 'warn' | 'error';
|
||||
args: any[];
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class DebugService {
|
||||
private _consoleSubject = new BehaviorSubject<ConsoleLog[]>([]);
|
||||
|
||||
logs$ = this._consoleSubject.asObservable();
|
||||
|
||||
constructor() {
|
||||
fromEvent(window, 'message').subscribe((event: MessageEvent) => {
|
||||
this.add({ type: 'log', args: [event.data] });
|
||||
});
|
||||
}
|
||||
|
||||
add(log: ConsoleLog) {
|
||||
this._consoleSubject.next([...this._consoleSubject.value, { ...log, timestamp: new Date() }]);
|
||||
}
|
||||
}
|
||||
46
apps/isa-app/src/app/guards/activate-process-id.guard.ts
Normal file
46
apps/isa-app/src/app/guards/activate-process-id.guard.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { inject } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivateFn, RouterStateSnapshot } from '@angular/router';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { Config } from '@core/config';
|
||||
import { take } from 'rxjs/operators';
|
||||
|
||||
export const ActivateProcessIdGuard: CanActivateFn = async (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
|
||||
const application = inject(ApplicationService);
|
||||
|
||||
const processIdStr = route.params.processId;
|
||||
|
||||
if (!processIdStr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const processId = Number(processIdStr);
|
||||
|
||||
// Check if Process already exists
|
||||
const process = await application.getProcessById$(processId).pipe(take(1)).toPromise();
|
||||
|
||||
if (!process) {
|
||||
application.createCustomerProcess(processId);
|
||||
}
|
||||
|
||||
application.activateProcess(processId);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
export const ActivateProcessIdWithConfigKeyGuard: (key: string) => CanActivateFn = (key) => async (
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot
|
||||
) => {
|
||||
const application = inject(ApplicationService);
|
||||
const config = inject(Config);
|
||||
|
||||
const processId = config.get(`process.ids.${key}`);
|
||||
|
||||
if (isNaN(processId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
application.activateProcess(processId);
|
||||
|
||||
return true;
|
||||
};
|
||||
24
apps/isa-app/src/app/guards/can-activate-assortment.guard.ts
Normal file
24
apps/isa-app/src/app/guards/can-activate-assortment.guard.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { Config } from '@core/config';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivateAssortmentGuard {
|
||||
constructor(private readonly _applicationService: ApplicationService, private readonly _config: Config) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const process = await this._applicationService.getProcessById$(this._config.get('process.ids.assortment')).pipe(first()).toPromise();
|
||||
if (!process) {
|
||||
await this._applicationService.createProcess({
|
||||
id: this._config.get('process.ids.assortment'),
|
||||
type: 'assortment',
|
||||
section: 'branch',
|
||||
name: 'Sortiment',
|
||||
});
|
||||
}
|
||||
this._applicationService.activateProcess(this._config.get('process.ids.assortment'));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
import { ApplicationProcess, ApplicationService } from '@core/application';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivateCartWithProcessIdGuard {
|
||||
constructor(private readonly _applicationService: ApplicationService) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const process = await this._applicationService
|
||||
.getProcessById$(+route.params.processId)
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
|
||||
// if (!(process?.type === 'cart')) {
|
||||
// // TODO:
|
||||
// // Anderer Prozesstyp mit gleicher Id - Was soll gemacht werden?
|
||||
// return false;
|
||||
// }
|
||||
|
||||
if (!process) {
|
||||
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||
await this._applicationService.createProcess({
|
||||
id: +route.params.processId,
|
||||
type: 'cart',
|
||||
section: 'customer',
|
||||
name: `Vorgang ${this.processNumber(processes)}`,
|
||||
});
|
||||
}
|
||||
|
||||
this._applicationService.activateProcess(+route.params.processId);
|
||||
return true;
|
||||
}
|
||||
|
||||
processNumber(processes: ApplicationProcess[]) {
|
||||
const processNumbers = processes?.map((process) => Number(process?.name?.replace(/\D/g, '')));
|
||||
return !!processNumbers && processNumbers?.length > 0 ? Math.max(...processNumbers) + 1 : 1;
|
||||
}
|
||||
}
|
||||
31
apps/isa-app/src/app/guards/can-activate-cart.guard.ts
Normal file
31
apps/isa-app/src/app/guards/can-activate-cart.guard.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { CheckoutNavigationService } from '@shared/services/navigation';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivateCartGuard {
|
||||
constructor(
|
||||
private readonly _applicationService: ApplicationService,
|
||||
private _checkoutNavigationService: CheckoutNavigationService,
|
||||
) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||
let lastActivatedProcessId = (
|
||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart').pipe(first()).toPromise()
|
||||
)?.id;
|
||||
if (!lastActivatedProcessId) {
|
||||
lastActivatedProcessId = Date.now();
|
||||
await this._applicationService.createProcess({
|
||||
id: lastActivatedProcessId,
|
||||
type: 'cart',
|
||||
section: 'customer',
|
||||
name: `Vorgang ${processes.length + 1}`,
|
||||
});
|
||||
}
|
||||
await this._checkoutNavigationService.getCheckoutReviewPath(lastActivatedProcessId).path;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
import { ApplicationProcess, ApplicationService } from '@core/application';
|
||||
import { BreadcrumbService } from '@core/breadcrumb';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivateCustomerOrdersWithProcessIdGuard {
|
||||
constructor(private readonly _applicationService: ApplicationService, private readonly _breadcrumbService: BreadcrumbService) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const process = await this._applicationService
|
||||
.getProcessById$(+route.params.processId)
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
|
||||
if (!process) {
|
||||
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||
await this._applicationService.createProcess({
|
||||
id: +route.params.processId,
|
||||
type: 'cart',
|
||||
section: 'customer',
|
||||
name: `Vorgang ${this.processNumber(processes.filter((process) => process.type === 'cart'))}`,
|
||||
});
|
||||
}
|
||||
|
||||
await this.removeBreadcrumbWithSameProcessId(route);
|
||||
this._applicationService.activateProcess(+route.params.processId);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fix #3292: Alle Breadcrumbs die nichts mit dem aktuellen Prozess zu tun haben, müssen removed werden
|
||||
async removeBreadcrumbWithSameProcessId(route: ActivatedRouteSnapshot) {
|
||||
const crumbs = await this._breadcrumbService
|
||||
.getBreadcrumbByKey$(+route.params.processId)
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
|
||||
// Entferne alle Crumbs die nichts mit den Kundenbestellungen zu tun haben
|
||||
if (crumbs.length > 1) {
|
||||
const crumbsToRemove = crumbs.filter((crumb) => crumb.tags.find((tag) => tag === 'customer-order') === undefined);
|
||||
for (const crumb of crumbsToRemove) {
|
||||
await this._breadcrumbService.removeBreadcrumb(crumb.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processNumber(processes: ApplicationProcess[]) {
|
||||
const processNumbers = processes?.map((process) => Number(process?.name?.replace(/\D/g, '')));
|
||||
return !!processNumbers && processNumbers.length > 0 ? this.findMissingNumber(processNumbers) : 1;
|
||||
}
|
||||
|
||||
findMissingNumber(processNumbers: number[]) {
|
||||
// Ticket #3272 Bei Klick auf "+" bzw. neuen Prozess hinzufügen soll der neue Tab immer die höchste Nummer haben (wie aktuell im Produktiv)
|
||||
// ----------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// for (let missingNumber = 1; missingNumber < Math.max(...processNumbers); missingNumber++) {
|
||||
// if (!processNumbers.find((number) => number === missingNumber)) {
|
||||
// return missingNumber;
|
||||
// }
|
||||
// }
|
||||
return Math.max(...processNumbers) + 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
import { ApplicationProcess, ApplicationService } from '@core/application';
|
||||
import { DomainCheckoutService } from '@domain/checkout';
|
||||
import { CustomerOrdersNavigationService } from '@shared/services/navigation';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivateCustomerOrdersGuard {
|
||||
constructor(
|
||||
private readonly _applicationService: ApplicationService,
|
||||
private readonly _checkoutService: DomainCheckoutService,
|
||||
private readonly _navigationService: CustomerOrdersNavigationService,
|
||||
) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||
|
||||
let lastActivatedProcessId = (
|
||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart').pipe(first()).toPromise()
|
||||
)?.id;
|
||||
|
||||
const lastActivatedCartCheckoutProcessId = (
|
||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout').pipe(first()).toPromise()
|
||||
)?.id;
|
||||
|
||||
const activatedProcessId = await this._applicationService.getActivatedProcessId$().pipe(first()).toPromise();
|
||||
|
||||
// Darf nur reinkommen wenn der aktuell aktive Tab ein Bestellabschluss Tab ist
|
||||
if (!!lastActivatedCartCheckoutProcessId && lastActivatedCartCheckoutProcessId === activatedProcessId) {
|
||||
await this.fromCartCheckoutProcess(processes, route, lastActivatedCartCheckoutProcessId);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!lastActivatedProcessId) {
|
||||
await this.fromGoodsOutProcess(processes, route);
|
||||
return false;
|
||||
} else {
|
||||
await this._navigationService.getCustomerOrdersBasePath(lastActivatedProcessId).navigate();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bei offenen Kundenbestellungen und Klick auf Kundenbestellungen
|
||||
async fromGoodsOutProcess(processes: ApplicationProcess[], route: ActivatedRouteSnapshot) {
|
||||
const newProcessId = Date.now();
|
||||
await this._applicationService.createProcess({
|
||||
id: newProcessId,
|
||||
type: 'cart',
|
||||
section: 'customer',
|
||||
name: `Vorgang ${this.processNumber(processes.filter((process) => process.type === 'cart'))}`,
|
||||
});
|
||||
|
||||
await this._navigationService.getCustomerOrdersBasePath(newProcessId).navigate();
|
||||
}
|
||||
|
||||
// Bei offener Bestellbestätigung und Klick auf Kundenbestellungen
|
||||
async fromCartCheckoutProcess(processes: ApplicationProcess[], route: ActivatedRouteSnapshot, processId: number) {
|
||||
// Um alle Checkout Daten zu resetten die mit dem Prozess assoziiert sind
|
||||
this._checkoutService.removeProcess({ processId });
|
||||
|
||||
// Ändere type cart-checkout zu customer-order
|
||||
this._applicationService.patchProcess(processId, {
|
||||
id: processId,
|
||||
type: 'cart',
|
||||
section: 'customer',
|
||||
name: `Vorgang ${this.processNumber(processes.filter((process) => process.type === 'cart'))}`,
|
||||
data: {},
|
||||
});
|
||||
|
||||
// Navigation
|
||||
await this._navigationService.getCustomerOrdersBasePath(processId).navigate();
|
||||
}
|
||||
|
||||
getUrlFromSnapshot(route: ActivatedRouteSnapshot, url: string[] = []): string[] {
|
||||
url.push(...route.url.map((segment) => segment.path));
|
||||
if (route.firstChild) {
|
||||
return this.getUrlFromSnapshot(route.firstChild, url);
|
||||
}
|
||||
return url.filter((segment) => !!segment);
|
||||
}
|
||||
|
||||
processNumber(processes: ApplicationProcess[]) {
|
||||
const processNumbers = processes?.map((process) => Number(process?.name?.replace(/\D/g, '')));
|
||||
return !!processNumbers && processNumbers.length > 0 ? this.findMissingNumber(processNumbers) : 1;
|
||||
}
|
||||
|
||||
findMissingNumber(processNumbers: number[]) {
|
||||
for (let missingNumber = 1; missingNumber < Math.max(...processNumbers); missingNumber++) {
|
||||
if (!processNumbers.find((number) => number === missingNumber)) {
|
||||
return missingNumber;
|
||||
}
|
||||
}
|
||||
return Math.max(...processNumbers) + 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
import { ApplicationProcess, ApplicationService } from '@core/application';
|
||||
import { BreadcrumbService } from '@core/breadcrumb';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivateCustomerWithProcessIdGuard {
|
||||
constructor(private readonly _applicationService: ApplicationService, private readonly _breadcrumbService: BreadcrumbService) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const process = await this._applicationService
|
||||
.getProcessById$(+route.params.processId)
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
|
||||
// if (!(process?.type === 'cart')) {
|
||||
// // TODO:
|
||||
// // Anderer Prozesstyp mit gleicher Id - Was soll gemacht werden?
|
||||
// return false;
|
||||
// }
|
||||
|
||||
if (!process) {
|
||||
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||
await this._applicationService.createProcess({
|
||||
id: +route.params.processId,
|
||||
type: 'cart',
|
||||
section: 'customer',
|
||||
name: `Vorgang ${this.processNumber(processes.filter((process) => process.type === 'cart'))}`,
|
||||
});
|
||||
}
|
||||
|
||||
await this.removeBreadcrumbWithSameProcessId(route);
|
||||
this._applicationService.activateProcess(+route.params.processId);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fix #3292: Alle Breadcrumbs die nichts mit dem aktuellen Prozess zu tun haben, müssen removed werden
|
||||
async removeBreadcrumbWithSameProcessId(route: ActivatedRouteSnapshot) {
|
||||
const crumbs = await this._breadcrumbService
|
||||
.getBreadcrumbByKey$(+route.params.processId)
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
|
||||
// Entferne alle Crumbs die nichts mit der Kundensuche zu tun haben
|
||||
if (crumbs.length > 1) {
|
||||
const crumbsToRemove = crumbs.filter((crumb) => crumb.tags.find((tag) => tag === 'customer') === undefined);
|
||||
for (const crumb of crumbsToRemove) {
|
||||
await this._breadcrumbService.removeBreadcrumb(crumb.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processNumber(processes: ApplicationProcess[]) {
|
||||
const processNumbers = processes?.map((process) => Number(process?.name?.replace(/\D/g, '')));
|
||||
return !!processNumbers && processNumbers.length > 0 ? this.findMissingNumber(processNumbers) : 1;
|
||||
}
|
||||
|
||||
findMissingNumber(processNumbers: number[]) {
|
||||
for (let missingNumber = 1; missingNumber < Math.max(...processNumbers); missingNumber++) {
|
||||
if (!processNumbers.find((number) => number === missingNumber)) {
|
||||
return missingNumber;
|
||||
}
|
||||
}
|
||||
return Math.max(...processNumbers) + 1;
|
||||
}
|
||||
}
|
||||
125
apps/isa-app/src/app/guards/can-activate-customer.guard.ts
Normal file
125
apps/isa-app/src/app/guards/can-activate-customer.guard.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';
|
||||
import { ApplicationProcess, ApplicationService } from '@core/application';
|
||||
import { DomainCheckoutService } from '@domain/checkout';
|
||||
import { CustomerSearchNavigation } from '@shared/services/navigation';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivateCustomerGuard {
|
||||
constructor(
|
||||
private readonly _applicationService: ApplicationService,
|
||||
private readonly _checkoutService: DomainCheckoutService,
|
||||
private readonly _router: Router,
|
||||
private readonly _navigation: CustomerSearchNavigation,
|
||||
) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||
let lastActivatedProcessId = (
|
||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart').pipe(first()).toPromise()
|
||||
)?.id;
|
||||
|
||||
const lastActivatedCartCheckoutProcessId = (
|
||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout').pipe(first()).toPromise()
|
||||
)?.id;
|
||||
|
||||
const lastActivatedGoodsOutProcessId = (
|
||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'goods-out').pipe(first()).toPromise()
|
||||
)?.id;
|
||||
|
||||
const activatedProcessId = await this._applicationService.getActivatedProcessId$().pipe(first()).toPromise();
|
||||
|
||||
// Darf nur reinkommen wenn der aktuell aktive Tab ein Bestellabschluss Tab ist
|
||||
if (!!lastActivatedCartCheckoutProcessId && lastActivatedCartCheckoutProcessId === activatedProcessId) {
|
||||
await this.fromCartCheckoutProcess(processes, lastActivatedCartCheckoutProcessId);
|
||||
return false;
|
||||
} else if (!!lastActivatedGoodsOutProcessId && lastActivatedGoodsOutProcessId === activatedProcessId) {
|
||||
await this.fromGoodsOutProcess(processes, lastActivatedGoodsOutProcessId);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!lastActivatedProcessId) {
|
||||
await this.fromCartProcess(processes);
|
||||
return false;
|
||||
} else {
|
||||
await this.navigateToDefaultRoute(lastActivatedProcessId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async navigateToDefaultRoute(processId: number) {
|
||||
const route = this._navigation.defaultRoute({ processId });
|
||||
|
||||
await this._router.navigate(route.path, { queryParams: route.queryParams });
|
||||
}
|
||||
|
||||
// Bei offener Artikelsuche/Kundensuche und Klick auf Footer Kundensuche
|
||||
async fromCartProcess(processes: ApplicationProcess[]) {
|
||||
const newProcessId = Date.now();
|
||||
await this._applicationService.createProcess({
|
||||
id: newProcessId,
|
||||
type: 'cart',
|
||||
section: 'customer',
|
||||
name: `Vorgang ${this.processNumber(processes.filter((process) => process.type === 'cart'))}`,
|
||||
});
|
||||
|
||||
await this.navigateToDefaultRoute(newProcessId);
|
||||
}
|
||||
|
||||
// Bei offener Bestellbestätigung und Klick auf Footer Kundensuche
|
||||
async fromCartCheckoutProcess(processes: ApplicationProcess[], processId: number) {
|
||||
// Um alle Checkout Daten zu resetten die mit dem Prozess assoziiert sind
|
||||
this._checkoutService.removeProcess({ processId });
|
||||
|
||||
// Ändere type cart-checkout zu cart
|
||||
this._applicationService.patchProcess(processId, {
|
||||
id: processId,
|
||||
type: 'cart',
|
||||
section: 'customer',
|
||||
name: `Vorgang ${this.processNumber(processes.filter((process) => process.type === 'cart'))}`,
|
||||
data: {},
|
||||
});
|
||||
|
||||
// Navigation
|
||||
await this.navigateToDefaultRoute(processId);
|
||||
}
|
||||
|
||||
// Bei offener Warenausgabe und Klick auf Footer Kundensuche
|
||||
async fromGoodsOutProcess(processes: ApplicationProcess[], processId: number) {
|
||||
const buyer = await this._checkoutService.getBuyer({ processId }).pipe(first()).toPromise();
|
||||
const customerFeatures = await this._checkoutService.getCustomerFeatures({ processId }).pipe(first()).toPromise();
|
||||
const name = buyer
|
||||
? customerFeatures?.b2b
|
||||
? buyer.organisation?.name
|
||||
? buyer.organisation?.name
|
||||
: buyer.lastName
|
||||
: buyer.lastName
|
||||
: `Vorgang ${this.processNumber(processes.filter((process) => process.type === 'cart'))}`;
|
||||
|
||||
// Ändere type goods-out zu cart
|
||||
this._applicationService.patchProcess(processId, {
|
||||
id: processId,
|
||||
type: 'cart',
|
||||
section: 'customer',
|
||||
name,
|
||||
});
|
||||
|
||||
// Navigation
|
||||
await this.navigateToDefaultRoute(processId);
|
||||
}
|
||||
|
||||
processNumber(processes: ApplicationProcess[]) {
|
||||
const processNumbers = processes?.map((process) => Number(process?.name?.replace(/\D/g, '')));
|
||||
return !!processNumbers && processNumbers.length > 0 ? this.findMissingNumber(processNumbers) : 1;
|
||||
}
|
||||
|
||||
findMissingNumber(processNumbers: number[]) {
|
||||
for (let missingNumber = 1; missingNumber < Math.max(...processNumbers); missingNumber++) {
|
||||
if (!processNumbers.find((number) => number === missingNumber)) {
|
||||
return missingNumber;
|
||||
}
|
||||
}
|
||||
return Math.max(...processNumbers) + 1;
|
||||
}
|
||||
}
|
||||
24
apps/isa-app/src/app/guards/can-activate-goods-in.guard.ts
Normal file
24
apps/isa-app/src/app/guards/can-activate-goods-in.guard.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { Config } from '@core/config';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivateGoodsInGuard {
|
||||
constructor(private readonly _applicationService: ApplicationService, private readonly _config: Config) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const process = await this._applicationService.getProcessById$(this._config.get('process.ids.goodsIn')).pipe(first()).toPromise();
|
||||
if (!process) {
|
||||
await this._applicationService.createProcess({
|
||||
id: this._config.get('process.ids.goodsIn'),
|
||||
type: 'goods-in',
|
||||
section: 'branch',
|
||||
name: '',
|
||||
});
|
||||
}
|
||||
this._applicationService.activateProcess(this._config.get('process.ids.goodsIn'));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
import { ApplicationProcess, ApplicationService } from '@core/application';
|
||||
import { BreadcrumbService } from '@core/breadcrumb';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivateGoodsOutWithProcessIdGuard {
|
||||
constructor(private readonly _applicationService: ApplicationService, private readonly _breadcrumbService: BreadcrumbService) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const process = await this._applicationService
|
||||
.getProcessById$(+route.params.processId)
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
|
||||
if (!process) {
|
||||
// const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||
await this._applicationService.createProcess({
|
||||
id: +route.params.processId,
|
||||
type: 'goods-out',
|
||||
section: 'customer',
|
||||
name: `Warenausgabe`,
|
||||
});
|
||||
}
|
||||
|
||||
await this.removeBreadcrumbWithSameProcessId(route);
|
||||
this._applicationService.activateProcess(+route.params.processId);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fix #3292: Alle Breadcrumbs die nichts mit dem aktuellen Prozess zu tun haben, müssen removed werden
|
||||
async removeBreadcrumbWithSameProcessId(route: ActivatedRouteSnapshot) {
|
||||
const crumbs = await this._breadcrumbService
|
||||
.getBreadcrumbByKey$(+route.params.processId)
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
|
||||
// Entferne alle Crumbs die nichts mit der Warenausgabe zu tun haben
|
||||
if (crumbs.length > 1) {
|
||||
const crumbsToRemove = crumbs.filter((crumb) => crumb.tags.find((tag) => tag === 'goods-out') === undefined);
|
||||
for (const crumb of crumbsToRemove) {
|
||||
await this._breadcrumbService.removeBreadcrumb(crumb.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processNumber(processes: ApplicationProcess[]) {
|
||||
const processNumbers = processes?.map((process) => Number(process?.name?.replace(/\D/g, '')));
|
||||
return !!processNumbers && processNumbers?.length > 0 ? Math.max(...processNumbers) + 1 : 1;
|
||||
}
|
||||
}
|
||||
183
apps/isa-app/src/app/guards/can-activate-goods-out.guard.ts
Normal file
183
apps/isa-app/src/app/guards/can-activate-goods-out.guard.ts
Normal file
@@ -0,0 +1,183 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';
|
||||
import { ApplicationProcess, ApplicationService } from '@core/application';
|
||||
import { DomainCheckoutService } from '@domain/checkout';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivateGoodsOutGuard {
|
||||
constructor(
|
||||
private readonly _applicationService: ApplicationService,
|
||||
private readonly _checkoutService: DomainCheckoutService,
|
||||
private readonly _router: Router
|
||||
) {}
|
||||
|
||||
// !!! Ticket #3272 Code soll vorerst bestehen bleiben. Prozess Warenausgabe soll wieder Vorgang heißen (wie aktuell im Produktiv), bis zum neuen Navigationskonzept
|
||||
// -----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
// const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||
|
||||
// let lastActivatedProcessId = (
|
||||
// await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'goods-out').pipe(first()).toPromise()
|
||||
// )?.id;
|
||||
|
||||
// const lastActivatedCartProcessId = (
|
||||
// await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart').pipe(first()).toPromise()
|
||||
// )?.id;
|
||||
|
||||
// const lastActivatedCartCheckoutProcessId = (
|
||||
// await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout').pipe(first()).toPromise()
|
||||
// )?.id;
|
||||
|
||||
// const activatedProcessId = await this._applicationService.getActivatedProcessId$().pipe(first()).toPromise();
|
||||
|
||||
// // Darf nur reinkommen wenn der aktuell aktive Tab ein Bestellabschluss Tab ist
|
||||
// if (!!lastActivatedCartProcessId && lastActivatedCartProcessId === activatedProcessId) {
|
||||
// await this.fromCartProcess(processes, route, lastActivatedCartProcessId);
|
||||
// return false;
|
||||
// } else if (!!lastActivatedCartCheckoutProcessId && lastActivatedCartCheckoutProcessId === activatedProcessId) {
|
||||
// await this.fromCartCheckoutProcess(processes, route, lastActivatedCartCheckoutProcessId);
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// if (!lastActivatedProcessId) {
|
||||
// await this.fromGoodsOutProcess(processes, route);
|
||||
// return false;
|
||||
// } else {
|
||||
// await this._router.navigate(this.getUrlFromSnapshot(route, ['/kunde', String(lastActivatedProcessId)]));
|
||||
// }
|
||||
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// // Bei offener Warenausgabe und Klick auf Footer Warenausgabe
|
||||
// async fromGoodsOutProcess(processes: ApplicationProcess[], route: ActivatedRouteSnapshot) {
|
||||
// const newProcessId = Date.now();
|
||||
// await this._applicationService.createProcess({
|
||||
// id: newProcessId,
|
||||
// type: 'goods-out',
|
||||
// section: 'customer',
|
||||
// name: `Warenausgabe ${this.processNumber(processes.filter((process) => process.type === 'goods-out'))}`,
|
||||
// });
|
||||
|
||||
// await this._router.navigate(this.getUrlFromSnapshot(route, ['/kunde', String(newProcessId)]));
|
||||
// }
|
||||
|
||||
// // Bei offener Artikelsuche/Kundensuche und Klick auf Footer Warenausgabe
|
||||
// async fromCartProcess(processes: ApplicationProcess[], route: ActivatedRouteSnapshot, processId: number) {
|
||||
// // Ändere type cart zu goods-out
|
||||
// this._applicationService.patchProcess(processId, {
|
||||
// id: processId,
|
||||
// type: 'goods-out',
|
||||
// section: 'customer',
|
||||
// name: `Warenausgabe ${this.processNumber(processes.filter((process) => process.type === 'goods-out'))}`,
|
||||
// });
|
||||
|
||||
// // Navigation
|
||||
// await this._router.navigate(this.getUrlFromSnapshot(route, ['/kunde', String(processId)]));
|
||||
// }
|
||||
|
||||
// // Bei offener Bestellbestätigung, Artikelsuche/Kundensuche und Klick auf Footer Warenausgabe
|
||||
// async fromCartCheckoutProcess(processes: ApplicationProcess[], route: ActivatedRouteSnapshot, processId: number) {
|
||||
// // Um alle Checkout Daten zu resetten die mit dem Prozess assoziiert sind
|
||||
// this._checkoutService.removeProcess({ processId });
|
||||
|
||||
// // Ändere type cart-checkout zu goods-out
|
||||
// this._applicationService.patchProcess(processId, {
|
||||
// id: processId,
|
||||
// type: 'goods-out',
|
||||
// section: 'customer',
|
||||
// name: `Warenausgabe ${this.processNumber(processes.filter((process) => process.type === 'goods-out'))}`,
|
||||
// data: {},
|
||||
// });
|
||||
|
||||
// // Navigation
|
||||
// await this._router.navigate(this.getUrlFromSnapshot(route, ['/kunde', String(processId)]));
|
||||
// }
|
||||
|
||||
// !!! Ticket #3272 Code soll vorerst bestehen bleiben. Prozess Warenausgabe soll wieder Vorgang heißen (wie aktuell im Produktiv), bis zum neuen Navigationskonzept
|
||||
// -----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||
|
||||
let lastActivatedProcessId = (
|
||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart').pipe(first()).toPromise()
|
||||
)?.id;
|
||||
|
||||
const lastActivatedCartCheckoutProcessId = (
|
||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout').pipe(first()).toPromise()
|
||||
)?.id;
|
||||
|
||||
const activatedProcessId = await this._applicationService.getActivatedProcessId$().pipe(first()).toPromise();
|
||||
|
||||
// Darf nur reinkommen wenn der aktuell aktive Tab ein Bestellabschluss Tab ist
|
||||
if (!!lastActivatedCartCheckoutProcessId && lastActivatedCartCheckoutProcessId === activatedProcessId) {
|
||||
await this.fromCartCheckoutProcess(processes, route, lastActivatedCartCheckoutProcessId);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!lastActivatedProcessId) {
|
||||
await this.fromGoodsOutProcess(processes, route);
|
||||
return false;
|
||||
} else {
|
||||
await this._router.navigate(this.getUrlFromSnapshot(route, ['/kunde', String(lastActivatedProcessId)]));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bei offener Warenausgabe und Klick auf Footer Warenausgabe
|
||||
async fromGoodsOutProcess(processes: ApplicationProcess[], route: ActivatedRouteSnapshot) {
|
||||
const newProcessId = Date.now();
|
||||
await this._applicationService.createProcess({
|
||||
id: newProcessId,
|
||||
type: 'cart',
|
||||
section: 'customer',
|
||||
name: `Vorgang ${this.processNumber(processes.filter((process) => process.type === 'cart'))}`,
|
||||
});
|
||||
|
||||
await this._router.navigate(this.getUrlFromSnapshot(route, ['/kunde', String(newProcessId)]));
|
||||
}
|
||||
|
||||
// Bei offener Bestellbestätigung und Klick auf Footer Warenausgabe
|
||||
async fromCartCheckoutProcess(processes: ApplicationProcess[], route: ActivatedRouteSnapshot, processId: number) {
|
||||
// Um alle Checkout Daten zu resetten die mit dem Prozess assoziiert sind
|
||||
this._checkoutService.removeProcess({ processId });
|
||||
|
||||
// Ändere type cart-checkout zu goods-out
|
||||
this._applicationService.patchProcess(processId, {
|
||||
id: processId,
|
||||
type: 'cart',
|
||||
section: 'customer',
|
||||
name: `Vorgang ${this.processNumber(processes.filter((process) => process.type === 'cart'))}`,
|
||||
data: {},
|
||||
});
|
||||
|
||||
// Navigation
|
||||
await this._router.navigate(this.getUrlFromSnapshot(route, ['/kunde', String(processId)]));
|
||||
}
|
||||
|
||||
getUrlFromSnapshot(route: ActivatedRouteSnapshot, url: string[] = []): string[] {
|
||||
url.push(...route.url.map((segment) => segment.path));
|
||||
if (route.firstChild) {
|
||||
return this.getUrlFromSnapshot(route.firstChild, url);
|
||||
}
|
||||
return url.filter((segment) => !!segment);
|
||||
}
|
||||
|
||||
processNumber(processes: ApplicationProcess[]) {
|
||||
const processNumbers = processes?.map((process) => Number(process?.name?.replace(/\D/g, '')));
|
||||
return !!processNumbers && processNumbers.length > 0 ? this.findMissingNumber(processNumbers) : 1;
|
||||
}
|
||||
|
||||
findMissingNumber(processNumbers: number[]) {
|
||||
for (let missingNumber = 1; missingNumber < Math.max(...processNumbers); missingNumber++) {
|
||||
if (!processNumbers.find((number) => number === missingNumber)) {
|
||||
return missingNumber;
|
||||
}
|
||||
}
|
||||
return Math.max(...processNumbers) + 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { Config } from '@core/config';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivatePackageInspectionGuard {
|
||||
constructor(private readonly _applicationService: ApplicationService, private readonly _config: Config) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const process = await this._applicationService
|
||||
.getProcessById$(this._config.get('process.ids.packageInspection'))
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
if (!process) {
|
||||
await this._applicationService.createProcess({
|
||||
id: this._config.get('process.ids.packageInspection'),
|
||||
type: 'package-inspection',
|
||||
section: 'branch',
|
||||
name: 'Packstück-Kontrolle',
|
||||
});
|
||||
}
|
||||
this._applicationService.activateProcess(this._config.get('process.ids.packageInspection'));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
import { ApplicationProcess, ApplicationService } from '@core/application';
|
||||
import { BreadcrumbService } from '@core/breadcrumb';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivateProductWithProcessIdGuard {
|
||||
constructor(private readonly _applicationService: ApplicationService, private readonly _breadcrumbService: BreadcrumbService) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const process = await this._applicationService
|
||||
.getProcessById$(+route.params.processId)
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
|
||||
// if (!(process?.type === 'cart')) {
|
||||
// // TODO:
|
||||
// // Anderer Prozesstyp mit gleicher Id - Was soll gemacht werden?
|
||||
// return false;
|
||||
// }
|
||||
|
||||
if (!process) {
|
||||
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||
await this._applicationService.createProcess({
|
||||
id: +route.params.processId,
|
||||
type: 'cart',
|
||||
section: 'customer',
|
||||
name: `Vorgang ${this.processNumber(processes.filter((process) => process.type === 'cart'))}`,
|
||||
});
|
||||
}
|
||||
|
||||
await this.removeBreadcrumbWithSameProcessId(route);
|
||||
this._applicationService.activateProcess(+route.params.processId);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fix #3292: Alle Breadcrumbs die nichts mit dem aktuellen Prozess zu tun haben, müssen removed werden
|
||||
async removeBreadcrumbWithSameProcessId(route: ActivatedRouteSnapshot) {
|
||||
const crumbs = await this._breadcrumbService
|
||||
.getBreadcrumbByKey$(+route.params.processId)
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
|
||||
// Entferne alle Crumbs die nichts mit der Artikelsuche zu tun haben
|
||||
if (crumbs.length > 1) {
|
||||
const crumbsToRemove = crumbs.filter((crumb) => crumb.tags.find((tag) => tag === 'catalog') === undefined);
|
||||
for (const crumb of crumbsToRemove) {
|
||||
await this._breadcrumbService.removeBreadcrumb(crumb.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processNumber(processes: ApplicationProcess[]) {
|
||||
const processNumbers = processes?.map((process) => Number(process?.name?.replace(/\D/g, '')));
|
||||
return !!processNumbers && processNumbers.length > 0 ? this.findMissingNumber(processNumbers) : 1;
|
||||
}
|
||||
|
||||
findMissingNumber(processNumbers: number[]) {
|
||||
// Ticket #3272 Bei Klick auf "+" bzw. neuen Prozess hinzufügen soll der neue Tab immer die höchste Nummer haben (wie aktuell im Produktiv)
|
||||
// ----------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// for (let missingNumber = 1; missingNumber < Math.max(...processNumbers); missingNumber++) {
|
||||
// if (!processNumbers.find((number) => number === missingNumber)) {
|
||||
// return missingNumber;
|
||||
// }
|
||||
// }
|
||||
return Math.max(...processNumbers) + 1;
|
||||
}
|
||||
}
|
||||
127
apps/isa-app/src/app/guards/can-activate-product.guard.ts
Normal file
127
apps/isa-app/src/app/guards/can-activate-product.guard.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
import { ApplicationProcess, ApplicationService } from '@core/application';
|
||||
import { DomainCheckoutService } from '@domain/checkout';
|
||||
import { ProductCatalogNavigationService } from '@shared/services/navigation';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivateProductGuard {
|
||||
constructor(
|
||||
private readonly _applicationService: ApplicationService,
|
||||
private readonly _checkoutService: DomainCheckoutService,
|
||||
private readonly _navigationService: ProductCatalogNavigationService,
|
||||
) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
|
||||
let lastActivatedProcessId = (
|
||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart').pipe(first()).toPromise()
|
||||
)?.id;
|
||||
|
||||
const lastActivatedCartCheckoutProcessId = (
|
||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout').pipe(first()).toPromise()
|
||||
)?.id;
|
||||
|
||||
const lastActivatedGoodsOutProcessId = (
|
||||
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'goods-out').pipe(first()).toPromise()
|
||||
)?.id;
|
||||
|
||||
const activatedProcessId = await this._applicationService.getActivatedProcessId$().pipe(first()).toPromise();
|
||||
|
||||
// Darf nur reinkommen wenn der aktuell aktive Tab ein Bestellabschluss Tab ist
|
||||
if (!!lastActivatedCartCheckoutProcessId && lastActivatedCartCheckoutProcessId === activatedProcessId) {
|
||||
await this.fromCartCheckoutProcess(processes, route, lastActivatedCartCheckoutProcessId);
|
||||
return false;
|
||||
} else if (!!lastActivatedGoodsOutProcessId && lastActivatedGoodsOutProcessId === activatedProcessId) {
|
||||
await this.fromGoodsOutProcess(processes, route, lastActivatedGoodsOutProcessId);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!lastActivatedProcessId) {
|
||||
await this.fromCartProcess(processes);
|
||||
return false;
|
||||
} else {
|
||||
await this._navigationService.getArticleSearchBasePath(lastActivatedProcessId).navigate();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bei offener Artikelsuche/Kundensuche und Klick auf Footer Artikelsuche
|
||||
async fromCartProcess(processes: ApplicationProcess[]) {
|
||||
const newProcessId = Date.now();
|
||||
await this._applicationService.createProcess({
|
||||
id: newProcessId,
|
||||
type: 'cart',
|
||||
section: 'customer',
|
||||
name: `Vorgang ${this.processNumber(processes.filter((process) => process.type === 'cart'))}`,
|
||||
});
|
||||
|
||||
await this._navigationService.getArticleSearchBasePath(newProcessId).navigate();
|
||||
}
|
||||
|
||||
// Bei offener Warenausgabe und Klick auf Footer Artikelsuche
|
||||
async fromGoodsOutProcess(processes: ApplicationProcess[], route: ActivatedRouteSnapshot, processId: number) {
|
||||
const buyer = await this._checkoutService.getBuyer({ processId }).pipe(first()).toPromise();
|
||||
const customerFeatures = await this._checkoutService.getCustomerFeatures({ processId }).pipe(first()).toPromise();
|
||||
const name = buyer
|
||||
? customerFeatures?.b2b
|
||||
? buyer.organisation?.name
|
||||
? buyer.organisation?.name
|
||||
: buyer.lastName
|
||||
: buyer.lastName
|
||||
: `Vorgang ${this.processNumber(processes.filter((process) => process.type === 'cart'))}`;
|
||||
|
||||
// Ändere type goods-out zu cart
|
||||
this._applicationService.patchProcess(processId, {
|
||||
id: processId,
|
||||
type: 'cart',
|
||||
section: 'customer',
|
||||
name,
|
||||
});
|
||||
|
||||
// Navigation
|
||||
await this._navigationService.getArticleSearchBasePath(processId).navigate();
|
||||
}
|
||||
|
||||
// Bei offener Bestellbestätigung und Klick auf Footer Artikelsuche
|
||||
async fromCartCheckoutProcess(processes: ApplicationProcess[], route: ActivatedRouteSnapshot, processId: number) {
|
||||
// Um alle Checkout Daten zu resetten die mit dem Prozess assoziiert sind
|
||||
this._checkoutService.removeProcess({ processId });
|
||||
|
||||
// Ändere type cart-checkout zu cart
|
||||
this._applicationService.patchProcess(processId, {
|
||||
id: processId,
|
||||
type: 'cart',
|
||||
section: 'customer',
|
||||
name: `Vorgang ${this.processNumber(processes.filter((process) => process.type === 'cart'))}`,
|
||||
data: {},
|
||||
});
|
||||
|
||||
// Navigation
|
||||
await this._navigationService.getArticleSearchBasePath(processId).navigate();
|
||||
}
|
||||
|
||||
getUrlFromSnapshot(route: ActivatedRouteSnapshot, url: string[] = []): string[] {
|
||||
url.push(...route.url.map((segment) => segment.path));
|
||||
if (route.firstChild) {
|
||||
return this.getUrlFromSnapshot(route.firstChild, url);
|
||||
}
|
||||
return url.filter((segment) => !!segment);
|
||||
}
|
||||
|
||||
processNumber(processes: ApplicationProcess[]) {
|
||||
const processNumbers = processes?.map((process) => Number(process?.name?.replace(/\D/g, '')));
|
||||
return !!processNumbers && processNumbers.length > 0 ? this.findMissingNumber(processNumbers) : 1;
|
||||
}
|
||||
|
||||
findMissingNumber(processNumbers: number[]) {
|
||||
for (let missingNumber = 1; missingNumber < Math.max(...processNumbers); missingNumber++) {
|
||||
if (!processNumbers.find((number) => number === missingNumber)) {
|
||||
return missingNumber;
|
||||
}
|
||||
}
|
||||
return Math.max(...processNumbers) + 1;
|
||||
}
|
||||
}
|
||||
36
apps/isa-app/src/app/guards/can-activate-remission.guard.ts
Normal file
36
apps/isa-app/src/app/guards/can-activate-remission.guard.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { Config } from '@core/config';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivateRemissionGuard {
|
||||
constructor(
|
||||
private readonly _applicationService: ApplicationService,
|
||||
private readonly _config: Config,
|
||||
private readonly _router: Router
|
||||
) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const process = await this._applicationService.getProcessById$(this._config.get('process.ids.remission')).pipe(first()).toPromise();
|
||||
if (!process) {
|
||||
await this._applicationService.createProcess({
|
||||
id: this._config.get('process.ids.remission'),
|
||||
type: 'remission',
|
||||
section: 'branch',
|
||||
name: 'Remission',
|
||||
});
|
||||
}
|
||||
|
||||
this._applicationService.activateProcess(this._config.get('process.ids.remission'));
|
||||
|
||||
if (!!process?.data?.active && !state.url.includes(`/filiale/remission/${process?.data?.active}`)) {
|
||||
const queryParams = process?.data?.queryParams ?? {};
|
||||
await this._router.navigate(['/filiale', 'remission', process?.data?.active, 'list'], { queryParams });
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { Config } from '@core/config';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CanActivateTaskCalendarGuard {
|
||||
constructor(private readonly _applicationService: ApplicationService, private readonly _config: Config) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const process = await this._applicationService.getProcessById$(this._config.get('process.ids.taskCalendar')).pipe(first()).toPromise();
|
||||
if (!process) {
|
||||
await this._applicationService.createProcess({
|
||||
id: this._config.get('process.ids.taskCalendar'),
|
||||
type: 'task-calendar',
|
||||
section: 'branch',
|
||||
name: 'Tätigkeitskalender',
|
||||
});
|
||||
}
|
||||
this._applicationService.activateProcess(this._config.get('process.ids.taskCalendar'));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
14
apps/isa-app/src/app/guards/index.ts
Normal file
14
apps/isa-app/src/app/guards/index.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
export * from './can-activate-cart-with-process-id.guard';
|
||||
export * from './can-activate-cart.guard';
|
||||
export * from './can-activate-customer-with-process-id.guard';
|
||||
export * from './can-activate-customer.guard';
|
||||
export * from './can-activate-goods-in.guard';
|
||||
export * from './can-activate-goods-out-with-process-id.guard';
|
||||
export * from './can-activate-goods-out.guard';
|
||||
export * from './can-activate-customer-orders.guard';
|
||||
export * from './can-activate-customer-orders-with-process-id.guard';
|
||||
export * from './can-activate-product-with-process-id.guard';
|
||||
export * from './can-activate-product.guard';
|
||||
export * from './can-activate-remission.guard';
|
||||
export * from './can-activate-task-calendar.guard';
|
||||
export * from './is-authenticated.guard';
|
||||
94
apps/isa-app/src/app/guards/is-authenticated.guard.ts
Normal file
94
apps/isa-app/src/app/guards/is-authenticated.guard.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';
|
||||
import { AuthService } from '@core/auth';
|
||||
import { ScanAdapterService } from '@adapter/scan';
|
||||
import { AuthService as IsaAuthService } from '@swagger/isa';
|
||||
import { UiConfirmModalComponent, UiErrorModalComponent, UiModalResult, UiModalService } from '@ui/modal';
|
||||
import { EnvironmentService } from '@core/environment';
|
||||
import { injectNetworkStatus$ } from '../services/network-status.service';
|
||||
import { toSignal } from '@angular/core/rxjs-interop';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class IsAuthenticatedGuard {
|
||||
constructor(
|
||||
private _router: Router,
|
||||
private _authService: AuthService,
|
||||
private _scanService: ScanAdapterService,
|
||||
private _isaAuthService: IsaAuthService,
|
||||
private _modal: UiModalService,
|
||||
private _environmentService: EnvironmentService,
|
||||
) {}
|
||||
|
||||
networkStatus = toSignal(injectNetworkStatus$());
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const authenticated = await this._authService.isAuthenticated();
|
||||
|
||||
if (!authenticated) {
|
||||
const token = await this.scanAndGetToken();
|
||||
|
||||
if (token) {
|
||||
this._authService.setKeyCardToken(token);
|
||||
}
|
||||
this._authService.login();
|
||||
}
|
||||
|
||||
return authenticated;
|
||||
}
|
||||
|
||||
async scanAndGetToken(): Promise<string> {
|
||||
if (this._environmentService.isDesktop()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let loginModalResult: UiModalResult<any>;
|
||||
|
||||
do {
|
||||
const loginModal = this._modal.open({
|
||||
content: UiConfirmModalComponent,
|
||||
title: 'Anmeldung',
|
||||
data: {
|
||||
message: 'Bitte wählen Sie die Anmeldeoption aus.',
|
||||
rejectLabel: 'Anmeldung mit Logindaten',
|
||||
confirmLabel: 'Anmeldung mit Keycard',
|
||||
},
|
||||
});
|
||||
|
||||
loginModalResult = await loginModal.afterClosed$.toPromise();
|
||||
} while (this.networkStatus() === 'offline');
|
||||
|
||||
if (!loginModalResult.data) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const result = await this._scanService.scan()?.toPromise();
|
||||
|
||||
if (typeof result === 'string') {
|
||||
try {
|
||||
const res = await this._isaAuthService
|
||||
.AuthLogin({
|
||||
code: result,
|
||||
application: 'isa',
|
||||
hostname: location.host,
|
||||
})
|
||||
.toPromise();
|
||||
|
||||
return res.token;
|
||||
} catch (error) {
|
||||
const errorModalRef = this._modal.open({
|
||||
content: UiErrorModalComponent,
|
||||
title: 'Fehler bei der Anmeldung',
|
||||
data: {
|
||||
message: 'Versuchen Sie es erneut\noder melden Sie sich mit\nIhren Benutzerdaten an.',
|
||||
},
|
||||
});
|
||||
|
||||
await errorModalRef.afterClosed$.toPromise();
|
||||
|
||||
return this.scanAndGetToken();
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
33
apps/isa-app/src/app/guards/process-id.guard.ts
Normal file
33
apps/isa-app/src/app/guards/process-id.guard.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { inject } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivateFn, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { take } from 'rxjs/operators';
|
||||
|
||||
export const ProcessIdGuard: CanActivateFn = async (
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot
|
||||
): Promise<boolean | UrlTree> => {
|
||||
const application = inject(ApplicationService);
|
||||
const router = inject(Router);
|
||||
|
||||
const process = await application.getLastActivatedProcessWithSection$('customer').pipe(take(1)).toPromise();
|
||||
|
||||
const processId = process?.id ?? Date.now();
|
||||
|
||||
const originalUrl = state.url?.split('?')[0] ?? '';
|
||||
|
||||
let url: string = '';
|
||||
|
||||
if (originalUrl.startsWith('/kunde')) {
|
||||
url = originalUrl.replace('/kunde', `/kunde/${processId}`);
|
||||
} else {
|
||||
url = originalUrl;
|
||||
}
|
||||
|
||||
if (originalUrl === url) {
|
||||
return true;
|
||||
}
|
||||
|
||||
await router.navigateByUrl(url);
|
||||
return false;
|
||||
};
|
||||
@@ -0,0 +1,66 @@
|
||||
// import { HttpErrorInterceptor } from './http-error.interceptor';
|
||||
// import { createServiceFactory, SpectatorService } from '@ngneat/spectator';
|
||||
// import { UiMessageModalComponent, UiModalResult, UiModalService } from '@ui/modal';
|
||||
// import { of, Subject, throwError } from 'rxjs';
|
||||
// import { HttpErrorResponse } from '@angular/common/http';
|
||||
// import { AuthService } from '@core/auth';
|
||||
|
||||
// describe('HttpErrorInterceptor', () => {
|
||||
// let spectator: SpectatorService<HttpErrorInterceptor>;
|
||||
// let modalMock: jasmine.SpyObj<UiModalService>;
|
||||
// let httpErrorInterceptor: HttpErrorInterceptor;
|
||||
|
||||
// const createService = createServiceFactory({
|
||||
// service: HttpErrorInterceptor,
|
||||
// mocks: [UiModalService, AuthService],
|
||||
// });
|
||||
|
||||
// beforeEach(() => {
|
||||
// spectator = createService();
|
||||
// httpErrorInterceptor = spectator.service;
|
||||
// modalMock = spectator.inject(UiModalService);
|
||||
|
||||
// modalMock.open.and.returnValue({
|
||||
// afterClosed$: of({} as UiModalResult<any>),
|
||||
// } as any);
|
||||
// });
|
||||
|
||||
// it('should be created', () => {
|
||||
// expect(httpErrorInterceptor).toBeTruthy();
|
||||
// });
|
||||
|
||||
// describe('intercept', () => {
|
||||
// it('should catch the error and call handleError', (done) => {
|
||||
// const error = new HttpErrorResponse({
|
||||
// status: 0,
|
||||
// statusText: '',
|
||||
// url: '',
|
||||
// });
|
||||
|
||||
// const handleErrorSpy = spyOn(httpErrorInterceptor, 'handleError').and.callThrough();
|
||||
// httpErrorInterceptor.intercept(null, { handle: () => throwError(error) }).subscribe({
|
||||
// error: () => {
|
||||
// expect(handleErrorSpy).toHaveBeenCalledWith(error);
|
||||
// done();
|
||||
// },
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
// describe('handleError', () => {
|
||||
// it('should call modal.open with offline message if status is 0', () => {
|
||||
// const error = {
|
||||
// error: {
|
||||
// message: 'test',
|
||||
// },
|
||||
// status: 0,
|
||||
// };
|
||||
// httpErrorInterceptor.handleError(error as any);
|
||||
// expect(modalMock.open).toHaveBeenCalledWith({
|
||||
// content: UiMessageModalComponent,
|
||||
// title: 'Sie sind offline, keine Verbindung zum Netzwerk',
|
||||
// data: { message: 'Bereits geladene Inhalte werden angezeigt. Interaktionen sind aktuell nicht möglich.' },
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
50
apps/isa-app/src/app/interceptors/http-error.interceptor.ts
Normal file
50
apps/isa-app/src/app/interceptors/http-error.interceptor.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpInterceptor, HttpEvent, HttpHandler, HttpRequest, HttpErrorResponse } from '@angular/common/http';
|
||||
import { NEVER, Observable, throwError } from 'rxjs';
|
||||
import { UiMessageModalComponent, UiModalService } from '@ui/modal';
|
||||
import { catchError, filter, mergeMap, takeUntil, tap } from 'rxjs/operators';
|
||||
import { AuthService } from '@core/auth';
|
||||
import { IsaLogProvider } from '../providers';
|
||||
import { LogLevel } from '@core/logger';
|
||||
import { injectOnline$ } from '../services/network-status.service';
|
||||
|
||||
@Injectable()
|
||||
export class HttpErrorInterceptor implements HttpInterceptor {
|
||||
readonly offline$ = injectOnline$().pipe(filter((online) => !online));
|
||||
|
||||
constructor(
|
||||
private _modal: UiModalService,
|
||||
private _auth: AuthService,
|
||||
private _isaLogProvider: IsaLogProvider,
|
||||
) {}
|
||||
|
||||
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
return next.handle(req).pipe(
|
||||
takeUntil(this.offline$),
|
||||
catchError((error: HttpErrorResponse, caught: any) => this.handleError(error)),
|
||||
);
|
||||
}
|
||||
|
||||
handleError(error: HttpErrorResponse): Observable<any> {
|
||||
if (error.status === 401) {
|
||||
return this._modal
|
||||
.open({
|
||||
content: UiMessageModalComponent,
|
||||
title: 'Sie sind nicht mehr angemeldet',
|
||||
data: { message: 'Sie werden neu angemeldet' },
|
||||
})
|
||||
.afterClosed$.pipe(
|
||||
tap(() => {
|
||||
this._auth.login();
|
||||
}),
|
||||
mergeMap(() => NEVER),
|
||||
);
|
||||
}
|
||||
|
||||
if (!error.url.endsWith('/isa/logging')) {
|
||||
this._isaLogProvider.log(LogLevel.ERROR, 'Http Error', error);
|
||||
}
|
||||
|
||||
return throwError(error);
|
||||
}
|
||||
}
|
||||
3
apps/isa-app/src/app/interceptors/index.ts
Normal file
3
apps/isa-app/src/app/interceptors/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
// start:ng42.barrel
|
||||
export * from './http-error.interceptor';
|
||||
// end:ng42.barrel
|
||||
3
apps/isa-app/src/app/main.component.html
Normal file
3
apps/isa-app/src/app/main.component.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<shell-root>
|
||||
<router-outlet></router-outlet>
|
||||
</shell-root>
|
||||
10
apps/isa-app/src/app/main.component.ts
Normal file
10
apps/isa-app/src/app/main.component.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-main',
|
||||
templateUrl: 'main.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class MainComponent {
|
||||
constructor() {}
|
||||
}
|
||||
3
apps/isa-app/src/app/preview/index.ts
Normal file
3
apps/isa-app/src/app/preview/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
// start:ng42.barrel
|
||||
export * from './preview.component';
|
||||
// end:ng42.barrel
|
||||
3
apps/isa-app/src/app/preview/preview.component.css
Normal file
3
apps/isa-app/src/app/preview/preview.component.css
Normal file
@@ -0,0 +1,3 @@
|
||||
:host {
|
||||
@apply grid min-h-screen content-center justify-center;
|
||||
}
|
||||
10
apps/isa-app/src/app/preview/preview.component.html
Normal file
10
apps/isa-app/src/app/preview/preview.component.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<h1>Platform: {{ platform | json }}</h1>
|
||||
<br />
|
||||
<h1>{{ appVersion }}</h1>
|
||||
<br />
|
||||
<h1>{{ userAgent }}</h1>
|
||||
<br />
|
||||
<h1>Navigator: {{ navigator | json }}</h1>
|
||||
<br />
|
||||
<br />
|
||||
<h1>Device: {{ device }}</h1>
|
||||
60
apps/isa-app/src/app/preview/preview.component.ts
Normal file
60
apps/isa-app/src/app/preview/preview.component.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { Platform, PlatformModule } from '@angular/cdk/platform';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { BranchSelectorComponent } from '@shared/components/branch-selector';
|
||||
import { BranchDTO } from '@swagger/checkout';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'app-preview',
|
||||
templateUrl: 'preview.component.html',
|
||||
styleUrls: ['preview.component.css'],
|
||||
imports: [CommonModule, BranchSelectorComponent, PlatformModule],
|
||||
standalone: true,
|
||||
})
|
||||
export class PreviewComponent implements OnInit {
|
||||
selectedBranch$ = new BehaviorSubject<BranchDTO>({});
|
||||
|
||||
get appVersion() {
|
||||
return 'App Version: ' + (window.navigator as any).appVersion;
|
||||
}
|
||||
|
||||
get userAgent() {
|
||||
return 'User Agent: ' + (window.navigator as any).userAgent;
|
||||
}
|
||||
|
||||
get navigator() {
|
||||
const nav = {};
|
||||
for (let i in window.navigator) nav[i] = navigator[i];
|
||||
return nav;
|
||||
}
|
||||
|
||||
get platform() {
|
||||
return this._platform;
|
||||
}
|
||||
|
||||
get device() {
|
||||
const isIpadNative = this._platform.IOS && !this._platform.SAFARI;
|
||||
const isIpadMini6Native = window?.navigator?.userAgent?.includes('Macintosh') && !this._platform.SAFARI;
|
||||
const isNative = isIpadNative || isIpadMini6Native;
|
||||
const isPWA = this._platform.IOS && this._platform.SAFARI;
|
||||
const isDesktop = !isNative && !isPWA;
|
||||
if (isNative) {
|
||||
if (isIpadMini6Native) {
|
||||
return 'IPAD mini 6 Native App';
|
||||
} else if (isIpadNative) {
|
||||
return 'IPAD mini 2 Native App or IPAD mini 5 Native App';
|
||||
}
|
||||
} else if (isPWA) {
|
||||
return 'IPAD Safari PWA';
|
||||
} else if (isDesktop) return 'Desktop or Macintosh';
|
||||
}
|
||||
|
||||
constructor(private readonly _platform: Platform) {}
|
||||
|
||||
ngOnInit() {}
|
||||
|
||||
setNewBranch(branch: BranchDTO) {
|
||||
this.selectedBranch$.next(branch);
|
||||
}
|
||||
}
|
||||
3
apps/isa-app/src/app/providers/index.ts
Normal file
3
apps/isa-app/src/app/providers/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
// start:ng42.barrel
|
||||
export * from './isa.log-provider';
|
||||
// end:ng42.barrel
|
||||
53
apps/isa-app/src/app/providers/isa.error-handler.ts
Normal file
53
apps/isa-app/src/app/providers/isa.error-handler.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { ErrorHandler, Injectable } from '@angular/core';
|
||||
import { AuthService } from '@core/auth';
|
||||
import { DialogModel, UiDialogModalComponent, UiErrorModalComponent, UiModalService } from '@ui/modal';
|
||||
import { IsaLogProvider } from './isa.log-provider';
|
||||
import { LogLevel } from '@core/logger';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class IsaErrorHandler implements ErrorHandler {
|
||||
constructor(
|
||||
private _modal: UiModalService,
|
||||
private _authService: AuthService,
|
||||
private _isaLogProvider: IsaLogProvider,
|
||||
) {}
|
||||
|
||||
async handleError(error: any): Promise<void> {
|
||||
console.error(error);
|
||||
|
||||
// Bei Klick auf Abbrechen auf der Login Seite erneut zur Login Seite weiterleiten
|
||||
if (error?.type === 'token_error') {
|
||||
this._authService.login();
|
||||
return;
|
||||
}
|
||||
|
||||
if (error instanceof HttpErrorResponse && error?.status === 401) {
|
||||
await this._modal
|
||||
.open({
|
||||
content: UiDialogModalComponent,
|
||||
title: 'Sitzung abgelaufen',
|
||||
data: {
|
||||
handleCommand: false,
|
||||
content: 'Sie waren zu lange nicht in der ISA aktiv. Bitte melden Sie sich erneut an',
|
||||
actions: [{ command: 'CLOSE', selected: true, label: 'Erneut anmelden' }],
|
||||
} as DialogModel,
|
||||
})
|
||||
.afterClosed$.toPromise();
|
||||
|
||||
this._authService.logout();
|
||||
return;
|
||||
}
|
||||
|
||||
this._isaLogProvider.log(LogLevel.ERROR, 'Client Error', error);
|
||||
|
||||
// this._modal.open({
|
||||
// content: UiErrorModalComponent,
|
||||
// title:
|
||||
// !navigator.onLine || (error instanceof HttpErrorResponse && error?.status === 0)
|
||||
// ? 'Sie sind offline, keine Verbindung zum Netzwerk'
|
||||
// : 'Unbekannter Fehler',
|
||||
// data: error,
|
||||
// });
|
||||
}
|
||||
}
|
||||
28
apps/isa-app/src/app/providers/isa.log-provider.ts
Normal file
28
apps/isa-app/src/app/providers/isa.log-provider.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { LogLevel, LogProvider } from '@core/logger';
|
||||
import { UserStateService } from '@swagger/isa';
|
||||
import { environment } from '../../environments/environment';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class IsaLogProvider implements LogProvider {
|
||||
static InfoService: UserStateService | undefined;
|
||||
|
||||
constructor() {}
|
||||
|
||||
log(logLevel: LogLevel, message: string, error: Error, ...optionalParams: any[]): void {
|
||||
if (!environment.production && (logLevel === LogLevel.WARN || logLevel === LogLevel.ERROR)) {
|
||||
IsaLogProvider.InfoService?.UserStateSaveLog({
|
||||
logType: logLevel,
|
||||
message: message,
|
||||
content: JSON.stringify({
|
||||
error: error?.name,
|
||||
message: error?.message,
|
||||
stack: error?.stack,
|
||||
data: optionalParams,
|
||||
}),
|
||||
})
|
||||
.toPromise()
|
||||
.catch(() => {});
|
||||
}
|
||||
}
|
||||
}
|
||||
4
apps/isa-app/src/app/resolvers/index.ts
Normal file
4
apps/isa-app/src/app/resolvers/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
// start:ng42.barrel
|
||||
export * from './process-id.resolver';
|
||||
export * from './section.resolver';
|
||||
// end:ng42.barrel
|
||||
12
apps/isa-app/src/app/resolvers/process-id.resolver.ts
Normal file
12
apps/isa-app/src/app/resolvers/process-id.resolver.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot } from '@angular/router';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ProcessIdResolver {
|
||||
constructor() {}
|
||||
|
||||
resolve(route: ActivatedRouteSnapshot): Observable<number> | Promise<number> | number {
|
||||
return route.params.processId;
|
||||
}
|
||||
}
|
||||
27
apps/isa-app/src/app/resolvers/section.resolver.ts
Normal file
27
apps/isa-app/src/app/resolvers/section.resolver.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot } from '@angular/router';
|
||||
import { ApplicationService } from '@core/application';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
export abstract class SectionResolver {
|
||||
constructor(protected section: 'customer' | 'branch', protected applicationService: ApplicationService) {}
|
||||
|
||||
resolve(route: ActivatedRouteSnapshot): Observable<string> | Promise<string> | string {
|
||||
this.applicationService.setSection(this.section);
|
||||
return this.section;
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CustomerSectionResolver extends SectionResolver {
|
||||
constructor(applicationService: ApplicationService) {
|
||||
super('customer', applicationService);
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class BranchSectionResolver extends SectionResolver {
|
||||
constructor(applicationService: ApplicationService) {
|
||||
super('branch', applicationService);
|
||||
}
|
||||
}
|
||||
25
apps/isa-app/src/app/services/network-status.service.ts
Normal file
25
apps/isa-app/src/app/services/network-status.service.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { map, Observable } from 'rxjs';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class NetworkStatusService {
|
||||
online$ = new Observable<boolean>((subscriber) => {
|
||||
const handler = () => subscriber.next(navigator.onLine);
|
||||
|
||||
window.addEventListener('online', handler);
|
||||
window.addEventListener('offline', handler);
|
||||
|
||||
handler();
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('online', handler);
|
||||
window.removeEventListener('offline', handler);
|
||||
};
|
||||
});
|
||||
|
||||
status$ = this.online$.pipe(map((online) => (online ? 'online' : 'offline')));
|
||||
}
|
||||
|
||||
export const injectNetworkStatus$ = () => inject(NetworkStatusService).status$;
|
||||
|
||||
export const injectOnline$ = () => inject(NetworkStatusService).online$;
|
||||
118
apps/isa-app/src/app/store/root-state.service.ts
Normal file
118
apps/isa-app/src/app/store/root-state.service.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Logger, LogLevel } from '@core/logger';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { UserStateService } from '@swagger/isa';
|
||||
import { debounceTime, switchMap, takeUntil } from 'rxjs/operators';
|
||||
import { RootState } from './root.state';
|
||||
import packageInfo from 'packageJson';
|
||||
import { environment } from '../../environments/environment';
|
||||
import { Subject } from 'rxjs';
|
||||
import { AuthService } from '@core/auth';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class RootStateService {
|
||||
static LOCAL_STORAGE_KEY = 'ISA_APP_INITIALSTATE';
|
||||
|
||||
private _cancelSave = new Subject<void>();
|
||||
|
||||
constructor(
|
||||
private readonly _authService: AuthService,
|
||||
private readonly _userStateService: UserStateService,
|
||||
private _logger: Logger,
|
||||
private _store: Store,
|
||||
) {
|
||||
if (!environment.production) {
|
||||
console.log('Die UserState kann in der Konsole mit der Funktion "clearUserState()" geleert werden.');
|
||||
}
|
||||
|
||||
window['clearUserState'] = () => {
|
||||
this.clear();
|
||||
};
|
||||
}
|
||||
|
||||
async init() {
|
||||
await this.load();
|
||||
this._store.dispatch({ type: 'HYDRATE', payload: RootStateService.LoadFromLocalStorage() });
|
||||
this.initSave();
|
||||
}
|
||||
|
||||
initSave() {
|
||||
this._store
|
||||
.select((state) => state)
|
||||
.pipe(
|
||||
takeUntil(this._cancelSave),
|
||||
debounceTime(1000),
|
||||
switchMap((state) => {
|
||||
const raw = JSON.stringify({ ...state, version: packageInfo.version, sub: this._authService.getClaimByKey('sub') });
|
||||
RootStateService.SaveToLocalStorageRaw(raw);
|
||||
return this._userStateService.UserStateSetUserState({ content: raw });
|
||||
}),
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the initial state from local storage and returns true/false if state was changed
|
||||
*/
|
||||
async load(): Promise<boolean> {
|
||||
try {
|
||||
const res = await this._userStateService.UserStateGetUserState().toPromise();
|
||||
|
||||
const resContent = res?.result?.content ?? null;
|
||||
const storageContent = RootStateService.LoadFromLocalStorageRaw();
|
||||
|
||||
if (resContent) {
|
||||
RootStateService.SaveToLocalStorageRaw(res.result.content);
|
||||
}
|
||||
|
||||
if (resContent !== storageContent) {
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
this._logger.log(LogLevel.ERROR, error);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async clear() {
|
||||
try {
|
||||
this._cancelSave.next();
|
||||
await this._userStateService.UserStateResetUserState().toPromise();
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
RootStateService.RemoveFromLocalStorage();
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
window.location.reload();
|
||||
} catch (error) {
|
||||
this._logger.log(LogLevel.ERROR, error);
|
||||
}
|
||||
}
|
||||
|
||||
static SaveToLocalStorage(state: RootState) {
|
||||
RootStateService.SaveToLocalStorageRaw(JSON.stringify(state));
|
||||
}
|
||||
|
||||
static SaveToLocalStorageRaw(state: string) {
|
||||
localStorage.setItem(RootStateService.LOCAL_STORAGE_KEY, state);
|
||||
}
|
||||
|
||||
static LoadFromLocalStorage(): RootState {
|
||||
const raw = RootStateService.LoadFromLocalStorageRaw();
|
||||
if (raw) {
|
||||
try {
|
||||
return JSON.parse(raw);
|
||||
} catch (error) {
|
||||
console.error('Error parsing local storage:', error);
|
||||
this.RemoveFromLocalStorage();
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
static LoadFromLocalStorageRaw(): string {
|
||||
return localStorage.getItem(RootStateService.LOCAL_STORAGE_KEY);
|
||||
}
|
||||
|
||||
static RemoveFromLocalStorage() {
|
||||
localStorage.removeItem(RootStateService.LOCAL_STORAGE_KEY);
|
||||
}
|
||||
}
|
||||
4
apps/isa-app/src/app/store/root.reducer.ts
Normal file
4
apps/isa-app/src/app/store/root.reducer.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { ActionReducerMap } from '@ngrx/store';
|
||||
import { RootState } from './root.state';
|
||||
|
||||
export const rootReducer: ActionReducerMap<RootState> = {};
|
||||
3
apps/isa-app/src/app/store/root.state.ts
Normal file
3
apps/isa-app/src/app/store/root.state.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export interface RootState {
|
||||
version?: string;
|
||||
}
|
||||
2
apps/isa-app/src/app/token-login/index.ts
Normal file
2
apps/isa-app/src/app/token-login/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './token-login.component';
|
||||
export * from './token-login.module';
|
||||
24
apps/isa-app/src/app/token-login/token-login.component.ts
Normal file
24
apps/isa-app/src/app/token-login/token-login.component.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Component, ChangeDetectionStrategy, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { AuthService } from '@core/auth';
|
||||
|
||||
@Component({
|
||||
selector: 'app-token-login',
|
||||
templateUrl: 'token-login.component.html',
|
||||
styleUrls: ['token-login.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class TokenLoginComponent implements OnInit {
|
||||
constructor(private _route: ActivatedRoute, private _authService: AuthService, private _router: Router) {}
|
||||
|
||||
ngOnInit() {
|
||||
if (this._route.snapshot.params.token && !this._authService.isAuthenticated()) {
|
||||
this._authService.setKeyCardToken(this._route.snapshot.params.token);
|
||||
this._authService.login();
|
||||
} else if (!this._authService.isAuthenticated()) {
|
||||
this._authService.login();
|
||||
} else if (this._authService.isAuthenticated()) {
|
||||
this._router.navigate(['/']);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
apps/isa-app/src/app/token-login/token-login.module.ts
Normal file
11
apps/isa-app/src/app/token-login/token-login.module.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { TokenLoginComponent } from './token-login.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule],
|
||||
exports: [TokenLoginComponent],
|
||||
declarations: [TokenLoginComponent],
|
||||
})
|
||||
export class TokenLoginModule {}
|
||||
BIN
apps/isa-app/src/assets/fonts/Open_Sans-400-cyrillic-ext1.woff2
Normal file
BIN
apps/isa-app/src/assets/fonts/Open_Sans-400-cyrillic-ext1.woff2
Normal file
Binary file not shown.
BIN
apps/isa-app/src/assets/fonts/Open_Sans-400-cyrillic2.woff2
Normal file
BIN
apps/isa-app/src/assets/fonts/Open_Sans-400-cyrillic2.woff2
Normal file
Binary file not shown.
BIN
apps/isa-app/src/assets/fonts/Open_Sans-400-greek-ext3.woff2
Normal file
BIN
apps/isa-app/src/assets/fonts/Open_Sans-400-greek-ext3.woff2
Normal file
Binary file not shown.
BIN
apps/isa-app/src/assets/fonts/Open_Sans-400-greek4.woff2
Normal file
BIN
apps/isa-app/src/assets/fonts/Open_Sans-400-greek4.woff2
Normal file
Binary file not shown.
BIN
apps/isa-app/src/assets/fonts/Open_Sans-400-hebrew5.woff2
Normal file
BIN
apps/isa-app/src/assets/fonts/Open_Sans-400-hebrew5.woff2
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user