mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Compare commits
2225 Commits
ISA-1.0.88
...
2.0.531
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12fb774b73 | ||
|
|
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 | ||
|
|
ea15f1941e | ||
|
|
c7549b8594 | ||
|
|
a79e84fad8 | ||
|
|
c9d7faf9a1 | ||
|
|
d87ceb1f74 | ||
|
|
c8fa18ed29 | ||
|
|
2d5d461f02 | ||
|
|
87885cb0bd | ||
|
|
ad929324df | ||
|
|
ee2805332b | ||
|
|
c1c2f3c41f | ||
|
|
a618ff0b63 | ||
|
|
47e468b585 | ||
|
|
6729a86e02 | ||
|
|
c04f39f9df | ||
|
|
49793da5be | ||
|
|
c1b3e5f759 | ||
|
|
2a9d3419e6 | ||
|
|
b1cfa3639b | ||
|
|
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 | ||
|
|
2e4ddcb958 | ||
|
|
7704a2ba97 | ||
|
|
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 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -34,6 +34,7 @@ speed-measure-plugin.json
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage
|
||||
/testresults
|
||||
/libpeerconnection.log
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
|
||||
16
.npmrc
16
.npmrc
@@ -1,13 +1,3 @@
|
||||
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
|
||||
|
||||
@isa:registry=https://pkgs.dev.azure.com/hugendubel/_packaging/hugendubel%40Local/npm/registry/
|
||||
@cmf:registry=https://pkgs.dev.azure.com/hugendubel/_packaging/hugendubel%40Local/npm/registry/
|
||||
always-auth=true
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
8
.vscode/extensions.json
vendored
Normal file
8
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"johnpapa.angular2",
|
||||
"esbenp.prettier-vscode",
|
||||
"angular.ng-template",
|
||||
"eg2.vscode-npm-script"
|
||||
]
|
||||
}
|
||||
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:14 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 test || true
|
||||
ENTRYPOINT [ "/bin/sleep", "60000" ]
|
||||
|
||||
|
||||
4
TASKS.md
Normal file
4
TASKS.md
Normal file
@@ -0,0 +1,4 @@
|
||||
- Neue Icon Module (z.B. mit SVG sprites)
|
||||
- Breadcrumb Navigation (Neu)
|
||||
- Remissions Produkt Liste (Refactoring / Neu)
|
||||
- Angular Version (Upgrade)
|
||||
3618
angular.json
3618
angular.json
File diff suppressed because it is too large
Load Diff
25
apps/adapter/scan/README.md
Normal file
25
apps/adapter/scan/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Scan
|
||||
|
||||
This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 12.2.0.
|
||||
|
||||
## Code scaffolding
|
||||
|
||||
Run `ng generate component component-name --project scan` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project scan`.
|
||||
|
||||
> Note: Don't forget to add `--project scan` or else it will be added to the default project in your `angular.json` file.
|
||||
|
||||
## Build
|
||||
|
||||
Run `ng build scan` to build the project. The build artifacts will be stored in the `dist/` directory.
|
||||
|
||||
## Publishing
|
||||
|
||||
After building your library with `ng build scan`, go to the dist folder `cd dist/scan` and run `npm publish`.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `ng test scan` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
||||
|
||||
## Further help
|
||||
|
||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
|
||||
41
apps/adapter/scan/karma.conf.js
Normal file
41
apps/adapter/scan/karma.conf.js
Normal file
@@ -0,0 +1,41 @@
|
||||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage'),
|
||||
require('@angular-devkit/build-angular/plugins/karma'),
|
||||
],
|
||||
client: {
|
||||
jasmine: {
|
||||
// you can add configuration options for Jasmine here
|
||||
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
|
||||
// for example, you can disable the random execution with `random: false`
|
||||
// or set a specific seed with `seed: 4321`
|
||||
},
|
||||
clearContext: false, // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
jasmineHtmlReporter: {
|
||||
suppressAll: true, // removes the duplicated traces
|
||||
},
|
||||
coverageReporter: {
|
||||
dir: require('path').join(__dirname, '../../../coverage/adapter/scan'),
|
||||
subdir: '.',
|
||||
reporters: [{ type: 'html' }, { type: 'text-summary' }],
|
||||
},
|
||||
reporters: ['progress', 'kjhtml'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['Chrome'],
|
||||
singleRun: false,
|
||||
restartOnFileChange: true,
|
||||
});
|
||||
};
|
||||
7
apps/adapter/scan/ng-package.json
Normal file
7
apps/adapter/scan/ng-package.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
||||
"dest": "../../../dist/adapter/scan",
|
||||
"lib": {
|
||||
"entryFile": "src/public-api.ts"
|
||||
}
|
||||
}
|
||||
11
apps/adapter/scan/package.json
Normal file
11
apps/adapter/scan/package.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "@adapter/scan",
|
||||
"version": "0.0.1",
|
||||
"peerDependencies": {
|
||||
"@angular/common": "^12.2.0",
|
||||
"@angular/core": "^12.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
}
|
||||
}
|
||||
46
apps/adapter/scan/src/lib/dev.scan-adapter.ts
Normal file
46
apps/adapter/scan/src/lib/dev.scan-adapter.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { PromptModalData, UiModalService, UiPromptModalComponent } from '@ui/modal';
|
||||
import { Observable } from 'rxjs';
|
||||
import { ScanAdapter } from './scan-adapter';
|
||||
|
||||
@Injectable()
|
||||
export class DevScanAdapter implements ScanAdapter {
|
||||
constructor(private _modal: UiModalService) {}
|
||||
|
||||
getName(): string {
|
||||
return 'Dev Scanner';
|
||||
}
|
||||
|
||||
isPrimary(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
isReady(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
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();
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
32
apps/adapter/scan/src/lib/native.scan-adapter.ts
Normal file
32
apps/adapter/scan/src/lib/native.scan-adapter.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { NativeContainerService } from 'native-container';
|
||||
import { Observable } from 'rxjs';
|
||||
import { filter, map, take } from 'rxjs/operators';
|
||||
import { ScanAdapter } from './scan-adapter';
|
||||
|
||||
@Injectable()
|
||||
export class NativeScanAdapter implements ScanAdapter {
|
||||
constructor(private readonly nativeContainerService: NativeContainerService) {}
|
||||
|
||||
getName(): string {
|
||||
return 'Native Scanner';
|
||||
}
|
||||
|
||||
isPrimary(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
isReady(): boolean {
|
||||
// TODO: Fix Login Keycard Dauerschleife
|
||||
return this.nativeContainerService.isUiWebview().isNative || this.nativeContainerService.isIpadMini6();
|
||||
// return false;
|
||||
}
|
||||
|
||||
scan(): Observable<string> {
|
||||
return this.nativeContainerService.openScanner('scanBook').pipe(
|
||||
filter((result) => result.status === 'SUCCESS'),
|
||||
map((result) => result.data),
|
||||
take(1)
|
||||
);
|
||||
}
|
||||
}
|
||||
11
apps/adapter/scan/src/lib/scan-adapter.ts
Normal file
11
apps/adapter/scan/src/lib/scan-adapter.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
export interface ScanAdapter {
|
||||
getName(): string;
|
||||
|
||||
isPrimary(): boolean;
|
||||
|
||||
isReady(): boolean;
|
||||
|
||||
scan(): Observable<string>;
|
||||
}
|
||||
16
apps/adapter/scan/src/lib/scan.module.ts
Normal file
16
apps/adapter/scan/src/lib/scan.module.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
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(dev?: boolean) {
|
||||
return {
|
||||
ngModule: ScanAdapterModule,
|
||||
providers: [{ provide: SCAN_ADAPTER, useClass: NativeScanAdapter, multi: true }],
|
||||
// Use for testing:
|
||||
// providers: [{ provide: SCAN_ADAPTER, useClass: dev ? DevScanAdapter : NativeScanAdapter, multi: true }],
|
||||
};
|
||||
}
|
||||
}
|
||||
30
apps/adapter/scan/src/lib/scan.service.ts
Normal file
30
apps/adapter/scan/src/lib/scan.service.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { ScanAdapter } from './scan-adapter';
|
||||
import { SCAN_ADAPTER } from './tokens';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ScanAdapterService {
|
||||
constructor(@Inject(SCAN_ADAPTER) private readonly scanAdapters: ScanAdapter[]) {}
|
||||
|
||||
scanners() {
|
||||
return this.scanAdapters.filter((adapter) => adapter.isReady());
|
||||
}
|
||||
|
||||
scanner() {
|
||||
return this.scanners().find((scanner) => scanner.isPrimary()) || this.scanners().find(() => true);
|
||||
}
|
||||
|
||||
isReady() {
|
||||
return this.scanAdapters.some((adapter) => adapter.isReady());
|
||||
}
|
||||
|
||||
scan() {
|
||||
const primaryScanner = this.scanner();
|
||||
if (primaryScanner) {
|
||||
return primaryScanner.scan();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
4
apps/adapter/scan/src/lib/tokens.ts
Normal file
4
apps/adapter/scan/src/lib/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');
|
||||
6
apps/adapter/scan/src/public-api.ts
Normal file
6
apps/adapter/scan/src/public-api.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
/*
|
||||
* Public API Surface of scan
|
||||
*/
|
||||
|
||||
export * from './lib/scan.service';
|
||||
export * from './lib/scan.module';
|
||||
25
apps/adapter/scan/src/test.ts
Normal file
25
apps/adapter/scan/src/test.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||
|
||||
import 'zone.js';
|
||||
import 'zone.js/testing';
|
||||
import { getTestBed } from '@angular/core/testing';
|
||||
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
|
||||
|
||||
declare const require: {
|
||||
context(
|
||||
path: string,
|
||||
deep?: boolean,
|
||||
filter?: RegExp
|
||||
): {
|
||||
keys(): string[];
|
||||
<T>(id: string): T;
|
||||
};
|
||||
};
|
||||
|
||||
// First, initialize the Angular testing environment.
|
||||
getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { teardown: { destroyAfterEach: true } });
|
||||
|
||||
// Then we find all the tests.
|
||||
const context = require.context('./', true, /\.spec\.ts$/);
|
||||
// And load the modules.
|
||||
context.keys().map(context);
|
||||
20
apps/adapter/scan/tsconfig.lib.json
Normal file
20
apps/adapter/scan/tsconfig.lib.json
Normal file
@@ -0,0 +1,20 @@
|
||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../../out-tsc/lib",
|
||||
"target": "es2015",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"inlineSources": true,
|
||||
"types": [],
|
||||
"lib": [
|
||||
"dom",
|
||||
"es2018"
|
||||
]
|
||||
},
|
||||
"exclude": [
|
||||
"src/test.ts",
|
||||
"**/*.spec.ts"
|
||||
]
|
||||
}
|
||||
10
apps/adapter/scan/tsconfig.lib.prod.json
Normal file
10
apps/adapter/scan/tsconfig.lib.prod.json
Normal file
@@ -0,0 +1,10 @@
|
||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||
{
|
||||
"extends": "./tsconfig.lib.json",
|
||||
"compilerOptions": {
|
||||
"declarationMap": false
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"compilationMode": "partial"
|
||||
}
|
||||
}
|
||||
17
apps/adapter/scan/tsconfig.spec.json
Normal file
17
apps/adapter/scan/tsconfig.spec.json
Normal file
@@ -0,0 +1,17 @@
|
||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../../out-tsc/spec",
|
||||
"types": [
|
||||
"jasmine"
|
||||
]
|
||||
},
|
||||
"files": [
|
||||
"src/test.ts"
|
||||
],
|
||||
"include": [
|
||||
"**/*.spec.ts",
|
||||
"**/*.d.ts"
|
||||
]
|
||||
}
|
||||
25
apps/cdn/product-image/README.md
Normal file
25
apps/cdn/product-image/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# ProductImage
|
||||
|
||||
This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 10.1.2.
|
||||
|
||||
## Code scaffolding
|
||||
|
||||
Run `ng generate component component-name --project product-image` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project product-image`.
|
||||
|
||||
> Note: Don't forget to add `--project product-image` or else it will be added to the default project in your `angular.json` file.
|
||||
|
||||
## Build
|
||||
|
||||
Run `ng build product-image` to build the project. The build artifacts will be stored in the `dist/` directory.
|
||||
|
||||
## Publishing
|
||||
|
||||
After building your library with `ng build product-image`, go to the dist folder `cd dist/product-image` and run `npm publish`.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `ng test product-image` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
||||
|
||||
## Further help
|
||||
|
||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
|
||||
32
apps/cdn/product-image/karma.conf.js
Normal file
32
apps/cdn/product-image/karma.conf.js
Normal file
@@ -0,0 +1,32 @@
|
||||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage-istanbul-reporter'),
|
||||
require('@angular-devkit/build-angular/plugins/karma'),
|
||||
],
|
||||
client: {
|
||||
clearContext: false, // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
coverageIstanbulReporter: {
|
||||
dir: require('path').join(__dirname, '../../../coverage/cdn/product-image'),
|
||||
reports: ['html', 'lcovonly', 'text-summary'],
|
||||
fixWebpackSourcePaths: true,
|
||||
},
|
||||
reporters: ['progress', 'kjhtml'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['Chrome'],
|
||||
singleRun: false,
|
||||
restartOnFileChange: true,
|
||||
});
|
||||
};
|
||||
7
apps/cdn/product-image/ng-package.json
Normal file
7
apps/cdn/product-image/ng-package.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
||||
"dest": "../../../dist/cdn/product-image",
|
||||
"lib": {
|
||||
"entryFile": "src/public-api.ts"
|
||||
}
|
||||
}
|
||||
11
apps/cdn/product-image/package.json
Normal file
11
apps/cdn/product-image/package.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "@cdn/product-image",
|
||||
"version": "0.0.1",
|
||||
"peerDependencies": {
|
||||
"@angular/common": "^10.1.2",
|
||||
"@angular/core": "^10.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": "^2.0.0"
|
||||
}
|
||||
}
|
||||
9
apps/cdn/product-image/src/lib/product-image.module.ts
Normal file
9
apps/cdn/product-image/src/lib/product-image.module.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { ProductImagePipe } from './product-image.pipe';
|
||||
|
||||
@NgModule({
|
||||
declarations: [ProductImagePipe],
|
||||
imports: [],
|
||||
exports: [ProductImagePipe],
|
||||
})
|
||||
export class ProductImageModule {}
|
||||
12
apps/cdn/product-image/src/lib/product-image.pipe.ts
Normal file
12
apps/cdn/product-image/src/lib/product-image.pipe.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { ProductImageService } from './product-image.service';
|
||||
|
||||
@Pipe({
|
||||
name: 'productImage',
|
||||
})
|
||||
export class ProductImagePipe implements PipeTransform {
|
||||
constructor(private imageService: ProductImageService) {}
|
||||
transform(imageId: string, width?: number, height?: number, showDummy?: boolean): any {
|
||||
return this.imageService.getImageUrl({ imageId, width, height, showDummy });
|
||||
}
|
||||
}
|
||||
16
apps/cdn/product-image/src/lib/product-image.service.spec.ts
Normal file
16
apps/cdn/product-image/src/lib/product-image.service.spec.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ProductImageService } from './product-image.service';
|
||||
|
||||
describe('ProductImageService', () => {
|
||||
let service: ProductImageService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(ProductImageService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
24
apps/cdn/product-image/src/lib/product-image.service.ts
Normal file
24
apps/cdn/product-image/src/lib/product-image.service.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { Config } from '@core/config';
|
||||
import { CDN_PRODUCT_IMAGE } from './tokens';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ProductImageService {
|
||||
constructor(private readonly _config: Config) {}
|
||||
|
||||
getImageUrl({
|
||||
imageId,
|
||||
width = 150,
|
||||
height = 150,
|
||||
showDummy = true,
|
||||
}: {
|
||||
imageId: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
showDummy?: boolean;
|
||||
}): string {
|
||||
return `${this._config.get('@cdn/product-image.url')}/${imageId}_${width}x${height}.jpg?showDummy=${showDummy}`;
|
||||
}
|
||||
}
|
||||
3
apps/cdn/product-image/src/lib/tokens.ts
Normal file
3
apps/cdn/product-image/src/lib/tokens.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { InjectionToken } from '@angular/core';
|
||||
|
||||
export const CDN_PRODUCT_IMAGE = new InjectionToken<string>('cdn.product.image');
|
||||
8
apps/cdn/product-image/src/public-api.ts
Normal file
8
apps/cdn/product-image/src/public-api.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* Public API Surface of product-image
|
||||
*/
|
||||
|
||||
export * from './lib/product-image.service';
|
||||
export * from './lib/product-image.module';
|
||||
export * from './lib/product-image.pipe';
|
||||
export * from './lib/tokens';
|
||||
24
apps/cdn/product-image/src/test.ts
Normal file
24
apps/cdn/product-image/src/test.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||
|
||||
import 'zone.js';
|
||||
import 'zone.js/testing';
|
||||
import { getTestBed } from '@angular/core/testing';
|
||||
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
|
||||
|
||||
declare const require: {
|
||||
context(
|
||||
path: string,
|
||||
deep?: boolean,
|
||||
filter?: RegExp
|
||||
): {
|
||||
keys(): string[];
|
||||
<T>(id: string): T;
|
||||
};
|
||||
};
|
||||
|
||||
// First, initialize the Angular testing environment.
|
||||
getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
|
||||
// Then we find all the tests.
|
||||
const context = require.context('./', true, /\.spec\.ts$/);
|
||||
// And load the modules.
|
||||
context.keys().map(context);
|
||||
25
apps/cdn/product-image/tsconfig.lib.json
Normal file
25
apps/cdn/product-image/tsconfig.lib.json
Normal file
@@ -0,0 +1,25 @@
|
||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../../out-tsc/lib",
|
||||
"target": "es2015",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"inlineSources": true,
|
||||
"types": [],
|
||||
"lib": [
|
||||
"dom",
|
||||
"es2018"
|
||||
]
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"skipTemplateCodegen": true,
|
||||
"strictMetadataEmit": true,
|
||||
"enableResourceInlining": true
|
||||
},
|
||||
"exclude": [
|
||||
"src/test.ts",
|
||||
"**/*.spec.ts"
|
||||
]
|
||||
}
|
||||
10
apps/cdn/product-image/tsconfig.lib.prod.json
Normal file
10
apps/cdn/product-image/tsconfig.lib.prod.json
Normal file
@@ -0,0 +1,10 @@
|
||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||
{
|
||||
"extends": "./tsconfig.lib.json",
|
||||
"compilerOptions": {
|
||||
"declarationMap": false
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"enableIvy": false
|
||||
}
|
||||
}
|
||||
17
apps/cdn/product-image/tsconfig.spec.json
Normal file
17
apps/cdn/product-image/tsconfig.spec.json
Normal file
@@ -0,0 +1,17 @@
|
||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../../out-tsc/spec",
|
||||
"types": [
|
||||
"jasmine"
|
||||
]
|
||||
},
|
||||
"files": [
|
||||
"src/test.ts"
|
||||
],
|
||||
"include": [
|
||||
"**/*.spec.ts",
|
||||
"**/*.d.ts"
|
||||
]
|
||||
}
|
||||
17
apps/cdn/product-image/tslint.json
Normal file
17
apps/cdn/product-image/tslint.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"extends": "../../../tslint.json",
|
||||
"rules": {
|
||||
"directive-selector": [
|
||||
true,
|
||||
"attribute",
|
||||
"cdn",
|
||||
"camelCase"
|
||||
],
|
||||
"component-selector": [
|
||||
true,
|
||||
"element",
|
||||
"cdn",
|
||||
"kebab-case"
|
||||
]
|
||||
}
|
||||
}
|
||||
25
apps/core/application/README.md
Normal file
25
apps/core/application/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Application
|
||||
|
||||
This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 10.1.2.
|
||||
|
||||
## Code scaffolding
|
||||
|
||||
Run `ng generate component component-name --project application` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project application`.
|
||||
|
||||
> Note: Don't forget to add `--project application` or else it will be added to the default project in your `angular.json` file.
|
||||
|
||||
## Build
|
||||
|
||||
Run `ng build application` to build the project. The build artifacts will be stored in the `dist/` directory.
|
||||
|
||||
## Publishing
|
||||
|
||||
After building your library with `ng build application`, go to the dist folder `cd dist/application` and run `npm publish`.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `ng test application` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
||||
|
||||
## Further help
|
||||
|
||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
|
||||
43
apps/core/application/karma.conf.js
Normal file
43
apps/core/application/karma.conf.js
Normal file
@@ -0,0 +1,43 @@
|
||||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
const customLaunchers = require('../../../karma/custom-launchers');
|
||||
const junitReporter = require('../../../karma/junit-reporter')('core-application');
|
||||
const coverageReporter = require('../../../karma/coverage-reporter')('core-application');
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage'),
|
||||
require('karma-junit-reporter'),
|
||||
require('@angular-devkit/build-angular/plugins/karma'),
|
||||
],
|
||||
client: {
|
||||
jasmine: {
|
||||
// you can add configuration options for Jasmine here
|
||||
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
|
||||
// for example, you can disable the random execution with `random: false`
|
||||
// or set a specific seed with `seed: 4321`
|
||||
},
|
||||
clearContext: false, // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
jasmineHtmlReporter: {
|
||||
suppressAll: true, // removes the duplicated traces
|
||||
},
|
||||
coverageReporter,
|
||||
junitReporter,
|
||||
reporters: ['progress', 'kjhtml'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['Chrome'],
|
||||
customLaunchers,
|
||||
singleRun: false,
|
||||
restartOnFileChange: true,
|
||||
});
|
||||
};
|
||||
7
apps/core/application/ng-package.json
Normal file
7
apps/core/application/ng-package.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
||||
"dest": "../../../dist/core/application",
|
||||
"lib": {
|
||||
"entryFile": "src/public-api.ts"
|
||||
}
|
||||
}
|
||||
11
apps/core/application/package.json
Normal file
11
apps/core/application/package.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "@core/application",
|
||||
"version": "0.0.1",
|
||||
"peerDependencies": {
|
||||
"@angular/common": "^10.1.2",
|
||||
"@angular/core": "^10.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": "^2.0.0"
|
||||
}
|
||||
}
|
||||
23
apps/core/application/src/lib/application.module.ts
Normal file
23
apps/core/application/src/lib/application.module.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { NgModule, ModuleWithProviders } from '@angular/core';
|
||||
import { StoreModule } from '@ngrx/store';
|
||||
import { applicationReducer } from './store';
|
||||
import { ApplicationService } from './application.service';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
imports: [],
|
||||
exports: [],
|
||||
})
|
||||
export class CoreApplicationModule {
|
||||
static forRoot(): ModuleWithProviders<CoreApplicationModule> {
|
||||
return {
|
||||
ngModule: RootCoreApplicationModule,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
imports: [StoreModule.forFeature('core-application', applicationReducer)],
|
||||
providers: [ApplicationService],
|
||||
})
|
||||
export class RootCoreApplicationModule {}
|
||||
233
apps/core/application/src/lib/application.service.spec.ts
Normal file
233
apps/core/application/src/lib/application.service.spec.ts
Normal file
@@ -0,0 +1,233 @@
|
||||
import { createServiceFactory, SpectatorService, SpyObject } from '@ngneat/spectator';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { first } from 'rxjs/operators';
|
||||
import { ApplicationProcess } from './defs';
|
||||
|
||||
import { ApplicationService } from './application.service';
|
||||
import * as actions from './store/application.actions';
|
||||
|
||||
describe('ApplicationService', () => {
|
||||
let spectator: SpectatorService<ApplicationService>;
|
||||
let store: SpyObject<Store>;
|
||||
const createService = createServiceFactory({
|
||||
service: ApplicationService,
|
||||
mocks: [Store],
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
spectator = createService({});
|
||||
store = spectator.inject(Store);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(spectator.service).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('activatedProcessId$', () => {
|
||||
it('should return an observable', () => {
|
||||
expect(spectator.service.activatedProcessId$).toBeInstanceOf(Observable);
|
||||
});
|
||||
});
|
||||
|
||||
describe('activatedProcessId', () => {
|
||||
it('should return the process id as a number', () => {
|
||||
spyOnProperty(spectator.service['activatedProcessIdSubject'] as any, 'value').and.returnValue(2);
|
||||
expect(spectator.service.activatedProcessId).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getProcesses$()', () => {
|
||||
it('should call select on store and return all selected processes', async () => {
|
||||
const processes: ApplicationProcess[] = [
|
||||
{ id: 1, name: 'Vorgang', type: 'cart', section: 'customer', data: { count: 1 } },
|
||||
{ id: 2, name: 'Vorgang', type: 'task-calendar', section: 'branch' },
|
||||
];
|
||||
store.select.and.returnValue(of(processes));
|
||||
const result = await spectator.service.getProcesses$().pipe(first()).toPromise();
|
||||
expect(result).toEqual(processes);
|
||||
expect(store.select).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call select on store and return all section customer processes', async () => {
|
||||
const processes: ApplicationProcess[] = [
|
||||
{ id: 1, name: 'Vorgang', type: 'cart', section: 'customer', data: { count: 1 } },
|
||||
{ id: 2, name: 'Vorgang', type: 'task-calendar', section: 'branch' },
|
||||
];
|
||||
store.select.and.returnValue(of(processes));
|
||||
const result = await spectator.service.getProcesses$('customer').pipe(first()).toPromise();
|
||||
expect(result).toEqual([processes[0]]);
|
||||
expect(store.select).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call select on store and return all section branch processes', async () => {
|
||||
const processes: ApplicationProcess[] = [
|
||||
{ id: 1, name: 'Vorgang', type: 'cart', section: 'customer', data: { count: 1 } },
|
||||
{ id: 2, name: 'Vorgang', type: 'task-calendar', section: 'branch' },
|
||||
];
|
||||
store.select.and.returnValue(of(processes));
|
||||
const result = await spectator.service.getProcesses$('branch').pipe(first()).toPromise();
|
||||
expect(result).toEqual([processes[1]]);
|
||||
expect(store.select).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getProcessById$()', () => {
|
||||
it('should return the process by id', async () => {
|
||||
const processes: ApplicationProcess[] = [
|
||||
{ id: 1, name: 'Vorgang 1', section: 'customer' },
|
||||
{ id: 2, name: 'Vorgang 2', section: 'customer' },
|
||||
];
|
||||
spyOn(spectator.service, 'getProcesses$').and.returnValue(of(processes));
|
||||
|
||||
const process = await spectator.service.getProcessById$(1).toPromise();
|
||||
expect(process.id).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getSection$()', () => {
|
||||
it('should return the selected section branch', async () => {
|
||||
const section = 'branch';
|
||||
store.select.and.returnValue(of(section));
|
||||
const result = await spectator.service.getSection$().pipe(first()).toPromise();
|
||||
expect(result).toEqual(section);
|
||||
expect(store.select).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getActivatedProcessId$', () => {
|
||||
it('should return the current selected activated process id', async () => {
|
||||
const activatedProcessId = 2;
|
||||
store.select.and.returnValue(of({ id: activatedProcessId }));
|
||||
const result = await spectator.service.getActivatedProcessId$().pipe(first()).toPromise();
|
||||
expect(result).toEqual(activatedProcessId);
|
||||
expect(store.select).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('activateProcess()', () => {
|
||||
it('should dispatch action setActivatedProcess with argument activatedProcessId and action type', () => {
|
||||
const activatedProcessId = 2;
|
||||
spectator.service.activateProcess(activatedProcessId);
|
||||
expect(store.dispatch).toHaveBeenCalledWith({ activatedProcessId, type: actions.setActivatedProcess.type });
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeProcess()', () => {
|
||||
it('should dispatch action removeProcess with argument processId and action type', () => {
|
||||
const processId = 2;
|
||||
spectator.service.removeProcess(processId);
|
||||
expect(store.dispatch).toHaveBeenCalledWith({ processId, type: actions.removeProcess.type });
|
||||
});
|
||||
});
|
||||
|
||||
describe('createProcess()', () => {
|
||||
it('should dispatch action addProcess with process', async () => {
|
||||
const process: ApplicationProcess = {
|
||||
id: 1,
|
||||
name: 'Vorgang 1',
|
||||
section: 'customer',
|
||||
type: 'cart',
|
||||
};
|
||||
|
||||
const timestamp = 100;
|
||||
spyOn(spectator.service as any, '_createTimestamp').and.returnValue(timestamp);
|
||||
spyOn(spectator.service, 'getProcessById$').and.returnValue(of(undefined));
|
||||
await spectator.service.createProcess(process);
|
||||
|
||||
expect(store.dispatch).toHaveBeenCalledWith({
|
||||
type: actions.addProcess.type,
|
||||
process: {
|
||||
...process,
|
||||
activated: 0,
|
||||
created: timestamp,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw an error if the process id is already existing', async () => {
|
||||
const process: ApplicationProcess = {
|
||||
id: 1,
|
||||
name: 'Vorgang 1',
|
||||
section: 'customer',
|
||||
type: 'cart',
|
||||
};
|
||||
spyOn(spectator.service, 'getProcessById$').and.returnValue(of(process));
|
||||
await expectAsync(spectator.service.createProcess(process)).toBeRejectedWithError('Process Id existiert bereits');
|
||||
});
|
||||
|
||||
it('should throw an error if the process id is not a number', async () => {
|
||||
const process: ApplicationProcess = {
|
||||
id: undefined,
|
||||
name: 'Vorgang 1',
|
||||
section: 'customer',
|
||||
type: 'cart',
|
||||
};
|
||||
spyOn(spectator.service, 'getProcessById$').and.returnValue(of({ id: 5, name: 'Vorgang 2', section: 'customer' }));
|
||||
await expectAsync(spectator.service.createProcess(process)).toBeRejectedWithError('Process Id nicht gesetzt');
|
||||
});
|
||||
});
|
||||
|
||||
describe('patchProcess', () => {
|
||||
it('should dispatch action patchProcess with changes', async () => {
|
||||
const process: ApplicationProcess = {
|
||||
id: 1,
|
||||
name: 'Vorgang 1',
|
||||
section: 'customer',
|
||||
type: 'cart',
|
||||
};
|
||||
|
||||
await spectator.service.patchProcess(process.id, process);
|
||||
|
||||
expect(store.dispatch).toHaveBeenCalledWith({
|
||||
type: actions.patchProcess.type,
|
||||
processId: process.id,
|
||||
changes: {
|
||||
...process,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('setSection()', () => {
|
||||
it('should dispatch action setSection with argument section and action type', () => {
|
||||
const section = 'customer';
|
||||
spectator.service.setSection(section);
|
||||
expect(store.dispatch).toHaveBeenCalledWith({ section, type: actions.setSection.type });
|
||||
});
|
||||
});
|
||||
|
||||
describe('getLastActivatedProcessWithSectionAndType()', () => {
|
||||
it('should return the last activated process by section and type', async () => {
|
||||
const processes: ApplicationProcess[] = [
|
||||
{ id: 1, name: 'Vorgang 1', section: 'customer', type: 'cart', activated: 100 },
|
||||
{ id: 2, name: 'Vorgang 2', section: 'customer', type: 'cart', activated: 200 },
|
||||
{ id: 3, name: 'Vorgang 3', section: 'customer', type: 'goodsOut', activated: 300 },
|
||||
];
|
||||
spyOn(spectator.service, 'getProcesses$').and.returnValue(of(processes));
|
||||
|
||||
expect(await spectator.service.getLastActivatedProcessWithSectionAndType$('customer', 'cart').pipe(first()).toPromise()).toBe(
|
||||
processes[1]
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getLastActivatedProcessWithSection()', () => {
|
||||
it('should return the last activated process by section', async () => {
|
||||
const processes: ApplicationProcess[] = [
|
||||
{ id: 1, name: 'Vorgang 1', section: 'customer', activated: 100 },
|
||||
{ id: 2, name: 'Vorgang 2', section: 'customer', activated: 200 },
|
||||
{ id: 3, name: 'Vorgang 3', section: 'customer', activated: 300 },
|
||||
];
|
||||
spyOn(spectator.service, 'getProcesses$').and.returnValue(of(processes));
|
||||
|
||||
expect(await spectator.service.getLastActivatedProcessWithSection$('customer').pipe(first()).toPromise()).toBe(processes[2]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('_createTimestamp', () => {
|
||||
it('should return the current timestamp in ms', () => {
|
||||
expect(spectator.service['_createTimestamp']()).toBeCloseTo(Date.now());
|
||||
});
|
||||
});
|
||||
});
|
||||
129
apps/core/application/src/lib/application.service.ts
Normal file
129
apps/core/application/src/lib/application.service.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { isBoolean, isNumber } from '@utils/common';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { first, map, switchMap } from 'rxjs/operators';
|
||||
import { ApplicationProcess } from './defs';
|
||||
import {
|
||||
removeProcess,
|
||||
selectSection,
|
||||
selectProcesses,
|
||||
setSection,
|
||||
addProcess,
|
||||
setActivatedProcess,
|
||||
selectActivatedProcess,
|
||||
patchProcess,
|
||||
patchProcessData,
|
||||
} from './store';
|
||||
|
||||
@Injectable()
|
||||
export class ApplicationService {
|
||||
/** @deprecated */
|
||||
private activatedProcessIdSubject = new BehaviorSubject<number>(undefined);
|
||||
|
||||
/** @deprecated */
|
||||
get activatedProcessId() {
|
||||
return this.activatedProcessIdSubject.value;
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
get activatedProcessId$() {
|
||||
return this.activatedProcessIdSubject.asObservable();
|
||||
}
|
||||
|
||||
constructor(private store: Store) {}
|
||||
|
||||
getProcesses$(section?: 'customer' | 'branch') {
|
||||
const processes$ = this.store.select(selectProcesses);
|
||||
return processes$.pipe(map((processes) => processes.filter((process) => (section ? process.section === section : true))));
|
||||
}
|
||||
|
||||
getProcessById$(processId: number): Observable<ApplicationProcess> {
|
||||
return this.getProcesses$().pipe(map((processes) => processes.find((process) => process.id === processId)));
|
||||
}
|
||||
|
||||
getSection$() {
|
||||
return this.store.select(selectSection);
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
getActivatedProcessId$() {
|
||||
return this.store.select(selectActivatedProcess).pipe(map((process) => process?.id));
|
||||
}
|
||||
|
||||
activateProcess(activatedProcessId: number) {
|
||||
this.store.dispatch(setActivatedProcess({ activatedProcessId }));
|
||||
this.activatedProcessIdSubject.next(activatedProcessId);
|
||||
}
|
||||
|
||||
removeProcess(processId: number) {
|
||||
this.store.dispatch(removeProcess({ processId }));
|
||||
}
|
||||
|
||||
patchProcess(processId: number, changes: Partial<ApplicationProcess>) {
|
||||
this.store.dispatch(patchProcess({ processId, changes }));
|
||||
}
|
||||
|
||||
patchProcessData(processId: number, data: Record<string, any>) {
|
||||
this.store.dispatch(patchProcessData({ processId, data }));
|
||||
}
|
||||
|
||||
async createProcess(process: ApplicationProcess) {
|
||||
const existingProcess = await this.getProcessById$(process?.id).pipe(first()).toPromise();
|
||||
if (existingProcess?.id === process?.id) {
|
||||
throw new Error('Process Id existiert bereits');
|
||||
}
|
||||
|
||||
if (!isNumber(process.id)) {
|
||||
throw new Error('Process Id nicht gesetzt');
|
||||
}
|
||||
|
||||
if (!isBoolean(process.closeable)) {
|
||||
process.closeable = true;
|
||||
}
|
||||
|
||||
if (!isBoolean(process.confirmClosing)) {
|
||||
process.confirmClosing = true;
|
||||
}
|
||||
|
||||
process.created = this._createTimestamp();
|
||||
process.activated = 0;
|
||||
this.store.dispatch(addProcess({ process }));
|
||||
}
|
||||
|
||||
setSection(section: 'customer' | 'branch') {
|
||||
this.store.dispatch(setSection({ section }));
|
||||
}
|
||||
|
||||
getLastActivatedProcessWithSectionAndType$(section: 'customer' | 'branch', type: string): Observable<ApplicationProcess> {
|
||||
return this.getProcesses$(section).pipe(
|
||||
map((processes) =>
|
||||
processes
|
||||
?.filter((process) => process.type === type)
|
||||
?.reduce((latest, current) => {
|
||||
if (!latest) {
|
||||
return current;
|
||||
}
|
||||
return latest?.activated > current?.activated ? latest : current;
|
||||
}, undefined)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
getLastActivatedProcessWithSection$(section: 'customer' | 'branch'): Observable<ApplicationProcess> {
|
||||
return this.getProcesses$(section).pipe(
|
||||
map((processes) =>
|
||||
processes?.reduce((latest, current) => {
|
||||
if (!latest) {
|
||||
return current;
|
||||
}
|
||||
return latest?.activated > current?.activated ? latest : current;
|
||||
}, undefined)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private _createTimestamp() {
|
||||
return Date.now();
|
||||
}
|
||||
}
|
||||
11
apps/core/application/src/lib/defs/application-process.ts
Normal file
11
apps/core/application/src/lib/defs/application-process.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export interface ApplicationProcess {
|
||||
id: number;
|
||||
created?: number;
|
||||
activated?: number;
|
||||
name: string;
|
||||
section: 'customer' | 'branch';
|
||||
type?: string;
|
||||
data?: { [key: string]: any };
|
||||
closeable?: boolean;
|
||||
confirmClosing?: boolean;
|
||||
}
|
||||
3
apps/core/application/src/lib/defs/index.ts
Normal file
3
apps/core/application/src/lib/defs/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
// start:ng42.barrel
|
||||
export * from './application-process';
|
||||
// end:ng42.barrel
|
||||
6
apps/core/application/src/lib/index.ts
Normal file
6
apps/core/application/src/lib/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
// start:ng42.barrel
|
||||
export * from './application.module';
|
||||
export * from './application.service';
|
||||
export * from './defs';
|
||||
export * from './store';
|
||||
// end:ng42.barrel
|
||||
16
apps/core/application/src/lib/store/application.actions.ts
Normal file
16
apps/core/application/src/lib/store/application.actions.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { createAction, props } from '@ngrx/store';
|
||||
import { ApplicationProcess } from '..';
|
||||
|
||||
const prefix = '[CORE-APPLICATION]';
|
||||
|
||||
export const setSection = createAction(`${prefix} Set Section`, props<{ section: 'customer' | 'branch' }>());
|
||||
|
||||
export const addProcess = createAction(`${prefix} Add Process`, props<{ process: ApplicationProcess }>());
|
||||
|
||||
export const removeProcess = createAction(`${prefix} Remove Process`, props<{ processId: number }>());
|
||||
|
||||
export const setActivatedProcess = createAction(`${prefix} Set Activated Process`, props<{ activatedProcessId: number }>());
|
||||
|
||||
export const patchProcess = createAction(`${prefix} Patch Process`, props<{ processId: number; changes: Partial<ApplicationProcess> }>());
|
||||
|
||||
export const patchProcessData = createAction(`${prefix} Patch Process Data`, props<{ processId: number; data: Record<string, any> }>());
|
||||
200
apps/core/application/src/lib/store/application.reducer.spec.ts
Normal file
200
apps/core/application/src/lib/store/application.reducer.spec.ts
Normal file
@@ -0,0 +1,200 @@
|
||||
import { INITIAL_APPLICATION_STATE } from './application.state';
|
||||
import * as actions from './application.actions';
|
||||
import { applicationReducer } from './application.reducer';
|
||||
import { ApplicationProcess } from '../defs';
|
||||
import { ApplicationState } from './application.state';
|
||||
|
||||
describe('applicationReducer', () => {
|
||||
describe('setSection()', () => {
|
||||
it('should return modified state with section customer', () => {
|
||||
const initialState = INITIAL_APPLICATION_STATE;
|
||||
|
||||
const action = actions.setSection({ section: 'customer' });
|
||||
const state = applicationReducer(initialState, action);
|
||||
|
||||
expect(state).toEqual({
|
||||
...initialState,
|
||||
section: 'customer',
|
||||
});
|
||||
});
|
||||
|
||||
it('should return modified state with section branch', () => {
|
||||
const initialState = INITIAL_APPLICATION_STATE;
|
||||
|
||||
const action = actions.setSection({ section: 'branch' });
|
||||
const state = applicationReducer(initialState, action);
|
||||
|
||||
expect(state).toEqual({
|
||||
...initialState,
|
||||
section: 'branch',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('addProcess()', () => {
|
||||
it('should return modified state with new process if no processes are registered in the state', () => {
|
||||
const initialState = INITIAL_APPLICATION_STATE;
|
||||
|
||||
const process: ApplicationProcess = {
|
||||
id: 1,
|
||||
name: 'Vorgang',
|
||||
section: 'customer',
|
||||
type: 'cart',
|
||||
data: {},
|
||||
};
|
||||
|
||||
const action = actions.addProcess({ process });
|
||||
const state = applicationReducer(initialState, action);
|
||||
expect(state.processes[0]).toEqual(process);
|
||||
});
|
||||
});
|
||||
|
||||
describe('patchProcess()', () => {
|
||||
it('should return modified state with updated process when id is found', () => {
|
||||
const initialState = INITIAL_APPLICATION_STATE;
|
||||
|
||||
const process: ApplicationProcess = {
|
||||
id: 1,
|
||||
name: 'Vorgang',
|
||||
section: 'customer',
|
||||
type: 'cart',
|
||||
};
|
||||
|
||||
const action = actions.patchProcess({ processId: process.id, changes: { ...process, name: 'Test' } });
|
||||
const state = applicationReducer(
|
||||
{
|
||||
...initialState,
|
||||
processes: [process],
|
||||
},
|
||||
action
|
||||
);
|
||||
expect(state.processes[0].name).toEqual('Test');
|
||||
});
|
||||
|
||||
it('should return unmodified state when id is not existing', () => {
|
||||
const initialState = INITIAL_APPLICATION_STATE;
|
||||
|
||||
const process: ApplicationProcess = {
|
||||
id: 1,
|
||||
name: 'Vorgang',
|
||||
section: 'customer',
|
||||
type: 'cart',
|
||||
};
|
||||
|
||||
const action = actions.patchProcess({ processId: process.id, changes: { ...process, id: 2 } });
|
||||
const state = applicationReducer(
|
||||
{
|
||||
...initialState,
|
||||
processes: [process],
|
||||
},
|
||||
action
|
||||
);
|
||||
expect(state.processes).toEqual([process]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeProcess()', () => {
|
||||
it('should return initial state if no processes are registered in the state', () => {
|
||||
const initialState = INITIAL_APPLICATION_STATE;
|
||||
|
||||
const action = actions.removeProcess({ processId: 2 });
|
||||
const state = applicationReducer(initialState, action);
|
||||
expect(state).toEqual(initialState);
|
||||
});
|
||||
|
||||
it('should return the unmodified state if processId not found', () => {
|
||||
const initialState = INITIAL_APPLICATION_STATE;
|
||||
const modifiedState: ApplicationState = {
|
||||
...initialState,
|
||||
section: 'customer',
|
||||
processes: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Vorgang',
|
||||
section: 'customer',
|
||||
type: 'cart',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Vorgang',
|
||||
section: 'customer',
|
||||
type: 'goods-out',
|
||||
},
|
||||
] as ApplicationProcess[],
|
||||
};
|
||||
|
||||
const action = actions.removeProcess({ processId: 2 });
|
||||
const state = applicationReducer(modifiedState, action);
|
||||
expect(state).toEqual(modifiedState);
|
||||
});
|
||||
|
||||
it('should return modified state, after process gets removed', () => {
|
||||
const initialState = INITIAL_APPLICATION_STATE;
|
||||
const modifiedState: ApplicationState = {
|
||||
...initialState,
|
||||
section: 'customer',
|
||||
processes: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Vorgang',
|
||||
section: 'customer',
|
||||
type: 'cart',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Vorgang',
|
||||
section: 'customer',
|
||||
type: 'goods-out',
|
||||
},
|
||||
] as ApplicationProcess[],
|
||||
};
|
||||
|
||||
const action = actions.removeProcess({ processId: 2 });
|
||||
const state = applicationReducer(modifiedState, action);
|
||||
expect(state.processes).toEqual([
|
||||
{
|
||||
id: 1,
|
||||
name: 'Vorgang',
|
||||
section: 'customer',
|
||||
type: 'cart',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setActivatedProcess()', () => {
|
||||
it('should return modified state with process.activated value', () => {
|
||||
const process: ApplicationProcess = {
|
||||
id: 3,
|
||||
name: 'Vorgang 3',
|
||||
section: 'customer',
|
||||
};
|
||||
const initialState: ApplicationState = {
|
||||
...INITIAL_APPLICATION_STATE,
|
||||
processes: [process],
|
||||
};
|
||||
|
||||
const action = actions.setActivatedProcess({ activatedProcessId: 3 });
|
||||
const state = applicationReducer(initialState, action);
|
||||
|
||||
expect(state.processes[0].activated).toBeDefined();
|
||||
});
|
||||
|
||||
it('should return modified state without process.activated value when activatedProcessId doesnt exist', () => {
|
||||
const process: ApplicationProcess = {
|
||||
id: 1,
|
||||
name: 'Vorgang 3',
|
||||
section: 'customer',
|
||||
};
|
||||
const initialState: ApplicationState = {
|
||||
...INITIAL_APPLICATION_STATE,
|
||||
processes: [process],
|
||||
};
|
||||
|
||||
const action = actions.setActivatedProcess({ activatedProcessId: 3 });
|
||||
const state = applicationReducer(initialState, action);
|
||||
|
||||
expect(state.processes[0].activated).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
47
apps/core/application/src/lib/store/application.reducer.ts
Normal file
47
apps/core/application/src/lib/store/application.reducer.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { Action, createReducer, on } from '@ngrx/store';
|
||||
import { setSection, addProcess, removeProcess, setActivatedProcess, patchProcess, patchProcessData } from './application.actions';
|
||||
import { ApplicationState, INITIAL_APPLICATION_STATE } from './application.state';
|
||||
|
||||
const _applicationReducer = createReducer(
|
||||
INITIAL_APPLICATION_STATE,
|
||||
on(setSection, (state, { section }) => ({ ...state, section })),
|
||||
on(addProcess, (state, { process }) => ({ ...state, processes: [...state.processes, { data: {}, ...process }] })),
|
||||
on(removeProcess, (state, { processId }) => {
|
||||
const processes = state?.processes?.filter((process) => process.id !== processId) || [];
|
||||
return { ...state, processes };
|
||||
}),
|
||||
on(setActivatedProcess, (state, { activatedProcessId }) => {
|
||||
const processes = state.processes.map((process) => {
|
||||
if (process.id === activatedProcessId) {
|
||||
return { ...process, activated: Date.now() };
|
||||
}
|
||||
return process;
|
||||
});
|
||||
|
||||
return { ...state, processes };
|
||||
}),
|
||||
on(patchProcess, (state, { processId, changes }) => {
|
||||
const processes = state.processes.map((process) => {
|
||||
if (process.id === processId) {
|
||||
return { ...process, ...changes, id: processId };
|
||||
}
|
||||
return process;
|
||||
});
|
||||
|
||||
return { ...state, processes };
|
||||
}),
|
||||
on(patchProcessData, (state, { processId, data }) => {
|
||||
const processes = state.processes.map((process) => {
|
||||
if (process.id === processId) {
|
||||
return { ...process, data: { ...(process.data || {}), ...data } };
|
||||
}
|
||||
return process;
|
||||
});
|
||||
|
||||
return { ...state, processes };
|
||||
})
|
||||
);
|
||||
|
||||
export function applicationReducer(state: ApplicationState, action: Action) {
|
||||
return _applicationReducer(state, action);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { ApplicationState } from './application.state';
|
||||
import { ApplicationProcess } from '../defs';
|
||||
import * as selectors from './application.selectors';
|
||||
|
||||
describe('applicationSelectors', () => {
|
||||
it('should select the processes', () => {
|
||||
const processes: ApplicationProcess[] = [{ id: 1, name: 'Vorgang 1', section: 'customer' }];
|
||||
const state: Partial<ApplicationState> = {
|
||||
processes,
|
||||
};
|
||||
expect(selectors.selectProcesses.projector(state)).toEqual(processes);
|
||||
});
|
||||
|
||||
it('should select the section', () => {
|
||||
const state: Partial<ApplicationState> = {
|
||||
section: 'customer',
|
||||
};
|
||||
expect(selectors.selectSection.projector(state)).toEqual('customer');
|
||||
});
|
||||
|
||||
it('should select the activatedProcess', () => {
|
||||
const processes: ApplicationProcess[] = [
|
||||
{ id: 1, name: 'Vorgang 1', section: 'customer', activated: 100 },
|
||||
{ id: 2, name: 'Vorgang 2', section: 'customer', activated: 300 },
|
||||
{ id: 3, name: 'Vorgang 3', section: 'customer', activated: 200 },
|
||||
];
|
||||
const state: Partial<ApplicationState> = {
|
||||
processes,
|
||||
};
|
||||
expect(selectors.selectActivatedProcess.projector(state)).toEqual(processes[1]);
|
||||
});
|
||||
});
|
||||
16
apps/core/application/src/lib/store/application.selectors.ts
Normal file
16
apps/core/application/src/lib/store/application.selectors.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { createFeatureSelector, createSelector } from '@ngrx/store';
|
||||
import { ApplicationState } from './application.state';
|
||||
export const selectApplicationState = createFeatureSelector<ApplicationState>('core-application');
|
||||
|
||||
export const selectSection = createSelector(selectApplicationState, (s) => s.section);
|
||||
|
||||
export const selectProcesses = createSelector(selectApplicationState, (s) => s.processes);
|
||||
|
||||
export const selectActivatedProcess = createSelector(selectApplicationState, (s) =>
|
||||
s?.processes?.reduce((process, current) => {
|
||||
if (!process) {
|
||||
return current;
|
||||
}
|
||||
return process.activated > current.activated ? process : current;
|
||||
}, undefined)
|
||||
);
|
||||
11
apps/core/application/src/lib/store/application.state.ts
Normal file
11
apps/core/application/src/lib/store/application.state.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { ApplicationProcess } from '../defs';
|
||||
|
||||
export interface ApplicationState {
|
||||
processes: ApplicationProcess[];
|
||||
section: 'customer' | 'branch';
|
||||
}
|
||||
|
||||
export const INITIAL_APPLICATION_STATE: ApplicationState = {
|
||||
processes: [],
|
||||
section: 'customer',
|
||||
};
|
||||
6
apps/core/application/src/lib/store/index.ts
Normal file
6
apps/core/application/src/lib/store/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
// start:ng42.barrel
|
||||
export * from './application.actions';
|
||||
export * from './application.reducer';
|
||||
export * from './application.selectors';
|
||||
export * from './application.state';
|
||||
// end:ng42.barrel
|
||||
5
apps/core/application/src/public-api.ts
Normal file
5
apps/core/application/src/public-api.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
* Public API Surface of application
|
||||
*/
|
||||
|
||||
export * from './lib';
|
||||
24
apps/core/application/src/test.ts
Normal file
24
apps/core/application/src/test.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||
|
||||
import 'zone.js';
|
||||
import 'zone.js/testing';
|
||||
import { getTestBed } from '@angular/core/testing';
|
||||
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
|
||||
|
||||
declare const require: {
|
||||
context(
|
||||
path: string,
|
||||
deep?: boolean,
|
||||
filter?: RegExp
|
||||
): {
|
||||
keys(): string[];
|
||||
<T>(id: string): T;
|
||||
};
|
||||
};
|
||||
|
||||
// First, initialize the Angular testing environment.
|
||||
getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
|
||||
// Then we find all the tests.
|
||||
const context = require.context('./', true, /\.spec\.ts$/);
|
||||
// And load the modules.
|
||||
context.keys().map(context);
|
||||
25
apps/core/application/tsconfig.lib.json
Normal file
25
apps/core/application/tsconfig.lib.json
Normal file
@@ -0,0 +1,25 @@
|
||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../../out-tsc/lib",
|
||||
"target": "es2015",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"inlineSources": true,
|
||||
"types": [],
|
||||
"lib": [
|
||||
"dom",
|
||||
"es2018"
|
||||
]
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"skipTemplateCodegen": true,
|
||||
"strictMetadataEmit": true,
|
||||
"enableResourceInlining": true
|
||||
},
|
||||
"exclude": [
|
||||
"src/test.ts",
|
||||
"**/*.spec.ts"
|
||||
]
|
||||
}
|
||||
10
apps/core/application/tsconfig.lib.prod.json
Normal file
10
apps/core/application/tsconfig.lib.prod.json
Normal file
@@ -0,0 +1,10 @@
|
||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||
{
|
||||
"extends": "./tsconfig.lib.json",
|
||||
"compilerOptions": {
|
||||
"declarationMap": false
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"enableIvy": false
|
||||
}
|
||||
}
|
||||
17
apps/core/application/tsconfig.spec.json
Normal file
17
apps/core/application/tsconfig.spec.json
Normal file
@@ -0,0 +1,17 @@
|
||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../../out-tsc/spec",
|
||||
"types": [
|
||||
"jasmine"
|
||||
]
|
||||
},
|
||||
"files": [
|
||||
"src/test.ts"
|
||||
],
|
||||
"include": [
|
||||
"**/*.spec.ts",
|
||||
"**/*.d.ts"
|
||||
]
|
||||
}
|
||||
17
apps/core/application/tslint.json
Normal file
17
apps/core/application/tslint.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"extends": "../../../tslint.json",
|
||||
"rules": {
|
||||
"directive-selector": [
|
||||
true,
|
||||
"attribute",
|
||||
"lib",
|
||||
"camelCase"
|
||||
],
|
||||
"component-selector": [
|
||||
true,
|
||||
"element",
|
||||
"lib",
|
||||
"kebab-case"
|
||||
]
|
||||
}
|
||||
}
|
||||
25
apps/core/auth/README.md
Normal file
25
apps/core/auth/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Auth
|
||||
|
||||
This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 12.2.0.
|
||||
|
||||
## Code scaffolding
|
||||
|
||||
Run `ng generate component component-name --project auth` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project auth`.
|
||||
|
||||
> Note: Don't forget to add `--project auth` or else it will be added to the default project in your `angular.json` file.
|
||||
|
||||
## Build
|
||||
|
||||
Run `ng build auth` to build the project. The build artifacts will be stored in the `dist/` directory.
|
||||
|
||||
## Publishing
|
||||
|
||||
After building your library with `ng build auth`, go to the dist folder `cd dist/auth` and run `npm publish`.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `ng test auth` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
||||
|
||||
## Further help
|
||||
|
||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
|
||||
43
apps/core/auth/karma.conf.js
Normal file
43
apps/core/auth/karma.conf.js
Normal file
@@ -0,0 +1,43 @@
|
||||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
const customLaunchers = require('../../../karma/custom-launchers');
|
||||
const junitReporter = require('../../../karma/junit-reporter')('core-auth');
|
||||
const coverageReporter = require('../../../karma/coverage-reporter')('core-auth');
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage'),
|
||||
require('karma-junit-reporter'),
|
||||
require('@angular-devkit/build-angular/plugins/karma'),
|
||||
],
|
||||
client: {
|
||||
jasmine: {
|
||||
// you can add configuration options for Jasmine here
|
||||
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
|
||||
// for example, you can disable the random execution with `random: false`
|
||||
// or set a specific seed with `seed: 4321`
|
||||
},
|
||||
clearContext: false, // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
jasmineHtmlReporter: {
|
||||
suppressAll: true, // removes the duplicated traces
|
||||
},
|
||||
coverageReporter,
|
||||
junitReporter,
|
||||
reporters: ['progress', 'kjhtml'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['Chrome'],
|
||||
customLaunchers,
|
||||
singleRun: false,
|
||||
restartOnFileChange: true,
|
||||
});
|
||||
};
|
||||
7
apps/core/auth/ng-package.json
Normal file
7
apps/core/auth/ng-package.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
||||
"dest": "../../../dist/core/auth",
|
||||
"lib": {
|
||||
"entryFile": "src/public-api.ts"
|
||||
}
|
||||
}
|
||||
11
apps/core/auth/package.json
Normal file
11
apps/core/auth/package.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "@core/auth",
|
||||
"version": "0.0.1",
|
||||
"peerDependencies": {
|
||||
"@angular/common": "^12.2.0",
|
||||
"@angular/core": "^12.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
}
|
||||
}
|
||||
17
apps/core/auth/src/lib/auth.module.ts
Normal file
17
apps/core/auth/src/lib/auth.module.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { ModuleWithProviders, NgModule } from '@angular/core';
|
||||
import { AuthService } from './auth.service';
|
||||
import { OAuthModule } from 'angular-oauth2-oidc';
|
||||
@NgModule({})
|
||||
export class AuthModule {
|
||||
static forRoot(): ModuleWithProviders<AuthModule> {
|
||||
return {
|
||||
ngModule: AuthModule,
|
||||
providers: [
|
||||
AuthService,
|
||||
OAuthModule.forRoot({
|
||||
resourceServer: { sendAccessToken: true },
|
||||
}).providers,
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
151
apps/core/auth/src/lib/auth.service.spec.ts
Normal file
151
apps/core/auth/src/lib/auth.service.spec.ts
Normal file
@@ -0,0 +1,151 @@
|
||||
import { Config } from '@core/config';
|
||||
import { SpectatorService, createServiceFactory, SpyObject } from '@ngneat/spectator';
|
||||
import { OAuthService } from 'angular-oauth2-oidc';
|
||||
import { JwksValidationHandler } from 'angular-oauth2-oidc-jwks';
|
||||
import { Observable } from 'rxjs';
|
||||
import { AuthService } from './auth.service';
|
||||
|
||||
describe('AuthService', () => {
|
||||
let spectator: SpectatorService<AuthService>;
|
||||
const createService = createServiceFactory({
|
||||
service: AuthService,
|
||||
mocks: [Config, OAuthService],
|
||||
});
|
||||
let config: SpyObject<Config>;
|
||||
let oAuthService: SpyObject<OAuthService>;
|
||||
|
||||
beforeEach(() => {
|
||||
spectator = createService();
|
||||
config = spectator.inject(Config);
|
||||
oAuthService = spectator.inject(OAuthService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(spectator.service).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('init()', () => {
|
||||
it('should configure the oAuthService', () => {
|
||||
config.get.and.returnValue({});
|
||||
spectator.service.init();
|
||||
expect(oAuthService.configure).toHaveBeenCalledWith({
|
||||
redirectUri: window.location.origin,
|
||||
silentRefreshRedirectUri: window.location.origin + '/silent-refresh.html',
|
||||
useSilentRefresh: true,
|
||||
});
|
||||
expect(oAuthService.tokenValidationHandler).toBeInstanceOf(JwksValidationHandler);
|
||||
expect(oAuthService.setupAutomaticSilentRefresh).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should load the discovery document', async () => {
|
||||
config.get.and.returnValue({});
|
||||
oAuthService.loadDiscoveryDocumentAndTryLogin.and.returnValue(Promise.resolve(true));
|
||||
|
||||
spyOn(spectator.service['_initialized'], 'next');
|
||||
await spectator.service.init();
|
||||
|
||||
expect(oAuthService.loadDiscoveryDocumentAndTryLogin).toHaveBeenCalled();
|
||||
expect(spectator.service['_initialized'].next).toHaveBeenCalledWith(true);
|
||||
});
|
||||
|
||||
it('should throw an error if its already initialized', async () => {
|
||||
spyOn(spectator.service['_initialized'], 'getValue').and.returnValue(true);
|
||||
await expectAsync(spectator.service.init()).toBeRejectedWithError('AuthService is already initialized');
|
||||
});
|
||||
});
|
||||
|
||||
describe('isAuthenticated()', () => {
|
||||
it('should call hasValidIdToken() and return its value', () => {
|
||||
oAuthService.hasValidIdToken.and.returnValue(true);
|
||||
expect(spectator.service.isAuthenticated()).toBeTrue();
|
||||
expect(oAuthService.hasValidIdToken).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getToken()', () => {
|
||||
it('should call getAccessToken() and return its value', () => {
|
||||
oAuthService.getAccessToken.and.returnValue('token');
|
||||
expect(spectator.service.getToken()).toEqual('token');
|
||||
expect(oAuthService.getAccessToken).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getClaims()', () => {
|
||||
it('should call getAccessToken() and return its value', () => {
|
||||
oAuthService.getAccessToken.and.returnValue('token');
|
||||
const claims = {
|
||||
claim1: 'value',
|
||||
claim2: 'value2',
|
||||
};
|
||||
spyOn(spectator.service, 'parseJwt').and.returnValue(claims);
|
||||
expect(spectator.service.getClaims()).toEqual(claims);
|
||||
expect(spectator.service.parseJwt).toHaveBeenCalledWith('token');
|
||||
expect(oAuthService.getAccessToken).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getClaimByKey()', () => {
|
||||
it('should call getClaims() and return its key value', () => {
|
||||
spyOn(spectator.service, 'getClaims').and.returnValue({
|
||||
claim1: 'value',
|
||||
claim2: 'value2',
|
||||
});
|
||||
|
||||
expect(spectator.service.getClaimByKey('claim1')).toEqual('value');
|
||||
expect(spectator.service.getClaims).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return null if getClaims() returns null or undefined', () => {
|
||||
spyOn(spectator.service, 'getClaims').and.returnValue(null);
|
||||
|
||||
expect(spectator.service.getClaimByKey('claim1')).toBeNull();
|
||||
expect(spectator.service.getClaims).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseJwt()', () => {
|
||||
it('should return null if the token is null or undefined', () => {
|
||||
expect(spectator.service.parseJwt(null)).toBeNull();
|
||||
expect(spectator.service.parseJwt(undefined)).toBeNull();
|
||||
});
|
||||
|
||||
it('should return the value of the key', () => {
|
||||
const token =
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ';
|
||||
expect(spectator.service.parseJwt(token)).toEqual({
|
||||
sub: '1234567890',
|
||||
name: 'John Doe',
|
||||
admin: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('login()', () => {
|
||||
it('should call initLoginFlow()', () => {
|
||||
spectator.service.login();
|
||||
expect(oAuthService.initLoginFlow).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('logout()', () => {
|
||||
it('should call revokeTokenAndLogout()', async () => {
|
||||
await spectator.service.logout();
|
||||
expect(oAuthService.revokeTokenAndLogout).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getToken()', () => {
|
||||
it('should return getAccessToken()', () => {
|
||||
spectator.service.getToken();
|
||||
expect(oAuthService.getAccessToken).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('initialized', () => {
|
||||
it('should return _initialized as Observable', () => {
|
||||
spyOn(spectator.service['_initialized'], 'asObservable').and.callThrough();
|
||||
expect(spectator.service.initialized$).toBeInstanceOf(Observable);
|
||||
expect(spectator.service['_initialized'].asObservable).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
84
apps/core/auth/src/lib/auth.service.ts
Normal file
84
apps/core/auth/src/lib/auth.service.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Config } from '@core/config';
|
||||
import { isNullOrUndefined } from '@utils/common';
|
||||
import { AuthConfig, OAuthService } from 'angular-oauth2-oidc';
|
||||
import { JwksValidationHandler } from 'angular-oauth2-oidc-jwks';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class AuthService {
|
||||
private readonly _initialized = new BehaviorSubject<boolean>(false);
|
||||
get initialized$() {
|
||||
return this._initialized.asObservable();
|
||||
}
|
||||
|
||||
constructor(private _config: Config, private readonly _oAuthService: OAuthService) {}
|
||||
|
||||
async init() {
|
||||
if (this._initialized.getValue()) {
|
||||
throw new Error('AuthService is already initialized');
|
||||
}
|
||||
|
||||
const authConfig: AuthConfig = this._config.get('@core/auth');
|
||||
|
||||
authConfig.redirectUri = window.location.origin;
|
||||
authConfig.silentRefreshRedirectUri = window.location.origin + '/silent-refresh.html';
|
||||
authConfig.useSilentRefresh = true;
|
||||
|
||||
this._oAuthService.configure(authConfig);
|
||||
this._oAuthService.tokenValidationHandler = new JwksValidationHandler();
|
||||
|
||||
this._oAuthService.setupAutomaticSilentRefresh();
|
||||
await this._oAuthService.loadDiscoveryDocumentAndTryLogin();
|
||||
|
||||
this._initialized.next(true);
|
||||
}
|
||||
|
||||
isAuthenticated() {
|
||||
return this._oAuthService.hasValidIdToken();
|
||||
}
|
||||
|
||||
getToken() {
|
||||
return this._oAuthService.getAccessToken();
|
||||
}
|
||||
|
||||
getClaims() {
|
||||
const token = this._oAuthService.getAccessToken();
|
||||
return this.parseJwt(token);
|
||||
}
|
||||
|
||||
getClaimByKey(key: string) {
|
||||
const claims = this.getClaims();
|
||||
if (isNullOrUndefined(claims)) {
|
||||
return null;
|
||||
}
|
||||
return claims[key];
|
||||
}
|
||||
|
||||
parseJwt(token: string) {
|
||||
if (isNullOrUndefined(token)) {
|
||||
return null;
|
||||
}
|
||||
const base64Url = token.split('.')[1];
|
||||
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
|
||||
|
||||
const encoded = window.atob(base64);
|
||||
return JSON.parse(encoded);
|
||||
}
|
||||
|
||||
login() {
|
||||
this._oAuthService.initLoginFlow();
|
||||
}
|
||||
|
||||
setKeyCardToken(token: string) {
|
||||
this._oAuthService.customQueryParams = {
|
||||
temp_token: token,
|
||||
};
|
||||
}
|
||||
|
||||
async logout() {
|
||||
await this._oAuthService.revokeTokenAndLogout();
|
||||
}
|
||||
}
|
||||
4
apps/core/auth/src/lib/index.ts
Normal file
4
apps/core/auth/src/lib/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
// start:ng42.barrel
|
||||
export * from './auth.module';
|
||||
export * from './auth.service';
|
||||
// end:ng42.barrel
|
||||
5
apps/core/auth/src/public-api.ts
Normal file
5
apps/core/auth/src/public-api.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
* Public API Surface of auth
|
||||
*/
|
||||
|
||||
export * from './lib';
|
||||
25
apps/core/auth/src/test.ts
Normal file
25
apps/core/auth/src/test.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||
|
||||
import 'zone.js';
|
||||
import 'zone.js/testing';
|
||||
import { getTestBed } from '@angular/core/testing';
|
||||
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
|
||||
|
||||
declare const require: {
|
||||
context(
|
||||
path: string,
|
||||
deep?: boolean,
|
||||
filter?: RegExp
|
||||
): {
|
||||
keys(): string[];
|
||||
<T>(id: string): T;
|
||||
};
|
||||
};
|
||||
|
||||
// First, initialize the Angular testing environment.
|
||||
getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { teardown: { destroyAfterEach: true } });
|
||||
|
||||
// Then we find all the tests.
|
||||
const context = require.context('./', true, /\.spec\.ts$/);
|
||||
// And load the modules.
|
||||
context.keys().map(context);
|
||||
20
apps/core/auth/tsconfig.lib.json
Normal file
20
apps/core/auth/tsconfig.lib.json
Normal file
@@ -0,0 +1,20 @@
|
||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../../out-tsc/lib",
|
||||
"target": "es2015",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"inlineSources": true,
|
||||
"types": [],
|
||||
"lib": [
|
||||
"dom",
|
||||
"es2018"
|
||||
]
|
||||
},
|
||||
"exclude": [
|
||||
"src/test.ts",
|
||||
"**/*.spec.ts"
|
||||
]
|
||||
}
|
||||
10
apps/core/auth/tsconfig.lib.prod.json
Normal file
10
apps/core/auth/tsconfig.lib.prod.json
Normal file
@@ -0,0 +1,10 @@
|
||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||
{
|
||||
"extends": "./tsconfig.lib.json",
|
||||
"compilerOptions": {
|
||||
"declarationMap": false
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"compilationMode": "partial"
|
||||
}
|
||||
}
|
||||
17
apps/core/auth/tsconfig.spec.json
Normal file
17
apps/core/auth/tsconfig.spec.json
Normal file
@@ -0,0 +1,17 @@
|
||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../../out-tsc/spec",
|
||||
"types": [
|
||||
"jasmine"
|
||||
]
|
||||
},
|
||||
"files": [
|
||||
"src/test.ts"
|
||||
],
|
||||
"include": [
|
||||
"**/*.spec.ts",
|
||||
"**/*.d.ts"
|
||||
]
|
||||
}
|
||||
25
apps/core/breadcrumb/README.md
Normal file
25
apps/core/breadcrumb/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Breadcrumb
|
||||
|
||||
This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 10.1.2.
|
||||
|
||||
## Code scaffolding
|
||||
|
||||
Run `ng generate component component-name --project breadcrumb` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project breadcrumb`.
|
||||
|
||||
> Note: Don't forget to add `--project breadcrumb` or else it will be added to the default project in your `angular.json` file.
|
||||
|
||||
## Build
|
||||
|
||||
Run `ng build breadcrumb` to build the project. The build artifacts will be stored in the `dist/` directory.
|
||||
|
||||
## Publishing
|
||||
|
||||
After building your library with `ng build breadcrumb`, go to the dist folder `cd dist/breadcrumb` and run `npm publish`.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `ng test breadcrumb` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
||||
|
||||
## Further help
|
||||
|
||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
|
||||
32
apps/core/breadcrumb/karma.conf.js
Normal file
32
apps/core/breadcrumb/karma.conf.js
Normal file
@@ -0,0 +1,32 @@
|
||||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage-istanbul-reporter'),
|
||||
require('@angular-devkit/build-angular/plugins/karma'),
|
||||
],
|
||||
client: {
|
||||
clearContext: false, // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
coverageIstanbulReporter: {
|
||||
dir: require('path').join(__dirname, '../../../coverage/core/breadcrumb'),
|
||||
reports: ['html', 'lcovonly', 'text-summary'],
|
||||
fixWebpackSourcePaths: true,
|
||||
},
|
||||
reporters: ['progress', 'kjhtml'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['Chrome'],
|
||||
singleRun: false,
|
||||
restartOnFileChange: true,
|
||||
});
|
||||
};
|
||||
7
apps/core/breadcrumb/ng-package.json
Normal file
7
apps/core/breadcrumb/ng-package.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
||||
"dest": "../../../dist/core/breadcrumb",
|
||||
"lib": {
|
||||
"entryFile": "src/public-api.ts"
|
||||
}
|
||||
}
|
||||
11
apps/core/breadcrumb/package.json
Normal file
11
apps/core/breadcrumb/package.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "@core/breadcrumb",
|
||||
"version": "0.0.1",
|
||||
"peerDependencies": {
|
||||
"@angular/common": "^10.1.2",
|
||||
"@angular/core": "^10.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": "^2.0.0"
|
||||
}
|
||||
}
|
||||
42
apps/core/breadcrumb/src/lib/breadcrumb.service.spec.ts
Normal file
42
apps/core/breadcrumb/src/lib/breadcrumb.service.spec.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { isNumber } from '@utils/common';
|
||||
import { of } from 'rxjs';
|
||||
import { BreadcrumbService } from './breadcrumb.service';
|
||||
import { Breadcrumb } from './defs';
|
||||
|
||||
import * as actions from './store/breadcrumb.actions';
|
||||
import * as selectors from './store/breadcrumb.selectors';
|
||||
|
||||
describe('Breadcrumb Service', () => {
|
||||
let store: jasmine.SpyObj<Store<any>>;
|
||||
let service: BreadcrumbService;
|
||||
|
||||
beforeEach(() => {
|
||||
store = jasmine.createSpyObj<Store<any>>('Store', ['select', 'dispatch']);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
providers: [BreadcrumbService, { provide: Store, useValue: store }],
|
||||
});
|
||||
|
||||
service = TestBed.inject(BreadcrumbService);
|
||||
});
|
||||
|
||||
describe('getByKey$', () => {
|
||||
it('should call store.select with the selectBreadcrumbsByKey selector', () => {
|
||||
store.select.and.returnValue(of([]));
|
||||
service.getByKey$('unit-test');
|
||||
expect(store.select).toHaveBeenCalledWith(selectors.selectBreadcrumbsByKey, 'unit-test');
|
||||
});
|
||||
});
|
||||
|
||||
describe('addBreadcrumb', () => {
|
||||
it('should call store.dispatch with the addBreadecrumb action and retuns a breadcrumb with an id', () => {
|
||||
let breadcrumb: Breadcrumb = { name: 'unit-test', key: 'hello-key', path: 'Run The Test' };
|
||||
breadcrumb = service.addBreadcrumb(breadcrumb);
|
||||
expect(store.dispatch).toHaveBeenCalledWith(actions.addBreadcrumb({ breadcrumb }));
|
||||
expect(isNumber(breadcrumb.id)).toBeTruthy();
|
||||
expect(isNumber(breadcrumb.timestamp)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
143
apps/core/breadcrumb/src/lib/breadcrumb.service.ts
Normal file
143
apps/core/breadcrumb/src/lib/breadcrumb.service.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { getNumberId } from '@utils/id';
|
||||
|
||||
import { Observable } from 'rxjs';
|
||||
import { first, map, take } from 'rxjs/operators';
|
||||
import { Breadcrumb } from './defs';
|
||||
|
||||
import * as actions from './store/breadcrumb.actions';
|
||||
import * as selectors from './store/breadcrumb.selectors';
|
||||
|
||||
@Injectable()
|
||||
export class BreadcrumbService {
|
||||
constructor(private store: Store<any>) {}
|
||||
|
||||
getAll$() {
|
||||
return this.store.select(selectors.selectBreadcrumbs);
|
||||
}
|
||||
|
||||
getByKey$(key: string): Observable<Breadcrumb[]> {
|
||||
return this.store.select(selectors.selectBreadcrumbsByKey, key);
|
||||
}
|
||||
|
||||
getBreadcrumbById$(id: number): Observable<Breadcrumb> {
|
||||
return this.store.select(selectors.selectBreadcrumbById, id);
|
||||
}
|
||||
|
||||
getBreadcrumbByKey$(key: string | number): Observable<Breadcrumb[]> {
|
||||
return this.store.select(selectors.selectBreadcrumbsByKey, key);
|
||||
}
|
||||
|
||||
getLastActivatedBreadcrumbByKey$(key: string | number): Observable<Breadcrumb> {
|
||||
return this.getBreadcrumbByKey$(key).pipe(
|
||||
map((crumbs) =>
|
||||
crumbs.reduce((latest, current) => {
|
||||
if (!latest) {
|
||||
return current;
|
||||
}
|
||||
return latest.timestamp > current.timestamp ? latest : current;
|
||||
}, undefined)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
addBreadcrumb(breadcrumb: Breadcrumb): Breadcrumb {
|
||||
const newBreadcrumb: Breadcrumb = { ...breadcrumb, id: getNumberId(), timestamp: Date.now(), changed: Date.now() };
|
||||
this.store.dispatch(actions.addBreadcrumb({ breadcrumb: newBreadcrumb }));
|
||||
return newBreadcrumb;
|
||||
}
|
||||
|
||||
patchBreadcrumb(breadcrumbId: number, changes: Partial<Breadcrumb>) {
|
||||
this.store.dispatch(actions.updateBreadcrumb({ id: breadcrumbId, changes: { ...changes, changed: Date.now() } }));
|
||||
}
|
||||
|
||||
async patchBreadcrumbByKeyAndTags(key: string | number, tags: string[], changes: Partial<Breadcrumb>) {
|
||||
const crumbs = await this.getBreadcrumbsByKeyAndTags$(key, tags).pipe(first()).toPromise();
|
||||
crumbs.forEach((crumb) => this.patchBreadcrumb(crumb.id, changes));
|
||||
}
|
||||
|
||||
async addBreadcrumbIfNotExists(breadcrumb: Breadcrumb) {
|
||||
const crumbs = await this.getBreadcrumbsByKeyAndTags$(breadcrumb.key, breadcrumb.tags).pipe(take(1)).toPromise();
|
||||
if (crumbs.length === 0) {
|
||||
return this.addBreadcrumb(breadcrumb);
|
||||
}
|
||||
return crumbs[0];
|
||||
}
|
||||
|
||||
async addOrUpdateBreadcrumbIfNotExists(breadcrumb: Breadcrumb) {
|
||||
const crumbs = await this.getBreadcrumbsByKeyAndTags$(breadcrumb.key, breadcrumb.tags).pipe(take(1)).toPromise();
|
||||
if (crumbs.length === 0) {
|
||||
return this.addBreadcrumb(breadcrumb);
|
||||
}
|
||||
return this.patchBreadcrumb(crumbs[0].id, breadcrumb);
|
||||
}
|
||||
|
||||
getBreadcrumbsByKeyAndTag$(key: string | number, tag: string): Observable<Breadcrumb[]> {
|
||||
return this.store.select(selectors.selectBreadcrumbsByKeyAndTag, { key, tag });
|
||||
}
|
||||
|
||||
getBreadcrumbsByKeyAndTags$(key: string | number, tags: string[]): Observable<Breadcrumb[]> {
|
||||
return this.store.select(selectors.selectBreadcrumbsByKeyAndTags, { key, tags });
|
||||
}
|
||||
|
||||
async removeBreadcrumbsAfter(breadcrumbId: number, withTags: string[] = []) {
|
||||
const breadcrumb = await this.getBreadcrumbById$(breadcrumbId).pipe(take(1)).toPromise();
|
||||
|
||||
if (!breadcrumb) {
|
||||
return;
|
||||
}
|
||||
|
||||
let breadcrumbs: Breadcrumb[];
|
||||
|
||||
if (withTags?.length > 0) {
|
||||
breadcrumbs = await this.getBreadcrumbsByKeyAndTags$(breadcrumb.key, withTags).pipe(take(1)).toPromise();
|
||||
} else {
|
||||
breadcrumbs = await this.getBreadcrumbByKey$(breadcrumb.key).pipe(take(1)).toPromise();
|
||||
}
|
||||
|
||||
if (!breadcrumbs?.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const breadcrumbsToRemove = breadcrumbs.filter((crumb) => crumb.timestamp > breadcrumb.timestamp);
|
||||
|
||||
if (!breadcrumbsToRemove.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.store.dispatch(actions.removeManyBreadcrumb({ ids: breadcrumbsToRemove.map((crumb) => crumb.id) }));
|
||||
}
|
||||
|
||||
async removeBreadcrumb(breadcrumbId: number, recursive: boolean = true) {
|
||||
const breadcrumb = await this.getBreadcrumbById$(breadcrumbId).pipe(take(1)).toPromise();
|
||||
|
||||
if (!breadcrumb) {
|
||||
return;
|
||||
}
|
||||
|
||||
let breadcrumbsToRemove = [breadcrumb];
|
||||
|
||||
if (recursive) {
|
||||
const breadcrumbs = await this.getBreadcrumbByKey$(breadcrumb.key).pipe(take(1)).toPromise();
|
||||
breadcrumbsToRemove = [...breadcrumbsToRemove, ...breadcrumbs.filter((crumb) => crumb.timestamp > breadcrumb.timestamp)];
|
||||
}
|
||||
|
||||
if (!breadcrumbsToRemove.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.store.dispatch(actions.removeManyBreadcrumb({ ids: breadcrumbsToRemove.map((crumb) => crumb.id) }));
|
||||
}
|
||||
|
||||
async removeBreadcrumbsByKeyAndTags(key: number | string, tags: string[]) {
|
||||
const crumbs = await this.getBreadcrumbsByKeyAndTags$(key, tags).pipe(first()).toPromise();
|
||||
crumbs.forEach((crumb) => this.removeBreadcrumb(crumb.id));
|
||||
}
|
||||
|
||||
getLatestBreadcrumbForSection(section: 'customer' | 'branch') {
|
||||
return this.store
|
||||
.select(selectors.selectBreadcrumbsBySection, { section })
|
||||
.pipe(map((crumbs) => crumbs.sort((a, b) => b.changed - a.changed).find((f) => true)));
|
||||
}
|
||||
}
|
||||
22
apps/core/breadcrumb/src/lib/core-breadcrumb.module.ts
Normal file
22
apps/core/breadcrumb/src/lib/core-breadcrumb.module.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { ModuleWithProviders, NgModule } from '@angular/core';
|
||||
import { EffectsModule } from '@ngrx/effects';
|
||||
import { StoreModule } from '@ngrx/store';
|
||||
import { BreadcrumbService } from './breadcrumb.service';
|
||||
import { BreadcrumbEffects } from './store/breadcrumb.effect';
|
||||
import { breadcrumbReducer } from './store/breadcrumb.reducer';
|
||||
import { featureName } from './store/breadcrumb.state';
|
||||
|
||||
@NgModule()
|
||||
export class CoreBreadcrumbModule {
|
||||
static forRoot(): ModuleWithProviders<CoreBreadcrumbModule> {
|
||||
return {
|
||||
ngModule: CoreBreadcrumbForRootModule,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
imports: [StoreModule.forFeature(featureName, breadcrumbReducer), EffectsModule.forFeature([BreadcrumbEffects])],
|
||||
providers: [BreadcrumbService],
|
||||
})
|
||||
export class CoreBreadcrumbForRootModule {}
|
||||
46
apps/core/breadcrumb/src/lib/defs/breadcrumb.model.ts
Normal file
46
apps/core/breadcrumb/src/lib/defs/breadcrumb.model.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
export interface Breadcrumb {
|
||||
/**
|
||||
* Eindeutige ID für die Entity
|
||||
*/
|
||||
id?: number;
|
||||
|
||||
/**
|
||||
* Identifier für ein Teilbereich/ProzessId der Applikation
|
||||
*/
|
||||
key: number | string;
|
||||
|
||||
/**
|
||||
* Tags
|
||||
*/
|
||||
tags?: string[];
|
||||
|
||||
/**
|
||||
* Anzeigename
|
||||
*/
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* Url
|
||||
*/
|
||||
path: string;
|
||||
|
||||
/**
|
||||
* Query Parameter
|
||||
*/
|
||||
params?: Object;
|
||||
|
||||
/**
|
||||
* Timestamp
|
||||
*/
|
||||
timestamp?: number;
|
||||
|
||||
/**
|
||||
* Cahnged
|
||||
*/
|
||||
changed?: number;
|
||||
|
||||
/**
|
||||
* Applicatiuon Section
|
||||
*/
|
||||
section: string;
|
||||
}
|
||||
3
apps/core/breadcrumb/src/lib/defs/index.ts
Normal file
3
apps/core/breadcrumb/src/lib/defs/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
// start:ng42.barrel
|
||||
export * from './breadcrumb.model';
|
||||
// end:ng42.barrel
|
||||
@@ -0,0 +1 @@
|
||||
describe('Breadcrumb Actions', () => {});
|
||||
24
apps/core/breadcrumb/src/lib/store/breadcrumb.actions.ts
Normal file
24
apps/core/breadcrumb/src/lib/store/breadcrumb.actions.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { createAction, props } from '@ngrx/store';
|
||||
import { Breadcrumb } from '../defs';
|
||||
|
||||
const prefix = '[CORE-BREADCRUMB]';
|
||||
|
||||
/**
|
||||
* Action um Breadcrumb zum State hinzufügen
|
||||
*/
|
||||
export const addBreadcrumb = createAction(`${prefix} Add Breadcrumb`, props<{ breadcrumb: Breadcrumb }>());
|
||||
|
||||
/**
|
||||
* Action um Breadcrumb im State zu ändern
|
||||
*/
|
||||
export const updateBreadcrumb = createAction(`${prefix} Update Breadcrumb`, props<{ id: number; changes: Partial<Breadcrumb> }>());
|
||||
|
||||
/**
|
||||
* Action um Breadcrumb im State zu entfernen
|
||||
*/
|
||||
export const removeBreadcrumb = createAction(`${prefix} Remove Breadcrumb`, props<{ id: number }>());
|
||||
|
||||
/**
|
||||
* Action um mehrere Breadcrumbs im State zu entfernen
|
||||
*/
|
||||
export const removeManyBreadcrumb = createAction(`${prefix} Remove Many Breadcrumb`, props<{ ids: number[] }>());
|
||||
27
apps/core/breadcrumb/src/lib/store/breadcrumb.effect.ts
Normal file
27
apps/core/breadcrumb/src/lib/store/breadcrumb.effect.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { removeProcess } from '@core/application';
|
||||
import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
import { NEVER } from 'rxjs';
|
||||
import { mergeMap, tap, first, map } from 'rxjs/operators';
|
||||
import { BreadcrumbService } from '../breadcrumb.service';
|
||||
|
||||
@Injectable()
|
||||
export class BreadcrumbEffects {
|
||||
removeProcess$ = createEffect(
|
||||
() =>
|
||||
this.actions$.pipe(
|
||||
ofType(removeProcess),
|
||||
mergeMap((action) =>
|
||||
this.breadcrumb.getBreadcrumbByKey$(action.processId).pipe(
|
||||
first(),
|
||||
tap((breadcrumbs) => {
|
||||
breadcrumbs?.forEach((crumb) => this.breadcrumb.removeBreadcrumb(crumb.id));
|
||||
})
|
||||
)
|
||||
)
|
||||
),
|
||||
{ dispatch: false }
|
||||
);
|
||||
|
||||
constructor(private actions$: Actions, private breadcrumb: BreadcrumbService) {}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
import { Breadcrumb } from '../defs';
|
||||
import * as action from './breadcrumb.actions';
|
||||
import { breadcrumbReducer } from './breadcrumb.reducer';
|
||||
import { INIT } from './breadcrumb.state';
|
||||
|
||||
describe('Breadcrumb Reducer', () => {
|
||||
it('should return the initial state if the current state is empty', () => {
|
||||
const fixture = breadcrumbReducer(undefined, { type: '' });
|
||||
|
||||
expect(fixture).toEqual(INIT);
|
||||
});
|
||||
|
||||
describe('addBreadcrumb', () => {
|
||||
it('should add the breadcrumb to the state', () => {
|
||||
const breadcrumb: Breadcrumb = {
|
||||
id: 1,
|
||||
key: 'unit-test',
|
||||
name: 'Test Name',
|
||||
path: 'Test Patch',
|
||||
};
|
||||
|
||||
const fixture = breadcrumbReducer(INIT, action.addBreadcrumb({ breadcrumb }));
|
||||
|
||||
expect(fixture.entities[1]).toEqual(breadcrumb);
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateBreadcrumb', () => {
|
||||
it('should update an existing breadcrumb', () => {
|
||||
const breadcrumb: Breadcrumb = {
|
||||
id: 1,
|
||||
key: 'unit-test',
|
||||
name: 'Test Name',
|
||||
path: 'Test Patch',
|
||||
};
|
||||
|
||||
const expected = {
|
||||
...breadcrumb,
|
||||
name: 'Test Name 2',
|
||||
};
|
||||
|
||||
const state = breadcrumbReducer(INIT, action.addBreadcrumb({ breadcrumb }));
|
||||
|
||||
const fixture = breadcrumbReducer(state, action.updateBreadcrumb({ id: breadcrumb.id, changes: { name: 'Test Name 2' } }));
|
||||
|
||||
expect(fixture.entities[breadcrumb.id]).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeBreadcrumb', () => {
|
||||
it('should remove the breadcrumb', () => {
|
||||
const breadcrumb: Breadcrumb = {
|
||||
id: 1,
|
||||
key: 'unit-test',
|
||||
name: 'Test Name',
|
||||
path: 'Test Patch',
|
||||
};
|
||||
|
||||
const state = breadcrumbReducer(INIT, action.addBreadcrumb({ breadcrumb }));
|
||||
|
||||
const fixture = breadcrumbReducer(state, action.removeBreadcrumb({ id: breadcrumb.id }));
|
||||
|
||||
expect(fixture.entities[breadcrumb.id]).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeManyBreadcrumb', () => {
|
||||
it('should remove all breadcrumbs for the given ids', () => {
|
||||
const breadcrumb1: Breadcrumb = {
|
||||
id: 1,
|
||||
key: 'unit-test',
|
||||
name: 'Test Name',
|
||||
path: 'Test Patch',
|
||||
};
|
||||
const breadcrumb2 = { ...breadcrumb1, id: 2 };
|
||||
const breadcrumb3 = { ...breadcrumb1, id: 3 };
|
||||
|
||||
let state = breadcrumbReducer(INIT, action.addBreadcrumb({ breadcrumb: breadcrumb1 }));
|
||||
state = breadcrumbReducer(state, action.addBreadcrumb({ breadcrumb: breadcrumb2 }));
|
||||
state = breadcrumbReducer(state, action.addBreadcrumb({ breadcrumb: breadcrumb3 }));
|
||||
|
||||
const fixture = breadcrumbReducer(state, action.removeManyBreadcrumb({ ids: [1, 3] }));
|
||||
|
||||
expect(Object.keys(fixture.entities).length).toEqual(1);
|
||||
expect(fixture.entities[breadcrumb2.id]).toEqual(breadcrumb2);
|
||||
});
|
||||
});
|
||||
});
|
||||
16
apps/core/breadcrumb/src/lib/store/breadcrumb.reducer.ts
Normal file
16
apps/core/breadcrumb/src/lib/store/breadcrumb.reducer.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { Action, createReducer, on } from '@ngrx/store';
|
||||
import { breadcrumbAdapter, BreadcrumbState, INIT } from './breadcrumb.state';
|
||||
|
||||
import * as actions from './breadcrumb.actions';
|
||||
|
||||
const _breadcrumbReducer = createReducer(
|
||||
INIT,
|
||||
on(actions.addBreadcrumb, (s, a) => breadcrumbAdapter.addOne(a.breadcrumb, s)),
|
||||
on(actions.updateBreadcrumb, (s, a) => breadcrumbAdapter.updateOne(a, s)),
|
||||
on(actions.removeBreadcrumb, (s, a) => breadcrumbAdapter.removeOne(a.id, s)),
|
||||
on(actions.removeManyBreadcrumb, (s, a) => breadcrumbAdapter.removeMany(a.ids, s))
|
||||
);
|
||||
|
||||
export function breadcrumbReducer(state: BreadcrumbState, action: Action) {
|
||||
return _breadcrumbReducer(state, action);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import * as selector from './breadcrumb.selectors';
|
||||
import * as action from './breadcrumb.actions';
|
||||
import { breadcrumbReducer } from './breadcrumb.reducer';
|
||||
|
||||
import { BreadcrumbState, INIT } from './breadcrumb.state';
|
||||
|
||||
describe('Breadcrumb Selectors', () => {
|
||||
let state: BreadcrumbState;
|
||||
|
||||
beforeEach(() => {
|
||||
state = breadcrumbReducer(INIT, action.addBreadcrumb({ breadcrumb: { id: 1, key: 'unit-test-1', path: '', name: 'Unit Test 1' } }));
|
||||
state = breadcrumbReducer(
|
||||
state,
|
||||
action.addBreadcrumb({ breadcrumb: { id: 2, key: 'unit-test-1', path: '', name: 'Unit Test 1', tags: ['details'] } })
|
||||
);
|
||||
state = breadcrumbReducer(state, action.addBreadcrumb({ breadcrumb: { id: 3, key: 'unit-test-2', path: '', name: 'Unit Test 1' } }));
|
||||
state = breadcrumbReducer(state, action.addBreadcrumb({ breadcrumb: { id: 4, key: 'unit-test-3', path: '', name: 'Unit Test 1' } }));
|
||||
state = breadcrumbReducer(
|
||||
state,
|
||||
action.addBreadcrumb({ breadcrumb: { id: 5, key: 'unit-test-3', path: '', name: 'Unit Test 1', tags: ['details'] } })
|
||||
);
|
||||
});
|
||||
|
||||
describe('selectBreadcrumbsByKey', () => {
|
||||
it('should return all breadcrumbs with the key unit-test-1', () => {
|
||||
const fixture = selector.selectBreadcrumbsByKey.projector(Object.values(state.entities), 'unit-test-1');
|
||||
expect(fixture.length).toBe(2);
|
||||
expect(fixture[0].key).toBe('unit-test-1');
|
||||
expect(fixture[1].key).toBe('unit-test-1');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectBreadcrumbsByKeyAndTag', () => {
|
||||
it('should return all breadcrumbs with the key unit-test-3 and tag details', () => {
|
||||
const fixture = selector.selectBreadcrumbsByKeyAndTag.projector(Object.values(state.entities), {
|
||||
key: 'unit-test-3',
|
||||
tag: 'details',
|
||||
});
|
||||
expect(fixture.length).toBe(1);
|
||||
expect(fixture[0].key).toBe('unit-test-3');
|
||||
expect(fixture[0].tags).toContain('details');
|
||||
});
|
||||
});
|
||||
});
|
||||
48
apps/core/breadcrumb/src/lib/store/breadcrumb.selectors.ts
Normal file
48
apps/core/breadcrumb/src/lib/store/breadcrumb.selectors.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { createSelector, createFeatureSelector } from '@ngrx/store';
|
||||
import { Breadcrumb } from '../defs';
|
||||
import { breadcrumbAdapter, BreadcrumbState, featureName } from './breadcrumb.state';
|
||||
import { isArray } from '@utils/common';
|
||||
|
||||
const selectFeature = createFeatureSelector<BreadcrumbState>(featureName);
|
||||
|
||||
const { selectAll, selectEntities } = breadcrumbAdapter.getSelectors(selectFeature);
|
||||
|
||||
/**
|
||||
* Gibt alle Breadcrumb Entities als Array zurück
|
||||
*/
|
||||
export const selectBreadcrumbs = selectAll;
|
||||
|
||||
/**
|
||||
* Gibt alle Breadcrumb Entities als Array zurück die den key enthalten
|
||||
*/
|
||||
export const selectBreadcrumbById = createSelector(selectEntities, (entities, id: number) => entities[id]);
|
||||
|
||||
/**
|
||||
* Gibt alle Breadcrumb Entities als Array zurück die den key enthalten
|
||||
*/
|
||||
export const selectBreadcrumbsByKey = createSelector(selectAll, (entities, key: string) => entities.filter((crumb) => crumb.key === key));
|
||||
|
||||
/**
|
||||
* Gibt alle Breadcrumb Entities als Array zurück die den key und tag enthalten
|
||||
*/
|
||||
export const selectBreadcrumbsByKeyAndTag = createSelector(
|
||||
selectAll,
|
||||
(entities: Breadcrumb[], { key, tag }: { key: string; tag: string }) =>
|
||||
entities.filter((crumb) => crumb.key === key && isArray(crumb.tags) && crumb.tags.includes(tag))
|
||||
);
|
||||
|
||||
/**
|
||||
* Gibt alle Breadcrumb Entities als Array zurück die den key und tags enthalten
|
||||
*/
|
||||
export const selectBreadcrumbsByKeyAndTags = createSelector(
|
||||
selectAll,
|
||||
(entities: Breadcrumb[], { key, tags }: { key: string; tags: string[] }) =>
|
||||
entities.filter((crumb) => crumb.key === key && isArray(crumb.tags) && tags.every((tag) => crumb.tags.includes(tag)))
|
||||
);
|
||||
|
||||
/**
|
||||
* Gibt alle Breadcrumb Entities als Array zurück die die tags enthalten
|
||||
*/
|
||||
export const selectBreadcrumbsBySection = createSelector(selectAll, (entities: Breadcrumb[], { section }: { section: string }) =>
|
||||
entities.filter((crumb) => crumb.section === section)
|
||||
);
|
||||
12
apps/core/breadcrumb/src/lib/store/breadcrumb.state.ts
Normal file
12
apps/core/breadcrumb/src/lib/store/breadcrumb.state.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { createEntityAdapter, EntityState } from '@ngrx/entity';
|
||||
import { Breadcrumb } from '../defs';
|
||||
|
||||
export interface BreadcrumbState extends EntityState<Breadcrumb> {}
|
||||
|
||||
export const featureName = 'core-breadcrumb';
|
||||
|
||||
export const breadcrumbAdapter = createEntityAdapter<Breadcrumb>();
|
||||
|
||||
export const INIT: BreadcrumbState = {
|
||||
...breadcrumbAdapter.getInitialState(),
|
||||
};
|
||||
7
apps/core/breadcrumb/src/public-api.ts
Normal file
7
apps/core/breadcrumb/src/public-api.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
* Public API Surface of breadcrumb
|
||||
*/
|
||||
|
||||
export * from './lib/breadcrumb.service';
|
||||
export * from './lib/core-breadcrumb.module';
|
||||
export * from './lib/defs';
|
||||
24
apps/core/breadcrumb/src/test.ts
Normal file
24
apps/core/breadcrumb/src/test.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||
|
||||
import 'zone.js';
|
||||
import 'zone.js/testing';
|
||||
import { getTestBed } from '@angular/core/testing';
|
||||
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
|
||||
|
||||
declare const require: {
|
||||
context(
|
||||
path: string,
|
||||
deep?: boolean,
|
||||
filter?: RegExp
|
||||
): {
|
||||
keys(): string[];
|
||||
<T>(id: string): T;
|
||||
};
|
||||
};
|
||||
|
||||
// First, initialize the Angular testing environment.
|
||||
getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
|
||||
// Then we find all the tests.
|
||||
const context = require.context('./', true, /\.spec\.ts$/);
|
||||
// And load the modules.
|
||||
context.keys().map(context);
|
||||
25
apps/core/breadcrumb/tsconfig.lib.json
Normal file
25
apps/core/breadcrumb/tsconfig.lib.json
Normal file
@@ -0,0 +1,25 @@
|
||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../../out-tsc/lib",
|
||||
"target": "es2015",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"inlineSources": true,
|
||||
"types": [],
|
||||
"lib": [
|
||||
"dom",
|
||||
"es2018"
|
||||
]
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"skipTemplateCodegen": true,
|
||||
"strictMetadataEmit": true,
|
||||
"enableResourceInlining": true
|
||||
},
|
||||
"exclude": [
|
||||
"src/test.ts",
|
||||
"**/*.spec.ts"
|
||||
]
|
||||
}
|
||||
10
apps/core/breadcrumb/tsconfig.lib.prod.json
Normal file
10
apps/core/breadcrumb/tsconfig.lib.prod.json
Normal file
@@ -0,0 +1,10 @@
|
||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||
{
|
||||
"extends": "./tsconfig.lib.json",
|
||||
"compilerOptions": {
|
||||
"declarationMap": false
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"enableIvy": false
|
||||
}
|
||||
}
|
||||
17
apps/core/breadcrumb/tsconfig.spec.json
Normal file
17
apps/core/breadcrumb/tsconfig.spec.json
Normal file
@@ -0,0 +1,17 @@
|
||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../../out-tsc/spec",
|
||||
"types": [
|
||||
"jasmine"
|
||||
]
|
||||
},
|
||||
"files": [
|
||||
"src/test.ts"
|
||||
],
|
||||
"include": [
|
||||
"**/*.spec.ts",
|
||||
"**/*.d.ts"
|
||||
]
|
||||
}
|
||||
17
apps/core/breadcrumb/tslint.json
Normal file
17
apps/core/breadcrumb/tslint.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"extends": "../../../tslint.json",
|
||||
"rules": {
|
||||
"directive-selector": [
|
||||
true,
|
||||
"attribute",
|
||||
"lib",
|
||||
"camelCase"
|
||||
],
|
||||
"component-selector": [
|
||||
true,
|
||||
"element",
|
||||
"lib",
|
||||
"kebab-case"
|
||||
]
|
||||
}
|
||||
}
|
||||
25
apps/core/cache/README.md
vendored
Normal file
25
apps/core/cache/README.md
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# Cache
|
||||
|
||||
This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 10.1.2.
|
||||
|
||||
## Code scaffolding
|
||||
|
||||
Run `ng generate component component-name --project cache` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project cache`.
|
||||
|
||||
> Note: Don't forget to add `--project cache` or else it will be added to the default project in your `angular.json` file.
|
||||
|
||||
## Build
|
||||
|
||||
Run `ng build cache` to build the project. The build artifacts will be stored in the `dist/` directory.
|
||||
|
||||
## Publishing
|
||||
|
||||
After building your library with `ng build cache`, go to the dist folder `cd dist/cache` and run `npm publish`.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `ng test cache` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
||||
|
||||
## Further help
|
||||
|
||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
|
||||
32
apps/core/cache/karma.conf.js
vendored
Normal file
32
apps/core/cache/karma.conf.js
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage-istanbul-reporter'),
|
||||
require('@angular-devkit/build-angular/plugins/karma'),
|
||||
],
|
||||
client: {
|
||||
clearContext: false, // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
coverageIstanbulReporter: {
|
||||
dir: require('path').join(__dirname, '../../../coverage/core/cache'),
|
||||
reports: ['html', 'lcovonly', 'text-summary'],
|
||||
fixWebpackSourcePaths: true,
|
||||
},
|
||||
reporters: ['progress', 'kjhtml'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['Chrome'],
|
||||
singleRun: false,
|
||||
restartOnFileChange: true,
|
||||
});
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user